鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    C++行为树中config().blackboard->template语法如何理解?

    已定时 已固定 已锁定 已移动 已解决
    综合问题
    1
    3
    325
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 小鱼小
      小鱼 技术大佬
      最后由 编辑

      在行为树使用中看到了一个比较陌生的语法,问一下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
      
      

      新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

      小鱼小 2 条回复 最后回复 回复 引用 0
      • 小鱼小
        小鱼 技术大佬 @小鱼
        最后由 编辑

        @小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)

        新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

        1 条回复 最后回复 回复 引用 0
        • 小鱼小
          小鱼 技术大佬 @小鱼
          最后由 编辑

          捞一下帖子,求C++大佬回答一下。

          新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

          1 条回复 最后回复 回复 引用 0
          • 小鱼小 小鱼 将这个主题转为问答主题,在
          • 小鱼小
            小鱼 技术大佬 @小鱼
            最后由 编辑

            @小鱼 已经解决了,这句话是指定调用某个模板函数,避免二义性。(来自十多年的C++大佬回答)

            新书配套视频:https://www.bilibili.com/video/BV1GW42197Ck/

            1 条回复 最后回复 回复 引用 0
            • 小鱼小 小鱼 将这个主题标记为已解决,在
            • 第一个帖子
              最后一个帖子
            皖ICP备16016415号-7
            Powered by NodeBB | 鱼香ROS