Skip to content

Commit f54e000

Browse files
committed
add NodeConfig::other_attributes
1 parent 6c958bd commit f54e000

File tree

6 files changed

+79
-34
lines changed

6 files changed

+79
-34
lines changed

include/behaviortree_cpp/basic_types.h

+2
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ struct Timestamp
342342

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

345+
[[nodiscard]] bool IsReservedAttribute(StringView str);
346+
345347
class TypeInfo
346348
{
347349
public:

include/behaviortree_cpp/tree_node.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct TreeNodeManifest
4141
};
4242

4343
using PortsRemapping = std::unordered_map<std::string, std::string>;
44+
using NonPortAttributes = std::unordered_map<std::string, std::string>;
4445

4546
enum class PreCond
4647
{
@@ -52,6 +53,10 @@ enum class PreCond
5253
COUNT_
5354
};
5455

56+
static const std::array<std::string, 4> PreCondNames = { //
57+
"_failureIf", "_successIf", "_skipIf", "_while"
58+
};
59+
5560
enum class PostCond
5661
{
5762
// order of the enums also tell us the execution order
@@ -62,11 +67,15 @@ enum class PostCond
6267
COUNT_
6368
};
6469

70+
static const std::array<std::string, 4> PostCondNames = { //
71+
"_onHalted", "_onFailure", "_onSuccess", "_post"
72+
};
73+
6574
template <>
66-
[[nodiscard]] std::string toStr<BT::PostCond>(const BT::PostCond& status);
75+
[[nodiscard]] std::string toStr<BT::PostCond>(const BT::PostCond& cond);
6776

6877
template <>
69-
[[nodiscard]] std::string toStr<BT::PreCond>(const BT::PreCond& status);
78+
[[nodiscard]] std::string toStr<BT::PreCond>(const BT::PreCond& cond);
7079

7180
using ScriptingEnumsRegistry = std::unordered_map<std::string, int>;
7281

@@ -84,6 +93,10 @@ struct NodeConfig
8493
// output ports
8594
PortsRemapping output_ports;
8695

96+
// Any other attributes found in the xml that are not parsed as ports
97+
// or built-in identifier (e.g. anything with a leading '_')
98+
NonPortAttributes other_attributes;
99+
87100
const TreeNodeManifest* manifest = nullptr;
88101

89102
// Numberic unique identifier

src/basic_types.cpp

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "behaviortree_cpp/basic_types.h"
2+
#include "behaviortree_cpp/tree_node.h"
23
#include "behaviortree_cpp/json_export.h"
34

45
#include <cstdlib>
@@ -420,10 +421,6 @@ const std::string& PortInfo::defaultValueString() const
420421

421422
bool IsAllowedPortName(StringView str)
422423
{
423-
if(str == "_autoremap")
424-
{
425-
return true;
426-
}
427424
if(str.empty())
428425
{
429426
return false;
@@ -433,11 +430,26 @@ bool IsAllowedPortName(StringView str)
433430
{
434431
return false;
435432
}
436-
if(str == "name" || str == "ID")
433+
return !IsReservedAttribute(str);
434+
}
435+
436+
bool IsReservedAttribute(StringView str)
437+
{
438+
for(const auto& name : PreCondNames)
437439
{
438-
return false;
440+
if(name == str)
441+
{
442+
return false;
443+
}
444+
}
445+
for(const auto& name : PostCondNames)
446+
{
447+
if(name == str)
448+
{
449+
return false;
450+
}
439451
}
440-
return true;
452+
return str == "name" || str == "ID" || str == "_autoremap";
441453
}
442454

443455
Any convertFromJSON(StringView json_text, std::type_index type)

src/tree_node.cpp

+8-24
Original file line numberDiff line numberDiff line change
@@ -464,39 +464,23 @@ void TreeNode::modifyPortsRemapping(const PortsRemapping& new_remapping)
464464
}
465465

