Skip to content

Commit

Permalink
preserve order of ports in PortsList
Browse files Browse the repository at this point in the history
  • Loading branch information
facontidavide committed Sep 21, 2024
1 parent c9dea7b commit b1064db
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 21 deletions.
14 changes: 13 additions & 1 deletion include/behaviortree_cpp/basic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,19 @@ template <typename T = AnyTypeAllowed>

//----------

using PortsList = std::unordered_map<std::string, PortInfo>;
using PortsList = std::vector<std::pair<std::string, PortInfo>>;

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 <typename T, typename = void>
struct has_static_method_providedPorts : std::false_type
Expand Down
4 changes: 2 additions & 2 deletions include/behaviortree_cpp/controls/switch_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ inline PortsList SwitchNode<NUM_CASES>::providedPorts()
{
static PortsList provided_ports = []() {
PortsList ports;
ports.insert(BT::InputPort<std::string>("variable"));
ports.push_back(BT::InputPort<std::string>("variable"));
for(unsigned i = 1; i <= NUM_CASES; i++)
{
auto key = std::string("case_") + std::to_string(i);
ports.insert(BT::InputPort<std::string>(key));
ports.push_back(BT::InputPort<std::string>(key));
}
return ports;
}();
Expand Down
16 changes: 8 additions & 8 deletions include/behaviortree_cpp/tree_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,30 +455,29 @@ inline Expected<Timestamp> 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<std::string>();
port_value_str = port_info->defaultValue().cast<std::string>();
}
else
{
destination = port_info.defaultValue().cast<T>();
destination = port_info->defaultValue().cast<T>();
return Timestamp{};
}
}
Expand Down Expand Up @@ -585,7 +584,8 @@ inline Result TreeNode::setOutput(const std::string& key, const T& value)

if constexpr(std::is_same_v<BT::Any, T>)
{
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<Any> is not allowed, unless the port "
"was declared using OutputPort<Any>");
Expand Down
19 changes: 9 additions & 10 deletions src/xml_parsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,31 +663,30 @@ 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 "
"providedPorts()"));
}
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);
}
}
Expand Down Expand Up @@ -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 ",
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit b1064db

Please sign in to comment.