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 #include "../sample_nodes/dummy_nodes.h"
00007
00008 using namespace BT;
00009
00010
00011
00012 static const char* xml_text = R"(
00013
00014 <root main_tree_to_execute = "MainTree" >
00015
00016 <BehaviorTree ID="MainTree">
00017 <Fallback name="root_selector">
00018
00019 <Sequence name="door_open_sequence">
00020 <Action ID="IsDoorOpen" />
00021 <Action ID="PassThroughDoor" />
00022 </Sequence>
00023
00024 <Sequence name="door_closed_sequence">
00025 <Decorator ID="Inverter">
00026 <Action ID="IsDoorOpen" />
00027 </Decorator>
00028 <Action ID="OpenDoor" />
00029 <Action ID="PassThroughDoor" />
00030 <Action ID="CloseDoor" />
00031 </Sequence>
00032
00033 <Action ID="PassThroughWindow" />
00034
00035 </Fallback>
00036 </BehaviorTree>
00037
00038 <!-- TreeNodesModel is used only by the Graphic interface -->
00039 <TreeNodesModel>
00040 <Action ID="IsDoorOpen" />
00041 <Action ID="PassThroughDoor" />
00042 <Action ID="CloseDoor" />
00043 <Action ID="OpenDoor" />
00044 <Action ID="PassThroughWindow" />
00045 </TreeNodesModel>
00046 </root>
00047 )";
00048
00049 static const char* xml_text_subtree = R"(
00050
00051 <root main_tree_to_execute = "MainTree" >
00052
00053 <BehaviorTree ID="CrossDoorSubtree">
00054 <Sequence name="door_sequence">
00055 <Decorator ID="Inverter">
00056 <Action ID="IsDoorLocked" />
00057 </Decorator>
00058 <Action ID="OpenDoor" />
00059 <Action ID="PassThroughDoor" />
00060 <Action ID="CloseDoor" />
00061 </Sequence>
00062 </BehaviorTree>
00063
00064 <!-- This tree will include the other one -->
00065 <BehaviorTree ID="MainTree">
00066 <Fallback name="root_selector">
00067 <SubTree ID="CrossDoorSubtree" />
00068 <Action ID="PassThroughWindow" />
00069 </Fallback>
00070 </BehaviorTree>
00071
00072 </root> )";
00073
00074
00075
00076 TEST(BehaviorTreeFactory, VerifyLargeTree)
00077 {
00078 BehaviorTreeFactory factory;
00079 CrossDoor::RegisterNodes(factory);
00080
00081 Tree tree = factory.createTreeFromText(xml_text);
00082
00083 printTreeRecursively(tree.root_node);
00084
00085 ASSERT_EQ(tree.root_node->name(), "root_selector");
00086
00087 auto fallback = dynamic_cast<const FallbackNode*>(tree.root_node);
00088 ASSERT_TRUE(fallback != nullptr);
00089
00090 ASSERT_EQ(fallback->children().size(), 3);
00091 ASSERT_EQ(fallback->child(0)->name(), "door_open_sequence");
00092 ASSERT_EQ(fallback->child(1)->name(), "door_closed_sequence");
00093 ASSERT_EQ(fallback->child(2)->name(), "PassThroughWindow");
00094
00095 auto sequence_open = dynamic_cast<const SequenceNode*>(fallback->child(0));
00096 ASSERT_TRUE(sequence_open != nullptr);
00097
00098 ASSERT_EQ(sequence_open->children().size(), 2);
00099 ASSERT_EQ(sequence_open->child(0)->name(), "IsDoorOpen");
00100 ASSERT_EQ(sequence_open->child(1)->name(), "PassThroughDoor");
00101
00102 auto sequence_closed = dynamic_cast<const SequenceNode*>(fallback->child(1));
00103 ASSERT_TRUE(sequence_closed != nullptr);
00104
00105 ASSERT_EQ(sequence_closed->children().size(), 4);
00106 ASSERT_EQ(sequence_closed->child(0)->name(), "Inverter");
00107 ASSERT_EQ(sequence_closed->child(1)->name(), "OpenDoor");
00108 ASSERT_EQ(sequence_closed->child(2)->name(), "PassThroughDoor");
00109 ASSERT_EQ(sequence_closed->child(3)->name(), "CloseDoor");
00110
00111 auto decorator = dynamic_cast<const InverterNode*>(sequence_closed->child(0));
00112 ASSERT_TRUE(decorator != nullptr);
00113
00114 ASSERT_EQ(decorator->child()->name(), "IsDoorOpen");
00115 }
00116
00117 TEST(BehaviorTreeFactory, Subtree)
00118 {
00119 BehaviorTreeFactory factory;
00120 CrossDoor::RegisterNodes(factory);
00121
00122 Tree tree = factory.createTreeFromText(xml_text_subtree);
00123
00124 printTreeRecursively(tree.root_node);
00125
00126 ASSERT_EQ(tree.root_node->name(), "root_selector");
00127
00128 auto root_selector = dynamic_cast<const FallbackNode*>(tree.root_node);
00129 ASSERT_TRUE(root_selector != nullptr);
00130 ASSERT_EQ(root_selector->children().size(), 2);
00131 ASSERT_EQ(root_selector->child(0)->name(), "CrossDoorSubtree");
00132 ASSERT_EQ(root_selector->child(1)->name(), "PassThroughWindow");
00133
00134 auto subtree = dynamic_cast<const DecoratorSubtreeNode*>(root_selector->child(0));
00135 ASSERT_TRUE(subtree != nullptr);
00136
00137 auto sequence = dynamic_cast<const SequenceNode*>(subtree->child());
00138 ASSERT_TRUE(sequence != nullptr);
00139
00140 ASSERT_EQ(sequence->children().size(), 4);
00141 ASSERT_EQ(sequence->child(0)->name(), "Inverter");
00142 ASSERT_EQ(sequence->child(1)->name(), "OpenDoor");
00143 ASSERT_EQ(sequence->child(2)->name(), "PassThroughDoor");
00144 ASSERT_EQ(sequence->child(3)->name(), "CloseDoor");
00145
00146 auto decorator = dynamic_cast<const InverterNode*>(sequence->child(0));
00147 ASSERT_TRUE(decorator != nullptr);
00148
00149 ASSERT_EQ(decorator->child()->name(), "IsDoorLocked");
00150 }
00151
00152 TEST(BehaviorTreeFactory, Issue7)
00153 {
00154 const std::string xml_text_issue = R"(
00155 <root>
00156 <BehaviorTree ID="ReceiveGuest">
00157 </BehaviorTree>
00158 </root> )";
00159
00160 BehaviorTreeFactory factory;
00161 XMLParser parser(factory);
00162
00163 EXPECT_THROW( parser.loadFromText(xml_text_issue), RuntimeError );
00164 }
00165
00166
00167
00168
00169 static const char* xml_ports_subtree = R"(
00170
00171 <root main_tree_to_execute = "MainTree" >
00172
00173 <BehaviorTree ID="TalkToMe">
00174 <Sequence>
00175 <SaySomething message="{hello_msg}" />
00176 <SaySomething message="{bye_msg}" />
00177 <SetBlackboard output_key="output" value="done!" />
00178 </Sequence>
00179 </BehaviorTree>
00180
00181 <BehaviorTree ID="MainTree">
00182 <Sequence>
00183 <SetBlackboard output_key="talk_hello" value="hello" />
00184 <SetBlackboard output_key="talk_bye" value="bye bye" />
00185 <SubTree ID="TalkToMe" hello_msg="talk_hello"
00186 bye_msg="talk_bye"
00187 output="talk_out" />
00188 <SaySomething message="{talk_out}" />
00189 </Sequence>
00190 </BehaviorTree>
00191
00192 </root> )";
00193
00194
00195
00196 TEST(BehaviorTreeFactory, SubTreeWithRemapping)
00197 {
00198 BehaviorTreeFactory factory;
00199 factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
00200
00201 Tree tree = factory.createTreeFromText(xml_ports_subtree);
00202
00203 auto main_bb = tree.blackboard_stack.at(0);
00204 auto talk_bb = tree.blackboard_stack.at(1);
00205
00206 std::cout << "\n --------------------------------- \n" << std::endl;
00207 main_bb->debugMessage();
00208 std::cout << "\n ----- \n" << std::endl;
00209 talk_bb->debugMessage();
00210 std::cout << "\n --------------------------------- \n" << std::endl;
00211
00212 ASSERT_EQ( main_bb->portInfo("talk_hello")->type(), &typeid(std::string) );
00213 ASSERT_EQ( main_bb->portInfo("talk_bye")->type(), &typeid(std::string) );
00214 ASSERT_EQ( main_bb->portInfo("talk_out")->type(), &typeid(std::string) );
00215
00216 ASSERT_EQ( talk_bb->portInfo("bye_msg")->type(), &typeid(std::string) );
00217 ASSERT_EQ( talk_bb->portInfo("hello_msg")->type(), &typeid(std::string) );
00218
00219
00220 tree.root_node->executeTick();
00221
00222 std::cout << "\n --------------------------------- \n" << std::endl;
00223 main_bb->debugMessage();
00224 std::cout << "\n ----- \n" << std::endl;
00225 talk_bb->debugMessage();
00226 std::cout << "\n --------------------------------- \n" << std::endl;
00227
00228 ASSERT_EQ( main_bb->portInfo("talk_hello")->type(), &typeid(std::string) );
00229 ASSERT_EQ( main_bb->portInfo("talk_bye")->type(), &typeid(std::string) );
00230 ASSERT_EQ( main_bb->portInfo("talk_out")->type(), &typeid(std::string) );
00231
00232 ASSERT_EQ( talk_bb->portInfo("bye_msg")->type(), &typeid(std::string) );
00233 ASSERT_EQ( talk_bb->portInfo("hello_msg")->type(), &typeid(std::string) );
00234 ASSERT_EQ( talk_bb->portInfo("output")->type(), &typeid(std::string) );
00235
00236
00237 ASSERT_EQ( main_bb->get<std::string>("talk_hello"), "hello");
00238 ASSERT_EQ( main_bb->get<std::string>("talk_bye"), "bye bye");
00239 ASSERT_EQ( main_bb->get<std::string>("talk_out"), "done!");
00240
00241
00242 ASSERT_FALSE( talk_bb->getAny("talk_hello") );
00243 ASSERT_FALSE( talk_bb->getAny("talk_bye") );
00244 ASSERT_FALSE( talk_bb->getAny("talk_out") );
00245 }
00246