行为树(BT)笔记(十一):动作和协同程序

本文介绍在BehaviorTree.CPP中使用协同程序(Coroutines)实现异步Action的高效方法,通过MyAsyncAction类示例展示如何创建、暂停及处理异步任务,适用于长时间运行且可中断的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Coroutines的异步操作

BehaviorTree.CPP提供了两个易于使用的抽象来创建异步Action,即那些以下操作:

  • 花很长时间才能得出结论。
  • 可以返回“RUNNING”。
  • 可以停止

第一个类是AsyncActionNode,它在一个单独的线程中执行tick()方法。

在本教程中,我们介绍了CoroActionNode,它是一个使用协同程序来实现类似结果的不同类。

协同程序不会产生新的线程,效率更高。

用户应该显式调用yield方法,他希望执行要挂起的Action。

在本教程中,我们将看到它如何使用一个非常简单的示例,您可以将其用作您自己实现的模板。

class MyAsyncAction: public CoroActionNode
{
  public:
    MyAsyncAction(const std::string& name):
      CoroActionNode(name, NodeParameters())
    {}

    // This is the ideal skeleton/template of an async action:
    //  - A request to a remote service provider.
    //  - A loop where we check if the reply has been received.
    //    Call setStatusRunningAndYield() to "pause".
    //  - Code to execute after the reply.
    //  - a simple way to handle halt().

    NodeStatus tick() override
    {
        std::cout << name() <<": Started. Send Request to server." << std::endl;

        int cycle = 0;
        bool reply_received = false;

        while( !reply_received )
        {
            std::cout << name() <<": Waiting reply." << std::endl;
            reply_received = ++cycle >= 3;

            if( !reply_received )
            {
                // set status to RUNNING and "pause/sleep"
                // If halt() is called, we will not resume execution
                setStatusRunningAndYield();
            }
        }

        // this part of the code is never reached if halt() is invoked.
        std::cout << name() <<": Done." << std::endl;
        return NodeStatus::SUCCESS;
    }

    void halt() override
    {
        std::cout << name() <<": Halted. Do your cleanup here." << std::endl;

        // Do not forget to call this at the end.
        CoroActionNode::halt();
    }
};

为了使示例的其余部分简单,我们使用编程方法创建一个简单的树,其中两个动作按顺序执行。

int main()
{
    // Simple tree: a sequence of two asycnhronous actions
    BT::SequenceNode sequence_root("sequence");
    MyAsyncAction action_A("actionA");
    MyAsyncAction action_B("actionB");

    // Add children to the sequence.
    sequence_root.addChild(&action_A);
    sequence_root.addChild(&action_B);

    NodeStatus status = NodeStatus::IDLE;

    while( status != NodeStatus::SUCCESS && status != NodeStatus::FAILURE)
    {
        status = sequence_root.executeTick();

        // It is often a good idea to add a sleep here to avoid busy loops
        std::this_thread::sleep_for( std::chrono::milliseconds(1) );
    }
    return 0;
}

/* Expected output:

actionA: Started. Send Request to server.
actionA: Waiting reply.
actionA: Waiting reply.
actionA: Waiting reply.
actionA: Done.
actionB: Started. Send Request to server.
actionB: Waiting reply.
actionB: Waiting reply.
actionB: Waiting reply.
actionB: Done.
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值