mecha10-behavior-patterns 0.1.23

Common behavior patterns for Mecha10 - subsumption, ensemble, and more
Documentation
# Mecha10 Behavior Patterns

Common behavior patterns as reusable `BehaviorNode` implementations for robotics and AI systems.

## Overview

This package provides two fundamental behavior patterns that solve common robotics problems:

1. **Subsumption** - Priority-based layered control for safety-critical systems
2. **Ensemble** - Multi-model fusion with various voting strategies

Both patterns implement the `BehaviorNode` trait from `mecha10-behavior-runtime`, making them composable with other behaviors.

## Installation

```toml
[dependencies]
mecha10-behavior-patterns = "0.1.0"
```

## Patterns

### Subsumption Architecture

The subsumption architecture organizes behaviors in priority layers. Higher priority behaviors can override lower priority ones. This is essential for safety-critical systems.

#### How It Works

- Layers are executed in order of priority (highest first)
- If a layer returns `Success` or `Running`, that status is returned immediately
- If a layer returns `Failure`, the next lower priority layer is tried
- If all layers fail, the node returns `Failure`

#### Example: Robot Navigation with Safety

```rust
use mecha10_behavior_patterns::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let ctx = Context::new("robot").await?;

    // Create subsumption architecture
    let mut subsumption = SubsumptionNode::new()
        .add_named_layer(10, "emergency_stop", Box::new(EmergencyStopBehavior))
        .add_named_layer(5, "avoid_obstacle", Box::new(AvoidObstacleBehavior))
        .add_named_layer(1, "navigate", Box::new(NavigateBehavior));

    // Execute
    let mut executor = BehaviorExecutor::new(Box::new(subsumption), 30.0);
    executor.run_until_complete(&ctx).await?;

    Ok(())
}
```

#### Priority Levels

We recommend this priority scheme:

- **10**: Emergency stop / safety critical
- **7-9**: Reactive obstacle avoidance
- **4-6**: Local navigation / path following
- **1-3**: High-level planning / goal pursuit

#### Use Cases

- **Safety systems**: Emergency stop overrides all other behaviors
- **Reactive control**: Obstacle avoidance overrides navigation
- **Hierarchical control**: Multiple layers of abstraction
- **Behavior arbitration**: Multiple behaviors competing for control

### Ensemble Learning

The ensemble pattern combines multiple AI models or behaviors to make more robust decisions. This is useful for redundancy, fault tolerance, and multi-modal sensor fusion.

#### Strategies

1. **Conservative** - All models must agree (high precision, low recall)
   ```rust
   let ensemble = EnsembleNode::new(EnsembleStrategy::Conservative)
       .add_model(Box::new(YoloV8), 1.0)
       .add_model(Box::new(YoloV10), 1.0);
   ```

2. **Optimistic** - Any model can succeed (high recall, low precision)
   ```rust
   let ensemble = EnsembleNode::new(EnsembleStrategy::Optimistic)
       .add_model(Box::new(PreciseSensor), 1.0)
       .add_model(Box::new(FallbackSensor), 1.0);
   ```

3. **Majority** - More than half must agree (balanced)
   ```rust
   let ensemble = EnsembleNode::new(EnsembleStrategy::Majority)
       .add_model(Box::new(Model1), 1.0)
       .add_model(Box::new(Model2), 1.0)
       .add_model(Box::new(Model3), 1.0);
   ```

4. **WeightedVote** - Weighted voting with threshold
   ```rust
   let ensemble = EnsembleNode::new(EnsembleStrategy::WeightedVote)
       .with_threshold(0.6)  // 60% threshold
       .add_model(Box::new(HighAccuracyModel), 0.5)
       .add_model(Box::new(FastModel), 0.3)
       .add_model(Box::new(BackupModel), 0.2);
   ```

#### Example: Multi-Model Object Detection

