Back to index
Everything autonomous lives inside robot Name { ... }:
robot Rover {
// sensors — how it sees
// actuators — how it moves
// safety — what it must never violate
// behaviors / tasks — what it does
}
Order inside the block is flexible, but this mental model helps.
sensor lidar: Lidar on "/scan";
| Piece | Meaning |
|---|---|
lidar |
Your name for this sensor |
Lidar |
Type (defines .read(), distances, etc.) |
on "/scan" |
Where data comes from (ROS-style topic) |
Read it in code:
let scan = lidar.read();
if scan.nearest_distance < 1.0 m {
wheels.stop();
}
Tip: Distances use units — 1.0 m, not bare 1.0. The compiler catches unit mistakes.
actuator wheels: DifferentialDrive;
Common commands:
wheels.drive(linear: 0.3 m/s, angular: 0.0 rad/s);
wheels.stop();
wheels.execute(safe_action); // only SafeAction, not raw AI output
safety {
max_speed = 1.0 m/s;
stop_if lidar.nearest_distance < 0.5 m;
}
These run before motion reaches hardware. Not comments. Not optional at runtime.
You can also define zones (keep-out regions) — see examples/patrol_with_zones.sd.
One-shot or looping logic:
behavior patrol() {
loop every 100ms {
// read sensors, decide, actuate
}
}
loop every 100ms = “run this block ten times per second.” Good for control loops.
task watchdog every 50ms {
let scan = lidar.read();
let _ = scan;
}
Tasks are scheduled separately from behaviors — useful for monitoring, logging, or parallel work.
Priorities: critical, high, low.
event ObstacleSeen;
on ObstacleSeen {
wheels.stop();
}
Emit from anywhere: emit ObstacleSeen;
More trigger types (timers, conditions, topics): see triggers.md or
examples/triggers_demo.sd.
hardware RoverV1 {
memory: 4 GB;
sensors [ Lidar ];
actuators [ DifferentialDrive ];
}
deploy Rover to RoverV1;
Then:
spanda verify rover.sd --target RoverV1
Verification answers: “Does this program match this hardware?” before you flash an SD card.
robot MyRover {
sensor lidar: Lidar on "/scan";
actuator wheels: DifferentialDrive;
safety {
max_speed = 1.0 m/s;
stop_if lidar.nearest_distance < 0.5 m;
}
behavior patrol() {
loop every 100ms {
let scan = lidar.read();
if scan.nearest_distance < 1.0 m {
wheels.stop();
} else {
wheels.drive(linear: 0.3 m/s, angular: 0.0 rad/s);
}
}
}
}
Save as my_rover.sd, then spanda check my_rover.sd and spanda run my_rover.sd.