C++行为树中config().blackboard->template语法如何理解?
鱼香ROS介绍:
鱼香ROS是由机器人爱好者共同组成的社区,欢迎一起参与机器人技术交流。 进群加V:fishros2048
文章信息:
标题:C++行为树中config().blackboard->template语法如何理解? 原文地址:https://fishros.org.cn/forum/topic/54 关键词: 参与者: 小鱼, 版权声明: 文章中所有知识产权归鱼香ROS及原作者所有。
1. 小鱼苦兮兮的说:在行为树使用中看到了一个比较陌生的语法,问一下C++大佬们。
这行代码的意思是从blackboard(存储数据的地方)中获取一个key为goal,类型为Pose2D的value。
Pose2D mygoal = config().blackboard->template get("goal");
不太理解的地方是config().blackboard->template
和get("goal")
之间的空格。
该开源库地址:https://github.com/BehaviorTree/BehaviorTree.CPP
其中blackboard.h
代码如下
#ifndef BLACKBOARD_H
#define BLACKBOARD_H
#include
#include
#include
#include
#include
#include
#include
#include "behaviortree_cpp_v3/basic_types.h"
#include "behaviortree_cpp_v3/utils/safe_any.hpp"
#include "behaviortree_cpp_v3/exceptions.h"
namespace BT
{
/**
* @brief The Blackboard is the mechanism used by BehaviorTrees to exchange
* typed data.
*/
class Blackboard
{
public:
typedef std::shared_ptr Ptr;
protected:
// This is intentionally protected. Use Blackboard::create instead
Blackboard(Blackboard::Ptr parent): parent_bb_(parent)
{}
public:
/** Use this static method to create an instance of the BlackBoard
* to share among all your NodeTrees.
*/
static Blackboard::Ptr create(Blackboard::Ptr parent = {})
{
return std::shared_ptr( new Blackboard(parent) );
}
virtual ~Blackboard() = default;
/**
* @brief The method getAny allow the user to access directly the type
* erased value.
*
* @return the pointer or nullptr if it fails.
*/
const Any* getAny(const std::string& key) const
{
std::unique_lock lock(mutex_);
if( auto parent = parent_bb_.lock())
{
auto remapping_it = internal_to_external_.find(key);
if( remapping_it != internal_to_external_.end())
{
return parent->getAny( remapping_it->second );
}
}
auto it = storage_.find(key);
return ( it == storage_.end()) ? nullptr : &(it->second.value);
}
Any* getAny(const std::string& key)
{
std::unique_lock lock(mutex_);
if( auto parent = parent_bb_.lock())
{
auto remapping_it = internal_to_external_.find(key);
if( remapping_it != internal_to_external_.end())
{
return parent->getAny( remapping_it->second );
}
}
auto it = storage_.find(key);
return ( it == storage_.end()) ? nullptr : &(it->second.value);
}
/** Return true if the entry with the given key was found.
* Note that this method may throw an exception if the cast to T failed.
*/
template
bool get(const std::string& key, T& value) const
{
const Any* val = getAny(key);
if (val)
{
value = val->cast();
}
return (bool)val;
}
/**
* Version of get() that throws if it fails.
*/
template
T get(const std::string& key) const
{
const Any* val = getAny(key);
if (val)
{
return val->cast();
}
else
{
throw RuntimeError("Blackboard::get() error. Missing key [", key, "]");
}
}
/// Update the entry with the given key
template
void set(const std::string& key, const T& value)
{
std::unique_lock lock(mutex_);
auto it = storage_.find(key);
if( auto parent = parent_bb_.lock())
{
auto remapping_it = internal_to_external_.find(key);
if( remapping_it != internal_to_external_.end())
{
const auto& remapped_key = remapping_it->second;
if( it == storage_.end() ) // virgin entry
{
auto parent_info = parent->portInfo(remapped_key);
if( parent_info )
{
storage_.insert( {key, Entry( *parent_info ) } );
}
else{
storage_.insert( {key, Entry( PortInfo() ) } );
}
}
parent->set( remapped_key, value );
return;
}
}
if( it != storage_.end() ) // already there. check the type
{
const PortInfo& port_info = it->second.port_info;
auto& previous_any = it->second.value;
const auto locked_type = port_info.type();
Any temp(value);
if( locked_type && *locked_type != typeid(T) && *locked_type != temp.type() )
{
bool mismatching = true;
if( std::is_constructible::value )
{
Any any_from_string = port_info.parseString( value );
if( any_from_string.empty() == false)
{
mismatching = false;
temp = std::move( any_from_string );
}
}
if( mismatching )
{
debugMessage();
throw LogicError( "Blackboard::set() failed: once declared, the type of a port shall not change. "
"Declared type [", demangle( locked_type ),
"] != current type [", demangle( typeid(T) ),"]" );
}
}
previous_any = std::move(temp);
}
else{ // create for the first time without any info
storage_.emplace( key, Entry( Any(value), PortInfo() ) );
}
return;
}
void setPortInfo(std::string key, const PortInfo& info);
const PortInfo *portInfo(const std::string& key);
void addSubtreeRemapping(StringView internal, StringView external);
void debugMessage() const;
std::vector getKeys() const;
void clear()
{
std::unique_lock lock(mutex_);
storage_.clear();
internal_to_external_.clear();
}
private:
struct Entry{
Any value;
const PortInfo port_info;
Entry( const PortInfo& info ):
port_info(info)
{}
Entry(Any&& other_any, const PortInfo& info):
value(std::move(other_any)),
port_info(info)
{}
};
mutable std::mutex mutex_;
std::unordered_map storage_;
std::weak_ptr parent_bb_;
std::unordered_map internal_to_external_;
};
} // end namespace
#endif // BLACKBOARD_H
2. 小鱼看着电脑说:
@小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)
3. 小鱼苦兮兮的说:捞一下帖子,求C++大佬回答一下。
4. 小鱼吃着火锅说:@小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)