From 7f02c44dbf04bad8bd3dab0ac90e97a6e19f7baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20=C3=89corchard?= Date: Mon, 17 Mar 2025 10:33:46 +0100 Subject: [PATCH] Return the tree ID when registering a file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return the attribute "main_tree_to_execute" or the ID of the single behavior-tree. Signed-off-by: Gaël Écorchard --- include/behaviortree_cpp/bt_factory.h | 10 ++++++--- include/behaviortree_cpp/bt_parser.h | 9 +++++--- include/behaviortree_cpp/xml_parsing.h | 8 ++++--- src/bt_factory.cpp | 10 ++++----- src/xml_parsing.cpp | 30 ++++++++++++++++++++------ 5 files changed, 47 insertions(+), 20 deletions(-) diff --git a/include/behaviortree_cpp/bt_factory.h b/include/behaviortree_cpp/bt_factory.h index c20385b3b..c96829fb4 100644 --- a/include/behaviortree_cpp/bt_factory.h +++ b/include/behaviortree_cpp/bt_factory.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "behaviortree_cpp/contrib/magic_enum.hpp" @@ -290,14 +291,17 @@ class BehaviorTreeFactory * * BehaviorTreeFactory::createTree(tree_id) * - * where "tree_id" come from the XML attribute + * where "tree_id" come from the XML attribute . + * + * Return the attribute `main_tree_to_execute` if specified or if the file + * defines a single SubTree, or an empty string otherwise. * */ - void registerBehaviorTreeFromFile(const std::filesystem::path& filename); + std::string registerBehaviorTreeFromFile(const std::filesystem::path& filename); /// Same of registerBehaviorTreeFromFile, but passing the XML text, /// instead of the filename. - void registerBehaviorTreeFromText(const std::string& xml_text); + std::string registerBehaviorTreeFromText(const std::string& xml_text); /// Returns the ID of the trees registered either with /// registerBehaviorTreeFromFile or registerBehaviorTreeFromText. diff --git a/include/behaviortree_cpp/bt_parser.h b/include/behaviortree_cpp/bt_parser.h index 3b6bcb637..1dfc5261f 100644 --- a/include/behaviortree_cpp/bt_parser.h +++ b/include/behaviortree_cpp/bt_parser.h @@ -13,6 +13,8 @@ #pragma once #include +#include + #include "behaviortree_cpp/bt_factory.h" #include "behaviortree_cpp/blackboard.h" @@ -36,10 +38,11 @@ class Parser Parser(Parser&& other) = default; Parser& operator=(Parser&& other) = default; - virtual void loadFromFile(const std::filesystem::path& filename, - bool add_includes = true) = 0; + virtual std::string loadFromFile(const std::filesystem::path& filename, + bool add_includes = true) = 0; - virtual void loadFromText(const std::string& xml_text, bool add_includes = true) = 0; + virtual std::string loadFromText(const std::string& xml_text, + bool add_includes = true) = 0; virtual std::vector registeredBehaviorTrees() const = 0; diff --git a/include/behaviortree_cpp/xml_parsing.h b/include/behaviortree_cpp/xml_parsing.h index d815ef85b..80b7a18f8 100644 --- a/include/behaviortree_cpp/xml_parsing.h +++ b/include/behaviortree_cpp/xml_parsing.h @@ -4,6 +4,7 @@ #include "behaviortree_cpp/bt_parser.h" #include +#include #include namespace BT @@ -26,10 +27,11 @@ class XMLParser : public Parser XMLParser(XMLParser&& other) noexcept; XMLParser& operator=(XMLParser&& other) noexcept; - void loadFromFile(const std::filesystem::path& filename, - bool add_includes = true) override; + std::string loadFromFile(const std::filesystem::path& filename, + bool add_includes = true) override; - void loadFromText(const std::string& xml_text, bool add_includes = true) override; + std::string loadFromText(const std::string& xml_text, + bool add_includes = true) override; [[nodiscard]] std::vector registeredBehaviorTrees() const override; diff --git a/src/bt_factory.cpp b/src/bt_factory.cpp index f66c3661f..efe5bc029 100644 --- a/src/bt_factory.cpp +++ b/src/bt_factory.cpp @@ -257,15 +257,15 @@ void BehaviorTreeFactory::registerFromROSPlugins() } #endif -void BehaviorTreeFactory::registerBehaviorTreeFromFile( - const std::filesystem::path& filename) +std::string +BehaviorTreeFactory::registerBehaviorTreeFromFile(const std::filesystem::path& filename) { - _p->parser->loadFromFile(filename); + return _p->parser->loadFromFile(filename); } -void BehaviorTreeFactory::registerBehaviorTreeFromText(const std::string& xml_text) +std::string BehaviorTreeFactory::registerBehaviorTreeFromText(const std::string& xml_text) { - _p->parser->loadFromText(xml_text); + return _p->parser->loadFromText(xml_text); } std::vector BehaviorTreeFactory::registeredBehaviorTrees() const diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index 885244ed9..0fa1d6801 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -107,7 +107,7 @@ struct XMLParser::PImpl void getPortsRecursively(const XMLElement* element, std::vector& output_ports); - void loadDocImpl(XMLDocument* doc, bool add_includes); + std::string loadDocImpl(XMLDocument* doc, bool add_includes); std::list > opened_documents; std::map tree_roots; @@ -156,7 +156,8 @@ XMLParser& XMLParser::operator=(XMLParser&& other) noexcept XMLParser::~XMLParser() {} -void XMLParser::loadFromFile(const std::filesystem::path& filepath, bool add_includes) +std::string XMLParser::loadFromFile(const std::filesystem::path& filepath, + bool add_includes) { _p->opened_documents.emplace_back(new XMLDocument()); @@ -165,17 +166,17 @@ void XMLParser::loadFromFile(const std::filesystem::path& filepath, bool add_inc _p->current_path = std::filesystem::absolute(filepath.parent_path()); - _p->loadDocImpl(doc, add_includes); + return _p->loadDocImpl(doc, add_includes); } -void XMLParser::loadFromText(const std::string& xml_text, bool add_includes) +std::string XMLParser::loadFromText(const std::string& xml_text, bool add_includes) { _p->opened_documents.emplace_back(new XMLDocument()); XMLDocument* doc = _p->opened_documents.back().get(); doc->Parse(xml_text.c_str(), xml_text.size()); - _p->loadDocImpl(doc, add_includes); + return _p->loadDocImpl(doc, add_includes); } std::vector XMLParser::registeredBehaviorTrees() const @@ -232,7 +233,7 @@ void BT::XMLParser::PImpl::loadSubtreeModel(const XMLElement* xml_root) } } -void XMLParser::PImpl::loadDocImpl(XMLDocument* doc, bool add_includes) +std::string XMLParser::PImpl::loadDocImpl(XMLDocument* doc, bool add_includes) { if(doc->Error()) { @@ -348,6 +349,23 @@ void XMLParser::PImpl::loadDocImpl(XMLDocument* doc, bool add_includes) tree_roots[tree_name] = bt_node; } + + // Get the name of the tree to run (either explicit or single tree). + std::string main_tree_to_execute; + if(const auto main_tree_attribute = xml_root->Attribute("main_tree_to_execute")) + { + main_tree_to_execute = main_tree_attribute; + } + else if(xml_root->FirstChild() == xml_root->LastChild()) + { + // special case: there is only one registered BT. + const auto& e = xml_root->FirstChildElement(); + if(e->FindAttribute("ID")) + { + main_tree_to_execute = e->Attribute("ID"); + } + } + return main_tree_to_execute; } void VerifyXML(const std::string& xml_text,