Coverage Report

Created: 2025-08-26 06:29

/src/behaviortreecpp/src/controls/sequence_node.cpp
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2015-2018 Michele Colledanchise -  All Rights Reserved
2
 * Copyright (C) 2018-2020 Davide Faconti, Eurecat -  All Rights Reserved
3
*
4
*   Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
5
*   to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6
*   and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
*   The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
*
9
*   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10
*   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
11
*   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
*/
13
14
#include "behaviortree_cpp/controls/sequence_node.h"
15
16
namespace BT
17
{
18
SequenceNode::SequenceNode(const std::string& name, bool make_async)
19
103
  : ControlNode::ControlNode(name, {}), current_child_idx_(0), asynch_(make_async)
20
103
{
21
103
  if(asynch_)
22
0
    setRegistrationID("AsyncSequence");
23
103
  else
24
103
    setRegistrationID("Sequence");
25
103
}
26
27
void SequenceNode::halt()
28
129
{
29
129
  current_child_idx_ = 0;
30
129
  skipped_count_ = 0;
31
129
  ControlNode::halt();
32
129
}
33
34
NodeStatus SequenceNode::tick()
35
0
{
36
0
  const size_t children_count = children_nodes_.size();
37
38
0
  if(!isStatusActive(status()))
39
0
  {
40
0
    skipped_count_ = 0;
41
0
  }
42
43
0
  setStatus(NodeStatus::RUNNING);
44
45
0
  while(current_child_idx_ < children_count)
46
0
  {
47
0
    TreeNode* current_child_node = children_nodes_[current_child_idx_];
48
49
0
    auto prev_status = current_child_node->status();
50
0
    const NodeStatus child_status = current_child_node->executeTick();
51
52
0
    switch(child_status)
53
0
    {
54
0
      case NodeStatus::RUNNING: {
55
0
        return NodeStatus::RUNNING;
56
0
      }
57
0
      case NodeStatus::FAILURE: {
58
        // Reset on failure
59
0
        resetChildren();
60
0
        current_child_idx_ = 0;
61
0
        return child_status;
62
0
      }
63
0
      case NodeStatus::SUCCESS: {
64
0
        current_child_idx_++;
65
        // Return the execution flow if the child is async,
66
        // to make this interruptible.
67
0
        if(asynch_ && requiresWakeUp() && prev_status == NodeStatus::IDLE &&
68
0
           current_child_idx_ < children_count)
69
0
        {
70
0
          emitWakeUpSignal();
71
0
          return NodeStatus::RUNNING;
72
0
        }
73
0
      }
74
0
      break;
75
76
0
      case NodeStatus::SKIPPED: {
77
        // It was requested to skip this node
78
0
        current_child_idx_++;
79
0
        skipped_count_++;
80
0
      }
81
0
      break;
82
83
0
      case NodeStatus::IDLE: {
84
0
        throw LogicError("[", name(), "]: A children should not return IDLE");
85
0
      }
86
0
    }  // end switch
87
0
  }    // end while loop
88
89
  // The entire while loop completed. This means that all the children returned SUCCESS.
90
0
  const bool all_children_skipped = (skipped_count_ == children_count);
91
0
  if(current_child_idx_ == children_count)
92
0
  {
93
0
    resetChildren();
94
0
    current_child_idx_ = 0;
95
0
    skipped_count_ = 0;
96
0
  }
97
  // Skip if ALL the nodes have been skipped
98
0
  return (all_children_skipped) ? NodeStatus::SKIPPED : NodeStatus::SUCCESS;
99
0
}
100
101
}  // namespace BT