Skip to content

Commit

Permalink
Merge pull request #4 from PickNikRobotics/non-port-fields
Browse files Browse the repository at this point in the history
Adds "Other Attributes" to a Tree Node's configuration with contains non-port fields
  • Loading branch information
dsobek authored Dec 30, 2024
2 parents 9336ead + 60b0964 commit 05c0777
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 9 deletions.
2 changes: 2 additions & 0 deletions include/behaviortree_cpp/basic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ struct Timestamp

[[nodiscard]] bool IsAllowedPortName(StringView str);

[[nodiscard]] bool IsNodeNameAttribute(StringView str);

class TypeInfo
{
public:
Expand Down
4 changes: 4 additions & 0 deletions include/behaviortree_cpp/tree_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct TreeNodeManifest
};

using PortsRemapping = std::unordered_map<std::string, std::string>;
using OtherAttributes = std::unordered_map<std::string, std::string>;

enum class PreCond
{
Expand Down Expand Up @@ -83,6 +84,9 @@ struct NodeConfig
// output ports
PortsRemapping output_ports;

// Any other attributes found in the xml that are not parsed as ports (e.g. anything with a leading '_')
OtherAttributes other_attributes;

const TreeNodeManifest* manifest = nullptr;

// Numberic unique identifier
Expand Down
11 changes: 6 additions & 5 deletions src/basic_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,12 @@ bool IsAllowedPortName(StringView str)
{
return false;
}
if(str == "name" || str == "ID")
{
return false;
}
return true;
return !IsNodeNameAttribute(str);
}

bool IsNodeNameAttribute(StringView str)
{
return str == "name" || str == "ID";
}

Any convertFromJSON(StringView json_text, std::type_index type)
Expand Down
15 changes: 11 additions & 4 deletions src/xml_parsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <sstream>
#include <string>
#include <typeindex>
#include "behaviortree_cpp/basic_types.h"

#if defined(_MSVC_LANG) && !defined(__clang__)
#define __bt_cplusplus (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
Expand Down Expand Up @@ -654,13 +655,13 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
}

PortsRemapping port_remap;
OtherAttributes other_attributes;
for(const XMLAttribute* att = element->FirstAttribute(); att; att = att->Next())
{
if(IsAllowedPortName(att->Name()))
const std::string port_name = att->Name();
const std::string port_value = att->Value();
if(IsAllowedPortName(port_name))
{
const std::string port_name = att->Name();
const std::string port_value = att->Value();

if(manifest)
{
auto port_model_it = manifest->ports.find(port_name);
Expand Down Expand Up @@ -696,6 +697,10 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,

port_remap[port_name] = port_value;
}
else if(!IsNodeNameAttribute(port_name))
{
other_attributes[port_name] = port_value;
}
}

NodeConfig config;
Expand All @@ -713,6 +718,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
if(auto script = element->Attribute(attr_name))
{
conditions.insert({ ID, std::string(script) });
other_attributes.erase(attr_name);
}
};

Expand All @@ -727,6 +733,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
AddCondition(config.post_conditions, toStr(post).c_str(), post);
}

config.other_attributes = other_attributes;
//---------------------------------------------
TreeNode::Ptr new_node;

Expand Down
25 changes: 25 additions & 0 deletions tests/gtest_ports.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <gtest/gtest.h>
#include "behaviortree_cpp/basic_types.h"
#include "behaviortree_cpp/bt_factory.h"
#include "behaviortree_cpp/xml_parsing.h"
#include "behaviortree_cpp/json_export.h"
Expand Down Expand Up @@ -129,6 +130,30 @@ TEST(PortTest, Descriptions)
ASSERT_EQ(status, NodeStatus::FAILURE); // failure because in_port_B="99"
}

TEST(PortsTest, NonPorts)
{
std::string xml_txt =
R"(
<root BTCPP_format="4" >
<BehaviorTree ID="MainTree">
<Action ID="NodeWithPorts" name="NodeWithPortsName" in_port_B="66" _not_da_port="whateva" _skipIf="true" />
</BehaviorTree>
</root>)";

BehaviorTreeFactory factory;
factory.registerNodeType<NodeWithPorts>("NodeWithPorts");

auto tree = factory.createTreeFromText(xml_txt);

const TreeNode* root = tree.rootNode();
ASSERT_NE(root, nullptr);
ASSERT_EQ(root->type(), NodeType::ACTION);

EXPECT_EQ(root->config().other_attributes.size(), 1);
ASSERT_TRUE(root->config().other_attributes.contains("_not_da_port"));
EXPECT_EQ(root->config().other_attributes.at("_not_da_port"), "whateva");
}

struct MyType
{
std::string value;
Expand Down

0 comments on commit 05c0777

Please sign in to comment.