Skip to content

Commit 0a3393c

Browse files
committed
test moved and port remapping fixed
1 parent 11aebe7 commit 0a3393c

File tree

3 files changed

+129
-68
lines changed

3 files changed

+129
-68
lines changed

src/xml_parsing.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -881,15 +881,19 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID,
881881
{
882882
auto new_bb = Blackboard::create(blackboard);
883883
const std::string subtree_ID = element->Attribute("ID");
884-
std::unordered_map<std::string, std::string> remapping;
884+
std::unordered_map<std::string, std::string> subtree_remapping;
885885
bool do_autoremap = false;
886886

887887
for(auto attr = element->FirstAttribute(); attr != nullptr; attr = attr->Next())
888888
{
889-
const char* attr_name = attr->Name();
890-
const char* attr_value = attr->Value();
889+
std::string attr_name = attr->Name();
890+
std::string attr_value = attr->Value();
891+
if(attr_value == "{=}")
892+
{
893+
attr_value = StrCat("{", attr_name, "}");
894+
}
891895

892-
if(StrEqual(attr_name, "_autoremap"))
896+
if(attr_name == "_autoremap")
893897
{
894898
do_autoremap = convertFromString<bool>(attr_value);
895899
new_bb->enableAutoRemapping(do_autoremap);
@@ -899,10 +903,10 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID,
899903
{
900904
continue;
901905
}
902-
remapping.insert({ attr_name, attr_value });
906+
subtree_remapping.insert({ attr_name, attr_value });
903907
}
904908
// check if this subtree has a model. If it does,
905-
// we want o check if all the mandatory ports were remapped and
909+
// we want to check if all the mandatory ports were remapped and
906910
// add default ones, if necessary
907911
auto subtree_model_it = subtree_models.find(subtree_ID);
908912
if(subtree_model_it != subtree_models.end())
@@ -913,9 +917,9 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID,
913917
// - if any of these has default value
914918
for(const auto& [port_name, port_info] : subtree_model_ports)
915919
{
916-
auto it = remapping.find(port_name);
920+
auto it = subtree_remapping.find(port_name);
917921
// don't override existing remapping
918-
if(it == remapping.end() && !do_autoremap)
922+
if(it == subtree_remapping.end() && !do_autoremap)
919923
{
920924
// remapping is not explicitly defined in the XML: use the model
921925
if(port_info.defaultValueString().empty())
@@ -927,13 +931,13 @@ void BT::XMLParser::PImpl::recursivelyCreateSubtree(const std::string& tree_ID,
927931
}
928932
else
929933
{
930-
remapping.insert({ port_name, port_info.defaultValueString() });
934+
subtree_remapping.insert({ port_name, port_info.defaultValueString() });
931935
}
932936
}
933937
}
934938
}
935939

936-
for(const auto& [attr_name, attr_value] : remapping)
940+
for(const auto& [attr_name, attr_value] : subtree_remapping)
937941
{
938942
if(TreeNode::isBlackboardPointer(attr_value))
939943
{

tests/gtest_enums.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,118 @@ TEST(Enums, SwitchNodeWithEnum)
124124

125125
ASSERT_EQ(status, NodeStatus::SUCCESS);
126126
}
127+
128+
enum BatteryStatus
129+
{
130+
NO_FAULT = 0,
131+
LOW_BATTERY = 1
132+
};
133+
134+
class PrintEnum : public BT::ConditionNode
135+
{
136+
public:
137+
explicit PrintEnum(const std::string& name, const BT::NodeConfig& config)
138+
: ConditionNode(name, config)
139+
{}
140+
141+
~PrintEnum() override = default;
142+
143+
static BT::PortsList providedPorts()
144+
{
145+
return {
146+
BT::InputPort<BatteryStatus>("enum", "Name of the check"),
147+
};
148+
}
149+
150+
private:
151+
BT::NodeStatus tick() override
152+
{
153+
auto enum_value = getInput<BatteryStatus>("enum");
154+
if(!enum_value)
155+
{
156+
std::cout << "missing required input [enum]" << std::endl;
157+
return BT::NodeStatus::FAILURE;
158+
}
159+
std::cout << "Enum value: " << (enum_value == NO_FAULT ? "NO_FAULT" : "LOW_BATTERY")
160+
<< std::endl;
161+
return BT::NodeStatus::SUCCESS;
162+
}
163+
};
164+
165+
class IsHealthOk : public BT::ConditionNode
166+
{
167+
public:
168+
explicit IsHealthOk(const std::string& name, const BT::NodeConfig& config)
169+
: BT::ConditionNode(name, config)
170+
{}
171+
172+
~IsHealthOk() override = default;
173+
174+
static BT::PortsList providedPorts()
175+
{
176+
return { BT::InputPort<std::string>("check_name"), BT::InputPort<bool>("health") };
177+
}
178+
179+
private:
180+
BT::NodeStatus tick() override
181+
{
182+
auto health = getInput<bool>("health");
183+
if(!health)
184+
{
185+
std::cout << "missing required input [health]" << std::endl;
186+
return BT::NodeStatus::FAILURE;
187+
}
188+
189+
if(health.value())
190+
{
191+
return BT::NodeStatus::SUCCESS;
192+
}
193+
else
194+
{
195+
std::cerr << "IsHealthOk FAILED " << std::endl;
196+
return BT::NodeStatus::FAILURE;
197+
}
198+
return BT::NodeStatus::SUCCESS;
199+
}
200+
};
201+
202+
TEST(Enums, SubtreeRemapping)
203+
{
204+
const std::string xml_txt = R"(
205+
<root BTCPP_format="4" >
206+
<BehaviorTree ID="MainTree">
207+
<Sequence>
208+
<Script code=" fault_status := NO_FAULT " />
209+
<PrintEnum enum="{fault_status}"/>
210+
211+
<SubTree ID="FailsafeCheck"
212+
health="false"
213+
trigger_fault_status="LOW_BATTERY"
214+
fault_status="{=}" />
215+
216+
<PrintEnum enum="{fault_status}"/>
217+
</Sequence>
218+
</BehaviorTree>
219+
220+
<BehaviorTree ID="FailsafeCheck">
221+
<ForceSuccess>
222+
<IsHealthOk
223+
health="{health}"
224+
_onFailure="fault_status = trigger_fault_status"/>
225+
</ForceSuccess>
226+
</BehaviorTree>
227+
</root>)";
228+
229+
BehaviorTreeFactory factory;
230+
factory.registerScriptingEnums<BatteryStatus>();
231+
factory.registerNodeType<PrintEnum>("PrintEnum");
232+
factory.registerNodeType<IsHealthOk>("IsHealthOk");
233+
234+
factory.registerBehaviorTreeFromText(xml_txt);
235+
236+
auto tree = factory.createTree("MainTree");
237+
NodeStatus status = tree.tickWhileRunning();
238+
239+
ASSERT_EQ(status, NodeStatus::SUCCESS);
240+
ASSERT_EQ(tree.rootBlackboard()->get<BatteryStatus>("fault_status"), LOW_BATTERY);
241+
}

tests/gtest_postconditions.cpp

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -85,61 +85,3 @@ TEST(PostConditions, Issue601)
8585

8686
ASSERT_EQ(tree.rootBlackboard()->get<std::string>("test"), "halted");
8787
}
88-
89-
enum BatteryStatus
90-
{
91-
BATTERY_OK,
92-
LOW_BATTERY
93-
};
94-
95-
class BatteryCheck : public BT::SyncActionNode
96-
{
97-
public:
98-
BatteryCheck(const std::string& name, const BT::NodeConfig& config)
99-
: BT::SyncActionNode(name, config)
100-
{}
101-
102-
static BT::PortsList providedPorts()
103-
{
104-
return { InputPort<int>("health") };
105-
}
106-
107-
BT::NodeStatus tick() override
108-
{
109-
int health = getInput<int>("health").value();
110-
return health > 10 ? NodeStatus::SUCCESS : NodeStatus::FAILURE;
111-
}
112-
};
113-
114-
TEST(PostConditions, OnFailure)
115-
{
116-
const std::string xml_text = R"(
117-
<root BTCPP_format="4" >
118-
<BehaviorTree ID="Main">
119-
<Sequence>
120-
<Script code="battery_voltage := 7"/>
121-
<Script code="battery_status := BATTERY_OK"/>
122-
<SubTree ID="Sub" _autoremap="true"
123-
fault_status="LOW_BATTERY"
124-
health="{battery_voltage}" />
125-
</Sequence>
126-
</BehaviorTree>
127-
128-
<BehaviorTree ID="Sub">
129-
<BatteryCheck health="{health}"
130-
_onFailure="battery_status := fault_status" />
131-
</BehaviorTree>
132-
</root>)";
133-
134-
BehaviorTreeFactory factory;
135-
factory.registerNodeType<BatteryCheck>("BatteryCheck");
136-
factory.registerScriptingEnums<BatteryStatus>();
137-
138-
factory.registerBehaviorTreeFromText(xml_text);
139-
140-
auto tree = factory.createTree("Main");
141-
const auto status = tree.tickWhileRunning();
142-
143-
ASSERT_EQ(status, NodeStatus::FAILURE);
144-
ASSERT_EQ(tree.rootBlackboard()->get<BatteryStatus>("battery_status"), LOW_BATTERY);
145-
}

0 commit comments

Comments
 (0)