action_node.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2015-2018 Michele Colledanchise - All Rights Reserved
2  * Copyright (C) 2018-2019 Davide Faconti, Eurecat - All Rights Reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
11 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 */
13 
15 #include "coroutine/coroutine.h"
16 
17 namespace BT
18 {
19 ActionNodeBase::ActionNodeBase(const std::string& name, const NodeConfiguration& config)
20  : LeafNode::LeafNode(name, config)
21 {
22 }
23 
24 
25 //-------------------------------------------------------
26 
28  SimpleActionNode::TickFunctor tick_functor,
30  : SyncActionNode(name, config), tick_functor_(std::move(tick_functor))
31 {
32 }
33 
35 {
36  NodeStatus prev_status = status();
37 
38  if (prev_status == NodeStatus::IDLE)
39  {
41  prev_status = NodeStatus::RUNNING;
42  }
43 
45  if (status != prev_status)
46  {
47  setStatus(status);
48  }
49  return status;
50 }
51 
52 //-------------------------------------------------------
53 
55  : ActionNodeBase(name, config),
56  keep_thread_alive_(true),
57  start_action_(false)
58 {
59  thread_ = std::thread(&AsyncActionNode::asyncThreadLoop, this);
60 }
61 
63 {
64  if (thread_.joinable())
65  {
67  }
68 }
69 
71 {
72  std::unique_lock<std::mutex> lock(start_mutex_);
73  while (!start_action_)
74  {
75  start_signal_.wait(lock);
76  }
77  start_action_ = false;
78 }
79 
81 {
82  std::unique_lock<std::mutex> lock(start_mutex_);
83  start_action_ = true;
84  start_signal_.notify_all();
85 }
86 
88 {
89  while (keep_thread_alive_.load())
90  {
91  waitStart();
92 
93  // check keep_thread_alive_ again because the tick_engine_ could be
94  // notified from the method stopAndJoinThread
96  {
97  // this will execute the blocking code.
98  try {
99  setStatus(tick());
100  }
101  catch (std::exception&)
102  {
103  std::cerr << "\nUncaught exception from the method tick() of an AsyncActionNode: ["
104  << registrationName() << "/" << name() << "]\n" << std::endl;
105  exptr_ = std::current_exception();
106  keep_thread_alive_ = false;
107  }
108  }
109  }
110 }
111 
113 {
114  //send signal to other thread.
115  // The other thread is in charge for changing the status
116  if (status() == NodeStatus::IDLE)
117  {
119  notifyStart();
120  }
121 
122  if( exptr_ )
123  {
124  std::rethrow_exception(exptr_);
125  }
126  return status();
127 }
128 
130 {
131  keep_thread_alive_.store(false);
132  notifyStart();
133  if (thread_.joinable())
134  {
135  thread_.join();
136  }
137 }
138 
139 //-------------------------------------
141 {
143  std::atomic<bool> pending_destroy;
144 
145 };
146 
147 
149  const NodeConfiguration& config):
150  ActionNodeBase (name, config),
151  _p(new Pimpl)
152 {
153  _p->coro = 0;
154  _p->pending_destroy = false;
155 }
156 
158 {
159  if( _p->coro != 0 )
160  {
161  coroutine::destroy(_p->coro);
162  }
163 }
164 
166 {
169 }
170 
172 {
173  if( _p->pending_destroy && _p->coro != 0 )
174  {
175  coroutine::destroy(_p->coro);
176  _p->coro = 0;
177  _p->pending_destroy = false;
178  }
179 
180  if ( _p->coro == 0)
181  {
182  _p->coro = coroutine::create( [this]()
183  {
184  setStatus(tick());
185  } );
186  }
187 
188  if( _p->coro != 0 )
189  {
190  if( _p->pending_destroy ||
192  {
193  coroutine::destroy(_p->coro);
194  _p->coro = 0;
195  _p->pending_destroy = false;
196  }
197  }
198  return status();
199 }
200 
202 {
203  _p->pending_destroy = true;
204 }
205 
207  ActionNodeBase(name, config)
208 {}
209 
211 {
212  auto stat = ActionNodeBase::executeTick();
213  if( stat == NodeStatus::RUNNING)
214  {
215  throw LogicError("SyncActionNode MUST never return RUNNING");
216  }
217  return stat;
218 }
219 
220 
221 
222 }
The ActionNodeBase is the base class to use to create any kind of action. A particular derived class ...
Definition: action_node.h:34
CoroActionNode(const std::string &name, const NodeConfiguration &config)
std::thread thread_
Definition: action_node.h:136
const std::string & name() const
Name of the instance, not the type.
Definition: tree_node.cpp:73
void yield()
Definition: coroutine.h:361
const NodeConfiguration & config() const
Definition: tree_node.cpp:99
virtual NodeStatus executeTick() overridefinal
The method that should be used to invoke tick() and setStatus();.
SimpleActionNode(const std::string &name, TickFunctor tick_functor, const NodeConfiguration &config)
Definition: action_node.cpp:27
std::atomic< bool > pending_destroy
void setStatusRunningAndYield()
Use this method to return RUNNING and temporary "pause" the Action.
Definition: any.hpp:455
routine_t create(std::function< void()> f)
Definition: coroutine.h:277
void destroy(routine_t id)
Definition: coroutine.h:296
unsigned routine_t
Definition: coroutine.h:54
void halt() override
SyncActionNode(const std::string &name, const NodeConfiguration &config)
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn&#39;t require a...
Definition: action_node.h:52
std::mutex start_mutex_
Definition: action_node.h:130
std::unique_ptr< Pimpl > _p
Definition: action_node.h:175
std::atomic< bool > keep_thread_alive_
Definition: action_node.h:126
coroutine::routine_t coro
virtual NodeStatus executeTick() overridefinal
The method that should be used to invoke tick() and setStatus();.
std::function< NodeStatus(TreeNode &)> TickFunctor
Definition: action_node.h:84
virtual NodeStatus executeTick() override
throws if the derived class return RUNNING.
NodeStatus status() const
Definition: tree_node.cpp:56
virtual ~CoroActionNode() override
std::condition_variable start_signal_
Definition: action_node.h:132
ResumeResult resume(routine_t id)
Definition: coroutine.h:316
ActionNodeBase(const std::string &name, const NodeConfiguration &config)
Definition: action_node.cpp:19
std::exception_ptr exptr_
Definition: action_node.h:134
NodeStatus
Definition: basic_types.h:35
virtual NodeStatus tick() overridefinal
Method to be implemented by the user.
Definition: action_node.cpp:34
TickFunctor tick_functor_
Definition: action_node.h:95
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
Definition: tree_node.cpp:33
AsyncActionNode(const std::string &name, const NodeConfiguration &config)
Definition: action_node.cpp:54
const std::string & registrationName() const
registrationName is the ID used by BehaviorTreeFactory to create an instance.
Definition: tree_node.cpp:94
virtual BT::NodeStatus tick()=0
Method to be implemented by the user.
void setStatus(NodeStatus new_status)
Definition: tree_node.cpp:40
virtual ~AsyncActionNode() override
Definition: action_node.cpp:62


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 18:04:04