gtest_subtree.cpp
Go to the documentation of this file.
1 #include <gtest/gtest.h>
3 #include "../sample_nodes/dummy_nodes.h"
4 #include "../sample_nodes/movebase_node.h"
5 
6 using namespace BT;
7 
8 TEST(SubTree, SiblingPorts_Issue_72)
9 {
10  static const char* xml_text = R"(
11 
12 <root main_tree_to_execute = "MainTree" >
13 
14  <BehaviorTree ID="MainTree">
15  <Sequence>
16  <SetBlackboard value="hello" output_key="myParam" />
17  <SubTree ID="mySubtree" param="myParam" />
18  <SetBlackboard value="world" output_key="myParam" />
19  <SubTree ID="mySubtree" param="myParam" />
20  </Sequence>
21  </BehaviorTree>
22 
23  <BehaviorTree ID="mySubtree">
24  <SaySomething message="{param}" />
25  </BehaviorTree>
26 </root> )";
27 
28  BehaviorTreeFactory factory;
29  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
30 
31  Tree tree = factory.createTreeFromText(xml_text);
32 
33  for (auto& bb : tree.blackboard_stack)
34  {
35  bb->debugMessage();
36  std::cout << "-----" << std::endl;
37  }
38 
39  auto ret = tree.tickRoot();
40 
41  ASSERT_EQ(ret, NodeStatus::SUCCESS);
42  ASSERT_EQ(tree.blackboard_stack.size(), 3);
43 }
44 
46 {
47 public:
48  CopyPorts(const std::string& name, const BT::NodeConfiguration& config) :
49  BT::SyncActionNode(name, config)
50  {}
51 
52  BT::NodeStatus tick() override
53  {
54  auto msg = getInput<std::string>("in");
55  if (!msg)
56  {
57  throw BT::RuntimeError("missing required input [message]: ", msg.error());
58  }
59  setOutput("out", msg.value());
61  }
62 
64  {
65  return {BT::InputPort<std::string>("in"), BT::OutputPort<std::string>("out")};
66  }
67 };
68 
69 TEST(SubTree, GoodRemapping)
70 {
71  static const char* xml_text = R"(
72 
73 <root main_tree_to_execute = "MainTree" >
74 
75  <BehaviorTree ID="MainTree">
76  <Sequence>
77  <SetBlackboard value="hello" output_key="thoughts" />
78  <SubTree ID="CopySubtree" in_arg="thoughts" out_arg="greetings"/>
79  <SaySomething message="{greetings}" />
80  </Sequence>
81  </BehaviorTree>
82 
83  <BehaviorTree ID="CopySubtree">
84  <CopyPorts in="{in_arg}" out="{out_arg}"/>
85  </BehaviorTree>
86 </root> )";
87 
88  BehaviorTreeFactory factory;
89  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
90  factory.registerNodeType<CopyPorts>("CopyPorts");
91 
92  Tree tree = factory.createTreeFromText(xml_text);
93  auto ret = tree.tickRoot();
94  ASSERT_EQ(ret, NodeStatus::SUCCESS);
95 }
96 
97 TEST(SubTree, BadRemapping)
98 {
99  BehaviorTreeFactory factory;
100  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
101  factory.registerNodeType<CopyPorts>("CopyPorts");
102 
103  static const char* xml_text_bad_in = R"(
104 <root main_tree_to_execute = "MainTree" >
105 
106  <BehaviorTree ID="MainTree">
107  <Sequence>
108  <SetBlackboard value="hello" output_key="thoughts" />
109  <SubTree ID="CopySubtree" out_arg="greetings"/>
110  <SaySomething message="{greetings}" />
111  </Sequence>
112  </BehaviorTree>
113 
114  <BehaviorTree ID="CopySubtree">
115  <CopyPorts in="{in_arg}" out="{out_arg}"/>
116  </BehaviorTree>
117 </root> )";
118 
119  Tree tree_bad_in = factory.createTreeFromText(xml_text_bad_in);
120  EXPECT_ANY_THROW(tree_bad_in.tickRoot());
121 
122  static const char* xml_text_bad_out = R"(
123 <root main_tree_to_execute = "MainTree" >
124 
125  <BehaviorTree ID="MainTree">
126  <Sequence>
127  <SetBlackboard value="hello" output_key="thoughts" />
128  <SubTree ID="CopySubtree" in_arg="thoughts"/>
129  <SaySomething message="{greetings}" />
130  </Sequence>
131  </BehaviorTree>
132 
133  <BehaviorTree ID="CopySubtree">
134  <CopyPorts in="{in_arg}" out="{out_arg}"/>
135  </BehaviorTree>
136 </root> )";
137 
138  Tree tree_bad_out = factory.createTreeFromText(xml_text_bad_out);
139  EXPECT_ANY_THROW(tree_bad_out.tickRoot());
140 }
141 
142 TEST(SubTree, SubtreePlusA)
143 {
144  static const char* xml_text = R"(
145 
146 <root main_tree_to_execute = "MainTree" >
147 
148  <BehaviorTree ID="MainTree">
149  <Sequence>
150  <SetBlackboard value="Auto remapped" output_key="param" />
151  <SubTreePlus ID="mySubtree" __autoremap="1" />
152  </Sequence>
153  </BehaviorTree>
154 
155  <BehaviorTree ID="mySubtree">
156  <SaySomething message="{param}" />
157  </BehaviorTree>
158 </root> )";
159 
160  BehaviorTreeFactory factory;
161  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
162 
163  Tree tree = factory.createTreeFromText(xml_text);
164  auto ret = tree.tickRoot();
165  ASSERT_EQ(ret, NodeStatus::SUCCESS);
166 }
167 
168 TEST(SubTree, SubtreePlusB)
169 {
170  static const char* xml_text = R"(
171 
172 <root main_tree_to_execute = "MainTree" >
173 
174  <BehaviorTree ID="MainTree">
175  <Sequence>
176  <SetBlackboard value="Hello World" output_key="myParam" />
177  <SetBlackboard value="Auto remapped" output_key="param3" />
178  <SubTreePlus ID="mySubtree" __autoremap="1" param1="{myParam}" param2="Straight Talking" />
179  </Sequence>
180  </BehaviorTree>
181 
182  <BehaviorTree ID="mySubtree">
183  <Sequence>
184  <SaySomething message="{param1}" />
185  <SaySomething message="{param2}" />
186  <SaySomething message="{param3}" />
187  </Sequence>
188  </BehaviorTree>
189 </root> )";
190 
191  BehaviorTreeFactory factory;
192  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
193 
194  Tree tree = factory.createTreeFromText(xml_text);
195  auto ret = tree.tickRoot();
196  ASSERT_EQ(ret, NodeStatus::SUCCESS);
197 }
198 
199 TEST(SubTree, SubtreePlusC)
200 {
201  static const char* xml_text = R"(
202 
203 <root main_tree_to_execute = "MainTree" >
204 
205  <BehaviorTree ID="MainTree">
206  <Sequence>
207  <SetBlackboard value="Hello" output_key="param1" />
208  <SetBlackboard value="World" output_key="param2" />
209  <SubTree ID="mySubtree" __shared_blackboard="true"/>
210  </Sequence>
211  </BehaviorTree>
212 
213  <BehaviorTree ID="mySubtree">
214  <Sequence>
215  <SaySomething message="{param1}" />
216  <SaySomething message="{param2}" />
217  </Sequence>
218  </BehaviorTree>
219 </root> )";
220 
221  BehaviorTreeFactory factory;
222  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
223 
224  Tree tree = factory.createTreeFromText(xml_text);
225  auto ret = tree.tickRoot();
226  ASSERT_EQ(ret, NodeStatus::SUCCESS);
227 }
228 
230 {
231 public:
232  ReadInConstructor(const std::string& name, const BT::NodeConfiguration& config) :
233  BT::SyncActionNode(name, config)
234  {
235  auto msg = getInput<std::string>("message");
236  if (!msg)
237  {
238  throw BT::RuntimeError("missing required input [message]: ", msg.error());
239  }
240  }
241 
242  BT::NodeStatus tick() override
243  {
245  }
247  {
248  return {BT::InputPort<std::string>("message")};
249  }
250 };
251 
252 TEST(SubTree, SubtreePlusD)
253 {
254  BT::NodeConfiguration config;
256  static const char* xml_text = R"(
257 
258 <root main_tree_to_execute = "MainTree" >
259 
260  <BehaviorTree ID="MainTree">
261  <Sequence>
262  <SubTreePlus ID="mySubtree" __autoremap="1"/>
263  </Sequence>
264  </BehaviorTree>
265  <BehaviorTree ID="mySubtree">
266  <ReadInConstructor message="{message}" />
267  </BehaviorTree>
268 </root> )";
269 
270  BT::BehaviorTreeFactory factory;
271  factory.registerNodeType<ReadInConstructor>("ReadInConstructor");
272  config.blackboard->set("message", "hello");
273  BT::Tree tree = factory.createTreeFromText(xml_text, config.blackboard);
274  auto ret = tree.tickRoot();
275  ASSERT_EQ(ret, BT::NodeStatus::SUCCESS);
276 }
277 
278 TEST(SubTree, SubtreeIssue433)
279 {
280  BT::NodeConfiguration config;
282  static const char* xml_text = R"(
283 
284 <root main_tree_to_execute = "TestTree" >
285  <BehaviorTree ID="Subtree1">
286  <Decorator ID="Repeat" num_cycles="{port_to_use}">
287  <Action ID="AlwaysSuccess"/>
288  </Decorator>
289  </BehaviorTree>
290 
291  <BehaviorTree ID="Subtree2">
292  <Action ID="SetBlackboard" output_key="test_port" value="{port_to_read}"/>
293  </BehaviorTree>
294 
295  <BehaviorTree ID="TestTree">
296  <Sequence>
297  <Action ID="SetBlackboard" output_key="test_port" value="1"/>
298  <SubTree ID="Subtree1" port_to_use="test_port"/>
299  <SubTree ID="Subtree2" port_to_read="test_port"/>
300  </Sequence>
301  </BehaviorTree>
302 </root> )";
303 
304  BT::BehaviorTreeFactory factory;
305 
306  BT::Tree tree = factory.createTreeFromText(xml_text, config.blackboard);
307  auto ret = tree.tickRoot();
308 
309  ASSERT_EQ(ret, BT::NodeStatus::SUCCESS);
310 }
311 
312 
314 {
315 public:
316  NaughtyNav2Node(const std::string& name, const BT::NodeConfiguration& config) :
317  BT::SyncActionNode(name, config)
318  {
319  std::cout << "CTOR:" << config.blackboard->get<std::string>("ros_node") << std::endl;
320  }
321 
322  BT::NodeStatus tick() override
323  {
324  std::cout << "tick:" << config().blackboard->get<std::string>("ros_node") << std::endl;
326  }
328  {
329  return {};
330  }
331 };
332 
333 TEST(SubTree, SubtreeNav2_Issue563)
334 {
335  static const char* xml_text = R"(
336 <root main_tree_to_execute="Tree1">
337 
338  <BehaviorTree ID="Tree1">
339  <Sequence>
340  <SetBlackboard output_key="the_message" value="hello world"/>
341  <SubTreePlus ID="Tree2" __autoremap="true"/>
342  <SaySomething message="{reply}" />
343  </Sequence>
344  </BehaviorTree>
345 
346  <BehaviorTree ID="Tree2">
347  <SubTreePlus ID="Tree3" __autoremap="true"/>
348  </BehaviorTree>
349 
350  <BehaviorTree ID="Tree3">
351  <SubTreePlus ID="Talker" __autoremap="true"/>
352  </BehaviorTree>
353 
354  <BehaviorTree ID="Talker">
355  <Sequence>
356  <SaySomething message="{the_message}" />
357  <SetBlackboard output_key="reply" value="done"/>
358  <NaughtyNav2Node/>
359  </Sequence>
360  </BehaviorTree>
361 
362 </root>)";
363 
364  BehaviorTreeFactory factory;
365  factory.registerNodeType<DummyNodes::SaySomething>("SaySomething");
366  factory.registerNodeType<NaughtyNav2Node>("NaughtyNav2Node");
367 
368  auto blackboard = BT::Blackboard::create();
369  blackboard->set<std::string>("ros_node", "nav2_shouldnt_do_this");
370 
371  Tree tree = factory.createTreeFromText(xml_text, blackboard);
372 
373  auto ret = tree.tickRoot();
374  ASSERT_EQ(ret, NodeStatus::SUCCESS);
375 }
376 
377 TEST(SubTree, SubtreeNav2_Issue724)
378 {
379  static const char* xml_text = R"(
380 <root main_tree_to_execute="Tree1">
381 
382  <BehaviorTree ID="Tree1">
383  <Sequence>
384  <SubTreePlus ID="Tree2" ros_node="{ros_node}"/>
385  </Sequence>
386  </BehaviorTree>
387 
388  <BehaviorTree ID="Tree2">
389  <SubTreePlus ID="Tree3" ros_node="{ros_node}"/>
390  </BehaviorTree>
391 
392  <BehaviorTree ID="Tree3">
393  <SubTreePlus ID="Talker" ros_node="{ros_node}"/>
394  </BehaviorTree>
395 
396  <BehaviorTree ID="Talker">
397  <Sequence>
398  <NaughtyNav2Node/>
399  </Sequence>
400  </BehaviorTree>
401 
402 </root>)";
403 
404  BehaviorTreeFactory factory;
405  factory.registerNodeType<NaughtyNav2Node>("NaughtyNav2Node");
406 
408 
409  auto blackboard = BT::Blackboard::create();
410  blackboard->set<std::string>("ros_node", "nav2_shouldnt_do_this");
411 
412  Tree tree = factory.createTreeFromText(xml_text, blackboard);
413 
414  auto ret = tree.tickRoot();
415  ASSERT_EQ(ret, NodeStatus::SUCCESS);
416 }
417 
418 TEST(SubTree, String_to_Pose_Issue623)
419 {
420  // clang-format off
421 
422  static const char* xml_text = R"(
423 <root main_tree_to_execute="Test">
424  <BehaviorTree ID="Test">
425  <ReactiveSequence name="MainSequence">
426  <SubTreePlus name="Visit2" ID="Visit2" tl1="1;2;3"/>
427  </ReactiveSequence>
428  </BehaviorTree>
429  <BehaviorTree ID="Visit2">
430  <Sequence name="Visit2MainSequence">
431  <Action name="MoveBase" ID="MoveBase" goal="{tl1}"/>
432  </Sequence>
433  </BehaviorTree>
434 </root>
435  )";
436 
437  // clang-format on
438 
439  BehaviorTreeFactory factory;
440  factory.registerNodeType<MoveBaseAction>("MoveBase");
441  auto tree = factory.createTreeFromText(xml_text);
442  tree.tickRootWhileRunning();
443 }
444 
446 {
447 public:
448  Assert(const std::string& name, const BT::NodeConfiguration& config)
449  : BT::SyncActionNode(name, config) {}
450 
452  return {BT::InputPort<bool>("condition")};
453  }
454 
455 private:
456  virtual BT::NodeStatus tick() override {
457  if (getInput<bool>("condition").value())
459  else
461  }
462 };
463 
464 TEST(SubTree, Issue653_SetBlackboard)
465 {
466  // clang-format off
467 
468  static const char* xml_text = R"(
469 <root main_tree_to_execute = "MainTree">
470  <BehaviorTree ID="MainTree">
471  <Sequence>
472  <SubTreePlus ID="Init" test="{test}" />
473  <Assert condition="{test}" />
474  </Sequence>
475  </BehaviorTree>
476 
477  <BehaviorTree ID="Init">
478  <SetBlackboard output_key="test" value="true"/>
479  </BehaviorTree>
480 </root>
481  )";
482 
483  // clang-format on
484 
485  BehaviorTreeFactory factory;
486  factory.registerNodeType<Assert>("Assert");
487  auto tree = factory.createTreeFromText(xml_text);
488  tree.tickRootWhileRunning();
489 }
Assert::providedPorts
static BT::PortsList providedPorts()
Definition: gtest_subtree.cpp:451
BT
Definition: ex01_wrap_legacy.cpp:29
BT::Tree::tickRoot
NodeStatus tickRoot()
tickRoot send the tick signal to the root node. It will propagate through the entire tree.
Definition: bt_factory.h:210
BT::BehaviorTreeFactory::registerNodeType
void registerNodeType(const std::string &ID)
Definition: bt_factory.h:364
Assert::Assert
Assert(const std::string &name, const BT::NodeConfiguration &config)
Definition: gtest_subtree.cpp:448
ReadInConstructor::tick
BT::NodeStatus tick() override
Method to be implemented by the user.
Definition: gtest_subtree.cpp:242
BT::Tree
Struct used to store a tree. If this object goes out of scope, the tree is destroyed.
Definition: bt_factory.h:125
BT::PortsList
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:342
bt_factory.h
MoveBaseAction
Definition: movebase_node.h:43
BT::NodeConfiguration
Definition: tree_node.h:44
TEST
TEST(SubTree, SiblingPorts_Issue_72)
Definition: gtest_subtree.cpp:8
Assert
Definition: gtest_subtree.cpp:445
BT::NodeStatus::FAILURE
@ FAILURE
ReadInConstructor::providedPorts
static BT::PortsList providedPorts()
Definition: gtest_subtree.cpp:246
BT::BehaviorTreeFactory::createTreeFromText
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:278
BT::RuntimeError
Definition: exceptions.h:58
NaughtyNav2Node::providedPorts
static BT::PortsList providedPorts()
Definition: gtest_subtree.cpp:327
NaughtyNav2Node
Definition: gtest_subtree.cpp:313
DummyNodes::SaySomething
Definition: dummy_nodes.h:50
ReadInConstructor
Definition: gtest_subtree.cpp:229
BT::BehaviorTreeFactory
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:251
BT::Blackboard::create
static Blackboard::Ptr create(Blackboard::Ptr parent={})
Definition: blackboard.h:36
ReadInConstructor::ReadInConstructor
ReadInConstructor(const std::string &name, const BT::NodeConfiguration &config)
Definition: gtest_subtree.cpp:232
BT::NodeStatus::SUCCESS
@ SUCCESS
BT::NodeConfiguration::blackboard
Blackboard::Ptr blackboard
Definition: tree_node.h:49
CopyPorts
Definition: gtest_subtree.cpp:45
CopyPorts::CopyPorts
CopyPorts(const std::string &name, const BT::NodeConfiguration &config)
Definition: gtest_subtree.cpp:48
Assert::tick
virtual BT::NodeStatus tick() override
Method to be implemented by the user.
Definition: gtest_subtree.cpp:456
NaughtyNav2Node::tick
BT::NodeStatus tick() override
Method to be implemented by the user.
Definition: gtest_subtree.cpp:322
NaughtyNav2Node::NaughtyNav2Node
NaughtyNav2Node(const std::string &name, const BT::NodeConfiguration &config)
Definition: gtest_subtree.cpp:316
BT::BehaviorTreeFactory::registerBehaviorTreeFromText
void registerBehaviorTreeFromText(const std::string &xml_text)
Definition: bt_factory.cpp:228
CopyPorts::tick
BT::NodeStatus tick() override
Method to be implemented by the user.
Definition: gtest_subtree.cpp:52
CopyPorts::providedPorts
static BT::PortsList providedPorts()
Definition: gtest_subtree.cpp:63
xml_text
static const char * xml_text
Definition: ex01_wrap_legacy.cpp:52
BT::SyncActionNode
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn't require a...
Definition: action_node.h:52
BT::NodeStatus
NodeStatus
Definition: basic_types.h:35


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Wed Jun 26 2024 02:51:19