bt_factory.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2018-2020 Davide Faconti, Eurecat - All Rights Reserved
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
4 * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
5 * 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:
6 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9 * 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,
10 * 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.
11 */
12 
13 #include <fstream>
17 
18 #ifdef USING_ROS
19 #include "filesystem/path.h"
20 #include <ros/package.h>
21 #endif
22 
23 namespace BT
24 {
26 {
27  parser_ = std::make_shared<XMLParser>(*this);
28  registerNodeType<FallbackNode>("Fallback");
29  registerNodeType<SequenceNode>("Sequence");
30  registerNodeType<SequenceStarNode>("SequenceStar");
31  registerNodeType<ParallelNode>("Parallel");
32  registerNodeType<ReactiveSequence>("ReactiveSequence");
33  registerNodeType<ReactiveFallback>("ReactiveFallback");
34  registerNodeType<IfThenElseNode>("IfThenElse");
35  registerNodeType<WhileDoElseNode>("WhileDoElse");
36 
37  registerNodeType<InverterNode>("Inverter");
38  //registerNodeType<RetryNodeTypo>("RetryUntilSuccesful"); //typo but back compatibility
39  registerNodeType<RetryNode>("RetryUntilSuccessful"); // correct one
40  registerNodeType<KeepRunningUntilFailureNode>("KeepRunningUntilFailure");
41  registerNodeType<RepeatNode>("Repeat");
42  registerNodeType<TimeoutNode<>>("Timeout");
43  registerNodeType<DelayNode>("Delay");
44 
45  registerNodeType<ForceSuccessNode>("ForceSuccess");
46  registerNodeType<ForceFailureNode>("ForceFailure");
47 
48  registerNodeType<AlwaysSuccessNode>("AlwaysSuccess");
49  registerNodeType<AlwaysFailureNode>("AlwaysFailure");
50  registerNodeType<SetBlackboard>("SetBlackboard");
51 
52  registerNodeType<SubtreeNode>("SubTree");
53  registerNodeType<SubtreePlusNode>("SubTreePlus");
54 
55  registerNodeType<BlackboardPreconditionNode<int>>("BlackboardCheckInt");
56  registerNodeType<BlackboardPreconditionNode<double>>("BlackboardCheckDouble");
57  registerNodeType<BlackboardPreconditionNode<std::string>>("BlackboardCheckString");
58  registerNodeType<BlackboardPreconditionNode<bool>>("BlackboardCheckBool");
59 
60  registerNodeType<SwitchNode<2>>("Switch2");
61  registerNodeType<SwitchNode<3>>("Switch3");
62  registerNodeType<SwitchNode<4>>("Switch4");
63  registerNodeType<SwitchNode<5>>("Switch5");
64  registerNodeType<SwitchNode<6>>("Switch6");
65 
66 #ifdef NCURSES_FOUND
67  registerNodeType<ManualSelectorNode>("ManualSelector");
68 #endif
69  for (const auto& it : builders_)
70  {
71  builtin_IDs_.insert(it.first);
72  }
73 }
74 
75 bool BehaviorTreeFactory::unregisterBuilder(const std::string& ID)
76 {
77  if (builtinNodes().count(ID))
78  {
79  throw LogicError("You can not remove the builtin registration ID [", ID, "]");
80  }
81  auto it = builders_.find(ID);
82  if (it == builders_.end())
83  {
84  return false;
85  }
86  builders_.erase(ID);
87  manifests_.erase(ID);
88  return true;
89 }
90 
92  const NodeBuilder& builder)
93 {
94  auto it = builders_.find(manifest.registration_ID);
95  if (it != builders_.end())
96  {
97  throw BehaviorTreeException("ID [", manifest.registration_ID, "] already registered");
98  }
99 
100  builders_.insert({manifest.registration_ID, builder});
101  manifests_.insert({manifest.registration_ID, manifest});
102 }
103 
105  const std::string& ID, const SimpleConditionNode::TickFunctor& tick_functor,
106  PortsList ports)
107 {
108  NodeBuilder builder = [tick_functor, ID](const std::string& name,
109  const NodeConfiguration& config) {
110  return std::make_unique<SimpleConditionNode>(name, tick_functor, config);
111  };
112 
113  TreeNodeManifest manifest = {NodeType::CONDITION, ID, std::move(ports), {}};
114  registerBuilder(manifest, builder);
115 }
116 
118  const std::string& ID, const SimpleActionNode::TickFunctor& tick_functor,
119  PortsList ports)
120 {
121  NodeBuilder builder = [tick_functor, ID](const std::string& name,
122  const NodeConfiguration& config) {
123  return std::make_unique<SimpleActionNode>(name, tick_functor, config);
124  };
125 
126  TreeNodeManifest manifest = {NodeType::ACTION, ID, std::move(ports), {}};
127  registerBuilder(manifest, builder);
128 }
129 
131  const std::string& ID, const SimpleDecoratorNode::TickFunctor& tick_functor,
132  PortsList ports)
133 {
134  NodeBuilder builder = [tick_functor, ID](const std::string& name,
135  const NodeConfiguration& config) {
136  return std::make_unique<SimpleDecoratorNode>(name, tick_functor, config);
137  };
138 
139  TreeNodeManifest manifest = {NodeType::DECORATOR, ID, std::move(ports), {}};
140  registerBuilder(manifest, builder);
141 }
142 
143 void BehaviorTreeFactory::registerFromPlugin(const std::string& file_path)
144 {
145  BT::SharedLibrary loader;
146  loader.load(file_path);
147  typedef void (*Func)(BehaviorTreeFactory&);
148 
149  if (loader.hasSymbol(PLUGIN_SYMBOL))
150  {
151  Func func = (Func)loader.getSymbol(PLUGIN_SYMBOL);
152  func(*this);
153  }
154  else
155  {
156  std::cout << "ERROR loading library [" << file_path << "]: can't find symbol ["
157  << PLUGIN_SYMBOL << "]" << std::endl;
158  }
159 }
160 
161 #ifdef USING_ROS
162 
163 #ifdef _WIN32
164 const char os_pathsep(';'); // NOLINT
165 #else
166 const char os_pathsep(':'); // NOLINT
167 #endif
168 
169 // This function is a copy from the one in class_loader_imp.hpp in ROS pluginlib
170 // package, licensed under BSD.
171 // https://github.com/ros/pluginlib
172 std::vector<std::string> getCatkinLibraryPaths()
173 {
174  std::vector<std::string> lib_paths;
175  const char* env = std::getenv("CMAKE_PREFIX_PATH");
176  if (env)
177  {
178  const std::string env_catkin_prefix_paths(env);
179  std::vector<BT::StringView> catkin_prefix_paths =
180  splitString(env_catkin_prefix_paths, os_pathsep);
181  for (BT::StringView catkin_prefix_path : catkin_prefix_paths)
182  {
183  filesystem::path path(static_cast<std::string>(catkin_prefix_path));
184  filesystem::path lib("lib");
185  lib_paths.push_back((path / lib).str());
186  }
187  }
188  return lib_paths;
189 }
190 
192 {
193  std::vector<std::string> plugins;
194  ros::package::getPlugins("behaviortree_cpp_v3", "bt_lib_plugin", plugins, true);
195  std::vector<std::string> catkin_lib_paths = getCatkinLibraryPaths();
196 
197  for (const auto& plugin : plugins)
198  {
199  auto filename = filesystem::path(plugin + BT::SharedLibrary::suffix());
200  for (const auto& lib_path : catkin_lib_paths)
201  {
202  const auto full_path = filesystem::path(lib_path) / filename;
203  if (full_path.exists())
204  {
205  std::cout << "Registering ROS plugins from " << full_path.str() << std::endl;
206  registerFromPlugin(full_path.str());
207  break;
208  }
209  }
210  }
211 }
212 #else
213 
215 {
216  throw RuntimeError("Using attribute [ros_pkg] in <include>, but this library was "
217  "compiled "
218  "without ROS support. Recompile the BehaviorTree.CPP using "
219  "catkin");
220 }
221 #endif
222 
223 void BehaviorTreeFactory::registerBehaviorTreeFromFile(const std::string& filename)
224 {
225  parser_->loadFromFile(filename);
226 }
227 
229 {
230  parser_->loadFromText(xml_text, true /* add_includes */);
231 }
232 
233 std::vector<std::string> BehaviorTreeFactory::registeredBehaviorTrees() const
234 {
235  return parser_->registeredBehaviorTrees();
236 }
237 
239 {
240  parser_->clearInternalState();
241 }
242 
244  const std::string& name, const std::string& ID, const NodeConfiguration& config) const
245 {
246  auto it = builders_.find(ID);
247  if (it == builders_.end())
248  {
249  std::cerr << ID << " not included in this list:" << std::endl;
250  for (const auto& builder_it : builders_)
251  {
252  std::cerr << builder_it.first << std::endl;
253  }
254  throw RuntimeError("BehaviorTreeFactory: ID [", ID, "] not registered");
255  }
256 
257  std::unique_ptr<TreeNode> node = it->second(name, config);
258  node->setRegistrationID(ID);
259  return node;
260 }
261 
262 const std::unordered_map<std::string, NodeBuilder>& BehaviorTreeFactory::builders() const
263 {
264  return builders_;
265 }
266 
267 const std::unordered_map<std::string, TreeNodeManifest>&
269 {
270  return manifests_;
271 }
272 
273 const std::set<std::string>& BehaviorTreeFactory::builtinNodes() const
274 {
275  return builtin_IDs_;
276 }
277 
279  Blackboard::Ptr blackboard)
280 {
281  if(!parser_->registeredBehaviorTrees().empty()) {
282  std::cout << "WARNING: You executed BehaviorTreeFactory::createTreeFromText "
283  "after registerBehaviorTreeFrom[File/Text].\n"
284  "This is NOTm probably, what you want to do.\n"
285  "You should probably use BehaviorTreeFactory::createTree, instead"
286  << std::endl;
287  }
288  XMLParser parser(*this);
289  parser.loadFromText(text);
290  auto tree = parser.instantiateTree(blackboard);
291  tree.manifests = this->manifests();
292  return tree;
293 }
294 
295 Tree BehaviorTreeFactory::createTreeFromFile(const std::string& file_path,
296  Blackboard::Ptr blackboard)
297 {
298  if(!parser_->registeredBehaviorTrees().empty()) {
299  std::cout << "WARNING: You executed BehaviorTreeFactory::createTreeFromFile "
300  "after registerBehaviorTreeFrom[File/Text].\n"
301  "This is NOTm probably, what you want to do.\n"
302  "You should probably use BehaviorTreeFactory::createTree, instead"
303  << std::endl;
304  }
305 
306  XMLParser parser(*this);
307  parser.loadFromFile(file_path);
308  auto tree = parser.instantiateTree(blackboard);
309  tree.manifests = this->manifests();
310  return tree;
311 }
312 
313 Tree BehaviorTreeFactory::createTree(const std::string& tree_name,
314  Blackboard::Ptr blackboard)
315 {
316  auto tree = parser_->instantiateTree(blackboard, tree_name);
317  tree.manifests = this->manifests();
318  return tree;
319 }
320 
321 void BehaviorTreeFactory::addDescriptionToManifest(const std::string& node_id,
322  const std::string& description)
323 {
324  auto it = manifests_.find(node_id);
325  if (it == manifests_.end())
326  {
327  throw std::runtime_error("addDescriptionToManifest: wrong ID");
328  }
329  it->second.description = description;
330 }
331 
332 void Tree::sleep(std::chrono::system_clock::duration timeout)
333 {
334  wake_up_->waitFor(timeout);
335 }
336 
338 {
339  haltTree();
340 }
341 
343 {
344  if (blackboard_stack.size() > 0)
345  {
346  return blackboard_stack.front();
347  }
348  return {};
349 }
350 
351 } // namespace BT
constexpr const char * PLUGIN_SYMBOL
Definition: bt_factory.h:115
void clearRegisteredBehaviorTrees()
Clear previously-registered behavior trees.
Definition: bt_factory.cpp:238
void sleep(std::chrono::system_clock::duration timeout)
Definition: bt_factory.cpp:332
std::function< NodeStatus(NodeStatus, TreeNode &)> TickFunctor
std::unique_ptr< TreeNode > instantiateTreeNode(const std::string &name, const std::string &ID, const NodeConfiguration &config) const
instantiateTreeNode creates an instance of a previously registered TreeNode.
Definition: bt_factory.cpp:243
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:32
const std::set< std::string > & builtinNodes() const
List of builtin IDs.
Definition: bt_factory.cpp:273
std::unordered_map< std::string, NodeBuilder > builders_
Definition: bt_factory.h:490
void loadFromFile(const std::string &filename, bool add_includes=true) override
Definition: xml_parsing.cpp:98
std::set< std::string > builtin_IDs_
Definition: bt_factory.h:492
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:25
This information is used mostly by the XMLParser.
Definition: tree_node.h:34
std::unordered_map< std::string, TreeNodeManifest > manifests_
Definition: bt_factory.h:491
Blackboard::Ptr rootBlackboard()
Definition: bt_factory.cpp:342
void addDescriptionToManifest(const std::string &node_id, const std::string &description)
Definition: bt_factory.cpp:321
bool hasSymbol(const std::string &name)
static const char * xml_text
Tree instantiateTree(const Blackboard::Ptr &root_blackboard, std::string main_tree_to_execute={}) override
std::vector< StringView > splitString(const StringView &strToSplit, char delimeter)
void registerBehaviorTreeFromText(const std::string &xml_text)
Definition: bt_factory.cpp:228
string manifest
static std::string suffix()
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:251
std::vector< std::string > registeredBehaviorTrees() const
Definition: bt_factory.cpp:233
void * getSymbol(const std::string &name)
nonstd::string_view StringView
Definition: basic_types.h:55
std::string registration_ID
Definition: tree_node.h:37
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:278
Tree createTree(const std::string &tree_name, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:313
void registerFromPlugin(const std::string &file_path)
registerFromPlugin load a shared library and execute the function BT_REGISTER_NODES (see macro)...
Definition: bt_factory.cpp:143
void loadFromText(const std::string &xml_text, bool add_includes=true) override
const std::unordered_map< std::string, NodeBuilder > & builders() const
All the builders. Made available mostly for debug purposes.
Definition: bt_factory.cpp:262
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:125
Simple class for manipulating paths on Linux/Windows/Mac OS.
Definition: path.h:42
void registerSimpleAction(const std::string &ID, const SimpleActionNode::TickFunctor &tick_functor, PortsList ports={})
registerSimpleAction help you register nodes of type SimpleActionNode.
Definition: bt_factory.cpp:117
ROSLIB_DECL void getPlugins(const std::string &package, const std::string &attribute, V_string &plugins, bool force_recrawl=false)
std::function< NodeStatus(TreeNode &)> TickFunctor
Definition: action_node.h:81
void load(const std::string &path, int flags=0)
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:333
static volatile int count
Definition: minitrace.cpp:55
The XMLParser is a class used to read the model of a BehaviorTree from file or text and instantiate t...
Definition: xml_parsing.h:15
const std::unordered_map< std::string, TreeNodeManifest > & manifests() const
Manifests of all the registered TreeNodes.
Definition: bt_factory.cpp:268
std::unordered_map< std::string, TreeNodeManifest > manifests
Definition: bt_factory.h:130
void registerBuilder(const TreeNodeManifest &manifest, const NodeBuilder &builder)
Definition: bt_factory.cpp:91
void registerFromROSPlugins()
registerFromROSPlugins finds all shared libraries that export ROS plugins for behaviortree_cpp, and calls registerFromPlugin for each library.
Definition: bt_factory.cpp:214
bool unregisterBuilder(const std::string &ID)
Remove a registered ID.
Definition: bt_factory.cpp:75
void registerBehaviorTreeFromFile(const std::string &filename)
registerBehaviorTreeFromFile. Load the definition of an entire behavior tree, but don&#39;t instantiate i...
Definition: bt_factory.cpp:223
Tree createTreeFromFile(const std::string &file_path, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:295
void registerSimpleDecorator(const std::string &ID, const SimpleDecoratorNode::TickFunctor &tick_functor, PortsList ports={})
registerSimpleDecorator help you register nodes of type SimpleDecoratorNode.
Definition: bt_factory.cpp:130
void registerSimpleCondition(const std::string &ID, const SimpleConditionNode::TickFunctor &tick_functor, PortsList ports={})
registerSimpleCondition help you register nodes of type SimpleConditionNode.
Definition: bt_factory.cpp:104
std::shared_ptr< BT::Parser > parser_
Definition: bt_factory.h:495
std::function< NodeStatus(TreeNode &)> TickFunctor


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14