使用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.
*/