Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
persistent_sequence.cpp
1 // Copyright (c) 2025 Enjoy Robotics
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 "nav2_behavior_tree/plugins/control/persistent_sequence.hpp"
16 #include "behaviortree_cpp/action_node.h"
17 #include "behaviortree_cpp/bt_factory.h"
18 
19 namespace nav2_behavior_tree
20 {
21 
22 PersistentSequenceNode::PersistentSequenceNode(
23  const std::string & name,
24  const BT::NodeConfiguration & conf)
25 : BT::ControlNode::ControlNode(name, conf) {}
26 
27 BT::NodeStatus PersistentSequenceNode::tick()
28 {
29  const int children_count = children_nodes_.size();
30 
31  int current_child_idx;
32  if (!getInput("current_child_idx", current_child_idx)) {
33  throw BT::RuntimeError(
34  "Missing required input [current_child_idx] in PersistentSequenceNode. "
35  "Set via <Script code=\"current_child_idx := 0\" />");
36  }
37 
38  setStatus(BT::NodeStatus::RUNNING);
39 
40  while (current_child_idx < children_count) {
41  TreeNode * current_child_node = children_nodes_[current_child_idx];
42  const BT::NodeStatus child_status = current_child_node->executeTick();
43 
44  switch (child_status) {
45  case BT::NodeStatus::RUNNING:
46  return child_status;
47 
48  case BT::NodeStatus::FAILURE:
49  // Reset on failure
50  resetChildren();
51  current_child_idx = 0;
52  setOutput("current_child_idx", 0);
53  return child_status;
54 
55  case BT::NodeStatus::SUCCESS:
56  case BT::NodeStatus::SKIPPED:
57  // Skip the child node
58  current_child_idx++;
59  setOutput("current_child_idx", current_child_idx);
60  break;
61 
62  case BT::NodeStatus::IDLE:
63  throw std::runtime_error("A child node must never return IDLE");
64  } // end switch
65  } // end while loop
66 
67  // The entire while loop completed. This means that all the children returned SUCCESS.
68  if (current_child_idx >= children_count) {
69  resetChildren();
70  setOutput("current_child_idx", 0);
71  }
72  return BT::NodeStatus::SUCCESS;
73 }
74 
75 } // namespace nav2_behavior_tree
76 
77 BT_REGISTER_NODES(factory)
78 {
79  BT::NodeBuilder builder =
80  [](const std::string & name, const BT::NodeConfiguration & config)
81  {
82  return std::make_unique<nav2_behavior_tree::PersistentSequenceNode>(
83  name, config);
84  };
85 
86  factory.registerBuilder<nav2_behavior_tree::PersistentSequenceNode>(
87  "PersistentSequence", builder);
88 }
The PersistentSequenceNode is similar to the SequenceNode, but it stores the index of the last runnin...