# {{project_name}}

A Mecha10 robotics project.

## Table of Contents

- [Getting Started](#getting-started)
- [Project Structure](#project-structure)
- [Configuration System](#configuration-system)
- [Behavior Trees](#behavior-trees)
- [Behavior Executors](#behavior-executors)
- [Working with Components](#working-with-components)
- [Project Cleanup](#project-cleanup)
- [Troubleshooting](#troubleshooting)
- [Documentation](#documentation)

## Getting Started

### Setup

Install Python dependencies for AI nodes (required for model quantization and inference):

```bash
mecha10 setup
```

Or manually:

```bash
pip install -r requirements.txt
```

**Python Requirements:**
- Python 3.8+
- `onnx` - ONNX model format support
- `onnxruntime` - AI model inference and quantization

### Development

Start the development environment:

```bash
mecha10 dev
```

### Building

Build the project:

```bash
mecha10 build
```

### Running

Run the robot:

```bash
mecha10 run
```

## Project Structure

```
{{project_name}}/
├── behaviors/              # Behavior tree definitions (source of truth)
│   ├── idle_wander.json   # Simple wandering behavior
│   └── patrol_simple.json # Square patrol pattern
├── configs/
│   ├── nodes/             # Node configurations (environment-aware)
│   │   └── @mecha10/      # Framework nodes
│   │       ├── speaker/
│   │       │   └── config.json
│   │       ├── listener/
│   │       │   └── config.json
│   │       └── ...
│   └── simulation/        # Simulation settings
│       └── config.json
├── nodes/                 # Custom task nodes
├── drivers/               # Hardware drivers
├── types/                 # Custom message types
├── simulation/            # Simulation files
├── logs/                  # Runtime logs
└── mecha10.json          # Project configuration
```

## Configuration System

Mecha10 uses an **environment-aware configuration system** with **lifecycle-based node management**.

### Lifecycle Configuration (`mecha10.json`)

The `lifecycle` section in `mecha10.json` defines **operational modes** that control which nodes run in different contexts:

```json
{
  "lifecycle": {
    "modes": {
      "dev": {
        "description": "Basic development - minimal nodes for testing",
        "nodes": ["@mecha10/listener", "@mecha10/speaker"]
      },
      "simulation": {
        "description": "Full simulation with vision and AI",
        "nodes": ["@mecha10/simulation-bridge", "@mecha10/image-classifier", "@mecha10/object-detector"]
      }
    },
    "default_mode": "dev"
  }
}
```

**How modes work:**
- `default_mode`: The mode that starts when you run `mecha10 dev`
- `modes.{name}.nodes`: List of node names that should run in this mode
- When switching modes, nodes not in the target mode are automatically stopped

**Switching modes at runtime:**
- Press `s` to enter simulation mode (starts simulation nodes + Godot)
- Press `t` to enter teleop mode (if configured)

### Node Configuration Files

Node configs use an **environment-aware format** with `dev` and `production` sections in a single file:

**Location:** `configs/nodes/@mecha10/{node-name}/config.json`

**Switching Environments:**

```bash
# Development (default)
MECHA10_ENVIRONMENT=dev mecha10 dev

# Production
MECHA10_ENVIRONMENT=production mecha10 dev
```

### Node Configuration Pattern

All node configs contain both `dev` and `production` environments:

**Example: Speaker Node** (`configs/nodes/@mecha10/speaker/config.json`)

```json
{
  "dev": {
    "interval_secs": 2,
    "message_prefix": "Hello from speaker"
  },
  "production": {
    "interval_secs": 5,
    "message_prefix": "Hello from speaker"
  }
}
```

**Example: Behavior Executor** (`configs/nodes/@mecha10/behavior-executor/config.json`)

```json
{
  "dev": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 5.0,
    "max_ticks": null,
    "log_stats": true,
    "topics": {
      "publishes": [{ "status": "/behavior/status" }],
      "subscribes": [{ "control": "/behavior/control" }]
    }
  },
  "production": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 20.0,
    "max_ticks": null,
    "log_stats": false,
    "topics": {
      "publishes": [{ "status": "/behavior/status" }],
      "subscribes": [{ "control": "/behavior/control" }]
    }
  }
}
```

**Topics Configuration:**

All node configs **should** include a `topics` field for static topology analysis:

```json
{
  "dev": {
    "topics": {
      "publishes": [
        { "output": "/topic/path" },
        { "status": "/status" }
      ],
      "subscribes": [
        { "input": "/input/topic" }
      ]
    }
  },
  "production": {
    "topics": { ... }
  }
}
```

Each topic is an object with:
- **Key** = Semantic name (e.g., "output", "status", "cmd_vel")
- **Value** = Topic path (e.g., "/vision/classification", "/motor/status")

### Simulation Configuration

Simulation config also uses environment-aware format:

**Location:** `configs/simulation/config.json`

```json
{
  "dev": {
    "model": "@mecha10/simulation-models/rover",
    "environment": "@mecha10/simulation-environments/basic_arena",
    "godot": {
      "headless": false,
      "viewport_width": 320,
      "viewport_height": 320
    }
  },
  "production": {
    "godot": {
      "headless": true
    }
  }
}
```

## Behavior Trees

Mecha10 uses behavior trees for autonomous robot control. Behaviors are:
- **Defined in JSON** - Easy to modify without recompiling
- **Environment-specific** - Different behaviors for dev vs production
- **Composable** - Built from action nodes and composition nodes

### Quick Start

**1. Configure which behavior to run:**

Edit `configs/nodes/@mecha10/behavior-executor/config.json`:

```json
{
  "dev": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 5.0,
    "log_stats": true
  },
  "production": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 20.0,
    "log_stats": false
  }
}
```

**2. Add to lifecycle mode:**

Edit `mecha10.json`:

```json
{
  "lifecycle": {
    "modes": {
      "simulation": {
        "nodes": [
          "@mecha10/simulation-bridge",
          "@mecha10/behavior-executor"
        ]
      }
    }
  }
}
```

**3. Run:**

```bash
mecha10 dev --mode simulation
```

### Behavior Tree Structure

**Basic example** (`behaviors/idle_wander.json`):

```json
{
  "$schema": "https://mecha10.dev/schemas/behavior-composition-v1.json",
  "name": "idle_wander",
  "description": "Simple random wandering behavior",
  "root": {
    "type": "node",
    "node": "wander",
    "config": {
      "topic": "/motor/cmd_vel",
      "linear_speed": 0.3,
      "angular_speed": 0.5,
      "change_interval_secs": 3.0
    }
  }
}
```

**Advanced example** with composition:

```json
{
  "name": "explore",
  "root": {
    "type": "selector",
    "children": [
      {
        "type": "sequence",
        "children": [
          {
            "type": "node",
            "node": "sensor_check",
            "config": {
              "topic": "/sensors/obstacle",
              "field": "distance",
              "operator": "less_than",
              "threshold": 0.5
            }
          },
          {
            "type": "node",
            "node": "move",
            "config": {
              "topic": "/motor/cmd_vel",
              "linear": -0.3,
              "angular": 0.8,
              "duration_secs": 2.0
            }
          }
        ]
      },
      {
        "type": "node",
        "node": "wander",
        "config": {
          "topic": "/motor/cmd_vel",
          "linear_speed": 0.3,
          "angular_speed": 0.5,
          "change_interval_secs": 3.0
        }
      }
    ]
  }
}
```

### Built-in Action Nodes

#### WanderNode
Random movement with periodic direction changes:
```json
{
  "type": "node",
  "node": "wander",
  "config": {
    "topic": "/motor/cmd_vel",
    "linear_speed": 0.3,
    "angular_speed": 0.5,
    "change_interval_secs": 3.0
  }
}
```
**Returns:** `Running` continuously

#### MoveNode
Fixed velocity for specified duration:
```json
{
  "type": "node",
  "node": "move",
  "config": {
    "topic": "/motor/cmd_vel",
    "linear": 0.5,
    "angular": 0.0,
    "duration_secs": 2.0
  }
}
```
**Returns:** `Running` while executing, `Success` when complete

#### TimerNode
Wait for specified duration:
```json
{
  "type": "node",
  "node": "timer",
  "config": {
    "duration_secs": 5.0
  }
}
```
**Returns:** `Running` until duration elapses, then `Success`

#### SensorCheckNode
Check sensor conditions:
```json
{
  "type": "node",
  "node": "sensor_check",
  "config": {
    "topic": "/sensors/distance",
    "field": "value",
    "operator": "less_than",
    "threshold": 0.5
  }
}
```
**Returns:** `Success` or `Failure` based on condition

### Composition Nodes

#### Sequence
Executes children in order until one fails:
```json
{
  "type": "sequence",
  "children": [
    { "type": "node", "node": "move", "config": {...} },
    { "type": "node", "node": "timer", "config": {...} }
  ]
}
```

#### Selector
Tries children until one succeeds (fallback pattern):
```json
{
  "type": "selector",
  "children": [
    { "type": "node", "node": "sensor_check", "config": {...} },
    { "type": "node", "node": "wander", "config": {...} }
  ]
}
```

#### Parallel
Executes all children concurrently:
```json
{
  "type": "parallel",
  "policy": "require_all",
  "children": [
    { "type": "node", "node": "wander", "config": {...} },
    { "type": "node", "node": "sensor_check", "config": {...} }
  ]
}
```

### Modifying Behaviors

**Option 1: Edit Base Behavior**

```bash
code behaviors/idle_wander.json
# Make changes
mecha10 dev  # Restart to apply
```

**Option 2: Environment-Aware Executor Config** (Recommended)

Configure different tick rates and logging per environment in `configs/nodes/@mecha10/behavior-executor/config.json`:

```json
{
  "dev": {
    "behavior_name": "idle_wander",
    "tick_rate_hz": 5.0,
    "log_stats": true
  },
  "production": {
    "behavior_name": "idle_wander",
    "tick_rate_hz": 20.0,
    "log_stats": false
  }
}
```

The active environment is selected via `MECHA10_ENVIRONMENT` variable.

### Creating Custom Behaviors

**1. Create behavior file:**

```bash
touch behaviors/my_behavior.json
```

**2. Define the behavior tree:**

```json
{
  "$schema": "https://mecha10.dev/schemas/behavior-composition-v1.json",
  "name": "my_behavior",
  "description": "My custom behavior",
  "root": {
    "type": "sequence",
    "children": [
      {
        "type": "node",
        "node": "move",
        "config": {
          "topic": "/motor/cmd_vel",
          "linear": 0.5,
          "angular": 0.0,
          "duration_secs": 2.0
        }
      },
      {
        "type": "node",
        "node": "timer",
        "config": {
          "duration_secs": 1.0
        }
      }
    ]
  }
}
```

**3. Configure executor to use it:**

Edit `configs/nodes/@mecha10/behavior-executor/config.json`:
```json
{
  "dev": {
    "behavior_name": "my_behavior",
    "tick_rate_hz": 5.0,
    "log_stats": true
  },
  "production": {
    "behavior_name": "my_behavior",
    "tick_rate_hz": 20.0,
    "log_stats": false
  }
}
```

**4. Run:**

```bash
mecha10 dev --mode simulation
```

## Behavior Executors

The **behavior-executor** node loads and executes behavior trees.

### Configuration

**Location:** `configs/{env}/nodes/behavior-executor/config.json`

**Configuration Fields:**

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `behavior_name` | string | required | Name of behavior to load (without .json) |
| `behaviors_dir` | string | `"behaviors"` | Directory containing behavior JSONs |
| `tick_rate_hz` | number | `10.0` | Execution frequency (Hz) |
| `max_ticks` | number/null | `null` | Max ticks before stopping (null = unlimited) |
| `log_stats` | boolean | `true` | Log periodic execution statistics |
| `topics.publishes` | array | - | Topics to publish to |
| `topics.subscribes` | array | - | Topics to subscribe to |

**Example:** (`configs/nodes/@mecha10/behavior-executor/config.json`)

```json
{
  "dev": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 5.0,
    "max_ticks": null,
    "log_stats": true,
    "topics": {
      "publishes": [{ "status": "/behavior/status" }],
      "subscribes": [{ "control": "/behavior/control" }]
    }
  },
  "production": {
    "behavior_name": "idle_wander",
    "behaviors_dir": "behaviors",
    "tick_rate_hz": 20.0,
    "max_ticks": null,
    "log_stats": false,
    "topics": {
      "publishes": [{ "status": "/behavior/status" }],
      "subscribes": [{ "control": "/behavior/control" }]
    }
  }
}
```

### Switching Behaviors

**Edit config file:**
```bash
code configs/nodes/@mecha10/behavior-executor/config.json
# Change "behavior_name": "new_behavior" in both dev and production sections
mecha10 dev  # Restart
```

### Creating Custom Executors

For custom action nodes, create a custom executor:

**1. Create custom behaviors library:**

```bash
mkdir -p nodes/custom-behaviors/src
```

```toml
# nodes/custom-behaviors/Cargo.toml
[package]
name = "custom-behaviors"
version = "0.1.0"
edition = "2021"

[dependencies]
mecha10-core = "0.1"
mecha10-behavior-runtime = "0.1"
tokio = { version = "1.36", features = ["full"] }
async-trait = "0.1"
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

**2. Implement custom nodes:**

```rust
// nodes/custom-behaviors/src/lib.rs
use mecha10_behavior_runtime::{BoxedBehavior, NodeRegistry};
use serde_json::Value;

pub fn register_custom_behaviors(registry: &mut NodeRegistry) {
    registry.register("my_custom_action", |config: Value| -> anyhow::Result<BoxedBehavior> {
        Ok(Box::new(MyCustomActionNode::from_json(config)?))
    });
}
```

**3. Create custom executor:**

```bash
mkdir -p nodes/my-behavior-executor/src
```

```rust
// nodes/my-behavior-executor/src/lib.rs
use mecha10_core::prelude::*;
use mecha10_behavior_runtime::{BehaviorLoader, BoxedBehavior, NodeRegistry};

#[derive(Debug, Node)]
#[node(name = "my-behavior-executor")]
pub struct MyBehaviorExecutorNode {
    behavior: BoxedBehavior,
    tick_rate_hz: f32,
}

#[async_trait]
impl NodeImpl for MyBehaviorExecutorNode {
    type Config = MyBehaviorExecutorConfig;

    async fn init(config: Self::Config) -> Result<Self> {
        let mut registry = NodeRegistry::new();

        // Register built-in actions
        mecha10_behavior_runtime::register_builtin_actions(&mut registry);

        // Register YOUR custom nodes
        custom_behaviors::register_custom_behaviors(&mut registry);

        let behavior_path = PathBuf::from(&config.behaviors_dir)
            .join(format!("{}.json", config.behavior_name));

        let loader = BehaviorLoader::new(registry);
        let behavior = loader.load_from_file(&behavior_path)?;

        Ok(Self { behavior, tick_rate_hz: config.tick_rate_hz })
    }

    async fn run(mut self, ctx: Context) -> Result<()> {
        let mut interval = tokio::time::interval(
            tokio::time::Duration::from_secs_f32(1.0 / self.tick_rate_hz)
        );

        loop {
            interval.tick().await;

            let status = self.behavior.tick(&ctx).await?;

            match status {
                NodeStatus::Success | NodeStatus::Failure => break,
                NodeStatus::Running => continue,
            }
        }

        Ok(())
    }
}
```

**4. Update workspace and config:**

```toml
# Cargo.toml
[workspace]
members = [
    "nodes/custom-behaviors",
    "nodes/my-behavior-executor",
]
```

```json
// mecha10.json
{
  "nodes": {
    "custom": [
      {
        "name": "my-behavior-executor",
        "path": "nodes/my-behavior-executor",
        "enabled": true
      }
    ]
  }
}
```

## Working with Components

### Nodes

Nodes are computational units that process data and control your robot.

#### Adding Framework Nodes

Add pre-built nodes from the framework:

```bash
# Add a camera driver
mecha10 add camera

# Add a motor controller
mecha10 add motor

# Add vision nodes
mecha10 add object-detector
mecha10 add image-classifier

# Add LLM command processing
mecha10 add llm-command
```

This automatically:
1. Adds node to `mecha10.json`
2. Creates `configs/nodes/@mecha10/{node-name}/config.json`
3. Makes node available in lifecycle modes

#### Creating Custom Nodes

**1. Create node directory:**
```bash
mkdir -p nodes/my-custom-node/src
cd nodes/my-custom-node
```

**2. Create `Cargo.toml`:**
```toml
[package]
name = "my-custom-node"
version = "0.1.0"
edition = "2021"

[dependencies]
mecha10-core = "0.1"
mecha10-messaging = "0.1"
tokio = { version = "1.40", features = ["full"] }
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```

**3. Implement node (src/lib.rs):**
```rust
use mecha10_core::prelude::*;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MyNodeConfig {
    pub rate_hz: f32,
    pub topics: TopicsConfig,
}

#[derive(Debug, Node)]
#[node(name = "my-custom-node")]
pub struct MyCustomNode {
    config: MyNodeConfig,
}

#[async_trait]
impl NodeImpl for MyCustomNode {
    type Config = MyNodeConfig;

    async fn init(config: Self::Config) -> Result<Self> {
        Ok(Self { config })
    }

    async fn run(self, ctx: Context) -> Result<()> {
        let mut interval = tokio::time::interval(
            tokio::time::Duration::from_secs_f32(1.0 / self.config.rate_hz)
        );

        loop {
            interval.tick().await;

            // Publish messages
            ctx.publish("output", json!({"value": 42})).await?;

            // Receive messages
            if let Some(msg) = ctx.try_recv::<serde_json::Value>("input")? {
                tracing::info!("Received: {:?}", msg);
            }
        }
    }
}
```

**4. Add to workspace (`Cargo.toml`):**
```toml
[workspace]
members = ["nodes/my-custom-node"]
```

**5. Add to `mecha10.json`:**
```json
{
  "nodes": {
    "custom": [
      {
        "name": "my-custom-node",
        "path": "nodes/my-custom-node",
        "enabled": true
      }
    ]
  }
}
```

**6. Create config:**
```bash
mkdir -p configs/nodes/@local/my-custom-node
cat > configs/nodes/@local/my-custom-node/config.json <<EOF
{
  "dev": {
    "rate_hz": 10.0,
    "topics": {
      "publishes": [{"output": "/my-node/output"}],
      "subscribes": [{"input": "/some/input"}]
    }
  },
  "production": {
    "rate_hz": 30.0,
    "topics": {
      "publishes": [{"output": "/my-node/output"}],
      "subscribes": [{"input": "/some/input"}]
    }
  }
}
EOF
```

**7. Build and run:**
```bash
cargo build
mecha10 dev
```

#### Modifying Nodes

**Configure existing nodes:**
```bash
# Edit node configuration
code configs/nodes/@mecha10/camera/config.json

# Changes take effect on next run
mecha10 dev
```

**Modify custom node code:**
```bash
# Edit source
code nodes/my-custom-node/src/lib.rs

# Rebuild
cargo build
mecha10 dev
```

---

### Simulation Models

Robot models define the physical and sensor properties of your simulated robot.

#### Using Existing Models

**Available models:**
- `rover` - Differential drive ground robot (0.5m × 0.3m × 0.2m)

**Configure model in `mecha10.json`:**
```json
{
  "simulation": {
    "model": "@mecha10/simulation-models/rover",
    "model_config": "simulation/models/model.json"
  }
}
```

#### Customizing Models

**1. Create local model config:**
```bash
mkdir -p simulation/models/rover
```

**2. Create/edit `simulation/models/rover/model.json`:**
```json
{
  "name": "rover",
  "locomotion": {
    "max_linear_speed": 1.0,     // Faster robot
    "max_angular_speed": 2.0
  },
  "sensors": {
    "cameras": [
      {
        "name": "CameraFront",
        "properties": {
          "fov": 90.0,            // Wider field of view
          "resolution": [1280, 720]  // Higher resolution
        }
      }
    ]
  }
}
```

**3. Update `mecha10.json` to use local config:**
```json
{
  "simulation": {
    "model": "@mecha10/simulation-models/rover",
    "model_config": "simulation/models/rover/model.json"
  }
}
```

**4. Test:**
```bash
mecha10 sim run
```

**Configuration options:**
- `physical_properties` - Mass, dimensions
- `locomotion` - Speed limits, wheel parameters
- `sensors` - Camera, LiDAR, IMU configuration

See framework's `packages/simulation/models/README.md` for complete schema.

---

### Simulation Environments

Environments define the world where your robot operates.

#### Using Existing Environments

**Available environments:**
- `basic_arena` - Simple 10×10m arena with spawn points

**Configure in `mecha10.json`:**
```json
{
  "simulation": {
    "environment": "@mecha10/simulation-environments/basic_arena",
    "environment_config": "simulation/environments/basic_arena/environment.json"
  }
}
```

#### Customizing Environments

**1. Create local environment config:**
```bash
mkdir -p simulation/environments/basic_arena
```

**2. Create/edit `simulation/environments/basic_arena/environment.json`:**
```json
{
  "name": "basic_arena",
  "dimensions": {
    "arena_size": [15.0, 15.0],   // Larger arena
    "arena_height": 4.0
  },
  "lighting": {
    "directional": {
      "energy": 1.5               // Brighter
    }
  },
  "spawn_points": [
    {"position": [0, 0.5, 0], "rotation": [0, 0, 0]},
    {"position": [5, 0.5, 5], "rotation": [0, 180, 0]}
  ],
  "objects": [
    {
      "type": "box",
      "position": [3, 0.5, 3],
      "scale": [2, 2, 2],         // Large obstacle
      "properties": {"color": "#FF0000"}
    }
  ]
}
```

**3. Update `mecha10.json`:**
```json
{
  "simulation": {
    "environment": "@mecha10/simulation-environments/basic_arena",
    "environment_config": "simulation/environments/basic_arena/environment.json"
  }
}
```

**4. Test:**
```bash
mecha10 sim run
```

**Configuration options:**
- `dimensions` - Arena size and height
- `lighting` - Directional and ambient lighting
- `spawn_points` - Robot spawn locations
- `objects` - Static objects (boxes, cylinders, etc.)

See framework's `packages/simulation/environments/ENVIRONMENT_SCHEMA.md` for complete schema.

---

### ML Models

Use machine learning models for vision, NLP, and other AI tasks.

#### Using ML Models in Nodes

**Image Classification:**
```bash
mecha10 add image-classifier
```

**Configure (`configs/nodes/@mecha10/image-classifier/config.json`):**
```json
{
  "dev": {
    "processing_rate_hz": 5,
    "model": { "name": "mobilenet-v2" },
    "topics": {
      "publishes": [{ "output": "/vision/classification" }],
      "subscribes": [{ "input": "/camera/rgb" }]
    }
  },
  "production": {
    "processing_rate_hz": 15,
    "model": { "name": "mobilenet-v2" },
    "topics": {
      "publishes": [{ "output": "/vision/classification" }],
      "subscribes": [{ "input": "/camera/rgb" }]
    }
  }
}
```

**Object Detection:**
```bash
mecha10 add object-detector
```

**Configure (`configs/nodes/@mecha10/object-detector/config.json`):**
```json
{
  "dev": {
    "model": { "name": "yolov8n" },
    "confidence_threshold": 0.5,
    "topics": {
      "publishes": [{ "output": "/vision/object/detections" }],
      "subscribes": [{ "input": "/camera/rgb" }]
    }
  },
  "production": {
    "model": { "name": "yolov8n" },
    "confidence_threshold": 0.6,
    "topics": {
      "publishes": [{ "output": "/vision/object/detections" }],
      "subscribes": [{ "input": "/camera/rgb" }]
    }
  }
}
```

**LLM Command Processing:**
```bash
mecha10 add llm-command

# Set API key
export OPENAI_API_KEY="sk-..."
```

**Configure (`configs/nodes/@mecha10/llm-command/config.json`):**
```json
{
  "dev": {
    "provider": "openai",
    "llm_model": "gpt-4o-mini",
    "temperature": 0.7,
    "topics": {
      "command_in": "/ai/command",
      "response_out": "/ai/response"
    }
  },
  "production": {
    "provider": "openai",
    "llm_model": "gpt-4o",
    "temperature": 0.5,
    "topics": {
      "command_in": "/ai/command",
      "response_out": "/ai/response"
    }
  }
}
```

#### Using Custom ML Models

**1. Download model:**
```bash
mkdir -p models/my-custom-model
cd models/my-custom-model

# Download ONNX model from HuggingFace or elsewhere
wget https://huggingface.co/user/model/resolve/main/model.onnx

# Download class labels
wget https://example.com/labels.txt
```

**2. Configure node to use custom model:**
```json
{
  "model_path": "models/my-custom-model/model.onnx",
  "labels_path": "models/my-custom-model/labels.txt",
  "input_size": [224, 224],
  "preprocessing": {
    "mean": [0.485, 0.456, 0.406],
    "std": [0.229, 0.224, 0.225],
    "channel_order": "RGB"
  }
}
```

**3. Test:**
```bash
mecha10 dev
```

**Model formats supported:**
- ONNX (recommended) - Cross-platform, optimized
- PyTorch (via conversion) - Convert to ONNX first

**Finding models:**
- [HuggingFace Models](https://huggingface.co/models?library=onnx) - ONNX models
- [ONNX Model Zoo](https://github.com/onnx/models) - Pre-trained models
- Custom training - Export to ONNX

---

## Project Cleanup

Some files may be present in your project that are no longer needed:

### Safe to Delete

| File/Directory | Reason |
|---------------|--------|
| `simulation/Dockerfile` | Uses published Docker image instead |
| `simulation/entrypoint.sh` | Uses published Docker image instead |
| `simulation/.dockerignore` | Uses published Docker image instead |
| `src/main.rs` | Only needed if building standalone binary (see below) |

### About `src/main.rs`

The `src/main.rs` file is for building a **standalone binary** that can be deployed to a robot without the CLI:

```bash
# Build standalone binary
cargo build --release --features target-robot

# Run on robot
./target/release/{{project_name}} run      # Start all nodes
./target/release/{{project_name}} list     # List enabled nodes
./target/release/{{project_name}} info     # Show project info
```

If you only use `mecha10 dev` for development, you can safely delete `src/main.rs`, `build.rs`, and `Cargo.toml`.

---

## Troubleshooting

### Behavior not loading

Check logs:
```bash
mecha10 logs behavior-executor
```

Common issues:
- JSON syntax error in behavior file
- Unknown node type (not registered)
- Missing required config fields
- File path incorrect

### Config not loading

1. Check file path: `configs/nodes/@mecha10/{node-name}/config.json` or `configs/nodes/@local/{node-name}/config.json`
2. Verify environment: `echo $MECHA10_ENVIRONMENT`
3. Check JSON syntax: `cat configs/nodes/@mecha10/my-node/config.json | jq`
4. Ensure config has both `dev` and `production` sections
5. Enable logging: `RUST_LOG=debug mecha10 dev`

## Documentation

### Framework Guides

- [Configuration System](https://github.com/laboratory-one/mecha10/blob/main/docs/architecture/CONFIGURATION.md)
- [Behavior Trees & Executors](https://github.com/laboratory-one/mecha10/blob/main/docs/BEHAVIOR_TREES_GUIDE.md)
- [AI Features](https://github.com/laboratory-one/mecha10/blob/main/docs/AI_GUIDE.md)
- [Simulation Guide](https://github.com/laboratory-one/mecha10/blob/main/docs/SIMULATION.md)
- [CLI Guide](https://github.com/laboratory-one/mecha10/blob/main/docs/CLI_GUIDE.md)

For more information, visit the [Mecha10 documentation](https://github.com/laboratory-one/mecha10).
