xml_parsing.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2018-2019 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 <functional>
14 #include <list>
15 
16 #if defined(__linux) || defined(__linux__)
17  #pragma GCC diagnostic push
18  #pragma GCC diagnostic ignored "-Wattributes"
19 #endif
20 
21 #ifdef _MSC_VER
22 #pragma warning(disable : 4996) // do not complain about sprintf
23 #endif
24 
26 #include "private/tinyxml2.h"
27 #include "filesystem/path.h"
28 
29 #ifdef USING_ROS
30 #include <ros/package.h>
31 #endif
32 
35 
36 namespace BT
37 {
38 using namespace BT_TinyXML2;
39 
41 {
42  TreeNode::Ptr createNodeFromXML(const XMLElement* element,
43  const Blackboard::Ptr& blackboard,
44  const TreeNode::Ptr& node_parent);
45 
46  void recursivelyCreateTree(const std::string& tree_ID,
47  Tree& output_tree,
48  Blackboard::Ptr blackboard,
49  const TreeNode::Ptr& root_parent);
50 
51  void loadDocImpl(BT_TinyXML2::XMLDocument* doc);
52 
53  std::list<std::unique_ptr<BT_TinyXML2::XMLDocument> > opened_documents;
54  std::unordered_map<std::string,const XMLElement*> tree_roots;
55 
57 
58  filesystem::path current_path;
59 
61 
62  explicit Pimpl(const BehaviorTreeFactory &fact):
63  factory(fact),
64  current_path( filesystem::path::getcwd() ),
65  suffix_count(0)
66  {}
67 
68  void clear()
69  {
70  suffix_count = 0;
71  current_path = filesystem::path::getcwd();
72  opened_documents.clear();
73  tree_roots.clear();
74  }
75 
76 };
77 
78 #if defined(__linux) || defined(__linux__)
79 #pragma GCC diagnostic pop
80 #endif
81 
83  _p( new Pimpl(factory) )
84 {
85 }
86 
88 {
89  delete _p;
90 }
91 
92 void XMLParser::loadFromFile(const std::string& filename)
93 {
94  _p->opened_documents.emplace_back(new BT_TinyXML2::XMLDocument());
95 
96  BT_TinyXML2::XMLDocument* doc = _p->opened_documents.back().get();
97  doc->LoadFile(filename.c_str());
98 
99  filesystem::path file_path( filename );
100  _p->current_path = file_path.parent_path().make_absolute();
101 
102  _p->loadDocImpl( doc );
103 }
104 
105 void XMLParser::loadFromText(const std::string& xml_text)
106 {
107  _p->opened_documents.emplace_back(new BT_TinyXML2::XMLDocument());
108 
109  BT_TinyXML2::XMLDocument* doc = _p->opened_documents.back().get();
110  doc->Parse(xml_text.c_str(), xml_text.size());
111 
112  _p->loadDocImpl( doc );
113 }
114 
116 {
117  if (doc->Error())
118  {
119  char buffer[200];
120  sprintf(buffer, "Error parsing the XML: %s", doc->ErrorName() );
121  throw RuntimeError(buffer);
122  }
123 
124  const XMLElement* xml_root = doc->RootElement();
125 
126  // recursively include other files
127  for (auto include_node = xml_root->FirstChildElement("include");
128  include_node != nullptr;
129  include_node = include_node->NextSiblingElement("include"))
130  {
131 
132  filesystem::path file_path( include_node->Attribute("path") );
133 
134  if( include_node->Attribute("ros_pkg") )
135  {
136 #ifdef USING_ROS
137  if( file_path.is_absolute() )
138  {
139  std::cout << "WARNING: <include path=\"...\"> containes an absolute path.\n"
140  << "Attribute [ros_pkg] will be ignored."<< std::endl;
141  }
142  else {
143  auto ros_pkg_path = ros::package::getPath( include_node->Attribute("ros_pkg") );
144  file_path = filesystem::path( ros_pkg_path ) / file_path;
145  }
146 #else
147  throw RuntimeError("Using attribute [ros_pkg] in <include>, but this library was compiled "
148  "without ROS support. Recompile the BehaviorTree.CPP using catkin");
149 #endif
150  }
151 
152  if( !file_path.is_absolute() )
153  {
154  file_path = current_path / file_path;
155  }
156 
157  opened_documents.emplace_back(new BT_TinyXML2::XMLDocument());
158  BT_TinyXML2::XMLDocument* next_doc = opened_documents.back().get();
159  next_doc->LoadFile(file_path.str().c_str());
160  loadDocImpl(next_doc);
161  }
162 
163  for (auto bt_node = xml_root->FirstChildElement("BehaviorTree");
164  bt_node != nullptr;
165  bt_node = bt_node->NextSiblingElement("BehaviorTree"))
166  {
167  std::string tree_name;
168  if (bt_node->Attribute("ID"))
169  {
170  tree_name = bt_node->Attribute("ID");
171  }
172  else{
173  tree_name = "BehaviorTree_" + std::to_string( suffix_count++ );
174  }
175  tree_roots.insert( {tree_name, bt_node} );
176  }
177 
178  std::set<std::string> registered_nodes;
179  XMLPrinter printer;
180  doc->Print(&printer);
181  auto xml_text = std::string(printer.CStr(), size_t(printer.CStrSize() - 1));
182 
183  for( const auto& it: factory.manifests())
184  {
185  registered_nodes.insert( it.first );
186  }
187  for( const auto& it: tree_roots)
188  {
189  registered_nodes.insert( it.first );
190  }
191 
192  VerifyXML(xml_text, registered_nodes);
193 }
194 
195 void VerifyXML(const std::string& xml_text,
196  const std::set<std::string>& registered_nodes)
197 {
198 
200  auto xml_error = doc.Parse( xml_text.c_str(), xml_text.size());
201  if (xml_error)
202  {
203  char buffer[200];
204  sprintf(buffer, "Error parsing the XML: %s", doc.ErrorName() );
205  throw RuntimeError( buffer );
206  }
207 
208  //-------- Helper functions (lambdas) -----------------
209  auto StrEqual = [](const char* str1, const char* str2) -> bool {
210  return strcmp(str1, str2) == 0;
211  };
212 
213  auto ThrowError = [&](int line_num, const std::string& text) {
214  char buffer[256];
215  sprintf(buffer, "Error at line %d: -> %s", line_num, text.c_str());
216  throw RuntimeError( buffer );
217  };
218 
219  auto ChildrenCount = [](const XMLElement* parent_node) {
220  int count = 0;
221  for (auto node = parent_node->FirstChildElement(); node != nullptr;
222  node = node->NextSiblingElement())
223  {
224  count++;
225  }
226  return count;
227  };
228  //-----------------------------
229 
230  const XMLElement* xml_root = doc.RootElement();
231 
232  if (!xml_root || !StrEqual(xml_root->Name(), "root"))
233  {
234  throw RuntimeError("The XML must have a root node called <root>");
235  }
236  //-------------------------------------------------
237  auto models_root = xml_root->FirstChildElement("TreeNodesModel");
238  auto meta_sibling = models_root ? models_root->NextSiblingElement("TreeNodesModel") : nullptr;
239 
240  if (meta_sibling)
241  {
242  ThrowError(meta_sibling->GetLineNum(),
243  " Only a single node <TreeNodesModel> is supported");
244  }
245  if (models_root)
246  {
247  // not having a MetaModel is not an error. But consider that the
248  // Graphical editor needs it.
249  for (auto node = xml_root->FirstChildElement(); node != nullptr;
250  node = node->NextSiblingElement())
251  {
252  const char* name = node->Name();
253  if (StrEqual(name, "Action") || StrEqual(name, "Decorator") ||
254  StrEqual(name, "SubTree") || StrEqual(name, "Condition"))
255  {
256  const char* ID = node->Attribute("ID");
257  if (!ID)
258  {
259  ThrowError(node->GetLineNum(),
260  "Error at line %d: -> The attribute [ID] is mandatory");
261  }
262  }
263  }
264  }
265  //-------------------------------------------------
266 
267  // function to be called recursively
268  std::function<void(const XMLElement*)> recursiveStep;
269 
270  recursiveStep = [&](const XMLElement* node) {
271  const int children_count = ChildrenCount(node);
272  const char* name = node->Name();
273  if (StrEqual(name, "Decorator"))
274  {
275  if (children_count != 1)
276  {
277  ThrowError(node->GetLineNum(),
278  "The node <Decorator> must have exactly 1 child");
279  }
280  if (!node->Attribute("ID"))
281  {
282  ThrowError(node->GetLineNum(),
283  "The node <Decorator> must have the attribute [ID]");
284  }
285  }
286  else if (StrEqual(name, "Action"))
287  {
288  if (children_count != 0)
289  {
290  ThrowError(node->GetLineNum(),
291  "The node <Action> must not have any child");
292  }
293  if (!node->Attribute("ID"))
294  {
295  ThrowError(node->GetLineNum(),
296  "The node <Action> must have the attribute [ID]");
297  }
298  }
299  else if (StrEqual(name, "Condition"))
300  {
301  if (children_count != 0)
302  {
303  ThrowError(node->GetLineNum(),
304  "The node <Condition> must not have any child");
305  }
306  if (!node->Attribute("ID"))
307  {
308  ThrowError(node->GetLineNum(),
309  "The node <Condition> must have the attribute [ID]");
310  }
311  }
312  else if (StrEqual(name, "Sequence") ||
313  StrEqual(name, "SequenceStar") ||
314  StrEqual(name, "Fallback") )
315  {
316  if (children_count == 0)
317  {
318  ThrowError(node->GetLineNum(),
319  "A Control node must have at least 1 child");
320  }
321  }
322  else if (StrEqual(name, "SubTree"))
323  {
324  for (auto child = node->FirstChildElement(); child != nullptr;
325  child = child->NextSiblingElement())
326  {
327  if( StrEqual(child->Name(), "remap") )
328  {
329  ThrowError(node->GetLineNum(), "<remap> was deprecated");
330  }
331  else{
332  ThrowError(node->GetLineNum(), "<SubTree> should not have any child");
333  }
334  }
335 
336  if (!node->Attribute("ID"))
337  {
338  ThrowError(node->GetLineNum(),
339  "The node <SubTree> must have the attribute [ID]");
340  }
341  }
342  else
343  {
344  // search in the factory and the list of subtrees
345  bool found = ( registered_nodes.find(name) != registered_nodes.end() );
346  if (!found)
347  {
348  ThrowError(node->GetLineNum(),
349  std::string("Node not recognized: ") + name);
350  }
351  }
352  //recursion
353  if (StrEqual(name, "SubTree") == false)
354  {
355  for (auto child = node->FirstChildElement(); child != nullptr;
356  child = child->NextSiblingElement())
357  {
358  recursiveStep(child);
359  }
360  }
361  };
362 
363  std::vector<std::string> tree_names;
364  int tree_count = 0;
365 
366  for (auto bt_root = xml_root->FirstChildElement("BehaviorTree"); bt_root != nullptr;
367  bt_root = bt_root->NextSiblingElement("BehaviorTree"))
368  {
369  tree_count++;
370  if (bt_root->Attribute("ID"))
371  {
372  tree_names.emplace_back(bt_root->Attribute("ID"));
373  }
374  if (ChildrenCount(bt_root) != 1)
375  {
376  ThrowError(bt_root->GetLineNum(),
377  "The node <BehaviorTree> must have exactly 1 child");
378  }
379  else
380  {
381  recursiveStep(bt_root->FirstChildElement());
382  }
383  }
384 
385  if (xml_root->Attribute("main_tree_to_execute"))
386  {
387  std::string main_tree = xml_root->Attribute("main_tree_to_execute");
388  if (std::find(tree_names.begin(), tree_names.end(), main_tree) == tree_names.end())
389  {
390  throw RuntimeError("The tree specified in [main_tree_to_execute] can't be found");
391  }
392  }
393  else
394  {
395  if (tree_count != 1)
396  {
397  throw RuntimeError("If you don't specify the attribute [main_tree_to_execute], "
398  "Your file must contain a single BehaviorTree");
399  }
400  }
401 }
402 
404 {
405  Tree output_tree;
406 
407  XMLElement* xml_root = _p->opened_documents.front()->RootElement();
408 
409  std::string main_tree_ID;
410  if (xml_root->Attribute("main_tree_to_execute"))
411  {
412  main_tree_ID = xml_root->Attribute("main_tree_to_execute");
413  }
414  else if( _p->tree_roots.size() == 1)
415  {
416  main_tree_ID = _p->tree_roots.begin()->first;
417  }
418  else{
419  throw RuntimeError("[main_tree_to_execute] was not specified correctly");
420  }
421  //--------------------------------------
422  if( !root_blackboard )
423  {
424  throw RuntimeError("XMLParser::instantiateTree needs a non-empty root_blackboard");
425  }
426  // first blackboard
427  output_tree.blackboard_stack.push_back( root_blackboard );
428 
429  _p->recursivelyCreateTree(main_tree_ID,
430  output_tree,
431  root_blackboard,
432  TreeNode::Ptr() );
433 
434  if( output_tree.nodes.size() > 0)
435  {
436  output_tree.root_node = output_tree.nodes.front().get();
437  }
438  return output_tree;
439 }
440 
442  const Blackboard::Ptr &blackboard,
443  const TreeNode::Ptr &node_parent)
444 {
445  const std::string element_name = element->Name();
446  std::string ID;
447  std::string instance_name;
448 
449  // Actions and Decorators have their own ID
450  if (element_name == "Action" || element_name == "Decorator" || element_name == "Condition")
451  {
452  ID = element->Attribute("ID");
453  }
454  else
455  {
456  ID = element_name;
457  }
458 
459  const char* attr_alias = element->Attribute("name");
460  if (attr_alias)
461  {
462  instance_name = attr_alias;
463  }
464  else
465  {
466  instance_name = ID;
467  }
468 
469  if (element_name == "SubTree")
470  {
471  instance_name = element->Attribute("ID");
472  }
473 
474  PortsRemapping remapping_parameters;
475 
476  if (element_name != "SubTree") // in Subtree attributes have different meaning...
477  {
478  for (const XMLAttribute* att = element->FirstAttribute(); att; att = att->Next())
479  {
480  const std::string attribute_name = att->Name();
481  if (attribute_name != "ID" && attribute_name != "name")
482  {
483  remapping_parameters[attribute_name] = att->Value();
484  }
485  }
486  }
487  NodeConfiguration config;
488  config.blackboard = blackboard;
489 
490  //---------------------------------------------
491  TreeNode::Ptr child_node;
492 
493  if( factory.builders().count(ID) != 0)
494  {
495  const auto& manifest = factory.manifests().at(ID);
496 
497  //Check that name in remapping can be found in the manifest
498  for(const auto& remapping_it: remapping_parameters)
499  {
500  if( manifest.ports.count( remapping_it.first ) == 0 )
501  {
502  throw RuntimeError("Possible typo? In the XML, you tried to remap port \"",
503  remapping_it.first, "\" in node [", ID," / ", instance_name,
504  "], but the manifest of this node does not contain a port with this name.");
505  }
506  }
507 
508  // Initialize the ports in the BB to set the type
509  for(const auto& port_it: manifest.ports)
510  {
511  const std::string& port_name = port_it.first;
512  const auto& port_info = port_it.second;
513 
514  auto remap_it = remapping_parameters.find(port_name);
515  if( remap_it == remapping_parameters.end())
516  {
517  continue;
518  }
519  StringView remapping_value = remap_it->second;
520  auto remapped_res = TreeNode::getRemappedKey(port_name, remapping_value);
521  if( remapped_res )
522  {
523  const auto& port_key = remapped_res.value().to_string();
524 
525  auto prev_info = blackboard->portInfo( port_key );
526  if( !prev_info )
527  {
528  // not found, insert for the first time.
529  blackboard->setPortInfo( port_key, port_info );
530  }
531  else{
532  // found. check consistency
533  if( prev_info->type() && port_info.type() && // null type means that everything is valid
534  prev_info->type()!= port_info.type())
535  {
536  blackboard->debugMessage();
537 
538  throw RuntimeError( "The creation of the tree failed because the port [", port_key,
539  "] was initially created with type [", demangle( prev_info->type() ),
540  "] and, later type [", demangle( port_info.type() ),
541  "] was used somewhere else." );
542  }
543  }
544  }
545  }
546 
547  // use manifest to initialize NodeConfiguration
548  for(const auto& remap_it: remapping_parameters)
549  {
550  const auto& port_name = remap_it.first;
551  auto port_it = manifest.ports.find( port_name );
552  if( port_it != manifest.ports.end() )
553  {
554  auto direction = port_it->second.direction();
555  if( direction != PortDirection::OUTPUT )
556  {
557  config.input_ports.insert( remap_it );
558  }
559  if( direction != PortDirection::INPUT )
560  {
561  config.output_ports.insert( remap_it );
562  }
563  }
564  }
565  // use default value if available for empty ports. Only inputs
566  for (const auto& port_it: manifest.ports)
567  {
568  const std::string& port_name = port_it.first;
569  const PortInfo& port_info = port_it.second;
570 
571  auto direction = port_info.direction();
572  if( direction != PortDirection::INPUT &&
573  config.input_ports.count(port_name) == 0 &&
574  port_info.defaultValue().empty() == false)
575  {
576  config.input_ports.insert( { port_name, port_info.defaultValue() } );
577  }
578  }
579  child_node = factory.instantiateTreeNode(instance_name, ID, config);
580  }
581  else if( tree_roots.count(ID) != 0) {
582  child_node = std::make_unique<DecoratorSubtreeNode>( instance_name );
583  }
584  else{
585  throw RuntimeError( ID, " is not a registered node, nor a Subtree");
586  }
587 
588  if (node_parent)
589  {
590  if (auto control_parent = dynamic_cast<ControlNode*>(node_parent.get()))
591  {
592  control_parent->addChild(child_node.get());
593  }
594  if (auto decorator_parent = dynamic_cast<DecoratorNode*>(node_parent.get()))
595  {
596  decorator_parent->setChild(child_node.get());
597  }
598  }
599  return child_node;
600 }
601 
602 void BT::XMLParser::Pimpl::recursivelyCreateTree(const std::string& tree_ID,
603  Tree& output_tree,
604  Blackboard::Ptr blackboard,
605  const TreeNode::Ptr& root_parent)
606 {
607  std::function<void(const TreeNode::Ptr&, const XMLElement*)> recursiveStep;
608 
609  recursiveStep = [&](const TreeNode::Ptr& parent,
610  const XMLElement* element)
611  {
612  auto node = createNodeFromXML(element, blackboard, parent);
613  output_tree.nodes.push_back(node);
614 
615  if( node->type() == NodeType::SUBTREE )
616  {
617  auto new_bb = Blackboard::create(blackboard);
618 
619  for (const XMLAttribute* attr = element->FirstAttribute(); attr != nullptr; attr = attr->Next())
620  {
621  new_bb->addSubtreeRemapping( attr->Name(), attr->Value() );
622  }
623 
624  output_tree.blackboard_stack.emplace_back(new_bb);
625  recursivelyCreateTree( node->name(), output_tree, new_bb, node );
626  }
627  else
628  {
629  for (auto child_element = element->FirstChildElement(); child_element;
630  child_element = child_element->NextSiblingElement())
631  {
632  recursiveStep(node, child_element);
633  }
634  }
635  };
636 
637  auto root_element = tree_roots[tree_ID]->FirstChildElement();
638 
639  // start recursion
640  recursiveStep(root_parent, root_element);
641 }
642 
643 
644 std::string writeTreeNodesModelXML(const BehaviorTreeFactory& factory)
645 {
646  using namespace BT_TinyXML2;
647 
649 
650  XMLElement* rootXML = doc.NewElement("root");
651  doc.InsertFirstChild(rootXML);
652 
653  XMLElement* model_root = doc.NewElement("TreeNodesModel");
654  rootXML->InsertEndChild(model_root);
655 
656  for (auto& model_it : factory.manifests())
657  {
658  const auto& registration_ID = model_it.first;
659  const auto& model = model_it.second;
660 
661  if( factory.builtinNodes().count( registration_ID ) != 0)
662  {
663  continue;
664  }
665 
666  if (model.type == NodeType::CONTROL)
667  {
668  continue;
669  }
670  XMLElement* element = doc.NewElement( toStr(model.type).c_str() );
671  element->SetAttribute("ID", model.registration_ID.c_str());
672 
673  for (auto& port : model.ports)
674  {
675  const auto& port_name = port.first;
676  const auto& port_info = port.second;
677 
678  XMLElement* port_element = nullptr;
679  switch( port_info.direction() )
680  {
681  case PortDirection::INPUT: port_element = doc.NewElement("input_port"); break;
682  case PortDirection::OUTPUT: port_element = doc.NewElement("output_port"); break;
683  case PortDirection::INOUT: port_element = doc.NewElement("inout_port"); break;
684  }
685 
686  port_element->SetAttribute("name", port_name.c_str() );
687  if( port_info.type() )
688  {
689  port_element->SetAttribute("type", BT::demangle( port_info.type() ).c_str() );
690  }
691  if( !port_info.defaultValue().empty() )
692  {
693  port_element->SetAttribute("default", port_info.defaultValue().c_str() );
694  }
695 
696  if( !port_info.description().empty() )
697  {
698  port_element->SetText( port_info.description().c_str() );
699  }
700 
701  element->InsertEndChild(port_element);
702  }
703 
704  model_root->InsertEndChild(element);
705  }
706 
707  XMLPrinter printer;
708  doc.Print(&printer);
709  return std::string(printer.CStr(), size_t(printer.CStrSize() - 1));
710 }
711 
712 Tree buildTreeFromText(const BehaviorTreeFactory& factory, const std::string& text,
713  const Blackboard::Ptr& blackboard)
714 {
715  XMLParser parser(factory);
716  parser.loadFromText(text);
717  return parser.instantiateTree(blackboard);
718 }
719 
720 Tree buildTreeFromFile(const BehaviorTreeFactory& factory, const std::string& filename,
721  const Blackboard::Ptr& blackboard)
722 {
723  XMLParser parser(factory);
724  parser.loadFromFile(filename);
725  return parser.instantiateTree(blackboard);
726 }
727 
728 }
Tree buildTreeFromText(const BehaviorTreeFactory &factory, const std::string &text, const Blackboard::Ptr &blackboard)
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1429
Pimpl(const BehaviorTreeFactory &fact)
Definition: xml_parsing.cpp:62
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:38
manifest
const XMLElement * NextSiblingElement(const char *name=0) const
Get the next (right) sibling element of this node, with an optionally supplied name.
Definition: tinyxml2.cpp:964
PortDirection direction() const
void recursivelyCreateTree(const std::string &tree_ID, Tree &output_tree, Blackboard::Ptr blackboard, const TreeNode::Ptr &root_parent)
static raw_event_t * buffer
Definition: minitrace.cpp:54
Pimpl * _p
Definition: xml_parsing.h:32
std::string toStr(T value)
Definition: basic_types.h:127
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1147
std::unordered_map< std::string, const XMLElement * > tree_roots
Definition: xml_parsing.cpp:54
filesystem::path current_path
Definition: xml_parsing.cpp:58
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:871
void loadDocImpl(BT_TinyXML2::XMLDocument *doc)
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
std::shared_ptr< Blackboard > Ptr
Definition: blackboard.h:26
const std::set< std::string > & builtinNodes() const
List of builtin IDs.
Definition: bt_factory.cpp:165
TreeNode * root_node
Definition: bt_factory.h:80
Blackboard::Ptr blackboard
Definition: tree_node.h:47
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2094
void SetText(const char *inText)
Definition: tinyxml2.cpp:1589
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2167
std::string demangle(char const *name)
Definition: demangle_util.h:78
XMLElement * RootElement()
Definition: tinyxml2.h:1747
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1819
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:98
const std::string & defaultValue() const
const char * CStr() const
Definition: tinyxml2.h:2241
std::vector< Blackboard::Ptr > blackboard_stack
Definition: bt_factory.h:82
nonstd::string_view StringView
Definition: basic_types.h:50
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2316
const BehaviorTreeFactory & factory
Definition: xml_parsing.cpp:56
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1472
XMLError Parse(const char *xml, size_t nBytes=(size_t)(-1))
Definition: tinyxml2.cpp:2285
PortsRemapping output_ports
Definition: tree_node.h:49
Tree instantiateTree(const Blackboard::Ptr &root_blackboard) override
Simple class for manipulating paths on Linux/Windows/Mac OS.
Definition: path.h:42
ROSLIB_DECL std::string getPath(const std::string &package_name)
static volatile int count
Definition: minitrace.cpp:55
const std::unordered_map< std::string, TreeNodeManifest > & manifests() const
Manifests of all the registered TreeNodes.
Definition: bt_factory.cpp:160
std::vector< TreeNode::Ptr > nodes
Definition: bt_factory.h:81
std::string writeTreeNodesModelXML(const BehaviorTreeFactory &factory)
The XMLParser is a class used to read the model of a BehaviorTree from file or text and instantiate t...
Definition: xml_parsing.h:14
int CStrSize() const
Definition: tinyxml2.h:2249
static const char * xml_text
void loadFromText(const std::string &xml_text) override
const char * ErrorName() const
Definition: tinyxml2.cpp:2375
std::list< std::unique_ptr< BT_TinyXML2::XMLDocument > > opened_documents
Definition: xml_parsing.cpp:53
XMLParser(const BehaviorTreeFactory &factory)
Definition: xml_parsing.cpp:82
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1252
std::shared_ptr< TreeNode > Ptr
Definition: tree_node.h:56
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:78
void VerifyXML(const std::string &xml_text, const std::set< std::string > &registered_nodes)
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1526
TreeNode::Ptr createNodeFromXML(const XMLElement *element, const Blackboard::Ptr &blackboard, const TreeNode::Ptr &node_parent)
void loadFromFile(const std::string &filename) override
Definition: xml_parsing.cpp:92
std::basic_string< CharT, Traits > to_string(basic_string_view< CharT, Traits > v)
PortsRemapping input_ports
Definition: tree_node.h:48
Tree buildTreeFromFile(const BehaviorTreeFactory &factory, const std::string &filename, const Blackboard::Ptr &blackboard)
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:841
static Optional< StringView > getRemappedKey(StringView port_name, StringView remapping_value)
Definition: tree_node.cpp:134
std::unordered_map< std::string, std::string > PortsRemapping
Definition: tree_node.h:39


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