目的是为了扩展之前的写法,如
MyCustomNode(const std::string& name, const NodeConfiguration& config);
如果需要在构造函数中,添加额外的参数
不建议使用黑板的形式:
理论上可以使用黑板中的输入端口来实现,但是错误情况如下:
参数在编译之前就知道(deployment-time.);
参数在运行时不能改变;
参数不需要从XML中来设置;
方法1:注册一个自定义的builder
下面自定义的节点成为Action_A:
打算传递三个附加的参数:可以是任意复杂的对象,不仅限于内建对象:
// Action_A has a different constructor than the default one.
class Action_A: public SyncActionNode
{
public:
// additional arguments passed to the constructor
Action_A(const std::string& name, const NodeConfiguration& config,
int arg1, double arg2, std::string arg3 ):
SyncActionNode(name, config),
_arg1(arg1),
_arg2(arg2),
_arg3(arg3) {}
// this example doesn't require any port
static PortsList providedPorts() { return {}; }
// tick() can access the private members
NodeStatus tick() override;
private:
int _arg1;
double _arg2;
std::string _arg3;
};
本节点通过如下注册:
BehaviorTreeFactory factory;
// A node builder is a functor that creates a std::unique_ptr<TreeNode>.
// Using lambdas or std::bind, we can easily "inject" additional arguments.
NodeBuilder builder_A =
[](const std::string& name, const NodeConfiguration& config)
{
return std::make_unique<Action_A>( name, config, 42, 3.14, "hello world" );
};
// BehaviorTreeFactory::registerBuilder is a more general way to
// register a custom node.
factory.registerBuilder<Action_A>( "Action_A", builder_A);
// Register more custom nodes, if needed.
// ....
// The rest of your code, where you create and tick the tree, goes here.
// ....
方法二:使用初始init函数
在tick树之前,使用init方法:
class Action_B: public SyncActionNode
{
public:
// The constructor looks as usual.
Action_B(const std::string& name, const NodeConfiguration& config):
SyncActionNode(name, config) {}
// We want this method to be called ONCE and BEFORE the first tick()
void init( int arg1, double arg2, const std::string& arg3 )
{
_arg1 = (arg1);
_arg2 = (arg2);
_arg3 = (arg3);
}
// this example doesn't require any port
static PortsList providedPorts() { return {}; }
// tick() can access the private members
NodeStatus tick() override;
private:
int _arg1;
double _arg2;
std::string _arg3;
};
注册和初始化Action_B有点不同:
BehaviorTreeFactory factory;
// The regitration of Action_B is done as usual, but remember
// that we still need to call Action_B::init()
factory.registerNodeType<Action_B>( "Action_B" );
// Register more custom nodes, if needed.
// ....
// Create the whole tree
auto tree = factory.createTreeFromText(xml_text);
// Iterate through all the nodes and call init() if it is an Action_B
for( auto& node: tree.nodes )
{
// Not a typo: it is "=", not "=="
if( auto action_B = dynamic_cast<Action_B*>( node.get() ))
{
action_B->init( 42, 3.14, "hello world");
}
}
// The rest of your code, where you tick the tree, goes here.
// ....