bonsai_bt/
lib.rs

1//!
2//! *Bonsai - Behavior Tree*
3//!
4//! You can serialize the
5//! behavior tree using [Serde](https://crates.io/crates/serde),
6//! [Ron](https://crates.io/crates/ron) and [graphviz](https://graphviz.org/)
7//!
8//! A _Behavior Tree_ (BT) is a data structure in which we can set the rules of how certain _behavior's_ can occur, and the order in which they would execute. BTs are a very efficient way of creating complex systems that are both modular and reactive. These properties are crucial in many applications, which has led to the spread of BT from computer game programming to many branches of AI and Robotics.
9//!
10//! ### How to use a Behavior tree?
11
12//! A Behavior Tree forms a tree structure where each node represents a process.
13//! When the process terminates, it signals `Success` or `Failure`. This can then
14//! be used by the parent node to select the next process.
15//! A signal `Running` is used to tell the process is not done yet.
16
17//! For example, if you have a state `A` and a state `B`:
18
19//! - Move from state `A` to state `B` if `A` succeeds: `Sequence([A, B])`
20//! - Try `A` first and then try `B` if `A` fails: `Select([A, B])`
21//! - If `condition` succeedes do `A`, else do `B` : `If(condition, A, B)`
22//! - If `A` succeeds, return failure (and vice-versa): `Invert(A)`
23//! - Do `B` repeatedly while `A` runs: `While(A, [B])`
24//! - Do `A`, `B` forever: `While(WaitForever, [A, B])`
25//! - Run `A` and `B` in parallell and wait for both to succeed: `WhenAll([A, B])`
26//! - Run `A` and `B` in parallell and wait for any to succeed: `WhenAny([A, B])`
27//! - Run `A` and `B` in parallell, but `A` has to succeed before `B`: `After([A, B])`
28//!
29//! See the `Behavior` enum for more information.
30
31//! ## Example of use
32
33//! This is a simple example with two possible Actions: Increment a number, Decrement a number. We
34//! construct a BT where we increment a number twice, one second apart. Then wait 0.5 seconds before we
35//! then decrement the same number again. Additionally we use a Blackboard to store/persist the immediate
36//! state of the number accessed by the key `count`.
37//!
38//! ```rust
39//! use bonsai_bt::{Event, Success, UpdateArgs, BT};
40//! use std::collections::HashMap;
41//! // Some test actions.
42//! #[derive(Clone, Debug, Copy)]
43//! pub enum Actions {
44//!     ///! Increment accumulator.
45//!     Inc,
46//!     ///! Decrement accumulator.
47//!     Dec,
48//! }
49//!
50//! // A test state machine that can increment and decrement.
51//! fn tick(mut acc: i32, dt: f64, bt: &mut BT<Actions, HashMap<String, i32>>) -> i32 {
52//! let e: Event = UpdateArgs { dt }.into();
53//!
54//!     let (_status, _dt) = bt.tick(&e, &mut |args, blackboard| match *args.action {
55//!         Actions::Inc => {
56//!             acc += 1;
57//!             (Success, args.dt)
58//!         }
59//!         Actions::Dec => {
60//!             acc -= 1;
61//!             (Success, args.dt)
62//!         }
63//!     }).unwrap();
64//!
65//!     // update counter in blackboard
66//!     let bb = bt.blackboard_mut();
67//!
68//!     bb.entry("count".to_string())
69//!         .and_modify(|count| *count = acc)
70//!         .or_insert(0)
71//!         .to_owned();
72//!
73//!     acc
74//! }
75//!
76//! fn main() {
77//!     use crate::Actions::{Inc, Dec};
78//!     use std::collections::HashMap;
79//!     use bonsai_bt::{Action, Sequence, Wait};
80//!
81//!     // create the behavior
82//!     let behavior = Sequence(vec![
83//!         Wait(1.0),
84//!         Action(Inc),
85//!         Wait(1.0),
86//!         Action(Inc),
87//!         Wait(0.5),
88//!         Action(Dec),
89//!     ]);
90//!
91//!     // you have to initialize a blackboard even though you're
92//!     // not necessarily using it for storage
93//!     let mut blackboard: HashMap<String, i32> = HashMap::new();
94//!
95//!     // instantiate the bt
96//!     let mut bt = BT::new(behavior, blackboard);
97//!
98//!     let a: i32 = 0;
99//!     let a = tick(a, 0.5, &mut bt); // have bt advance 0.5 seconds into the future
100//!     assert_eq!(a, 0);
101//!     let a = tick(a, 0.5, &mut bt); // have bt advance another 0.5 seconds into the future
102//!     assert_eq!(a, 1);
103//!     let a = tick(a, 0.5, &mut bt);
104//!     assert_eq!(a, 1);
105//!     let a = tick(a, 0.5, &mut bt);
106//!     assert_eq!(a, 2);
107//!     let a = tick(a, 0.5, &mut bt);
108//!     assert_eq!(a, 1);
109//!
110//!     let bb = bt.blackboard_mut();
111//!     let count = bb.get("count").unwrap();
112//!     assert_eq!(*count, 1);
113//!
114//!     // if the behavior tree concludes (reaches a steady state)
115//!     // you can reset the tree back to it's initial state at t=0.0
116//!     bt.reset_bt();
117//! }
118//! ```
119
120pub use behavior::Behavior::{
121    self, Action, After, AlwaysSucceed, If, Invert, Select, Sequence, Wait, WaitForever, WhenAll, WhenAny, While,
122    WhileAll,
123};
124
125pub use bt::BT;
126pub use event::{Event, Timer, UpdateArgs, UpdateEvent};
127pub use state::{ActionArgs, RUNNING};
128pub use status::Status::{self, Failure, Running, Success};
129
130mod behavior;
131mod bt;
132mod event;
133mod sequence;
134mod state;
135mod status;
136mod when_all;
137
138#[cfg(feature = "visualize")]
139mod visualizer;
140
141#[cfg(feature = "f32")]
142pub type Float = f32;
143
144#[cfg(not(feature = "f32"))]
145pub type Float = f64;