466466
template <>
467-
std::string toStr<PreCond>(const PreCond& pre)
467+
std::string toStr<PreCond>(const PreCond& cond)
468468
{
469-
switch(pre)
469+
if(cond < PreCond::COUNT_)
470470
{
471-
case PreCond::SUCCESS_IF:
472-
return "_successIf";
473-
case PreCond::FAILURE_IF:
474-
return "_failureIf";
475-
case PreCond::SKIP_IF:
476-
return "_skipIf";
477-
case PreCond::WHILE_TRUE:
478-
return "_while";
479-
default:
480-
return "Undefined";
471+
return BT::PreCondNames[static_cast<size_t>(cond)];
481472
}
473+
return "Undefined";
482474
}
483475

484476
template <>
485-
std::string toStr<PostCond>(const PostCond& pre)
477+
std::string toStr<PostCond>(const PostCond& cond)
486478
{
487-
switch(pre)
479+
if(cond < BT::PostCond::COUNT_)
488480
{
489-
case PostCond::ON_SUCCESS:
490-
return "_onSuccess";
491-
case PostCond::ON_FAILURE:
492-
return "_onFailure";
493-
case PostCond::ALWAYS:
494-
return "_post";
495-
case PostCond::ON_HALTED:
496-
return "_onHalted";
497-
default:
498-
return "Undefined";
481+
return BT::PostCondNames[static_cast<size_t>(cond)];
499482
}
483+
return "Undefined";
500484
}
501485

502486
AnyPtrLocked BT::TreeNode::getLockedPortContent(const std::string& key)

src/xml_parsing.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <sstream>
1919
#include <string>
2020
#include <typeindex>
21+
#include "behaviortree_cpp/basic_types.h"
2122

2223
#if defined(_MSVC_LANG) && !defined(__clang__)
2324
#define __bt_cplusplus (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
@@ -677,9 +678,13 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
677678
}
678679

679680
PortsRemapping port_remap;
681+
NonPortAttributes other_attributes;
682+
680683
for(const XMLAttribute* att = element->FirstAttribute(); att; att = att->Next())
681684
{
682-
if(IsAllowedPortName(att->Name()))
685+
const std::string port_name = att->Name();
686+
const std::string port_value = att->Value();
687+
if(IsAllowedPortName(port_name))
683688
{
684689
const std::string port_name = att->Name();
685690
const std::string port_value = att->Value();
@@ -721,6 +726,10 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
721726

722727
port_remap[port_name] = port_value;
723728
}
729+
else if(!IsReservedAttribute(port_name))
730+
{
731+
other_attributes[port_name] = port_value;
732+
}
724733
}
725734

726735
NodeConfig config;

tests/gtest_ports.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <gtest/gtest.h>
2+
#include "behaviortree_cpp/basic_types.h"
23
#include "behaviortree_cpp/bt_factory.h"
34
#include "behaviortree_cpp/xml_parsing.h"
45
#include "behaviortree_cpp/json_export.h"
@@ -129,6 +130,30 @@ TEST(PortTest, Descriptions)
129130
ASSERT_EQ(status, NodeStatus::FAILURE); // failure because in_port_B="99"
130131
}
131132

133+
TEST(PortsTest, NonPorts)
134+
{
135+
std::string xml_txt =
136+
R"(
137+
<root BTCPP_format="4" >
138+
<BehaviorTree ID="MainTree">
139+
<Action ID="NodeWithPorts" name="NodeWithPortsName" in_port_B="66" _not_da_port="whateva" _skipIf="true" />
140+
</BehaviorTree>
141+
</root>)";
142+
143+
BehaviorTreeFactory factory;
144+
factory.registerNodeType<NodeWithPorts>("NodeWithPorts");
145+
146+
auto tree = factory.createTreeFromText(xml_txt);
147+
148+
const TreeNode* root = tree.rootNode();
149+
ASSERT_NE(root, nullptr);
150+
ASSERT_EQ(root->type(), NodeType::ACTION);
151+
152+
EXPECT_EQ(root->config().other_attributes.size(), 1);
153+
ASSERT_TRUE(root->config().other_attributes.contains("_not_da_port"));
154+
EXPECT_EQ(root->config().other_attributes.at("_not_da_port"), "whateva");
155+
}
156+
132157
struct MyType
133158
{
134159
std::string value;

0 commit comments

Comments
 (0)