State Machine
The state machine node (state_machine_node.py) is the central safety and control authority for the kart. It determines what drives the wheels by muxing cmd_vel based on two independent variables: the mission (what the kart should do) and the AS state (whether the autonomous system is allowed to drive).
Source: src/kart_bringup/scripts/state_machine_node.py
Two Independent Variables
Mission
The mission is selected from the dashboard. It determines the operating mode:
| Mission | Type | Description |
|---|---|---|
manual |
Manual | Direct control via joystick/dashboard |
remote_control |
Manual | Same as manual (dashboard remote) |
throttle_test |
Test | Fixed 50% throttle for hardware debugging |
acceleration |
Autonomous | FS acceleration event |
skidpad |
Autonomous | FS skidpad event |
autocross |
Autonomous | FS autocross event |
trackdrive |
Autonomous | FS trackdrive event |
ebs_test |
Autonomous | Emergency braking system test |
inspection |
Autonomous | Technical inspection demo |
AS State (Autonomous System State)
The AS state tracks the autonomous system lifecycle per Formula Student rules (T14.8):
| State | ID | Description |
|---|---|---|
AS_OFF |
0 | Autonomous system inactive |
AS_READY |
1 | Armed and waiting for "Go" signal |
AS_DRIVING |
2 | Autonomous driving active |
AS_FINISHED |
3 | Mission complete, vehicle stopped |
AS_EMERGENCY |
4 | Emergency braking activated |
cmd_vel Mux Logic
The state machine selects which velocity command reaches the actuators:
| Mission | AS State | Output | Why |
|---|---|---|---|
manual / remote_control |
any | Manual cmd_vel | Operator has direct control |
throttle_test |
any | Fixed 50% throttle | Hardware test, no perception |
| Any autonomous | AS_DRIVING |
Autonomous cmd_vel | Controller drives the kart |
| Any autonomous | anything else | Zero (stopped) | Safety: no motion unless AS_DRIVING |
Key insight
AS state only matters for autonomous missions. Manual and throttle_test bypass it entirely -- the operator is always in control.
State Transitions
stateDiagram-v2
classDef off fill:#6c757d,color:#fff
classDef ready fill:#ffc107,color:#000
classDef driving fill:#28a745,color:#fff
classDef finished fill:#17a2b8,color:#fff
classDef emergency fill:#dc3545,color:#fff
[*] --> AS_OFF
AS_OFF --> AS_READY : Select autonomous mission
AS_READY --> AS_DRIVING : "start" command
AS_DRIVING --> AS_FINISHED : "finish" command
AS_DRIVING --> AS_READY : "stop" (auto mission)
AS_READY --> AS_OFF : Switch to manual
AS_FINISHED --> AS_OFF : "reset" command
AS_EMERGENCY --> AS_OFF : "reset" command
AS_READY --> AS_EMERGENCY : "ebs" command
AS_DRIVING --> AS_EMERGENCY : "ebs" command
AS_FINISHED --> AS_EMERGENCY : "ebs" command
AS_DRIVING --> AS_READY : Select new auto mission
AS_FINISHED --> AS_READY : Select new auto mission
class AS_OFF off
class AS_READY ready
class AS_DRIVING driving
class AS_FINISHED finished
class AS_EMERGENCY emergency
Transition Details
| Trigger | From | To | Notes |
|---|---|---|---|
| Select autonomous mission | AS_OFF, AS_DRIVING, AS_FINISHED |
AS_READY |
Auto-arms the system |
| Switch to manual | Any (except AS_OFF) |
AS_OFF |
Fully disarms |
start |
AS_READY |
AS_DRIVING |
Begin autonomous driving |
stop (auto mission active) |
AS_READY, AS_DRIVING, AS_FINISHED, AS_EMERGENCY |
AS_READY |
Stays armed |
stop (manual mission) |
Any | AS_OFF |
Fully disarms |
ebs |
Any (except AS_OFF) |
AS_EMERGENCY |
Emergency braking |
finish |
AS_DRIVING |
AS_FINISHED |
Mission complete |
reset |
AS_FINISHED, AS_EMERGENCY |
AS_OFF |
Clear error/completion |
ASSI (Autonomous System Status Indicator)
The ASSI communicates the AS state visually, as required by FS rules:
| State | ASSI Signal |
|---|---|
AS_OFF |
Off |
AS_READY |
Yellow continuous |
AS_DRIVING |
Yellow flashing (2-5 Hz) |
AS_FINISHED |
Blue continuous |
AS_EMERGENCY |
Blue flashing (2-5 Hz) |
Formula Student Competition Context
These states map to the FS T14.8 AS Status (Figure 15 in FS Rules 2026). See also the rules reference for the full FS decision tree and hardware requirements.
In a real competition, additional checks gate each transition:
- AS_READY requires: mission selected + ASMS on + ASB checks OK + TS active + brakes engaged
- AS_DRIVING (R2D) is triggered only via the RES (Remote Emergency System) "Go" signal, after 5 seconds in AS_READY
- The vehicle must not move until 3 seconds after entering AS_DRIVING
Current limitations
We simulate the RES "Go" signal with the dashboard "start" button since we don't have RES hardware yet. The 5-second AS_READY hold time and the 3-second AS_DRIVING standstill requirement are not yet implemented.
ROS Topics
Subscriptions (inputs)
| Topic | Type | Source | Purpose |
|---|---|---|---|
/dashboard/mission |
String |
Dashboard | Mission selection |
/dashboard/state_cmd |
String |
Dashboard | Commands: start, stop, ebs, finish, reset |
/kart/cmd_vel |
Twist |
Controller | Autonomous velocity command |
/kart/cmd_vel_manual |
Twist |
Joystick / Dashboard | Manual velocity command |
Publications (outputs)
| Topic | Type | Rate | Purpose |
|---|---|---|---|
/kart/cmd_vel_muxed |
Twist |
100 Hz | Final muxed velocity command |
/kart/state |
String |
10 Hz | Current AS state name (heartbeat) |
/orin/machine_state |
Frame |
On change | AS state ID to ESP32 |
/orin/mision |
Frame |
On change | Mission ID to ESP32 |
/orin/steer_mode |
Frame |
On change | Steering mode (PID/PWM) to ESP32 |
Implementation Notes
The node runs two timers:
- 100 Hz mux timer (
_mux_tick): Reads the current mission and state, selects the appropriatecmd_velsource, and publishes to/kart/cmd_vel_muxed. - 10 Hz heartbeat (
_publish_state): Publishes the current state name so other nodes and the dashboard can monitor it.
State transitions are triggered by ROS topic callbacks, not by the timers. Each transition logs the change and publishes the new state to both ROS topics and ESP32 frames.
When an autonomous mission is selected, the node forces PID steering mode via /orin/steer_mode to ensure the ESP32 uses closed-loop steering control.