Remapping ports between Trees and SubTrees
重新映射树和子树之间的端口
在CrossDoor
示例中,我们看到一个SubTree
从其父节点(示例中的MainTree
)的角度看起来像一个单独的叶子节点。
此外,为了避免在非常大的树中发生名称冲突,任何树和子树都使用不同的黑板实例。
因此,我们需要明确地将树的端口连接到其子树的端口。
再一次, 由于这种重新映射完全在 XML 定义中完成, 您 不需要 修改您的 C++ 实现。
示例
让我们考虑这个行为树
<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
的主树,其中包含一个名为MoveRobot
的子树 - 我们要在
MoveRobot
子树内部的端口与MainTree
中的其他端口“连接”(即“重新映射”) - 这是使用 XML 标记 完成的,其中单词 internal/external 分别指向子树和其父级
以下图片显示了这两棵不同树之间的重新映射。
请注意,该图表示的是__数据流__以及黑板中的条目,而不是行为树方面的关系。
就C++而言,我们不需要做太多。为了调试目的,我们可以使用debugMessage()
方法来显示关于黑板当前状态的一些信息。
int main()
{
BT::BehaviorTreeFactory factory;
factory.registerNodeType<SaySomething>("SaySomething");
factory.registerNodeType<MoveBaseAction>("MoveBase");
auto tree = factory.createTreeFromText(xml_text);
NodeStatus status = NodeStatus::RUNNING;
// Keep on ticking until you get either a SUCCESS or FAILURE state
while( status == NodeStatus::RUNNING)
{
status = tree.tickRoot();
// IMPORTANT: add sleep to avoid busy loops.
// You should use Tree::sleep(). Don't be afraid to run this at 1 KHz.
tree.sleep( std::chrono::milliseconds(1) );
}
// let's visualize some information about the current state of the blackboards.
std::cout << "--------------" << std::endl;
tree.blackboard_stack[0]->debugMessage();
std::cout << "--------------" << std::endl;
tree.blackboard_stack[1]->debugMessage();
std::cout << "--------------" << std::endl;
return 0;
}
/* Expected output:
[ MoveBase: STARTED ]. goal: x=1 y=2.0 theta=3.00
[ MoveBase: FINISHED ]
Robot says: mission accomplished
--------------
move_result (std::string) -> full
move_goal (Pose2D) -> full
--------------
output (std::string) -> remapped to parent [move_result]
target (Pose2D) -> remapped to parent [move_goal]
--------------
*/