17#include "behaviortree_cpp/xml_parsing.h"
26 doc_.Parse(
"<root BTCPP_format=\"4\"></root>");
33 for (
const auto& [node_name, params] : node_manifest.
getInternalMap())
36 if (registered_nodes.find(node_name) != registered_nodes.end())
40 factory_ptr_->unregisterBuilder(node_name);
45 "' is already registered. Set override = true to allow for "
46 "overriding previously registered nodes.");
51 if (!tree_node_loader.isClassAvailable(params.class_name))
54 ")' cannot be loaded, because the class name is not known to the class loader. "
55 "Make sure that it's spelled correctly and registered by calling "
56 "auto_apms_behavior_tree_register_nodes() in the CMakeLists.txt of the "
57 "corresponding package.");
60 RCLCPP_DEBUG(node_ptr->get_logger(),
"Loading behavior tree node '%s' (Class: %s) from library %s.",
61 node_name.c_str(), params.class_name.c_str(),
62 tree_node_loader.getClassLibraryPath(params.class_name).c_str());
64 pluginlib::UniquePtr<NodeRegistrationInterface> plugin_instance;
67 plugin_instance = tree_node_loader.createUniqueInstance(params.class_name);
69 catch (
const std::exception& e)
72 " (Class: " + params.class_name +
73 ")'. Remember that the AUTO_APMS_BEHAVIOR_TREE_REGISTER_NODE "
74 "macro must be called in the source file for the node class to be discoverable. "
81 if (plugin_instance->requiresROSNodeParams())
84 plugin_instance->registerWithBehaviorTreeFactory(*factory_ptr_, node_name, &ros_node_context);
88 plugin_instance->registerWithBehaviorTreeFactory(*factory_ptr_, node_name);
91 catch (
const std::exception& e)
94 ")': " + e.what() +
".");
110 auto other_root = doc.RootElement();
113 if (
const auto name = other_root->Attribute(MAIN_TREE_ATTRIBUTE_NAME.c_str()))
120 std::vector<std::string> same_names;
121 std::set_intersection(this_tree_names.begin(), this_tree_names.end(), other_tree_names.begin(),
122 other_tree_names.end(), std::inserter(same_names, same_names.begin()));
123 if (!same_names.empty())
125 std::ostringstream oss;
126 std::copy(same_names.begin(), same_names.end() - 1, std::ostream_iterator<std::string>(oss,
", "));
127 oss << same_names.back();
129 "Cannot merge tree document: The following trees are already defined: " + oss.str() +
".");
133 auto this_root = doc_.RootElement();
134 for (
const tinyxml2::XMLElement* child = other_root->FirstChildElement(); child !=
nullptr;
135 child = child->NextSiblingElement())
138 auto copied_child = child->DeepClone(&doc_);
140 this_root->InsertEndChild(copied_child);
148 catch (
const BT::RuntimeError& e)
157 tinyxml2::XMLDocument new_doc;
158 if (new_doc.Parse(tree_str.c_str()) != tinyxml2::XMLError::XML_SUCCESS)
167 tinyxml2::XMLDocument new_doc;
168 if (new_doc.LoadFile(tree_file_path.c_str()) != tinyxml2::XMLError::XML_SUCCESS)
183 if (
const auto main_tree_name = doc_.RootElement()->Attribute(MAIN_TREE_ATTRIBUTE_NAME.c_str()))
184 return main_tree_name;
190 if (!main_tree_name.empty())
191 doc_.RootElement()->SetAttribute(MAIN_TREE_ATTRIBUTE_NAME.c_str(), main_tree_name.c_str());
202 std::unordered_map<std::string, BT::NodeType> registered_nodes;
203 for (
const auto& it : factory_ptr_->manifests())
204 registered_nodes.insert({ it.first, it.second.type });
205 return registered_nodes;
216 factory_ptr_->clearRegisteredBehaviorTrees();
218 catch (
const std::exception& e)
232 std::set<std::string> names;
233 if (
const auto root = doc.RootElement())
235 for (
const tinyxml2::XMLElement* child = root->FirstChildElement(); child !=
nullptr;
236 child = child->NextSiblingElement())
238 if (TREE_ELEMENT_NAME.compare(child->Name()) == 0)
240 if (
const auto name = child->Attribute(TREE_ID_ATTRIBUTE_NAME.c_str()))
247 TREE_ID_ATTRIBUTE_NAME +
"' is missing.");
257 tinyxml2::XMLPrinter printer;
259 return printer.CStr();
Data structure for resource lookup data and configuration parameters required for loading and registe...
static NodeManifest fromFile(const std::string &file_path)
Create a node plugin manifest from a file.
const ParamMap & getInternalMap() const
Version of pluginlib::ClassLoader specifically for loading installed behavior tree node plugins.
Class for creating behavior trees according to the builder design pattern.
TreeBuilder & addTreeFromString(const std::string &tree_str)
TreeBuilder(std::shared_ptr< BT::BehaviorTreeFactory > factory_ptr=std::make_shared< BT::BehaviorTreeFactory >())
TreeBuilder & addTreeFromFile(const std::string &tree_file_path)
static std::set< std::string > getTreeNames(const tinyxml2::XMLDocument &doc)
std::unordered_map< std::string, BT::NodeType > getRegisteredNodes()
TreeBuilder & addTreeFromResource(const TreeResource &resource, rclcpp::Node::SharedPtr node_ptr)
std::string writeTreeXMLToString() const
static std::string writeXMLDocumentToString(const tinyxml2::XMLDocument &doc)
TreeBuilder & addTreeFromXMLDocument(const tinyxml2::XMLDocument &doc)
TreeBuilder & setMainTreeName(const std::string &main_tree_name)
TreeBuilder & registerNodePlugins(rclcpp::Node::SharedPtr node_ptr, const NodeManifest &node_manifest, NodePluginClassLoader &tree_node_loader, bool override=false)
Load behavior tree node plugins and register with behavior tree factory.
Tree buildTree(const std::string main_tree_name, TreeBlackboardSharedPtr root_bb_ptr=TreeBlackboard::create())
std::string getMainTreeName() const
std::shared_ptr< TreeBlackboard > TreeBlackboardSharedPtr
Struct containing behavior tree resource data.
std::string node_manifest_file_path
std::string tree_file_path