在本教程中,我们将了解如何处理不适合与BehaviorTree.CPP一起使用的遗留代码。
让我们开始假设这是我的类。
// This is my custom type.
struct Point3D { double x,y,z; };
class MyLegacyMoveTo
{
public:
bool go(Point3D goal)
{
printf("Going to: %f %f %f\n", goal.x, goal.y, goal.z);
return true; // true means success in my legacy code
}
};
我们想要创建一个名为“MoveTo”的ActionNode,它调用方法MyLegacyMoveTo :: go()。
最终目标是能够在这样的树中使用此ActionNode:
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<SequenceStar name="root">
<MoveTo goal="-1;3;0.5" />
<MoveTo goal="${myGoal}" />
</SequenceStar>
</BehaviorTree>
</root>
我们需要做的第一件事是允许我们的库将NodeParameter(只不过是一对表示键/值的字符串)转换为Point3D。
正如我们在之前的教程中所做的那样,我们应该为convertFromString实现模板特化。
Point3D的特定字符串表示由三个以分号分隔的数字组成,表示__x,y和z_。
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<SequenceStar name="root">
<MoveTo goal="-1;3;0.5" />
<MoveTo goal="${myGoal}" />
</SequenceStar>
</BehaviorTree>
</root>
最后,我们可以使用C ++ 11 lambda(或者,std :: bind)将方法包装到具有正确签名的函数中。
<root main_tree_to_execute = "MainTree" >
<BehaviorTree ID="MainTree">
<SequenceStar name="root">
<MoveTo goal="-1;3;0.5" />
<MoveTo goal="${myGoal}" />
</SequenceStar>
</BehaviorTree>
</root>
int main()
{
using namespace BT;
MyLegacyMoveTo move_to;
// Here we use a lambda that captures the reference of move_to
auto MoveToWrapperWithLambda = [&move_to](TreeNode& parent_node) -> NodeStatus
{
Point3D goal;
// thanks to paren_node, you can access easily the NodeParameters and the blackboard
parent_node.getParam("goal", goal);
bool res = move_to.go( goal );
// convert bool to NodeStatus
return res ? NodeStatus::SUCCESS : NodeStatus::FAILURE;
};
BehaviorTreeFactory factory;
factory.registerSimpleAction("MoveTo", MoveToWrapperWithLambda);
auto blackboard = Blackboard::create<BlackboardLocal>();
auto tree = buildTreeFromText(factory, xml_text, blackboard);
// We set the entry "myGoal" in the blackboard.
Point3D my_goal = {3,4,5};
blackboard->set("myGoal", my_goal);
NodeStatus status = NodeStatus::RUNNING;
while (status == NodeStatus::RUNNING)
{
status = tree.root_node->executeTick();
}
return 0;
}
/* Expected output:
Going to: -1.000000 3.000000 0.500000
Going to: 3.000000 4.000000 5.000000
The first MoveTo read the parameter from the string "-1;3;0.5"
whilst the second from the blackboard, that contains a copy of the Point3D my_goal.
*/
我们传递给SimpleActionNode的仿函数需要以下形式:
BT :: NodeStatus myFunction (BT :: TreeNode &amp ; parent )
因此,我们可以通过访问NodeParameter
parent.getParam()
甚至使用设置/获取Blackboard的条目
parent.blackboard()