紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
C++行为树中config().blackboard->template语法如何理解?
-
在行为树使用中看到了一个比较陌生的语法,问一下C++大佬们。
这行代码的意思是从blackboard(存储数据的地方)中获取一个key为goal,类型为Pose2D的value。
Pose2D mygoal = config().blackboard->template get<Pose2D>("goal");
不太理解的地方是
config().blackboard->template
和get<Pose2D>("goal")
之间的空格。该开源库地址:https://github.com/BehaviorTree/BehaviorTree.CPP
其中
blackboard.h
代码如下#ifndef BLACKBOARD_H #define BLACKBOARD_H #include <iostream> #include <string> #include <memory> #include <stdint.h> #include <unordered_map> #include <mutex> #include <sstream> #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<Blackboard> 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<Blackboard>( 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<std::mutex> 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<std::mutex> 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 <typename T> bool get(const std::string& key, T& value) const { const Any* val = getAny(key); if (val) { value = val->cast<T>(); } return (bool)val; } /** * Version of get() that throws if it fails. */ template <typename T> T get(const std::string& key) const { const Any* val = getAny(key); if (val) { return val->cast<T>(); } else { throw RuntimeError("Blackboard::get() error. Missing key [", key, "]"); } } /// Update the entry with the given key template <typename T> void set(const std::string& key, const T& value) { std::unique_lock<std::mutex> 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<StringView, T>::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<StringView> getKeys() const; void clear() { std::unique_lock<std::mutex> 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<std::string, Entry> storage_; std::weak_ptr<Blackboard> parent_bb_; std::unordered_map<std::string,std::string> internal_to_external_; }; } // end namespace #endif // BLACKBOARD_H
-
@小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)
-
捞一下帖子,求C++大佬回答一下。
-
-
@小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)
-