Skip to content

Commit 42f5ce2

Browse files
Merge branch 'master' into master
2 parents 9dc3e8a + 48f6c5b commit 42f5ce2

File tree

8 files changed

+87
-40
lines changed

8 files changed

+87
-40
lines changed

Doxyfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ PROJECT_LOGO =
5858
# entered, it will be relative to the location where doxygen was started. If
5959
# left blank the current directory will be used.
6060

61-
OUTPUT_DIRECTORY = /home/davide.faconti/ws_behavior_tree/src/Behavior-Tree/doc
61+
OUTPUT_DIRECTORY = ./doc
6262

6363
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
6464
# directories (in 2 levels) under the output directory of each output format and
@@ -781,7 +781,7 @@ WARN_LOGFILE =
781781
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
782782
# Note: If this tag is empty the current directory is searched.
783783

784-
INPUT = /home/davide.faconti/ws_behavior_tree/src/Behavior-Tree/include
784+
INPUT = ./include
785785

786786
# This tag can be used to specify the character encoding of the source files
787787
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -863,8 +863,8 @@ RECURSIVE = YES
863863
# Note that relative paths are relative to the directory from which doxygen is
864864
# run.
865865

866-
EXCLUDE = /home/davide.faconti/ws_behavior_tree/src/Behavior-Tree/3rdparty \
867-
/home/davide.faconti/ws_behavior_tree/src/Behavior-Tree/gtest
866+
EXCLUDE = ./3rdparty \
867+
./gtest
868868

869869
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
870870
# directories that are symbolic links (a Unix file system feature) are excluded

include/behaviortree_cpp/basic_types.h

Lines changed: 2 additions & 0 deletions
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

Lines changed: 15 additions & 2 deletions
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
{
@@ -53,6 +54,10 @@ enum class PreCond
5354
COUNT_
5455
};
5556

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

71+
static const std::array<std::string, 4> PostCondNames = { //
72+
"_onHalted", "_onFailure", "_onSuccess", "_post"
73+
};
74+
6675
template <>
67-
[[nodiscard]] std::string toStr<BT::PostCond>(const BT::PostCond& status);
76+
[[nodiscard]] std::string toStr<BT::PostCond>(const BT::PostCond& cond);
6877

6978
template <>
70-
[[nodiscard]] std::string toStr<BT::PreCond>(const BT::PreCond& status);
79+
[[nodiscard]] std::string toStr<BT::PreCond>(const BT::PreCond& cond);
7180

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

@@ -85,6 +94,10 @@ struct NodeConfig
8594
// output ports
8695
PortsRemapping output_ports;
8796

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

90103
// Numberic unique identifier

src/basic_types.cpp

Lines changed: 19 additions & 7 deletions
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 true;
443+
}
444+
}
445+
for(const auto& name : PostCondNames)
446+
{
447+
if(name == str)
448+
{
449+
return true;
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/decorators/retry_node.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ NodeStatus RetryNode::tick()
6767

6868
case NodeStatus::FAILURE: {
6969
try_count_++;
70+
// Refresh max_attempts_ in case it changed in one of the child nodes
71+
getInput(NUM_ATTEMPTS, max_attempts_);
7072
do_loop = try_count_ < max_attempts_ || max_attempts_ == -1;
7173

7274
resetChild();

src/tree_node.cpp

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -468,41 +468,23 @@ void TreeNode::modifyPortsRemapping(const PortsRemapping& new_remapping)
468468
}
469469

470470
template <>
471-
std::string toStr<PreCond>(const PreCond& pre)
471+
std::string toStr<PreCond>(const PreCond& cond)
472472
{
473-
switch(pre)
473+
if(cond < PreCond::COUNT_)
474474
{
475-
case PreCond::SUCCESS_IF:
476-
return "_successIf";
477-
case PreCond::FAILURE_IF:
478-
return "_failureIf";
479-
case PreCond::SKIP_IF:
480-
return "_skipIf";
481-
case PreCond::WHILE_TRUE:
482-
return "_while";
483-
case PreCond::ON_START:
484-
return "_onStart";
485-
default:
486-
return "Undefined";
475+
return BT::PreCondNames[static_cast<size_t>(cond)];
487476
}
477+
return "Undefined";
488478
}
489479

490480
template <>
491-
std::string toStr<PostCond>(const PostCond& pre)
481+
std::string toStr<PostCond>(const PostCond& cond)
492482
{
493-
switch(pre)
483+
if(cond < BT::PostCond::COUNT_)
494484
{
495-
case PostCond::ON_SUCCESS:
496-
return "_onSuccess";
497-
case PostCond::ON_FAILURE:
498-
return "_onFailure";
499-
case PostCond::ALWAYS:
500-
return "_post";
501-
case PostCond::ON_HALTED:
502-
return "_onHalted";
503-
default:
504-
return "Undefined";
485+
return BT::PostCondNames[static_cast<size_t>(cond)];
505486
}
487+
return "Undefined";
506488
}
507489

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

src/xml_parsing.cpp

Lines changed: 12 additions & 1 deletion
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;
@@ -738,6 +747,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
738747
if(auto script = element->Attribute(attr_name))
739748
{
740749
conditions.insert({ ID, std::string(script) });
750+
other_attributes.erase(attr_name);
741751
}
742752
};
743753

@@ -752,6 +762,7 @@ TreeNode::Ptr XMLParser::PImpl::createNodeFromXML(const XMLElement* element,
752762
AddCondition(config.post_conditions, toStr(post).c_str(), post);
753763
}
754764

765+
config.other_attributes = other_attributes;
755766
//---------------------------------------------
756767
TreeNode::Ptr new_node;
757768

tests/gtest_ports.cpp

Lines changed: 25 additions & 0 deletions
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)