00001 #include "behaviortree_cpp/blackboard/blackboard_local.h" 00002 #include "behaviortree_cpp/behavior_tree.h" 00003 00004 using namespace BT; 00005 00012 class MyAsyncAction: public CoroActionNode 00013 { 00014 public: 00015 MyAsyncAction(const std::string& name): 00016 CoroActionNode(name, NodeParameters()) 00017 {} 00018 00019 // This is the ideal skeleton/template of an async action: 00020 // - A request to a remote service provider. 00021 // - A loop where we check if the reply has been received. 00022 // Call setStatusRunningAndYield() to "pause". 00023 // - Code to execute after the reply. 00024 // - a simple way to handle halt(). 00025 00026 NodeStatus tick() override 00027 { 00028 std::cout << name() <<": Started. Send Request to server." << std::endl; 00029 00030 int cycle = 0; 00031 bool reply_received = false; 00032 00033 while( !reply_received ) 00034 { 00035 std::cout << name() <<": Waiting reply." << std::endl; 00036 reply_received = ++cycle >= 3; 00037 00038 if( !reply_received ) 00039 { 00040 // set status to RUNNING and "pause/sleep" 00041 // If halt() is called, we will not resume execution 00042 setStatusRunningAndYield(); 00043 } 00044 } 00045 00046 // this part of the code is never reached if halt() is invoked. 00047 std::cout << name() <<": Done." << std::endl; 00048 return NodeStatus::SUCCESS; 00049 } 00050 00051 void halt() override 00052 { 00053 std::cout << name() <<": Halted. Do your cleanup here." << std::endl; 00054 00055 // Do not forget to call this at the end. 00056 CoroActionNode::halt(); 00057 } 00058 }; 00059 00060 00061 int main() 00062 { 00063 // Simple tree: a sequence of two asycnhronous actions 00064 BT::SequenceNode sequence_root("sequence"); 00065 MyAsyncAction action_A("actionA"); 00066 MyAsyncAction action_B("actionB"); 00067 00068 // Add children to the sequence. 00069 sequence_root.addChild(&action_A); 00070 sequence_root.addChild(&action_B); 00071 00072 NodeStatus status = NodeStatus::IDLE; 00073 00074 while( status != NodeStatus::SUCCESS && status != NodeStatus::FAILURE) 00075 { 00076 status = sequence_root.executeTick(); 00077 00078 // It is often a good idea to add a sleep here to avoid busy loops 00079 std::this_thread::sleep_for( std::chrono::milliseconds(1) ); 00080 } 00081 00082 return 0; 00083 } 00084 00085 /* Expected output: 00086 00087 actionA: Started. Request service using async call 00088 actionA: Waiting reply 00089 actionA: Waiting reply 00090 actionA: Waiting reply 00091 actionA: Done 00092 actionB: Started. Request service using async call 00093 actionB: Waiting reply 00094 actionB: Waiting reply 00095 actionB: Waiting reply 00096 actionB: Done 00097 */