Skip to main content

BehaviorNode

Trait BehaviorNode 

Source
pub trait BehaviorNode:
    Send
    + Sync
    + Debug {
    // Required method
    fn tick<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        ctx: &'life1 Context,
    ) -> Pin<Box<dyn Future<Output = Result<NodeStatus, Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait;

    // Provided methods
    fn name(&self) -> &str { ... }
    fn children_mut(&mut self) -> Vec<&mut dyn BehaviorNode> { ... }
    fn reset<'life0, 'async_trait>(
        &'life0 mut self,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             Self: 'async_trait { ... }
    fn on_init<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        ctx: &'life1 Context,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait { ... }
    fn on_terminate<'life0, 'life1, 'async_trait>(
        &'life0 mut self,
        ctx: &'life1 Context,
    ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
       where 'life0: 'async_trait,
             'life1: 'async_trait,
             Self: 'async_trait { ... }
}
Expand description

Core trait that all behavior nodes must implement.

This is the fundamental building block of the behavior system. Everything - from simple actions to complex AI models to composition primitives - implements this trait.

§Design Principles

  1. Simplicity - One method: tick()
  2. Async-first - All behaviors are async by default
  3. Composable - Nodes can be freely combined
  4. Type-safe - Rust’s type system ensures correctness

§Example

use mecha10_behavior_runtime::prelude::*;

#[derive(Debug)]
struct PrintMessage {
    message: String,
}

#[async_trait]
impl BehaviorNode for PrintMessage {
    async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus> {
        println!("{}", self.message);
        Ok(NodeStatus::Success)
    }

    fn name(&self) -> &str {
        "print_message"
    }
}

Required Methods§

Source

fn tick<'life0, 'life1, 'async_trait>( &'life0 mut self, ctx: &'life1 Context, ) -> Pin<Box<dyn Future<Output = Result<NodeStatus, Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Execute one tick of the behavior.

This method is called repeatedly by the execution engine. It should:

  • Perform one unit of work
  • Return quickly (non-blocking)
  • Return NodeStatus to indicate progress
§Arguments
  • ctx - Execution context with access to messaging, sensors, etc.
§Returns
  • NodeStatus::Success - Behavior completed successfully
  • NodeStatus::Failure - Behavior failed (irrecoverable error)
  • NodeStatus::Running - Behavior is still executing (call again)
§Errors

Return an error for exceptional conditions that should halt execution. For recoverable failures, return Ok(NodeStatus::Failure) instead.

Provided Methods§

Source

fn name(&self) -> &str

Get the name of this behavior node.

Used for debugging, logging, and monitoring. The default implementation returns the type name.

Source

fn children_mut(&mut self) -> Vec<&mut dyn BehaviorNode>

Return mutable references to this node’s child behaviors, in the order they should receive lifecycle events.

Leaf nodes have no children and should not override this - the default implementation returns an empty list. Composite nodes (e.g. SequenceNode, SelectOrNode, ParallelNode, SubsumptionNode, EnsembleNode) override this to expose their children, which drives the default on_init/ on_terminate/reset propagation below without each composite having to hand-roll the same loop.

Source

fn reset<'life0, 'async_trait>( &'life0 mut self, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, Self: 'async_trait,

Reset the behavior to its initial state.

Called when the behavior needs to be restarted (e.g., in a loop or after a failure). The default implementation propagates the reset to every child returned by children_mut.

Source

fn on_init<'life0, 'life1, 'async_trait>( &'life0 mut self, ctx: &'life1 Context, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Called when the behavior is first initialized.

Use this for one-time setup like loading models, establishing connections, etc. The default implementation propagates on_init to every child returned by children_mut.

Source

fn on_terminate<'life0, 'life1, 'async_trait>( &'life0 mut self, ctx: &'life1 Context, ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Called when the behavior is being terminated.

Use this for cleanup like closing connections, saving state, etc. The default implementation propagates on_terminate to every child returned by children_mut.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§