BT11:行为树内外的数据传输
大家好,欢迎大家关注我的知乎专栏慢慢悠悠小马车
下面的文章有关于blackboard、entry、port、subtree remapping的简介,这是理解行为树的数据解析和传递的重点和难点。行为树不是封闭的,对内有不同subtree、不同port间的数据传递,对外有调用方的状态或结果获取,毕竟很多情况调用方不会满足于只知道执行结果的成功与失败,还想知道为何失败等详细信息。BT4:库中基本类型——Factory和Blackboard_silver bullet-CSDN博客基本的类定义https://blog.csdn.net/linxigjs/article/details/123033365?spm=1001.2014.3001.5501
树内即ports之间
参考BehaviorTree.CPP/examples/t02_basic_ports.cpp 的示例。
<root main_tree_to_execute = "MainTree" ><BehaviorTree ID="MainTree"><Sequence name="root"><SaySomething message="start thinking..." /><ThinkWhatToSay text="{the_answer}"/><SaySomething message="{the_answer}" /><SaySomething2 message="SaySomething2 works too..." /><SaySomething2 message="{the_answer}" /></Sequence></BehaviorTree></root>
类ThinkWhatToSay有1个string类型的OutputPort,并会在tick()时向该port写入值。
class ThinkWhatToSay : public BT::SyncActionNode {public:BT::NodeStatus tick() override {setOutput("text", "The answer is 42");return BT::NodeStatus::SUCCESS;}static BT::PortsList providedPorts() {return {BT::OutputPort<std::string>("text")};}
};
类SaySomething有1个string类型的InputPort,并会在tick()时从该port读取值。
class SaySomething : public BT::SyncActionNode {public:BT::NodeStatus tick() override {auto msg = getInput<std::string>("message");...std::cout << "Robot says: " << msg.value() << std::endl;return BT::NodeStatus::SUCCESS;}static BT::PortsList providedPorts() {return {BT::InputPort<std::string>("message")};}
};
ThinkWhatToSay和SaySomething,通过所在树的blackboard的1个名称为"the_answer"的entry进行数据读写传输。entry可以传输的数据的类型,由port限定。我们把blackboard的数量和包含的entry的名称打印出来,size=1因为没有子树,且只有1个名为"the_answer"的entry。
std::cout << tree.blackboard_stack.size() << std::endl;
for(const auto str : tree.blackboard_stack[0]->getKeys()) {std::cout << str << std::endl;
}
1
the_answer
subtree之间
参考BehaviorTree.CPP/examples/t06_basic_ports.cpp 的示例。
<root main_tree_to_execute = "MainTree"><BehaviorTree ID="MainTree"><Sequence name="main_sequence"><SetBlackboard output_key="move_goal" value="1;2;3" /><SubTree ID="MoveRobot" target="move_goal" output="move_result" /><SaySomething message="{move_result}"/></Sequence></BehaviorTree><BehaviorTree ID="MoveRobot"><Fallback name="move_robot_main"><SequenceStar><MoveBase goal="{target}"/><SetBlackboard output_key="output" value="mission accomplished" /></SequenceStar><ForceFailure><SetBlackboard output_key="output" value="mission failed" /></ForceFailure></Fallback></BehaviorTree></root>
MainTree中包含1个MoveRobot subtree,所以有2个blackboard,blackboard[0]是MainTree的(一定是最外层树的),具有move_result和move_goal 2个entry,而MoveRobot具有output和target 2个entry。在树运行之后,使用debugMessage()可以打印树之间的ports映射如下。full表明对应port已经被设置值,可以被外部读取。
move_result (std::string) -> full
move_goal (Pose2D) -> full
--------------
output (std::string) -> remapped to parent [move_result]
target (Pose2D) -> remapped to parent [move_goal]
如果我们调整下debugMessage()在树创建之后、运行之前,映射会变成什么样呢?
int main() {...auto tree = factory.createTreeFromText(xml_text);// 在树创建之后、运行之前打印映射信息std::cout << "--------------" << std::endl;tree.blackboard_stack[0]->debugMessage();std::cout << "--------------" << std::endl;tree.blackboard_stack[1]->debugMessage();std::cout << "--------------" << std::endl;// auto p = tree.blackboard_stack[0]->get<Pose2D>("move_goal");// std::cout << "get pose (" << p.x << "," << p.y << "," << p.theta << ")" << std::endl;NodeStatus status = NodeStatus::RUNNING;while (status == NodeStatus::RUNNING) {status = tree.tickRoot();SleepMS(1); // optional sleep to avoid "busy loops"}return 0;
}
结果如下,可见MainTree的2个entry都没有设置值(empty),且MoveRobot subtree也少了1个entry信息,因为此时树未运行SetBlackboard节点,自然也就不会创建出output entry。若读取empty的entry,就会发生异常。
move_result (std::string) -> empty
move_goal (Pose2D) -> empty
--------------
target (Pose2D) -> remapped to parent [move_goal]
树与调用方之间
本小节需要和上一小节结合起来看。
当debugMessage()打印key->full时,才可以在外部读取树的blackboard的entry的值。
while (status == NodeStatus::RUNNING) {status = tree.tickRoot();SleepMS(1); // optional sleep to avoid "busy loops"
}
// 添加在树运行后和return之间,此时entry的值是保持的。
// 如果添加在树运行之前,可能会因为port还未被设置而读取触发异常。
auto p = tree.blackboard_stack[0]->get<Pose2D>("move_goal");
std::cout << "get pose (" << p.x << "," << p.y << "," << p.theta << ")" << std::endl;return 0;
运行上面的代码,我们会得到:
get pose (1,2,3) // 是XML中SetBlackboard的结果
当debugMessage()打印key->empty时, 读取值抛出异常,参考上一小节被注释的代码。
terminate called after throwing an instance of 'std::runtime_error'
what(): Any::cast failed because it is empty
当然,从外部设置entry的值并不受其是empty/full的影响。
Pose2D p, q;
p.x = 10, p.y = 11, p.theta = 3.14;
tree.blackboard_stack[0]->set<Pose2D>("move_goal", p);
tree.blackboard_stack[0]->get<Pose2D>("move_goal", q);
std::cout << "get pose (" << q.x << "," << q.y << "," << q.theta << ")" << std::endl;
运行上面的代码,我们会得到:
get pose (10,11,3.14)
BT11:行为树内外的数据传输相关推荐
- 蚂蚁变大象:浅谈常规网站是如何从小变大的(转)
2005年,我开始和朋友们开始拉活儿做网站,当时第一个网站是在linux上用jsp搭建的,到后来逐步的引入了多种框架,如webwork.hibernate等.在到后来,进入公司,开始用c/c++,做分 ...
- aws mysql价格_mysql – AWS RDS“转出”成本有多贵?
我在AWS上托管了一个社交网络网站.我是否会因RDS的"转移成本"而被收取费用(因为RDS将通过AWS连接到EC2)?这是否意味着我只需支付EC2'转账费用'?与"图像& ...
- 蚂蚁变大象:浅谈常规网站是如何从小变大的
言归正传,计划了很久写这篇文章,不过心里还是比较忐忑,担心自己在技术上的深度和沉淀还是不够.不过,最后想起某老师说的:follow my heart! 想想,人生就这么些年,想做啥就做啥吧,不用想的太 ...
- 蚂蚁变大象:浅谈常规网站是如何从小变大的(五)
[ 前一段时间写了关于架构的总结,一共十篇,放在新浪博客上 :http://blog.sina.com.cn/zgwangbo001 ,今天放到csdn上] 也可以关注微信公众号:simplemain ...
- [转]蚂蚁变大象:浅谈常规网站是如何从小变大的
作者:老王 (http://blog.sina.com.cn/zgwangbo001) 来源:http://stblog.baidu-tech.com/?p=1643 2005年,我开始和朋友们开始拉 ...
- (转)蚂蚁变大象:浅谈常规网站是如何从小变大的
2005年,我开始和朋友们开始拉活儿做网站,当时第一个网站是在linux上用jsp搭建的,到后来逐步的引入了多种框架,如webwork.hibernate等.在到后来,进入公司,开始用c/c++,做分 ...
- 【定期更新】操作系统通读课本
*参考书目:<清华大学计算机系列教材 计算机操作系统教程(第4版)> 张尧学 宋虹 长高 快速目录 第一章 绪论 1.1 操作系统的概念 操作系统的定义 1.2 操作系统的历史 早期批处理 ...
- 系统设计:如何从零用户扩展到百万用户
设计一个支持百万用户的系统是具有挑战性的,这是一段需要不断改进和不断提升的旅程.在本章中,我们将构建一个支持单个用户的系统,并逐渐扩展以服务于数百万用户.阅读本章后,您将掌握一些技巧,帮助您解决系统设 ...
- PHP相关系列 - 蚂蚁变大象:浅谈常规网站是如何从小变大的
来源:http://stblog.baidu-tech.com/?p=1643 2005年,我开始和朋友们开始拉活儿做网站,当时第一个网站是在linux上用jsp搭建的,到后来逐步的引入了多种框架,如 ...
最新文章
- Common Lisp 初学者快速入门指导
- Python-OpenCV 处理图像(六)(七)(八):对象识别 图像灰度化处理 图像二值化处理
- activemq网络桥接_ActiveMQ –经纪人网络解释–第5部分
- 【渝粤教育】国家开放大学2018年春季 8126-21T制药工程 参考试题
- java定义接口规范_关于java的接口的一些规范
- [vue require动态引入组件、变量]
- oracle零碎要点---ip地址问题,服务问题,系统默认密码问题
- 计量风险系列—两大定价产品怎么计算风险损失
- iPhone13系列预计5499起;蔚来回应31岁企业家“自动驾驶”车祸去世;小米取消MIX4防丢失模式无卡联网服务|极客头条...
- CSDN2013年度博客之星评选
- 7-8 统计工龄 (20 分)
- wps所有宏被禁用_WPS 2019怎么启用宏功能?WPS 2019启用宏功能教程
- 垃圾分类数据集-8w张图片245个类附赠tensorflow代码
- CodeForces - 735D Taxes (哥德巴赫猜想)
- APIO10-特别行动队-题解
- vue中,input输入框只允许输入数字
- 【vue】v-html中的内容修改样式,图片修改尺寸
- 企业网站建设改版的未来方向
- C++类的多种构造函数
- SpringBoot 日志(学习笔记13)