在CrossDoor例子中,我们看到一颗SubTree树,从其父节点(例子中是MainTree)来看其就像是一个叶子节点。
进一步,为了避免在大的树中的命名冲突,任何树和子树使用不同的黑板实例。
针对这个原因,我们需要去显示将一颗树和其子树进行连接;
不需要修改C++实现,因为在XML中完成即可;
例子:
<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对应主树;
端口映射:
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(); SleepMS(1); // optional sleep to avoid "busy loops" } // 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] -------------- */