From b1064db503573ca00c185d68df460b63d3a05265 Mon Sep 17 00:00:00 2001 From: Davide Faconti Date: Sat, 21 Sep 2024 12:35:54 +0200 Subject: [PATCH] preserve order of ports in PortsList --- include/behaviortree_cpp/basic_types.h | 14 +++++++++++++- .../behaviortree_cpp/controls/switch_node.h | 4 ++-- include/behaviortree_cpp/tree_node.h | 16 ++++++++-------- src/xml_parsing.cpp | 19 +++++++++---------- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/include/behaviortree_cpp/basic_types.h b/include/behaviortree_cpp/basic_types.h index 244f4b2a3..64c448a5e 100644 --- a/include/behaviortree_cpp/basic_types.h +++ b/include/behaviortree_cpp/basic_types.h @@ -582,7 +582,19 @@ template //---------- -using PortsList = std::unordered_map; +using PortsList = std::vector>; + +inline const PortInfo* findPortInfo(const PortsList& ports, const std::string& key) +{ + for(auto& it : ports) + { + if(it.first == key) + { + return &it.second; + } + } + return nullptr; +} template struct has_static_method_providedPorts : std::false_type diff --git a/include/behaviortree_cpp/controls/switch_node.h b/include/behaviortree_cpp/controls/switch_node.h index 7ffb989a2..ba3d6a382 100644 --- a/include/behaviortree_cpp/controls/switch_node.h +++ b/include/behaviortree_cpp/controls/switch_node.h @@ -91,11 +91,11 @@ inline PortsList SwitchNode::providedPorts() { static PortsList provided_ports = []() { PortsList ports; - ports.insert(BT::InputPort("variable")); + ports.push_back(BT::InputPort("variable")); for(unsigned i = 1; i <= NUM_CASES; i++) { auto key = std::string("case_") + std::to_string(i); - ports.insert(BT::InputPort(key)); + ports.push_back(BT::InputPort(key)); } return ports; }(); diff --git a/include/behaviortree_cpp/tree_node.h b/include/behaviortree_cpp/tree_node.h index 537176519..51917c1f3 100644 --- a/include/behaviortree_cpp/tree_node.h +++ b/include/behaviortree_cpp/tree_node.h @@ -455,30 +455,29 @@ inline Expected TreeNode::getInputStamped(const std::string& key, else { // maybe it is declared with a default value in the manifest - auto port_manifest_it = config().manifest->ports.find(key); - if(port_manifest_it == config().manifest->ports.end()) + const auto* port_info = findPortInfo(config().manifest->ports, key); + if(!port_info) { return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(), "' failed because the manifest doesn't " "contain the key: [", key, "]")); } - const auto& port_info = port_manifest_it->second; // there is a default value - if(port_info.defaultValue().empty()) + if(port_info->defaultValue().empty()) { return nonstd::make_unexpected(StrCat("getInput() of node '", fullPath(), "' failed because nor the manifest or the " "XML contain the key: [", key, "]")); } - if(port_info.defaultValue().isString()) + if(port_info->defaultValue().isString()) { - port_value_str = port_info.defaultValue().cast(); + port_value_str = port_info->defaultValue().cast(); } else { - destination = port_info.defaultValue().cast(); + destination = port_info->defaultValue().cast(); return Timestamp{}; } } @@ -585,7 +584,8 @@ inline Result TreeNode::setOutput(const std::string& key, const T& value) if constexpr(std::is_same_v) { - if(config().manifest->ports.at(key).type() != typeid(BT::Any)) + const auto* port_info = findPortInfo(config().manifest->ports, key); + if(port_info && port_info->type() != typeid(BT::Any)) { throw LogicError("setOutput is not allowed, unless the port " "was declared using OutputPort"); diff --git a/src/xml_parsing.cpp b/src/xml_parsing.cpp index 2e950e4d9..16f7b6f3c 100644 --- a/src/xml_parsing.cpp +++ b/src/xml_parsing.cpp @@ -663,8 +663,8 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element, if(manifest) { - auto port_model_it = manifest->ports.find(port_name); - if(port_model_it == manifest->ports.end()) + const auto* port_model = findPortInfo(manifest->ports, port_name); + if(!port_model) { throw RuntimeError(StrCat("a port with name [", port_name, "] is found in the XML, but not in the " @@ -672,22 +672,21 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element, } else { - const auto& port_model = port_model_it->second; bool is_blacbkboard = port_value.size() >= 3 && port_value.front() == '{' && port_value.back() == '}'; // let's test already if conversion is possible - if(!is_blacbkboard && port_model.converter() && port_model.isStronglyTyped()) + if(!is_blacbkboard && port_model->converter() && port_model->isStronglyTyped()) { // This may throw try { - port_model.converter()(port_value); + port_model->converter()(port_value); } catch(std::exception& ex) { auto msg = StrCat("The port with name \"", port_name, "\" and value \"", port_value, "\" can not be converted to ", - port_model.typeName()); + port_model->typeName()); throw LogicError(msg); } } @@ -750,7 +749,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element, //Check that name in remapping can be found in the manifest for(const auto& [name_in_subtree, _] : port_remap) { - if(manifest->ports.count(name_in_subtree) == 0) + if(!findPortInfo(manifest->ports, name_in_subtree)) { throw RuntimeError("Possible typo? In the XML, you tried to remap port \"", name_in_subtree, "\" in node [", config.path, "(type ", @@ -809,10 +808,10 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element, for(const auto& remap_it : port_remap) { const auto& port_name = remap_it.first; - auto port_it = manifest->ports.find(port_name); - if(port_it != manifest->ports.end()) + const auto* port_info = findPortInfo(manifest->ports, port_name); + if(port_info != nullptr) { - auto direction = port_it->second.direction(); + auto direction = port_info->direction(); if(direction != PortDirection::OUTPUT) { config.input_ports.insert(remap_it);