action_node.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2015-2018 Michele Colledanchise - All Rights Reserved
2  * Copyright (C) 2018-2020 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 
16 using namespace BT;
17 
18 ActionNodeBase::ActionNodeBase(const std::string& name, const NodeConfiguration& config)
19  : LeafNode::LeafNode(name, config)
20 {
21 }
22 
23 
24 //-------------------------------------------------------
25 
27  SimpleActionNode::TickFunctor tick_functor,
29  : SyncActionNode(name, config), tick_functor_(std::move(tick_functor))
30 {
31 }
32 
34 {
35  NodeStatus prev_status = status();
36 
37  if (prev_status == NodeStatus::IDLE)
38  {
40  prev_status = NodeStatus::RUNNING;
41  }
42 
44  if (status != prev_status)
45  {
46  setStatus(status);
47  }
48  return status;
49 }
50 
51 //-------------------------------------------------------
52 
54  ActionNodeBase(name, config)
55 {}
56 
58 {
59  auto stat = ActionNodeBase::executeTick();
60  if( stat == NodeStatus::RUNNING)
61  {
62  throw LogicError("SyncActionNode MUST never return RUNNING");
63  }
64  return stat;
65 }
66 
67 
68 //-------------------------------------
69 #ifndef BT_NO_COROUTINES
70 
71 #ifdef BT_BOOST_COROUTINE2
72 #include <boost/coroutine2/all.hpp>
73 using namespace boost::coroutines2;
74 #endif
75 
76 #ifdef BT_BOOST_COROUTINE
77 #include <boost/coroutine/all.hpp>
78 using namespace boost::coroutines;
79 #endif
80 
82 {
83  std::unique_ptr<coroutine<void>::pull_type> coro;
84  std::function<void(coroutine<void>::push_type & yield)> func;
85  coroutine<void>::push_type * yield_ptr;
86 };
87 
89  const NodeConfiguration& config):
90  ActionNodeBase (name, config), _p( new Pimpl)
91 {
92  _p->func = [this](coroutine<void>::push_type & yield) {
93  _p->yield_ptr = &yield;
94  setStatus(tick());
95  };
96 }
97 
99 {
100 }
101 
103 {
105  (*_p->yield_ptr)();
106 }
107 
109 {
110  if( !(_p->coro) || !(*_p->coro) )
111  {
112  _p->coro.reset( new coroutine<void>::pull_type(_p->func) );
113  return status();
114  }
115 
116  if( status() == NodeStatus::RUNNING && (bool)_p->coro )
117  {
118  (*_p->coro)();
119  }
120 
121  return status();
122 }
123 
125 {
126  _p->coro.reset();
127 }
128 #endif
129 
130 
131 
133 {
134  const NodeStatus initial_status = status();
135 
136  if( initial_status == NodeStatus::IDLE )
137  {
138  NodeStatus new_status = onStart();
139  if( new_status == NodeStatus::IDLE)
140  {
141  throw std::logic_error("AsyncActionNode2::onStart() must not return IDLE");
142  }
143  return new_status;
144  }
145  //------------------------------------------
146  if( initial_status == NodeStatus::RUNNING )
147  {
148  NodeStatus new_status = onRunning();
149  if( new_status == NodeStatus::IDLE)
150  {
151  throw std::logic_error("AsyncActionNode2::onRunning() must not return IDLE");
152  }
153  return new_status;
154  }
155  //------------------------------------------
156  return initial_status;
157 }
158 
160 {
161  if( status() == NodeStatus::RUNNING)
162  {
163  onHalted();
164  }
166 }
167 
169 {
170  //send signal to other thread.
171  // The other thread is in charge for changing the status
172  if (status() == NodeStatus::IDLE)
173  {
175  halt_requested_ = false;
176  thread_handle_ = std::async(std::launch::async, [this]() {
177 
178  try {
179  setStatus(tick());
180  }
181  catch (std::exception&)
182  {
183  std::cerr << "\nUncaught exception from the method tick(): ["
184  << registrationName() << "/" << name() << "]\n" << std::endl;
185  exptr_ = std::current_exception();
186  thread_handle_.wait();
187  }
188  return status();
189  });
190  }
191 
192  if( exptr_ )
193  {
194  std::rethrow_exception(exptr_);
195  }
196  return status();
197 }
198 
200 {
201  halt_requested_.store(true);
202 
203  if( thread_handle_.valid() ){
204  thread_handle_.wait();
205  }
206  thread_handle_ = {};
207 }
The ActionNodeBase is the base class to use to create any kind of action. A particular derived class ...
Definition: action_node.h:35
const std::string & name() const
Name of the instance, not the type.
Definition: tree_node.cpp:73
virtual void halt() override
const NodeConfiguration & config() const
Definition: tree_node.cpp:99
Definition: any.hpp:455
virtual NodeStatus executeTick() override
throws if the derived class return RUNNING.
Definition: action_node.cpp:57
SyncActionNode(const std::string &name, const NodeConfiguration &config)
Definition: action_node.cpp:53
void halt() override
void halt() overridefinal
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn&#39;t require a...
Definition: action_node.h:53
std::unique_ptr< Pimpl > _p
Definition: action_node.h:218
virtual ~CoroActionNode() override
Definition: action_node.cpp:98
ActionNodeBase(const std::string &name, const NodeConfiguration &config)
Definition: action_node.cpp:18
std::unique_ptr< coroutine< void >::pull_type > coro
Definition: action_node.cpp:83
virtual NodeStatus executeTick() overridefinal
The method that should be used to invoke tick() and setStatus();.
virtual NodeStatus executeTick() overridefinal
The method that should be used to invoke tick() and setStatus();.
std::function< NodeStatus(TreeNode &)> TickFunctor
Definition: action_node.h:85
SimpleActionNode(const std::string &name, TickFunctor tick_functor, const NodeConfiguration &config)
Definition: action_node.cpp:26
void setStatusRunningAndYield()
Use this method to return RUNNING and temporary "pause" the Action.
NodeStatus status() const
Definition: tree_node.cpp:56
NodeStatus tick() overridefinal
Method to be implemented by the user.
NodeStatus
Definition: basic_types.h:35
TickFunctor tick_functor_
Definition: action_node.h:96
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
Definition: tree_node.cpp:33
CoroActionNode(const std::string &name, const NodeConfiguration &config)
Definition: action_node.cpp:88
coroutine< void >::push_type * yield_ptr
Definition: action_node.cpp:85
const std::string & registrationName() const
registrationName is the ID used by BehaviorTreeFactory to create an instance.
Definition: tree_node.cpp:94
virtual NodeStatus tick() overridefinal
Method to be implemented by the user.
Definition: action_node.cpp:33
virtual BT::NodeStatus tick()=0
Method to be implemented by the user.
void setStatus(NodeStatus new_status)
Definition: tree_node.cpp:40


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:24