ex04_waypoints.cpp
Go to the documentation of this file.
4 #include <list>
5 
6 using namespace BT;
7 
8 /*
9  * In this example we will show how a common design pattern could be implemented.
10  * We want to iterate through the elements of a queue, for instance a list of waypoints.
11  *
12  * Two ways to create a "loop" are presented, one using the actions "QueueSize" and "PopFromQueue"
13  * and the other using the decorator "ConsumeQueue".
14  */
15 
16 struct Pose2D
17 {
18  double x, y, theta;
19 };
20 
25 {
26 public:
27  GenerateWaypoints(const std::string& name, const NodeConfiguration& config) :
28  SyncActionNode(name, config)
29  {}
30 
31  NodeStatus tick() override
32  {
33  auto queue = std::make_shared<ProtectedQueue<Pose2D>>();
34  for (int i = 0; i < 10; i++)
35  {
36  queue->items.push_back(Pose2D{double(i), double(i), 0});
37  }
38  setOutput("waypoints", queue);
39  return NodeStatus::SUCCESS;
40  }
41 
43  {
44  return {OutputPort<std::shared_ptr<ProtectedQueue<Pose2D>>>("waypoints")};
45  }
46 };
47 //--------------------------------------------------------------
49 {
50 public:
51  UseWaypointQueue(const std::string& name, const NodeConfiguration& config) :
52  AsyncActionNode(name, config)
53  {}
54 
55  NodeStatus tick() override
56  {
57  std::shared_ptr<ProtectedQueue<Pose2D>> queue;
58  if (getInput("waypoints", queue) && queue)
59  {
60  Pose2D wp;
61  {
62  // Since we are using reference semantic (the queue is wrapped in
63  // a shared_ptr) to modify the queue inside the blackboard,
64  // we are effectively bypassing the thread safety of the BB.
65  // This is the reason why we need to use a mutex explicitly.
66  std::unique_lock<std::mutex> lk(queue->mtx);
67 
68  auto& waypoints = queue->items;
69  if (waypoints.empty())
70  {
71  return NodeStatus::FAILURE;
72  }
73  wp = waypoints.front();
74  waypoints.pop_front();
75 
76  } // end mutex lock
77 
78  std::this_thread::sleep_for(std::chrono::milliseconds(100));
79  std::cout << "Using waypoint: " << wp.x << "/" << wp.y << std::endl;
80 
81  return NodeStatus::SUCCESS;
82  }
83  else
84  {
85  return NodeStatus::FAILURE;
86  }
87  }
88 
90  {
91  return {InputPort<std::shared_ptr<ProtectedQueue<Pose2D>>>("waypoints")};
92  }
93 };
94 
99 {
100 public:
101  UseWaypoint(const std::string& name, const NodeConfiguration& config) :
102  AsyncActionNode(name, config)
103  {}
104 
105  NodeStatus tick() override
106  {
107  Pose2D wp;
108  if (getInput("waypoint", wp))
109  {
110  std::this_thread::sleep_for(std::chrono::milliseconds(100));
111  std::cout << "Using waypoint: " << wp.x << "/" << wp.y << std::endl;
112  return NodeStatus::SUCCESS;
113  }
114  else
115  {
116  return NodeStatus::FAILURE;
117  }
118  }
119 
121  {
122  return {InputPort<Pose2D>("waypoint")};
123  }
124 };
125 
126 // clang-format off
127 
128 static const char* xml_implicit = R"(
129  <root main_tree_to_execute = "TreeImplicit" >
130  <BehaviorTree ID="TreeImplicit">
131  <Sequence>
132  <GenerateWaypoints waypoints="{waypoints}" />
133  <KeepRunningUntilFailure>
134  <UseWaypointQueue waypoints="{waypoints}" />
135  </KeepRunningUntilFailure>
136  </Sequence>
137  </BehaviorTree>
138  </root>
139  )";
140 
141 
142 static const char* xml_A = R"(
143  <root main_tree_to_execute = "TreeA" >
144  <BehaviorTree ID="TreeA">
145  <Sequence>
146  <GenerateWaypoints waypoints="{waypoints}" />
147  <QueueSize queue="{waypoints}" size="{wp_size}" />
148  <Repeat num_cycles="{wp_size}" >
149  <Sequence>
150  <PopFromQueue queue="{waypoints}" popped_item="{wp}" />
151  <UseWaypoint waypoint="{wp}" />
152  </Sequence>
153  </Repeat>
154  </Sequence>
155  </BehaviorTree>
156  </root>
157  )";
158 
159 static const char* xml_B = R"(
160  <root main_tree_to_execute = "TreeB" >
161  <BehaviorTree ID="TreeB">
162  <Sequence>
163  <GenerateWaypoints waypoints="{waypoints}" />
164  <ConsumeQueue queue="{waypoints}" popped_item="{wp}">
165  <UseWaypoint waypoint="{wp}" />
166  </ConsumeQueue>
167  </Sequence>
168  </BehaviorTree>
169  </root>
170  )";
171 
172 // clang-format on
173 
174 int main()
175 {
176  BehaviorTreeFactory factory;
177 
178  factory.registerNodeType<PopFromQueue<Pose2D>>("PopFromQueue");
179  factory.registerNodeType<QueueSize<Pose2D>>("QueueSize");
180  factory.registerNodeType<ConsumeQueue<Pose2D>>("ConsumeQueue");
181 
182  factory.registerNodeType<UseWaypoint>("UseWaypoint");
183  factory.registerNodeType<UseWaypointQueue>("UseWaypointQueue");
184  factory.registerNodeType<GenerateWaypoints>("GenerateWaypoints");
185 
186  for (const auto& xml_text : {xml_implicit, xml_A, xml_B})
187  {
188  auto tree = factory.createTreeFromText(xml_text);
189  while (tree.tickRoot() == NodeStatus::RUNNING)
190  {
191  tree.sleep(std::chrono::milliseconds(10));
192  }
193  std::cout << "--------------" << std::endl;
194  }
195 
196  return 0;
197 }
void sleep(std::chrono::system_clock::duration timeout)
Definition: bt_factory.cpp:332
static PortsList providedPorts()
void registerNodeType(const std::string &ID)
Definition: bt_factory.h:364
static const char * xml_A
int main()
GenerateWaypoints(const std::string &name, const NodeConfiguration &config)
The AsyncActionNode uses a different thread, where the action will be executed.
Definition: action_node.h:114
static const char * xml_text
double x
The SyncActionNode is an ActionNode that explicitly prevents the status RUNNING and doesn&#39;t require a...
Definition: action_node.h:52
The BehaviorTreeFactory is used to create instances of a TreeNode at run-time.
Definition: bt_factory.h:251
NodeStatus tick() override
Method to be implemented by the user.
Tree createTreeFromText(const std::string &text, Blackboard::Ptr blackboard=Blackboard::create())
Definition: bt_factory.cpp:278
NodeStatus tick() override
Method to be implemented by the user.
static const char * xml_B
UseWaypoint(const std::string &name, const NodeConfiguration &config)
std::unordered_map< std::string, PortInfo > PortsList
Definition: basic_types.h:333
Dummy action that generates a list of poses.
static PortsList providedPorts()
static const char * xml_implicit
static PortsList providedPorts()
NodeStatus
Definition: basic_types.h:35
double y
UseWaypointQueue(const std::string &name, const NodeConfiguration &config)
Simple Action that uses the output of PopFromQueue<Pose2D> or ConsumeQueue<Pose2D> ...
NodeStatus tick() override
Method to be implemented by the user.


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14