#behavior-tree #cpp #robust

behaviortree-rs

Rust implementation of BehaviorTree.CPP, a robust behavior tree library in C++

3 unstable releases

new 0.2.3 Apr 25, 2024
0.2.2 Mar 1, 2024
0.2.1 Feb 5, 2024
0.1.2 Feb 2, 2024
0.1.0 Jan 16, 2024

#331 in Machine learning

Download history 3/week @ 2024-01-11 10/week @ 2024-02-01 36/week @ 2024-02-15 39/week @ 2024-02-22 198/week @ 2024-02-29 106/week @ 2024-03-07 88/week @ 2024-03-14 130/week @ 2024-03-21 90/week @ 2024-03-28 24/week @ 2024-04-04 3/week @ 2024-04-11

276 downloads per month

MIT license

125KB
2.5K SLoC

behaviortree-rs

Rust implementation of BehaviorTree.CPP. Still a WIP. A table of features can be found below.

Usage

To create your own custom nodes in behaviortree-rs, you need to use the provided attribute macro to transform your struct and impl blocks. You also need to implement certain functions for each node type, plus the option to implement some optional functions.

Creating a node

To create your own node, use the #[bt_node(...)] macro. The argument to the macro is the type of node you want to create. The bt_node macro modifies your struct, adding fields, and method implementations.

For example, the following node definition:

use behaviortree_rs::bt_node;

#[bt_node(SyncActionNode)]
struct DummyActionNode {}

#[bt_node(SyncActionNode)]
impl DummyActionNode {
// Implementations go here
}

Of course, you can add your own fields to the struct, which get included in the generated struct. When you add fields, you have the option to require their definition in the node constructor, or have a default value that is populated without the ability to modify when instantiating the node.

#[bt_node(SyncActionNode)]
struct DummyActionNode {
foo: String,
bar: u32
}

If you don't want the ability to set a field manually at initialization time, add the #[bt(default)] attribute. Just writing #[bt(default)] will call <type>::default(), which only works if the specified type implements the Default trait. To specify an explicit default value: #[bt(default = "10")]. Notice the value is wrapped in quotes, so the text in the quotes will be evaluated as Rust code. The valid options to provide as a default are:

// Function calls
#[bt(default = "String::from(10)")]

// Variables
#[bt(default = "foo")]

// Paths (like enums)
#[bt(default = "NodeStatus::Idle")]

// Literals
#[bt(default = "10")]

An example in practice:

use behaviortree_rs::bt_node;

#[bt_node(SyncActionNode)]
struct DummyActionNode {
#[bt(default = "NodeStatus::Success")]
foo: NodeStatus,
#[bt(default)] // defaults to empty String
bar: String
}

Node functions

use behaviortree_rs::prelude::*;

#[bt_node(SyncActionNode)]
struct DummyActionStruct {}

#[bt_node(
SyncActionNode,
ports = ports,
tick = tick,
)]
impl DummyActionStruct {
async fn tick(&mut self) -> NodeResult {
// Some implementation
// ...

// You must return a `NodeStatus` (i.e. Failure, Success, Running, or Skipped)
// Or an Err
Ok(NodeStatus::Success)
}

fn ports() -> PortsList {
define_ports!(
// No default value
input_port!("foo"),
// With default value
input_port!("bar", 16)
)
}
}

Dependencies

~5–7.5MB
~130K SLoC