Files
wifi-densepose/crates/ruvector-robotics/examples/behavior_tree.rs
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

86 lines
3.1 KiB
Rust

//! Example: composable behavior trees for robot task execution.
//!
//! Demonstrates:
//! - Building a patrol behavior with sequence/selector/decorator nodes
//! - Ticking the tree and observing status changes
//! - Using the blackboard for inter-node communication
use ruvector_robotics::cognitive::{
BehaviorNode, BehaviorStatus, BehaviorTree, DecoratorType,
};
fn main() {
println!("=== Behavior Tree Demo ===\n");
// Build a patrol behavior:
// Selector [
// Sequence [has_obstacle → avoid_obstacle]
// Sequence [has_target → move_to_target → interact]
// Repeat(3) [ patrol_waypoint ]
// ]
let tree_root = BehaviorNode::Selector(vec![
// Priority 1: avoid obstacles
BehaviorNode::Sequence(vec![
BehaviorNode::Condition("has_obstacle".into()),
BehaviorNode::Action("avoid_obstacle".into()),
]),
// Priority 2: pursue target
BehaviorNode::Sequence(vec![
BehaviorNode::Condition("has_target".into()),
BehaviorNode::Action("move_to_target".into()),
BehaviorNode::Action("interact".into()),
]),
// Priority 3: patrol
BehaviorNode::Decorator(
DecoratorType::Repeat(3),
Box::new(BehaviorNode::Action("patrol_waypoint".into())),
),
]);
let mut tree = BehaviorTree::new(tree_root);
// Scenario 1: No obstacle, no target → patrol
println!("--- Scenario 1: Patrolling ---");
tree.set_action_result("patrol_waypoint", BehaviorStatus::Success);
tree.set_action_result("avoid_obstacle", BehaviorStatus::Success);
tree.set_action_result("move_to_target", BehaviorStatus::Success);
tree.set_action_result("interact", BehaviorStatus::Success);
let status = tree.tick();
println!(" Tick 1 result: {:?}", status);
println!(" (Should patrol since no conditions are true)\n");
// Scenario 2: Obstacle detected
println!("--- Scenario 2: Obstacle detected ---");
tree.set_condition("has_obstacle", true);
let status = tree.tick();
println!(" Tick 2 result: {:?}", status);
println!(" (Should avoid obstacle via selector priority)\n");
// Scenario 3: Obstacle cleared, target found
println!("--- Scenario 3: Target acquired ---");
tree.set_condition("has_obstacle", false);
tree.set_condition("has_target", true);
let status = tree.tick();
println!(" Tick 3 result: {:?}", status);
println!(" (Should move to target and interact)\n");
// Scenario 4: Timeout decorator
println!("--- Scenario 4: Timeout behavior ---");
let timeout_tree = BehaviorNode::Decorator(
DecoratorType::Timeout(2),
Box::new(BehaviorNode::Action("long_task".into())),
);
let mut t2 = BehaviorTree::new(timeout_tree);
t2.set_action_result("long_task", BehaviorStatus::Running);
for i in 1..=4 {
let s = t2.tick();
println!(" Tick {}: {:?}{}", i, s,
if s == BehaviorStatus::Failure { " (TIMED OUT)" } else { "" }
);
}
println!("\nFinal tick count: {}", tree.context().tick_count);
}