行为树BehaviorTree学习记录6_传递额外的参数到节点

(为免误导,特免责声明如下:本文所有内容,只是基于个人当前理解和实际做法,后面亦会有更正和修订,但任何版本都不免有个人能力有限、理解有误或者工作环境不同的状况,故文中内容仅供参考。任何人都可以借鉴或者直接使用代码片段,但对任何直接引用或者借鉴产生的技术问题等后果,作者不承担任何责任。)

本文简介

介绍节点如何与系统打交道。因为节点是由树工厂根据xml创建的节点实例,如何传参给这些实例对象,把系统当前的一些状态告诉节点,是一个非常重要的问题。

引入

到目前为止,每个例子我们都被要求提供一个这样式的构造函数:

MyCustomNode(const std::string& name, const NodeConfig& config);

很多情况下,我们需要把额外的参数,变量,指针,引用等传递到节点类的构造函数。
注意 有人采用黑板来这么做,不要!
接下来我们下面就用变量这个词。
理论上说,是可以用输入端口来传递这些变量,但这不是正确的方法,因为下面的情形:

  • 变量是在部署的时候(当构建树的时候)才被知道的.
  • 变量在运行时不会改变.
  • 变量不需要从XML设置
    上面的情况下,就极其不推荐使用端口或者黑板。

推荐做法

推荐的做法是在构造函数里面增加变量,看下下面这个定制的节点类:Action_A.
我们想传递2个额外的参数,可以是任意复杂对象,并不限定于内建类型。

// 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 NodeConfig& config,
             int arg_int, std::string arg_str):
        SyncActionNode(name, config),
        _arg1(arg_int),
        _arg2(arg_str) {}

    // this example doesn't require any port
    static PortsList providedPorts() { return {}; }

    // tick() can access the private members
    NodeStatus tick() override;

private:
    int _arg1;
    std::string _arg2;
};

注册节点和传递参数可以简单的做到:

BT::BehaviorTreeFactory factory;
factory.registerNodeType<Action_A>("Action_A", 42, "hello world");
// If you prefer to specify the template parameters
// factory.registerNodeType<Action_A, int, std::string>("Action_A", 42, "hello world");

使用一个初始化函数 “initialize”

如果,因为某种原因,你需要传递不同的值给一个节点的不同实例,可以考虑下面的模式:

class Action_B: public SyncActionNode
{

public:
    // The constructor looks as usual.
    Action_B(const std::string& name, const NodeConfig& config):
        SyncActionNode(name, config) {}

    // We want this method to be called ONCE and BEFORE the first tick()
    void initialize(int arg_int, const std::string& arg_str)
    {
        _arg1 = arg_int;
        _arg2 = arg_str;
    }

    // this example doesn't require any port
    static PortsList providedPorts() { return {}; }

    // tick() can access the private members
    NodeStatus tick() override;

private:
    int _arg1;
    std::string _arg2;
};

注册和初始化Action_B有点不同:

BT::BehaviorTreeFactory factory;

// Register as usual, but we still need to initialize
factory.registerNodeType<Action_B>("Action_B");

// Create the whole tree. Instances of Action_B are not initialized yet
auto tree = factory.createTreeFromText(xml_text);

// visitor will initialize the instances of 
auto visitor = [](TreeNode* node)
{
  if (auto action_B_node = dynamic_cast<Action_B*>(node))
  {
    action_B_node->initialize(69, "interesting_value");
  }
};

// Apply the visitor to ALL the nodes of the tree
tree.applyVisitor(visitor);
  • 理解:
    • visitor 是lambda函数
    • tree.applyVisitor(visitor) 是用这个函去访问所有tree生成的节点,即如果根据xml生成的树里N个节点,则分别把这些节点对象的指针当做参数,调用visitor(pCurNodeObj额),调用N次。
    • 每次调用,函数内会对节点对象进行类型转换(dynamic_cast),如果能转换成功,说明这个节点就是Action_B类的实例,则调用它的initialize方法,把参数传递进去,当然也可以再根据它的名称做不同的处理(xml里面可以指定node实例的名称)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值