```rust
use mecha10_behavior_patterns::prelude::*;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let ctx = Context::new("detector").await?;

    // Combine multiple YOLO models with weighted voting
    let ensemble = EnsembleNode::new(EnsembleStrategy::WeightedVote)
        .with_threshold(0.7)
        .add_named_model("yolov8", Box::new(YoloV8Detector), 0.4)
        .add_named_model("yolov10", Box::new(YoloV10Detector), 0.4)
        .add_named_model("custom", Box::new(CustomDetector), 0.2);

    // Execute
    let mut executor = BehaviorExecutor::new(Box::new(ensemble), 10.0);
    let (status, stats) = executor.run_until_complete(&ctx).await?;

    println!("Detection complete: {} in {} ticks", status, stats.tick_count);
    Ok(())
}
```

#### Use Cases

- **Multi-model AI**: Combine YOLO, custom models for robust detection
- **Sensor fusion**: Merge data from multiple sensors (LIDAR + camera)
- **Fault tolerance**: Redundant models for critical systems
- **Confidence boosting**: Require multiple models to agree

## Combining Patterns

Subsumption and Ensemble can be combined for powerful control architectures:

```rust
// Safety layer uses ensemble of multiple safety checks
let safety_ensemble = EnsembleNode::new(EnsembleStrategy::Conservative)
    .add_model(Box::new(BatteryCheck), 1.0)
    .add_model(Box::new(TemperatureCheck), 1.0)
    .add_model(Box::new(ObstacleCheck), 1.0);

// Navigation uses ensemble of path planners
let nav_ensemble = EnsembleNode::new(EnsembleStrategy::WeightedVote)
    .add_model(Box::new(AStarPlanner), 0.6)
    .add_model(Box::new(RRTPlanner), 0.4);

// Combine with subsumption
let control = SubsumptionNode::new()
    .add_layer(10, Box::new(safety_ensemble))
    .add_layer(1, Box::new(nav_ensemble));
```

## JSON Configuration

Both patterns support JSON configuration (when used with the node registry):

### Subsumption JSON

```json
{
  "type": "subsumption",
  "layers": [
    {
      "priority": 10,
      "name": "emergency_stop",
      "node": "emergency_stop_behavior",
      "config": { "max_speed": 0.0 }
    },
    {
      "priority": 5,
      "name": "avoid_obstacle",
      "node": "obstacle_avoidance",
      "config": { "safety_distance": 0.5 }
    }
  ]
}
```

### Ensemble JSON

```json
{
  "type": "ensemble",
  "strategy": "weighted_vote",
  "threshold": 0.6,
  "models": [
    {
      "name": "yolov8",
      "node": "yolo_v8_detector",
      "weight": 0.4,
      "config": { "confidence": 0.7 }
    },
    {
      "name": "yolov10",
      "node": "yolo_v10_detector",
      "weight": 0.6,
      "config": { "confidence": 0.7 }
    }
  ]
}
```

## Testing

```bash
# Run tests
cargo test -p mecha10-behavior-patterns

# Run clippy
cargo clippy -p mecha10-behavior-patterns -- -D warnings
```

## Architecture

Both patterns are built on top of `mecha10-behavior-runtime` and implement the `BehaviorNode` trait:

```rust
#[async_trait]
pub trait BehaviorNode: Send + Sync + Debug {
    async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus>;
    // ... lifecycle methods ...
}
```

This makes them fully composable with:
- Core composition primitives (Sequence, Selector, Parallel)
- Other pattern nodes
- Custom behavior implementations
- AI inference nodes (Vision, Language, etc.)

## Performance

- **Subsumption**: O(n) where n = number of layers
- **Ensemble**: O(m) where m = number of models (executed in parallel)

Both patterns are designed for real-time performance with minimal overhead.

## See Also

- [mecha10-behavior-runtime]../behavior-runtime/README.md - Core behavior system
- [AI Features Documentation]../../docs/AI_FEATURES.md - AI integration guide
- [TODOS.md]../../TODOS.md - Priority 7: AI Native features

## License

MIT