Skip to main content

behaviortree_rs/nodes/control/
reactive_fallback.rs

1use behaviortree_rs_derive::bt_node;
2
3use crate::{
4    basic_types::NodeStatus,
5    nodes::{NodeError, NodeResult},
6};
7
8/// The ReactiveFallback is similar to a ParallelNode.
9/// All the children are ticked from first to last:
10///
11/// - If a child returns RUNNING, continue to the next sibling.
12/// - If a child returns FAILURE, continue to the next sibling.
13/// - If a child returns SUCCESS, stop and return SUCCESS.
14///
15/// If all the children fail, than this node returns FAILURE.
16///
17/// IMPORTANT: to work properly, this node should not have more than
18///            a single asynchronous child.
19#[bt_node(ControlNode)]
20pub struct ReactiveFallbackNode {}
21
22#[bt_node(ControlNode)]
23impl ReactiveFallbackNode {
24    async fn tick(&mut self) -> NodeResult {
25        let mut all_skipped = true;
26        node_.status = NodeStatus::Running;
27
28        for index in 0..node_.children.len() {
29            let cur_child = &mut node_.children[index];
30
31            let child_status = cur_child.execute_tick().await?;
32
33            all_skipped &= child_status == NodeStatus::Skipped;
34
35            match &child_status {
36                NodeStatus::Running => {
37                    for i in 0..index {
38                        node_.halt_child_idx(i).await?;
39                    }
40
41                    return Ok(NodeStatus::Running);
42                }
43                NodeStatus::Failure => {}
44                NodeStatus::Success => {
45                    node_.reset_children().await;
46                    return Ok(NodeStatus::Success);
47                }
48                NodeStatus::Skipped => {
49                    node_.halt_child_idx(index).await?;
50                }
51                NodeStatus::Idle => {
52                    return Err(NodeError::StatusError(
53                        "Name here".to_string(),
54                        "Idle".to_string(),
55                    ));
56                }
57            };
58        }
59
60        node_.reset_children().await;
61
62        match all_skipped {
63            true => Ok(NodeStatus::Skipped),
64            false => Ok(NodeStatus::Failure),
65        }
66    }
67
68    async fn halt(&mut self) {
69        node_.reset_children().await;
70    }
71}