Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "behaviortree_cpp/action_node.h"
00015 #include "coroutine/coroutine.h"
00016
00017 namespace BT
00018 {
00019 ActionNodeBase::ActionNodeBase(const std::string& name, const NodeParameters& parameters)
00020 : LeafNode::LeafNode(name, parameters)
00021 {
00022 }
00023
00024 NodeStatus ActionNodeBase::executeTick()
00025 {
00026 initializeOnce();
00027 NodeStatus prev_status = status();
00028
00029 if (prev_status == NodeStatus::IDLE || prev_status == NodeStatus::RUNNING)
00030 {
00031 setStatus(tick());
00032 }
00033 return status();
00034 }
00035
00036
00037
00038 SimpleActionNode::SimpleActionNode(const std::string& name,
00039 SimpleActionNode::TickFunctor tick_functor,
00040 const NodeParameters& params)
00041 : ActionNodeBase(name, params), tick_functor_(std::move(tick_functor))
00042 {
00043 }
00044
00045 NodeStatus SimpleActionNode::tick()
00046 {
00047 NodeStatus prev_status = status();
00048
00049 if (prev_status == NodeStatus::IDLE)
00050 {
00051 setStatus(NodeStatus::RUNNING);
00052 prev_status = NodeStatus::RUNNING;
00053 }
00054
00055 NodeStatus status = tick_functor_(*this);
00056 if (status != prev_status)
00057 {
00058 setStatus(status);
00059 }
00060 return status;
00061 }
00062
00063
00064
00065 AsyncActionNode::AsyncActionNode(const std::string& name, const NodeParameters& parameters)
00066 : ActionNodeBase(name, parameters), loop_(true)
00067 {
00068 thread_ = std::thread(&AsyncActionNode::waitForTick, this);
00069 }
00070
00071 AsyncActionNode::~AsyncActionNode()
00072 {
00073 if (thread_.joinable())
00074 {
00075 stopAndJoinThread();
00076 }
00077 }
00078
00079 void AsyncActionNode::waitForTick()
00080 {
00081 while (loop_.load())
00082 {
00083 tick_engine_.wait();
00084
00085
00086
00087 if (loop_ && status() == NodeStatus::IDLE)
00088 {
00089 setStatus(NodeStatus::RUNNING);
00090 setStatus(tick());
00091 }
00092 }
00093 }
00094
00095 NodeStatus AsyncActionNode::executeTick()
00096 {
00097 initializeOnce();
00098
00099
00100 if (status() == NodeStatus::IDLE)
00101 {
00102 tick_engine_.notify();
00103 }
00104
00105
00106 const NodeStatus stat = waitValidStatus();
00107 return stat;
00108 }
00109
00110 void AsyncActionNode::stopAndJoinThread()
00111 {
00112 loop_.store(false);
00113 tick_engine_.notify();
00114 if (thread_.joinable())
00115 {
00116 thread_.join();
00117 }
00118 }
00119
00120
00121 struct CoroActionNode::Pimpl
00122 {
00123 coroutine::routine_t coro;
00124 Pimpl(): coro(0) {}
00125 };
00126
00127
00128 CoroActionNode::CoroActionNode(const std::string &name,
00129 const NodeParameters ¶meters):
00130 ActionNodeBase (name, parameters),
00131 _p(new Pimpl)
00132 {
00133 }
00134
00135 CoroActionNode::~CoroActionNode()
00136 {
00137 halt();
00138 }
00139
00140 void CoroActionNode::setStatusRunningAndYield()
00141 {
00142 setStatus( NodeStatus::RUNNING );
00143 coroutine::yield();
00144 }
00145
00146 NodeStatus CoroActionNode::executeTick()
00147 {
00148 initializeOnce();
00149 if (status() == NodeStatus::IDLE)
00150 {
00151 _p->coro = coroutine::create( [this]() { setStatus(tick()); } );
00152 }
00153
00154 if( _p->coro != 0)
00155 {
00156 auto res = coroutine::resume(_p->coro);
00157
00158 if( res == coroutine::ResumeResult::FINISHED)
00159 {
00160 coroutine::destroy(_p->coro);
00161 _p->coro = 0;
00162 }
00163 }
00164 return status();
00165 }
00166
00167 void CoroActionNode::halt()
00168 {
00169 if( _p->coro != 0 )
00170 {
00171 coroutine::destroy(_p->coro);
00172 _p->coro = 0;
00173 }
00174 }
00175
00176 SyncActionNode::SyncActionNode(const std::string &name, const NodeParameters ¶meters):
00177 ActionNodeBase(name, parameters)
00178 {}
00179
00180 NodeStatus SyncActionNode::executeTick()
00181 {
00182 auto stat = ActionNodeBase::executeTick();
00183 if( stat == NodeStatus::RUNNING)
00184 {
00185 throw std::logic_error("SyncActionNode MUSt never return RUNNING");
00186 }
00187 return stat;
00188 }
00189
00190
00191
00192 }