BehaviorTree.CPP.行为树XML格式(六)
The XML format
XML模式的基础
在第一个教程中,介绍了这个简单的树。
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<Sequence name="root_sequence">
<SaySomething name="action_hello" message="Hello"/>
<OpenGripper name="open_gripper"/>
<ApproachObject name="approach_object"/>
<CloseGripper name="close_gripper"/>
</Sequence>
</BehaviorTree>
</root>
您可能会注意到:
- 树的第一个标签是
<root>。它应包含1个或多个标签<BehaviorTree>。 - 标签
<BehaviorTree>应具有属性[ID]。 - 标签
<root>应包含属性[main_tree_to_execute]。 [main_tree_to_execute]如果文件包含多个<BehaviorTree>,则该属性为必填,否则为可选。- 每个
TreeNode由单个标签表示。特别是:- 标签的名称是用于在工厂中注册
TreeNode的ID。 - 该属性
[name]引用实例的名称,并且是可选的。 - 使用属性配置端口。在前面的示例中,该操作
SaySomething需要输入端口message。
- 标签的名称是用于在工厂中注册
- 在子节点的数量方面:
ControlNodes容纳1到N个子节点。DecoratorNodes和子树仅包含1个子项。ActionNodes和ConditionNodes有没有子项。
端口重新映射和指向Blackboards条目的指针
如第二篇教程中所述,可以使用Blackboard中条目的名称(即BB的键/值对的键)来重新映射输入/输出端口。
BB密钥使用以下语法表示:{key_name}。
在以下示例中:
- 序列的第一个子节点打印
"Hello", - 第二个子节点读取和写入包含在黑板条目“ my_message”中的值;
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<Sequence name="root_sequence">
<SaySomething message="Hello"/>
<SaySomething message="{my_message}"/>
</Sequence>
</BehaviorTree>
</root>
紧凑与显式表示
以下两种语法均有效:
<SaySomething name="action_hello" message="Hello World"/>
<Action ID="SaySomething" name="action_hello" message="Hello World"/>
我们将前一种语法称为“紧凑”,而后一种称为“显式”。用显式语法表示的第一个示例将变为:
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<Sequence name="root_sequence">
<Action ID="SaySomething" name="action_hello" message="Hello"/>
<Action ID="OpenGripper" name="open_gripper"/>
<Action ID="ApproachObject" name="approach_object"/>
<Action ID="CloseGripper" name="close_gripper"/>
</Sequence>
</BehaviorTree>
</root>
即使紧凑语法更方便和易于编写,但它提供的有关TreeNode模型的信息也太少了。像Groot这样的工具需要显式语法或其他信息。可以使用标签添加此信息<TreeNodeModel>。
为了使我们的树的精简版与Groot兼容,必须对XML进行如下修改:
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<Sequence name="root_sequence">
<SaySomething name="action_hello" message="Hello"/>
<OpenGripper name="open_gripper"/>
<ApproachObject name="approach_object"/>
<CloseGripper name="close_gripper"/>
</Sequence>
</BehaviorTree>
<!-- the BT executor don't require this, but Groot does -->
<TreeNodeModel>
<Action ID="SaySomething">
<input_port name="message" type="std::string" />
</Action>
<Action ID="OpenGripper"/>
<Action ID="ApproachObject"/>
<Action ID="CloseGripper"/>
</TreeNodeModel>
</root>
您可以在此处下载XML模式。
子树
正如我们在本教程中所看到的,可以在另一棵树中包括一个子树,以避免在多个位置“复制和粘贴”同一棵树并降低复杂性。
假设我们想将很少的动作封装到behaviorTree"GraspObject"中(为方便起见,省略了属性[name])。
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<Sequence>
<Action ID="SaySomething" message="Hello World"/>
<Subtree ID="GraspObject"/> <!-- "GraspObject" -->
</Sequence>
</BehaviorTree>
<BehaviorTree ID="GraspObject">
<Sequence>
<Action ID="OpenGripper"/>
<Action ID="ApproachObject"/>
<Action ID="CloseGripper"/>
</Sequence>
</BehaviorTree>
</root>
我们可能会注意到,整个树"GraspObject"在"SaySomething"之后执行。
包括外部文件
从2.4版本开始。
您可以采用类似于#include的方式包含外部文件在C++中。我们可以使用标签轻松地做到这一点:
<include path="relative_or_absolute_path_to_file">
使用前面的示例,我们可以将两个行为树分成两个文件:
<!-- file maintree.xml -->
<root main_tree_to_execute = "MainTree" >
<include path="grasp.xml"/>
<BehaviorTree ID="MainTree">
<Sequence>
<Action ID="SaySomething" message="Hello World"/>
<Subtree ID="GraspObject"/>
</Sequence>
</BehaviorTree>
</root>
<!-- file grasp.xml -->
<root main_tree_to_execute = "GraspObject" >
<BehaviorTree ID="GraspObject">
<Sequence>
<Action ID="OpenGripper"/>
<Action ID="ApproachObject"/>
<Action ID="CloseGripper"/>
</Sequence>
</BehaviorTree>
</root>
^ x ^
ROS用户注意事项
如果要在ROS包中查找文件,可以使用以下语法:
<include ros_pkg="name_package" path="path_relative_to_pkg/grasp.xml"/>
BehaviorTree.CPP.行为树XML格式(六)的更多相关文章
- BehaviorTree.CPP行为树BT的入门(二)
节点与树 用户必须创建自己的ActionNodes和ConditionNodes(LeafNodes):该库可帮助您轻松地将它们组成树. 将LeafNodes视为组成复杂系统所需的构建块. 根据定义, ...
- BehaviorTree.CPP行为树BT的装饰器节点(五)
Decorators 装饰器是只能有一个子项的节点. 由装饰者来决定是否,何时以及对子节点进行tick. InverterNode tick子节点一次,如果子节点失败则返回SUCCESS,如果孩子成功 ...
- BehaviorTree.CPP行为树BT的选择节点(四)
Fallback 该节点家族在其他框架中被称为"选择器Selector"或"优先级Priority". 他们的目的是尝试不同的策略,直到找到可行的策略. 它们具 ...
- BehaviorTree.CPP行为树BT的队列节点(三)
Sequences(队列) 只要序列的所有子代返回SUCCESS,它便会对其进行Tick. 如果有任何子级返回FAILURE,则序列中止. 当前,该框架提供三种节点: Sequence Sequenc ...
- BehaviorTree.CPP行为树BT的介绍(一)
节点类型 ControlNode是可以具有1到N个子节点的节点.一旦接收到tick,tick可以传播到一个或多个子节点. DecoratorNodes与ControlNode相似,但只能有一个子节点. ...
- .net数据库连接防注入参数查询 命令执行 读取 备份 导出导入转化XML格式
ADO.NET是一组类库,让我们通过程序的方式访问数据库.SYSTEM.DATA这个类提供了统一的接口访问Oracle MSSQL Access.像SYSTEM.IO类操作文件一样. **connec ...
- Android中解析XML格式数据的方法
XML介绍:Extensible Markup Language,即可扩展标记语言 一.概述 Android中解析XML格式数据大致有三种方法: SAX DOM PULL 二.详解 2.1 SAX S ...
- (转载)将一段符合XML格式规范字符串插入已有XML文档当中
想我们已经存在一个XML文档,结构如下: < xmlversion="1.0"encoding="utf-8">< employees&g ...
- [转] IIS配置文件的XML格式不正确 applicationHost.config崩溃 恢复解决办法
IIS配置文件的XML格式不正确 applicationHost.config崩溃 恢复解决办法 源文件:http://www.cnblogs.com/yuejin/p/3385584.html ...
随机推荐
- HttpServletResponse 入门
继承体系 功能: 设置响应消息 1. 设置响应行 格式:HTTP/1.1 200 ok 设置状态码:setStatus(int sc) 2. 设置响应头:setHeader(String name, ...
- Docker--harbor私有仓库部署与管理
目录 一.Harbor简介 二.Harbor 部署 三.维护管理Harbor 一.Harbor简介 1.什么是Harbor ? Harbor 是 VMware 公司开源的企业级 Docker Re ...
- webRTC中语音降噪模块ANS细节详解(二)
上篇(webRTC中语音降噪模块ANS细节详解(一))讲了维纳滤波的基本原理.本篇先给出webRTC中ANS的基本处理过程,然后讲其中两步(即时域转频域和频域转时域)中的一些处理细节. ANS的基本处 ...
- CSP-J 2021 复赛游记
Day-1 啥也没干 晚上看了看洛谷的讨论,据说freopen在打开的最后要加 fclose(stdin);fclose(stdout); 不加也可.不过据说Linux在return 0之前不会自动关 ...
- 剑指offer:JZ12 矩阵中的路径
JZ12 矩阵中的路径 描述 请设计一个函数,用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上, ...
- 利用DMA实现采样数据的直接搬运存储
尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了. 找了不少例子参考,ADC和DMA的设置了解了个大概,并直接利用开发板来做一些实验来验证相关的操作 ...
- Go语言核心36讲(Go语言进阶技术十三)--学习笔记
19 | 错误处理(上) 提到 Go 语言中的错误处理,我们其实已经在前面接触过几次了. 比如,我们声明过error类型的变量err,也调用过errors包中的New函数. 我们说过error类型其实 ...
- 如何将声学的spectrogram(声谱图)重新反变换成时域语音信号
最近在研究一些信号分析的事情,感兴趣如何将频谱信号反变换成时域信号.fft 与ifft可以顺畅的转变,但是这个是一帧信号,当时间较长的信号再一起是,通过反变换变成一帧一帧的时域信号,如何把他们拼接起来 ...
- 攻防世界 WEB 高手进阶区 NSCTF web2 Writeup
攻防世界 WEB 高手进阶区 NSCTF web2 Writeup 题目介绍 题目考点 php基本函数语法 加密解密函数 base64_decode().str_rot13() 字符串反转函数 str ...
- 快速排序--洛谷卡TLE后最终我还是选择了三向切割
写在前边 这篇文章呢,我们接着聊一下排序算法,我们之前已经谈到了简单插入排序 和ta的优化版希尔排序,这节我们要接触一个更"高级"的算法了--快速排序. 在做洛谷的时候,遇到了一道 ...