Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
round_robin_node.cpp
1 // Copyright (c) 2019 Intel Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <string>
16 
17 #include "nav2_behavior_tree/plugins/control/round_robin_node.hpp"
18 
19 namespace nav2_behavior_tree
20 {
21 
22 RoundRobinNode::RoundRobinNode(const std::string & name)
23 : BT::ControlNode::ControlNode(name, {}), wrap_around_(false)
24 {
25 }
26 
28  const std::string & name,
29  const BT::NodeConfiguration & config)
30 : BT::ControlNode(name, config)
31 {
32  getInput("wrap_around", wrap_around_);
33 }
34 
35 BT::NodeStatus RoundRobinNode::tick()
36 {
37  const auto num_children = children_nodes_.size();
38 
39  setStatus(BT::NodeStatus::RUNNING);
40  unsigned num_skipped_children = 0;
41 
42  while (num_failed_children_ + num_skipped_children < num_children) {
43  TreeNode * child_node = children_nodes_[current_child_idx_];
44  const BT::NodeStatus child_status = child_node->executeTick();
45 
46  if (child_status != BT::NodeStatus::RUNNING) {
47  // Increment index and wrap around to the first child if enabled
48  if (++current_child_idx_ == num_children) {
49  if (wrap_around_) {
50  current_child_idx_ = 0;
51  } else {
52  if (child_status == BT::NodeStatus::SKIPPED) {
53  num_skipped_children++;
54  } else if (child_status == BT::NodeStatus::FAILURE) {
55  num_failed_children_++;
56  }
57  // Exit early if wrap around is disabled and we've reached the end
58  break;
59  }
60  }
61  }
62 
63  switch (child_status) {
64  case BT::NodeStatus::SUCCESS:
65  {
66  num_failed_children_ = 0;
67  ControlNode::haltChildren();
68  return BT::NodeStatus::SUCCESS;
69  }
70 
71  case BT::NodeStatus::FAILURE:
72  {
73  num_failed_children_++;
74  break;
75  }
76 
77  case BT::NodeStatus::SKIPPED:
78  {
79  num_skipped_children++;
80  break;
81  }
82  case BT::NodeStatus::RUNNING:
83  return BT::NodeStatus::RUNNING;
84 
85  default:
86  throw BT::LogicError("Invalid status return from BT node");
87  }
88  }
89 
90  const bool all_skipped = (num_skipped_children == num_children);
91  halt();
92  // If all the children were skipped, this node is considered skipped
93  return all_skipped ? BT::NodeStatus::SKIPPED : BT::NodeStatus::FAILURE;
94 }
95 
97 {
98  ControlNode::halt();
99  current_child_idx_ = 0;
100  num_failed_children_ = 0;
101 }
102 
103 } // namespace nav2_behavior_tree
104 
105 BT_REGISTER_NODES(factory)
106 {
107  factory.registerNodeType<nav2_behavior_tree::RoundRobinNode>("RoundRobin");
108 }
Type of sequence node that ticks children in a round-robin fashion.
void halt() override
The other (optional) override required by a BT action to reset node state.
BT::NodeStatus tick() override
The main override required by a BT action.
RoundRobinNode(const std::string &name)
A constructor for nav2_behavior_tree::RoundRobinNode.