deploy_controller tool compiles, verifies, and deploys the controller — all in one step.
Required Export
Every controller must export aprocess function that takes a tick counter:
i64 parameter is a monotonically increasing tick counter starting from 0.
Host Function Table
Controllers import host functions to interact with the robot. These are the available imports:| Module | Function | Signature | Description |
|---|---|---|---|
command | set | (i32, f64) -> i32 | Write a value to command channel |
command | count | () -> i32 | Number of command channels |
command | limit_min | (i32) -> f64 | Min limit for channel |
command | limit_max | (i32) -> f64 | Max limit for channel |
state | get | (i32) -> f64 | Read a state channel |
state | count | () -> i32 | Number of state channels |
math | sin | (f64) -> f64 | Sine (WASM has no trig intrinsics) |
math | cos | (f64) -> f64 | Cosine |
safety | request_estop | () -> () | Request an emergency stop |
timing | now_ns | () -> i64 | Wall-clock nanoseconds since epoch |
timing | sim_time_ns | () -> i64 | Simulation time in nanoseconds |
telemetry | emit_metric | (f64) -> () | Record a scalar metric for observability |
timing::sim_time_ns respects pause and speed scaling in simulation, while timing::now_ns returns real wall-clock time. Use sim_time_ns for time-based trajectories.Example: Constant Velocity
A minimal controller that sets all joints to a constant velocity:Example: Sine Wave Oscillation
A controller that oscillates joint 0 with a sine wave using simulation time:Deploy Lifecycle
When the agent callsdeploy_controller, the code goes through a multi-step pipeline before reaching the robot:
Compile
WAT source is compiled to WASM bytecode using wasmtime. Compilation errors are returned to the agent immediately.
Link host functions
The WASM module’s imports are resolved against the host function table. Missing or mismatched imports cause a link error.
Verify (100 ticks)
The compiled module runs for 100 ticks under production safety limits. The safety filter checks every command value against the channel manifest’s limits. If any tick produces a safety violation (value exceeds limits, NaN output, or a WASM trap), the controller is rejected.
Epoch-Based Interruption
Eachprocess(tick) call has an 8 ms budget. If the controller does not return within 8 ms, wasmtime’s epoch interruption mechanism traps the execution.
This prevents infinite loops or excessively complex computations from blocking the 100 Hz control loop. The 8 ms budget leaves 2 ms of headroom within the 10 ms tick period for safety filtering, actuator communication, and sensor reads.
What Happens on Rejection
If verification fails, thedeploy_controller tool returns an error message describing what went wrong. The agent can then fix the code and try again. Common rejection reasons:
- Compilation error — invalid WAT syntax or unsupported WASM features
- Link error — importing a host function that does not exist or with the wrong signature
- Safety violation — a command value exceeded the channel’s configured limits during the 100-tick verification
- NaN output — a command channel received a NaN or infinite value (mapped to zero by the safety filter, but flagged as a rejection)
- WASM trap — the module hit an unreachable instruction, divided by zero, or exceeded the epoch deadline
Source
- Deploy tool:
roz-local/src/tools/deploy_controller.rs - WASM runtime:
roz-copper/src/wasm.rs - Host functions:
roz-copper/src/wit_host.rs