1 #include <gtest/gtest.h> 6 #include "../sample_nodes/crossdoor_nodes.h" 7 #include "../sample_nodes/dummy_nodes.h" 15 <root main_tree_to_execute = "MainTree" > 17 <BehaviorTree ID="MainTree"> 18 <Fallback name="root_selector"> 20 <Sequence name="door_open_sequence"> 21 <Action ID="IsDoorOpen" /> 22 <Action ID="PassThroughDoor" /> 25 <Sequence name="door_closed_sequence"> 26 <Decorator ID="Inverter"> 27 <Action ID="IsDoorOpen" /> 29 <Action ID="OpenDoor" /> 30 <Action ID="PassThroughDoor" /> 31 <Action ID="CloseDoor" /> 34 <Action ID="PassThroughWindow" /> 39 <!-- TreeNodesModel is used only by the Graphic interface --> 41 <Action ID="IsDoorOpen" /> 42 <Action ID="PassThroughDoor" /> 43 <Action ID="CloseDoor" /> 44 <Action ID="OpenDoor" /> 45 <Action ID="PassThroughWindow" /> 52 <root main_tree_to_execute = "MainTree" > 54 <BehaviorTree ID="CrossDoorSubtree"> 55 <Sequence name="door_sequence"> 56 <Decorator ID="Inverter"> 57 <Action ID="IsDoorLocked" /> 59 <Action ID="OpenDoor" /> 60 <Action ID="PassThroughDoor" /> 61 <Action ID="CloseDoor" /> 65 <!-- This tree will include the other one --> 66 <BehaviorTree ID="MainTree"> 67 <Fallback name="root_selector"> 68 <SubTree ID="CrossDoorSubtree" /> 69 <Action ID="PassThroughWindow" /> 78 <BehaviorTree ID="MainTree"> 79 <Fallback name="root_selector"> 80 <SubTree ID="CrossDoorSubtree" /> 81 <Action ID="PassThroughWindow" /> 89 <BehaviorTree ID="CrossDoorSubtree"> 90 <Sequence name="door_sequence"> 91 <Decorator ID="Inverter"> 92 <Action ID="IsDoorLocked" /> 94 <Action ID="OpenDoor" /> 95 <Action ID="PassThroughDoor" /> 96 <Action ID="CloseDoor" /> 112 ASSERT_EQ(trees.size(), 2);
113 ASSERT_EQ(trees[0],
"CrossDoorSubtree");
114 ASSERT_EQ(trees[1],
"MainTree");
121 ASSERT_EQ(trees.size(), 2);
122 ASSERT_EQ(trees[0],
"CrossDoorSubtree");
123 ASSERT_EQ(trees[1],
"MainTree");
130 ASSERT_EQ(trees.size(), 2);
131 ASSERT_EQ(trees[0],
"CrossDoorSubtree");
132 ASSERT_EQ(trees[1],
"MainTree");
148 ASSERT_TRUE(fallback !=
nullptr);
150 ASSERT_EQ(fallback->children().size(), 3);
151 ASSERT_EQ(fallback->child(0)->name(),
"door_open_sequence");
152 ASSERT_EQ(fallback->child(1)->name(),
"door_closed_sequence");
153 ASSERT_EQ(fallback->child(2)->name(),
"PassThroughWindow");
155 auto sequence_open =
dynamic_cast<const SequenceNode*
>(fallback->child(0));
156 ASSERT_TRUE(sequence_open !=
nullptr);
158 ASSERT_EQ(sequence_open->children().size(), 2);
159 ASSERT_EQ(sequence_open->child(0)->name(),
"IsDoorOpen");
160 ASSERT_EQ(sequence_open->child(1)->name(),
"PassThroughDoor");
162 auto sequence_closed =
dynamic_cast<const SequenceNode*
>(fallback->child(1));
163 ASSERT_TRUE(sequence_closed !=
nullptr);
165 ASSERT_EQ(sequence_closed->children().size(), 4);
166 ASSERT_EQ(sequence_closed->child(0)->name(),
"Inverter");
167 ASSERT_EQ(sequence_closed->child(1)->name(),
"OpenDoor");
168 ASSERT_EQ(sequence_closed->child(2)->name(),
"PassThroughDoor");
169 ASSERT_EQ(sequence_closed->child(3)->name(),
"CloseDoor");
171 auto decorator =
dynamic_cast<const InverterNode*
>(sequence_closed->child(0));
172 ASSERT_TRUE(decorator !=
nullptr);
174 ASSERT_EQ(decorator->child()->name(),
"IsDoorOpen");
189 ASSERT_TRUE(root_selector !=
nullptr);
190 ASSERT_EQ(root_selector->children().size(), 2);
191 ASSERT_EQ(root_selector->child(0)->name(),
"CrossDoorSubtree");
192 ASSERT_EQ(root_selector->child(1)->name(),
"PassThroughWindow");
194 auto subtree =
dynamic_cast<const SubtreeNode*
>(root_selector->child(0));
195 ASSERT_TRUE(subtree !=
nullptr);
197 auto sequence =
dynamic_cast<const SequenceNode*
>(subtree->child());
198 ASSERT_TRUE(sequence !=
nullptr);
200 ASSERT_EQ(sequence->children().size(), 4);
201 ASSERT_EQ(sequence->child(0)->name(),
"Inverter");
202 ASSERT_EQ(sequence->child(1)->name(),
"OpenDoor");
203 ASSERT_EQ(sequence->child(2)->name(),
"PassThroughDoor");
204 ASSERT_EQ(sequence->child(3)->name(),
"CloseDoor");
206 auto decorator =
dynamic_cast<const InverterNode*
>(sequence->child(0));
207 ASSERT_TRUE(decorator !=
nullptr);
209 ASSERT_EQ(decorator->child()->name(),
"IsDoorLocked");
214 const std::string xml_text_issue = R
"( 216 <BehaviorTree ID="ReceiveGuest"> 228 EXPECT_TRUE( trees.empty() );
235 <root main_tree_to_execute = "MainTree" > 237 <BehaviorTree ID="TalkToMe"> 239 <SaySomething message="{hello_msg}" /> 240 <SaySomething message="{bye_msg}" /> 241 <SetBlackboard output_key="output" value="done!" /> 245 <BehaviorTree ID="MainTree"> 247 <SetBlackboard output_key="talk_hello" value="hello" /> 248 <SetBlackboard output_key="talk_bye" value="bye bye" /> 249 <SubTree ID="TalkToMe" hello_msg="talk_hello" 252 <SaySomething message="{talk_out}" /> 268 auto talk_bb = tree.blackboard_stack.at(1);
270 std::cout <<
"\n --------------------------------- \n" << std::endl;
271 main_bb->debugMessage();
272 std::cout <<
"\n ----- \n" << std::endl;
273 talk_bb->debugMessage();
274 std::cout <<
"\n --------------------------------- \n" << std::endl;
276 ASSERT_EQ(main_bb->portInfo(
"talk_hello")->type(), &
typeid(std::string));
277 ASSERT_EQ(main_bb->portInfo(
"talk_bye")->type(), &
typeid(std::string));
278 ASSERT_EQ(main_bb->portInfo(
"talk_out")->type(), &
typeid(std::string));
280 ASSERT_EQ(talk_bb->portInfo(
"bye_msg")->type(), &
typeid(std::string));
281 ASSERT_EQ(talk_bb->portInfo(
"hello_msg")->type(), &
typeid(std::string));
286 std::cout <<
"\n --------------------------------- \n" << std::endl;
287 main_bb->debugMessage();
288 std::cout <<
"\n ----- \n" << std::endl;
289 talk_bb->debugMessage();
290 std::cout <<
"\n --------------------------------- \n" << std::endl;
292 ASSERT_EQ(main_bb->portInfo(
"talk_hello")->type(), &
typeid(std::string));
293 ASSERT_EQ(main_bb->portInfo(
"talk_bye")->type(), &
typeid(std::string));
294 ASSERT_EQ(main_bb->portInfo(
"talk_out")->type(), &
typeid(std::string));
296 ASSERT_EQ(talk_bb->portInfo(
"bye_msg")->type(), &
typeid(std::string));
297 ASSERT_EQ(talk_bb->portInfo(
"hello_msg")->type(), &
typeid(std::string));
298 ASSERT_EQ(talk_bb->portInfo(
"output")->type(), &
typeid(std::string));
300 ASSERT_EQ(main_bb->get<std::string>(
"talk_hello"),
"hello");
301 ASSERT_EQ(main_bb->get<std::string>(
"talk_bye"),
"bye bye");
302 ASSERT_EQ(main_bb->get<std::string>(
"talk_out"),
"done!");
305 ASSERT_FALSE(talk_bb->getAny(
"talk_hello"));
306 ASSERT_FALSE(talk_bb->getAny(
"talk_bye"));
307 ASSERT_FALSE(talk_bb->getAny(
"talk_out"));
310 #if !defined(USING_ROS) && !defined(USING_ROS2) 317 "parent_no_include.xml");
327 auto path = (
environment->executable_path.parent_path() /
"trees/child/" 328 "child_include_sibling.xml");
339 "parent_include_child.xml");
346 CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromSameDirectory)
352 "parent_include_child_" 353 "include_sibling.xml");
360 CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromChildDirectory)
366 "parent_include_child_" 367 "include_child.xml");
374 CreateTreeFromFileWhichIncludesFileFromChildDirectoryWhichIncludesFileFromParentDirectory)
380 "parent_include_child_" 381 "include_parent.xml");
390 const std::string tree_xml = R
"( 392 <BehaviorTree ID="Main"> 405 const std::string tree_xml = R
"( 407 <BehaviorTree ID="Main"> 422 const std::string xml_text_ok = R
"( 424 <BehaviorTree ID="ValidTree"> 425 <Sequence name="door_open_sequence"> 426 <Action ID="AlwaysSuccess" /> 431 const std::string xml_text_invalid = R
"( 433 <BehaviorTree ID="InvalidTreeWithNoChildren"> 448 ASSERT_EQ(trees.size(), 1);
449 EXPECT_EQ(trees[0],
"ValidTree");
457 const std::string xml_text_invalid = R
"( 459 <BehaviorTree ID="InvalidTreeWithBadChild"> 460 <Sequence name="seq"> 461 <Action ID="AlwaysSuccess" > 475 EXPECT_TRUE(trees.empty());
482 const std::string xml_text_invalid = R
"( 483 <BehaviorTree ID="InvalidTreeNoRoot"> 484 <Sequence name="seq"> 485 <Action ID="AlwaysSuccess" /> 498 EXPECT_TRUE(trees.empty());
503 const std::string tree_xml = R
"( 505 <BehaviorTree ID="Main"> 517 ASSERT_FALSE(trees.empty());
522 EXPECT_TRUE(trees_after_clear.empty());
528 const std::string tree_xml = R
"( 530 <BehaviorTree ID="Main"> 539 ASSERT_FALSE(trees.empty());
544 EXPECT_TRUE(trees_after_clear.empty());
void clearRegisteredBehaviorTrees()
Clear previously-registered behavior trees.
void registerNodeType(const std::string &ID)
static const char * xml_ports_subtree
std::vector< Blackboard::Ptr > blackboard_stack
static const char * xml_text_subtree_part2
static const char * xml_text_subtree
TreeNode * rootNode() const
void clearInternalState() override
void RegisterNodes(BT::BehaviorTreeFactory &factory)
Environment * environment
void registerBehaviorTreeFromText(const std::string &xml_text)
const std::string & name() const
Name of the instance, not the type.
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
std::vector< std::string > registeredBehaviorTrees() const
NodeStatus tickRoot()
tickRoot send the tick signal to the root node. It will propagate through the entire tree...
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
void printTreeRecursively(const TreeNode *root_node, std::ostream &stream=std::cout)
void loadFromText(const std::string &xml_text, bool add_includes=true) override
The SubtreeNode is a way to wrap an entire Subtree, creating a separated BlackBoard. If you want to have data flow through ports, you need to explicitly remap the ports.
The InverterNode returns SUCCESS if child fails of FAILURE is child succeeds. RUNNING status is propa...
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Simple class for manipulating paths on Linux/Windows/Mac OS.
std::vector< std::string > registeredBehaviorTrees() const override
std::string str(path_type type=native_path) const
The XMLParser is a class used to read the model of a BehaviorTree from file or text and instantiate t...
static const char * xml_text_subtree_part1
The FallbackNode is used to try different strategies, until one succeeds. If any child returns RUNNIN...
Tree createTreeFromFile(const std::string &file_path, Blackboard::Ptr blackboard=Blackboard::create())
static const char * xml_text
The SequenceNode is used to tick children in an ordered sequence. If any child returns RUNNING...
TEST(BehaviorTreeFactory, XMLParsingOrder)