Go to the documentation of this file.00001 #include <gtest/gtest.h>
00002 #include "action_test_node.h"
00003 #include "condition_test_node.h"
00004 #include "behaviortree_cpp/xml_parsing.h"
00005 #include "../sample_nodes/crossdoor_nodes.h"
00006
00007
00008
00009 const std::string xml_text = R"(
00010
00011 <root main_tree_to_execute = "MainTree" >
00012
00013 <BehaviorTree ID="MainTree">
00014 <Fallback name="root_selector">
00015
00016 <Sequence name="door_open_sequence">
00017 <Action ID="IsDoorOpen" />
00018 <Action ID="PassThroughDoor" />
00019 </Sequence>
00020
00021 <Sequence name="door_closed_sequence">
00022 <Decorator ID="Inverter">
00023 <Action ID="IsDoorOpen" />
00024 </Decorator>
00025 <Action ID="OpenDoor" />
00026 <Action ID="PassThroughDoor" />
00027 <Action ID="CloseDoor" />
00028 </Sequence>
00029
00030 <Action ID="PassThroughWindow" />
00031
00032 </Fallback>
00033 </BehaviorTree>
00034
00035 <!-- TreeNodesModel is used only by the Graphic interface -->
00036 <TreeNodesModel>
00037 <Action ID="IsDoorOpen" />
00038 <Action ID="PassThroughDoor" />
00039 <Action ID="CloseDoor" />
00040 <Action ID="OpenDoor" />
00041 <Action ID="PassThroughWindow" />
00042 <Decorator ID="Invert" />
00043 <Decorator ID="RetryUntilSuccesful">
00044 <Parameter label="num_attempts" type="Int" />
00045 </Decorator>
00046 <Decorator ID="Repeat">
00047 <Parameter label="num_cycles" type="Int" />
00048 </Decorator>
00049 </TreeNodesModel>
00050 </root>
00051 )";
00052
00053 const std::string xml_text_subtree = R"(
00054
00055 <root main_tree_to_execute = "MainTree" >
00056
00057 <BehaviorTree ID="CrossDoorSubtree">
00058 <Sequence name="door_sequence">
00059 <Decorator ID="Inverter">
00060 <Action ID="IsDoorLocked" />
00061 </Decorator>
00062 <Action ID="OpenDoor" />
00063 <Action ID="PassThroughDoor" />
00064 <Action ID="CloseDoor" />
00065 </Sequence>
00066 </BehaviorTree>
00067
00068 <!-- This tree will include the other one -->
00069 <BehaviorTree ID="MainTree">
00070 <Fallback name="root_selector">
00071 <SubTree ID="CrossDoorSubtree" />
00072 <Action ID="PassThroughWindow" />
00073 </Fallback>
00074 </BehaviorTree>
00075
00076 </root>
00077 )";
00078
00079
00080 TEST(BehaviorTreeFactory, VerifyLargeTree)
00081 {
00082 BT::BehaviorTreeFactory factory;
00083 CrossDoor::RegisterNodes(factory);
00084
00085 BT::XMLParser parser(factory);
00086 parser.loadFromText(xml_text);
00087
00088 std::vector<BT::TreeNode::Ptr> nodes;
00089
00090 BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes, Blackboard::Ptr());
00091
00092 BT::printTreeRecursively(root_node.get());
00093
00094 ASSERT_EQ(root_node->name(), "root_selector");
00095
00096 auto fallback = dynamic_cast<const BT::FallbackNode*>(root_node.get());
00097 ASSERT_TRUE(fallback != nullptr);
00098
00099 ASSERT_EQ(fallback->children().size(), 3);
00100 ASSERT_EQ(fallback->child(0)->name(), "door_open_sequence");
00101 ASSERT_EQ(fallback->child(1)->name(), "door_closed_sequence");
00102 ASSERT_EQ(fallback->child(2)->name(), "PassThroughWindow");
00103
00104 auto sequence_open = dynamic_cast<const BT::SequenceNode*>(fallback->child(0));
00105 ASSERT_TRUE(sequence_open != nullptr);
00106
00107 ASSERT_EQ(sequence_open->children().size(), 2);
00108 ASSERT_EQ(sequence_open->child(0)->name(), "IsDoorOpen");
00109 ASSERT_EQ(sequence_open->child(1)->name(), "PassThroughDoor");
00110
00111 auto sequence_closed = dynamic_cast<const BT::SequenceNode*>(fallback->child(1));
00112 ASSERT_TRUE(sequence_closed != nullptr);
00113
00114 ASSERT_EQ(sequence_closed->children().size(), 4);
00115 ASSERT_EQ(sequence_closed->child(0)->name(), "Inverter");
00116 ASSERT_EQ(sequence_closed->child(1)->name(), "OpenDoor");
00117 ASSERT_EQ(sequence_closed->child(2)->name(), "PassThroughDoor");
00118 ASSERT_EQ(sequence_closed->child(3)->name(), "CloseDoor");
00119
00120 auto decorator = dynamic_cast<const BT::InverterNode*>(sequence_closed->child(0));
00121 ASSERT_TRUE(decorator != nullptr);
00122
00123 ASSERT_EQ(decorator->child()->name(), "IsDoorOpen");
00124 }
00125
00126 TEST(BehaviorTreeFactory, Subtree)
00127 {
00128 BT::BehaviorTreeFactory factory;
00129 CrossDoor::RegisterNodes(factory);
00130
00131 BT::XMLParser parser(factory);
00132 parser.loadFromText(xml_text_subtree);
00133
00134 std::vector<BT::TreeNode::Ptr> nodes;
00135
00136 BT::TreeNode::Ptr root_node = parser.instantiateTree(nodes, Blackboard::Ptr());
00137 BT::printTreeRecursively(root_node.get());
00138
00139 ASSERT_EQ(root_node->name(), "root_selector");
00140
00141 auto root_selector = dynamic_cast<const BT::FallbackNode*>(root_node.get());
00142 ASSERT_TRUE(root_selector != nullptr);
00143 ASSERT_EQ(root_selector->children().size(), 2);
00144 ASSERT_EQ(root_selector->child(0)->name(), "CrossDoorSubtree");
00145 ASSERT_EQ(root_selector->child(1)->name(), "PassThroughWindow");
00146
00147 auto subtree = dynamic_cast<const BT::DecoratorSubtreeNode*>(root_selector->child(0));
00148 ASSERT_TRUE(subtree != nullptr);
00149
00150 auto sequence = dynamic_cast<const BT::SequenceNode*>(subtree->child());
00151 ASSERT_TRUE(sequence != nullptr);
00152
00153 ASSERT_EQ(sequence->children().size(), 4);
00154 ASSERT_EQ(sequence->child(0)->name(), "Inverter");
00155 ASSERT_EQ(sequence->child(1)->name(), "OpenDoor");
00156 ASSERT_EQ(sequence->child(2)->name(), "PassThroughDoor");
00157 ASSERT_EQ(sequence->child(3)->name(), "CloseDoor");
00158
00159 auto decorator = dynamic_cast<const BT::InverterNode*>(sequence->child(0));
00160 ASSERT_TRUE(decorator != nullptr);
00161
00162 ASSERT_EQ(decorator->child()->name(), "IsDoorLocked");
00163 }
00164
00165 TEST(BehaviorTreeFactory, Issue7)
00166 {
00167 const std::string xml_text_issue = R"(
00168 <root>
00169 <BehaviorTree ID="ReceiveGuest">
00170 </BehaviorTree>
00171 </root> )";
00172
00173 BT::BehaviorTreeFactory factory;
00174 BT::XMLParser parser(factory);
00175
00176 EXPECT_THROW( parser.loadFromText(xml_text_issue), std::runtime_error );
00177 }