bt_factory.h
Go to the documentation of this file.
1 /* Copyright (C) 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 
14 #ifndef BT_FACTORY_H
15 #define BT_FACTORY_H
16 
17 #include <functional>
18 #include <memory>
19 #include <unordered_map>
20 #include <unordered_set>
21 #include <cstring>
22 #include <algorithm>
23 #include <set>
24 
25 
27 
28 namespace BT
29 {
30 
32 typedef std::function<std::unique_ptr<TreeNode>(const std::string&, const NodeConfiguration&)>
34 
35 template <typename T>
36 using has_default_constructor = typename std::is_constructible<T, const std::string&>;
37 
38 template <typename T>
39 using has_params_constructor = typename std::is_constructible<T, const std::string&, const NodeConfiguration&>;
40 
41 
42 template <typename T> inline
44  has_params_constructor<T>::value >::type* = nullptr)
45 {
46  return [](const std::string& name, const NodeConfiguration& config)
47  {
48  // Special case. Use default constructor if parameters are empty
49  if( config.input_ports.empty() &&
50  config.output_ports.empty() &&
52  {
53  return std::make_unique<T>(name);
54  }
55  return std::make_unique<T>(name, config);
56  };
57 }
58 
59 template <typename T> inline
61  has_params_constructor<T>::value >::type* = nullptr)
62 {
63  return [](const std::string& name, const NodeConfiguration& params)
64  {
65  return std::unique_ptr<TreeNode>(new T(name, params));
66  };
67 }
68 
69 template <typename T> inline
71  !has_params_constructor<T>::value >::type* = nullptr)
72 {
73  return [](const std::string& name, const NodeConfiguration&)
74  {
75  return std::unique_ptr<TreeNode>(new T(name));
76  };
77 }
78 
79 
80 template <typename T> inline
81 TreeNodeManifest CreateManifest(const std::string& ID, PortsList portlist = getProvidedPorts<T>())
82 {
83  return { getType<T>(), ID, portlist };
84 }
85 
86 
87 constexpr const char* PLUGIN_SYMBOL = "BT_RegisterNodesFromPlugin";
88 
89 #ifndef BT_PLUGIN_EXPORT
90 
91 /* Use this macro to automatically register one or more custom Nodes
92 into a factory. For instance:
93 
94 BT_REGISTER_NODES(factory)
95 {
96  factory.registerNodeType<MoveBaseAction>("MoveBase");
97 }
98 
99 IMPORTANT: this must funtion MUST be declared in a cpp file, NOT a header file.
100 See examples for more information about configuring CMake correctly
101 */
102 #define BT_REGISTER_NODES(factory) \
103  static void BT_RegisterNodesFromPlugin(BT::BehaviorTreeFactory& factory)
104 
105 #else
106 
107 #if defined(__linux__) || defined __APPLE__
108 
109 #define BT_REGISTER_NODES(factory) \
110  extern "C" void __attribute__((visibility("default"))) \
111  BT_RegisterNodesFromPlugin(BT::BehaviorTreeFactory& factory)
112 
113 #elif _WIN32
114 
115 #define BT_REGISTER_NODES(factory) \
116  extern "C" void __declspec(dllexport) BT_RegisterNodesFromPlugin(BT::BehaviorTreeFactory& factory)
117 #endif
118 
119 #endif
120 
121 
130 class Tree
131 {
132 public:
133 
134  std::vector<TreeNode::Ptr> nodes;
135  std::vector<Blackboard::Ptr> blackboard_stack;
136  std::unordered_map<std::string, TreeNodeManifest> manifests;
137 
138  Tree(){}
139 
140  // non-copyable. Only movable
141  Tree(const Tree& ) = delete;
142  Tree& operator=(const Tree&) = delete;
143 
144  Tree(Tree&& other)
145  {
146  (*this) = std::move(other);
147  }
148 
149  Tree& operator=(Tree&& other)
150  {
151  nodes = std::move(other.nodes);
152  blackboard_stack = std::move(other.blackboard_stack);
153  manifests = std::move(other.manifests);
154  return *this;
155  }
156 
157  void haltTree()
158  {
159  if(!rootNode())
160  {
161  return;
162  }
163  // the halt should propagate to all the node if the nodes
164  // have been implemented correctly
165  rootNode()->halt();
167 
168  //but, just in case.... this should be no-op
169  auto visitor = [](BT::TreeNode * node) {
170  node->halt();
171  node->setStatus(BT::NodeStatus::IDLE);
172  };
174  }
175 
177  {
178  return nodes.empty() ? nullptr : nodes.front().get();
179  }
180 
182  {
183  if(!rootNode())
184  {
185  throw RuntimeError("Empty Tree");
186  }
187  NodeStatus ret = rootNode()->executeTick();
188  if( ret == NodeStatus::SUCCESS || ret == NodeStatus::FAILURE){
190  }
191  return ret;
192  }
193 
194  ~Tree();
195 
197 
198 };
199 
208 {
209 public:
211 
213  bool unregisterBuilder(const std::string& ID);
214 
216  void registerBuilder(const TreeNodeManifest& manifest, const NodeBuilder& builder);
217 
218  template <typename T>
219  void registerBuilder(const std::string& ID, const NodeBuilder& builder )
220  {
221  auto manifest = CreateManifest<T>(ID);
222  registerBuilder(manifest, builder);
223  }
224 
233  void registerSimpleAction(const std::string& ID,
234  const SimpleActionNode::TickFunctor& tick_functor,
235  PortsList ports = {});
244  void registerSimpleCondition(const std::string& ID,
245  const SimpleConditionNode::TickFunctor& tick_functor,
246  PortsList ports = {});
255  void registerSimpleDecorator(const std::string& ID,
256  const SimpleDecoratorNode::TickFunctor& tick_functor,
257  PortsList ports = {});
258 
264  void registerFromPlugin(const std::string &file_path);
265 
271  void registerFromROSPlugins();
272 
281  std::unique_ptr<TreeNode> instantiateTreeNode(const std::string& name, const std::string &ID,
282  const NodeConfiguration& config) const;
283 
289  template <typename T>
290  void registerNodeType(const std::string& ID)
291  {
292  static_assert(std::is_base_of<ActionNodeBase, T>::value ||
293  std::is_base_of<ControlNode, T>::value ||
294  std::is_base_of<DecoratorNode, T>::value ||
295  std::is_base_of<ConditionNode, T>::value,
296  "[registerNode]: accepts only classed derived from either ActionNodeBase, "
297  "DecoratorNode, ControlNode or ConditionNode");
298 
299  static_assert(!std::is_abstract<T>::value,
300  "[registerNode]: Some methods are pure virtual. "
301  "Did you override the methods tick() and halt()?");
302 
303  constexpr bool default_constructable = std::is_constructible<T, const std::string&>::value;
304  constexpr bool param_constructable =
305  std::is_constructible<T, const std::string&, const NodeConfiguration&>::value;
306  constexpr bool has_static_ports_list =
308 
309  static_assert(default_constructable || param_constructable,
310  "[registerNode]: the registered class must have at least one of these two "
311  "constructors: "
312  " (const std::string&, const NodeConfiguration&) or (const std::string&).");
313 
314  static_assert(!(param_constructable && !has_static_ports_list),
315  "[registerNode]: you MUST implement the static method: "
316  " PortsList providedPorts();\n");
317 
318  static_assert(!(has_static_ports_list && !param_constructable),
319  "[registerNode]: since you have a static method providedPorts(), "
320  "you MUST add a constructor sign signature (const std::string&, const "
321  "NodeParameters&)\n");
322 
323  registerBuilder( CreateManifest<T>(ID), CreateBuilder<T>());
324  }
325 
326  template <typename T>
327  void registerNodeType(const std::string& ID, PortsList ports)
328  {
329  static_assert(std::is_base_of<ActionNodeBase, T>::value ||
330  std::is_base_of<ControlNode, T>::value ||
331  std::is_base_of<DecoratorNode, T>::value ||
332  std::is_base_of<ConditionNode, T>::value,
333  "[registerNode]: accepts only classed derived from either ActionNodeBase, "
334  "DecoratorNode, ControlNode or ConditionNode");
335 
336  static_assert(!std::is_abstract<T>::value,
337  "[registerNode]: Some methods are pure virtual. "
338  "Did you override the methods tick() and halt()?");
339 
340  constexpr bool default_constructable = std::is_constructible<T, const std::string&>::value;
341  constexpr bool param_constructable =
342  std::is_constructible<T, const std::string&, const NodeConfiguration&>::value;
343  constexpr bool has_static_ports_list =
345 
346  static_assert(default_constructable || param_constructable,
347  "[registerNode]: the registered class must have at least one of these two "
348  "constructors: (const std::string&, const NodeConfiguration&) or (const std::string&).");
349 
350  static_assert(!has_static_ports_list,
351  "[registerNode]: ports are passed to this node explicitly. The static method"
352  "providedPorts() should be removed to avoid ambiguities\n");
353 
354  static_assert(param_constructable,
355  "[registerNode]: since this node has ports, "
356  "you MUST add a constructor sign signature (const std::string&, const "
357  "NodeParameters&)\n");
358 
359  registerBuilder( CreateManifest<T>(ID, ports), CreateBuilder<T>());
360  }
361 
363  const std::unordered_map<std::string, NodeBuilder>& builders() const;
364 
366  const std::unordered_map<std::string, TreeNodeManifest>& manifests() const;
367 
369  const std::set<std::string>& builtinNodes() const;
370 
371  Tree createTreeFromText(const std::string& text,
372  Blackboard::Ptr blackboard = Blackboard::create());
373 
374  Tree createTreeFromFile(const std::string& file_path,
375  Blackboard::Ptr blackboard = Blackboard::create());
376 
377 private:
378  std::unordered_map<std::string, NodeBuilder> builders_;
379  std::unordered_map<std::string, TreeNodeManifest> manifests_;
380  std::set<std::string> builtin_IDs_;
381 
382  // clang-format on
383 };
384 
385 
386 } // end namespace
387 
388 #endif // BT_FACTORY_H
constexpr const char * PLUGIN_SYMBOL
Definition: bt_factory.h:87
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:38
virtual void halt()=0
manifest
void registerNodeType(const std::string &ID)
Definition: bt_factory.h:290
std::function< NodeStatus(NodeStatus, TreeNode &)> TickFunctor
std::function< std::unique_ptr< TreeNode >const std::string &, const NodeConfiguration &)> NodeBuilder
The term "Builder" refers to the Builder Pattern (https://en.wikipedia.org/wiki/Builder_pattern) ...
Definition: bt_factory.h:33
NodeBuilder CreateBuilder(typename std::enable_if< has_default_constructor< T >::value &&has_params_constructor< T >::value >::type *=nullptr)
Definition: bt_factory.h:43
std::unordered_map< std::string, NodeBuilder > builders_
Definition: bt_factory.h:378
Tree(Tree &&other)
Definition: bt_factory.h:144
std::set< std::string > builtin_IDs_
Definition: bt_factory.h:380
void haltTree()
Definition: bt_factory.h:157
std::vector< Blackboard::Ptr > blackboard_stack
Definition: bt_factory.h:135
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:26
This information is used mostly by the XMLParser.
Definition: tree_node.h:32
std::unordered_map< std::string, TreeNodeManifest > manifests_
Definition: bt_factory.h:379
Blackboard::Ptr rootBlackboard()
Definition: bt_factory.cpp:274
Tree & operator=(Tree &&other)
Definition: bt_factory.h:149
TreeNode * rootNode() const
Definition: bt_factory.h:176
void registerBuilder(const std::string &ID, const NodeBuilder &builder)
Definition: bt_factory.h:219
typename std::is_constructible< T, const std::string &, const NodeConfiguration & > has_params_constructor
Definition: bt_factory.h:39
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:207
TreeNodeManifest CreateManifest(const std::string &ID, PortsList portlist=getProvidedPorts< T >())
Definition: bt_factory.h:81
NodeStatus tickRoot()
Definition: bt_factory.h:181
Tree & operator=(const Tree &)=delete
typename std::is_constructible< T, const std::string & > has_default_constructor
Definition: bt_factory.h:36
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:130
Abstract base class for Behavior Tree Nodes.
Definition: tree_node.h:53
typename std::enable_if< Predicate::value >::type * enable_if
Definition: basic_types.h:168
std::function< NodeStatus(TreeNode &)> TickFunctor
Definition: action_node.h:85
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:317
std::vector< TreeNode::Ptr > nodes
Definition: bt_factory.h:134
std::unordered_map< std::string, TreeNodeManifest > manifests
Definition: bt_factory.h:136
NodeStatus
Definition: basic_types.h:35
virtual BT::NodeStatus executeTick()
The method that should be used to invoke tick() and setStatus();.
Definition: tree_node.cpp:33
void setStatus(NodeStatus new_status)
Definition: tree_node.cpp:40
void registerNodeType(const std::string &ID, PortsList ports)
Definition: bt_factory.h:327
std::function< NodeStatus(TreeNode &)> TickFunctor
void applyRecursiveVisitor(const TreeNode *root_node, const std::function< void(const TreeNode *)> &visitor)


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