Skip to main content

behaviortree_rs/nodes/control/
sequence_star.rs

1use behaviortree_rs_derive::bt_node;
2
3use crate::{
4    basic_types::NodeStatus,
5    nodes::{NodeError, NodeResult},
6};
7/// The SequenceStarNode is used to tick children in an ordered sequence.
8/// If any child returns RUNNING, previous children are not ticked again.
9///
10/// - If all the children return SUCCESS, this node returns SUCCESS.
11///
12/// - If a child returns RUNNING, this node returns RUNNING.
13///   Loop is NOT restarted, the same running child will be ticked again.
14///
15/// - If a child returns FAILURE, stop the loop and return FAILURE.
16///   Loop is NOT restarted, the same running child will be ticked again.
17#[bt_node(ControlNode)]
18pub struct SequenceWithMemoryNode {
19    #[bt(default = "0")]
20    child_idx: usize,
21    #[bt(default = "false")]
22    all_skipped: bool,
23}
24
25#[bt_node(ControlNode)]
26impl SequenceWithMemoryNode {
27    async fn tick(&mut self) -> NodeResult {
28        if node_.status == NodeStatus::Idle {
29            self.all_skipped = true;
30        }
31
32        node_.status = NodeStatus::Running;
33
34        while self.child_idx < node_.children.len() {
35            let cur_child = &mut node_.children[self.child_idx];
36
37            let _prev_status = cur_child.status();
38            let child_status = cur_child.execute_tick().await?;
39
40            self.all_skipped &= child_status == NodeStatus::Skipped;
41
42            match &child_status {
43                NodeStatus::Running => return Ok(NodeStatus::Running),
44                NodeStatus::Failure => {
45                    // Do NOT reset child_idx on failure
46                    // Halt children at and after this index
47                    node_.halt_children(self.child_idx).await?;
48
49                    return Ok(NodeStatus::Failure);
50                }
51                NodeStatus::Success | NodeStatus::Skipped => {
52                    self.child_idx += 1;
53                }
54                NodeStatus::Idle => {
55                    return Err(NodeError::StatusError(
56                        "SequenceStarNode".to_string(),
57                        "Idle".to_string(),
58                    ))
59                }
60            };
61        }
62
63        // All children returned Success
64        if self.child_idx == node_.children.len() {
65            node_.reset_children().await;
66            self.child_idx = 0;
67        }
68
69        match self.all_skipped {
70            true => Ok(NodeStatus::Skipped),
71            false => Ok(NodeStatus::Failure),
72        }
73    }
74
75    async fn halt(&mut self) {
76        self.child_idx = 0;
77        node_.reset_children().await;
78    }
79}