Tutorial 8: Additional arguments

翻译自:https://www.behaviortree.dev

Pass additional arguments during initialization and/or construction

[在初始化和/或构造期间传递其他参数]

In every single example we explored so far we were “forced” to provide a constructor with the following signature [到目前为止,在我们探索的每个示例中,我们都“被迫”提供具有以下签名的构造函数]

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

In same cases, it is desirable to pass to the constructor of our class additional arguments, parameters, pointers, references, etc. [在同样的情况下,最好向我们的类的构造函数传递额外的参数、参数、指针、引用等。]

Many people use blackboards to do that: this is not recomendable. [许多人使用黑板来做到这一点:这是不推荐的。]

We will just use the word “arguments” for the rest of the tutorial. [在本教程的其余部分,我们将只使用“参数”这个词。]

Even if, theoretically, these arguments could be passed using Input Ports, that would be the wrong way to do it if: [即使理论上可以使用输入端口传递这些参数,但如果出现以下情况,那将是错误的方法:]

  • The arguments are known at deployment-time. [这些参数在部署时是已知的。]
  • The arguments don’t change at run-time. [参数在运行时不会改变。]
  • The arguments don’t need to be set from the XML. [不需要从 XML 设置参数。]

If all these conditions are met, using ports or the blackboard is cumbersome and highly discouraged. [如果所有这些条件都满足,那么使用端口或黑板会很麻烦并且非常不鼓励使用。]

Method 1: register a custom builder

Consider the following custom node called Action_A. [请考虑以下名为 Action_A 的自定义节点。]

We want to pass three additional arguments; they can be arbitrarily complex objects, you are not limited to built-in types. [我们想传递三个额外的参数;它们可以是任意复杂的对象,您不限于内置类型。]

// 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;
};

This node should be registered as shown further: [这个节点应该被注册,如下图所示:]

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.
// ....

Method 2: use an init method

Alternatively, you may call an init method before ticking the tree. [或者,您可以在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;
};

The way we register and initialize Action_B is slightly different: [我们注册和初始化 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.
// ....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值