1 #include <gtest/gtest.h> 5 #include "../sample_nodes/crossdoor_nodes.h" 11 <root main_tree_to_execute = "MainTree" > 13 <BehaviorTree ID="MainTree"> 14 <Fallback name="root_selector"> 16 <Sequence name="door_open_sequence"> 17 <Action ID="IsDoorOpen" /> 18 <Action ID="PassThroughDoor" /> 21 <Sequence name="door_closed_sequence"> 22 <Decorator ID="Inverter"> 23 <Action ID="IsDoorOpen" /> 25 <Action ID="OpenDoor" /> 26 <Action ID="PassThroughDoor" /> 27 <Action ID="CloseDoor" /> 30 <Action ID="PassThroughWindow" /> 35 <!-- TreeNodesModel is used only by the Graphic interface --> 37 <Action ID="IsDoorOpen" /> 38 <Action ID="PassThroughDoor" /> 39 <Action ID="CloseDoor" /> 40 <Action ID="OpenDoor" /> 41 <Action ID="PassThroughWindow" /> 42 <Decorator ID="Invert" /> 43 <Decorator ID="RetryUntilSuccesful"> 44 <Parameter label="num_attempts" type="Int" /> 46 <Decorator ID="Repeat"> 47 <Parameter label="num_cycles" type="Int" /> 55 <root main_tree_to_execute = "MainTree" > 57 <BehaviorTree ID="CrossDoorSubtree"> 58 <Sequence name="door_sequence"> 59 <Decorator ID="Inverter"> 60 <Action ID="IsDoorLocked" /> 62 <Action ID="OpenDoor" /> 63 <Action ID="PassThroughDoor" /> 64 <Action ID="CloseDoor" /> 68 <!-- This tree will include the other one --> 69 <BehaviorTree ID="MainTree"> 70 <Fallback name="root_selector"> 71 <SubTree ID="CrossDoorSubtree" /> 72 <Action ID="PassThroughWindow" /> 88 std::vector<BT::TreeNode::Ptr> nodes;
94 ASSERT_EQ(root_node->name(),
"root_selector");
97 ASSERT_TRUE(fallback !=
nullptr);
99 ASSERT_EQ(fallback->children().size(), 3);
100 ASSERT_EQ(fallback->child(0)->name(),
"door_open_sequence");
101 ASSERT_EQ(fallback->child(1)->name(),
"door_closed_sequence");
102 ASSERT_EQ(fallback->child(2)->name(),
"PassThroughWindow");
104 auto sequence_open =
dynamic_cast<const BT::SequenceNode*
>(fallback->child(0));
105 ASSERT_TRUE(sequence_open !=
nullptr);
107 ASSERT_EQ(sequence_open->children().size(), 2);
108 ASSERT_EQ(sequence_open->child(0)->name(),
"IsDoorOpen");
109 ASSERT_EQ(sequence_open->child(1)->name(),
"PassThroughDoor");
111 auto sequence_closed =
dynamic_cast<const BT::SequenceNode*
>(fallback->child(1));
112 ASSERT_TRUE(sequence_closed !=
nullptr);
114 ASSERT_EQ(sequence_closed->children().size(), 4);
115 ASSERT_EQ(sequence_closed->child(0)->name(),
"Inverter");
116 ASSERT_EQ(sequence_closed->child(1)->name(),
"OpenDoor");
117 ASSERT_EQ(sequence_closed->child(2)->name(),
"PassThroughDoor");
118 ASSERT_EQ(sequence_closed->child(3)->name(),
"CloseDoor");
120 auto decorator =
dynamic_cast<const BT::InverterNode*
>(sequence_closed->child(0));
121 ASSERT_TRUE(decorator !=
nullptr);
123 ASSERT_EQ(decorator->child()->name(),
"IsDoorOpen");
134 std::vector<BT::TreeNode::Ptr> nodes;
139 ASSERT_EQ(root_node->name(),
"root_selector");
141 auto root_selector =
dynamic_cast<const BT::FallbackNode*
>(root_node.get());
142 ASSERT_TRUE(root_selector !=
nullptr);
143 ASSERT_EQ(root_selector->children().size(), 2);
144 ASSERT_EQ(root_selector->child(0)->name(),
"CrossDoorSubtree");
145 ASSERT_EQ(root_selector->child(1)->name(),
"PassThroughWindow");
148 ASSERT_TRUE(subtree !=
nullptr);
151 ASSERT_TRUE(sequence !=
nullptr);
153 ASSERT_EQ(sequence->children().size(), 4);
154 ASSERT_EQ(sequence->child(0)->name(),
"Inverter");
155 ASSERT_EQ(sequence->child(1)->name(),
"OpenDoor");
156 ASSERT_EQ(sequence->child(2)->name(),
"PassThroughDoor");
157 ASSERT_EQ(sequence->child(3)->name(),
"CloseDoor");
160 ASSERT_TRUE(decorator !=
nullptr);
162 ASSERT_EQ(decorator->child()->name(),
"IsDoorLocked");
167 const std::string xml_text_issue = R
"( 169 <BehaviorTree ID="ReceiveGuest"> 176 EXPECT_THROW( parser.loadFromText(xml_text_issue), std::runtime_error ); const std::string xml_text_subtree
const std::string xml_text
TEST(BehaviorTreeFactory, VerifyLargeTree)
void printTreeRecursively(const TreeNode *root_node)
std::shared_ptr< Blackboard > Ptr
void RegisterNodes(BT::BehaviorTreeFactory &factory)
TreeNode::Ptr instantiateTree(std::vector< TreeNode::Ptr > &nodes, const Blackboard::Ptr &blackboard)
void loadFromText(const std::string &xml_text)
std::shared_ptr< TreeNode > Ptr
The FallbackNode is used to try different strategies, until one succeed. If any child returns RUNNING...
The SequenceNode is used to execute a sequence of children. If any child returns RUNNING, previous children will be ticked again.