|
| 1 | +# State Machine |
| 2 | + |
| 3 | +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). |
| 4 | + |
| 5 | +**Source:** `src/kart_bringup/scripts/state_machine_node.py` |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Two Independent Variables |
| 10 | + |
| 11 | +### Mission |
| 12 | + |
| 13 | +The **mission** is selected from the dashboard. It determines the operating mode: |
| 14 | + |
| 15 | +| Mission | Type | Description | |
| 16 | +|---------|------|-------------| |
| 17 | +| `manual` | Manual | Direct control via joystick/dashboard | |
| 18 | +| `remote_control` | Manual | Same as manual (dashboard remote) | |
| 19 | +| `throttle_test` | Test | Fixed 50% throttle for hardware debugging | |
| 20 | +| `acceleration` | Autonomous | FS acceleration event | |
| 21 | +| `skidpad` | Autonomous | FS skidpad event | |
| 22 | +| `autocross` | Autonomous | FS autocross event | |
| 23 | +| `trackdrive` | Autonomous | FS trackdrive event | |
| 24 | +| `ebs_test` | Autonomous | Emergency braking system test | |
| 25 | +| `inspection` | Autonomous | Technical inspection demo | |
| 26 | + |
| 27 | +### AS State (Autonomous System State) |
| 28 | + |
| 29 | +The **AS state** tracks the autonomous system lifecycle per Formula Student rules (T14.8): |
| 30 | + |
| 31 | +| State | ID | Description | |
| 32 | +|-------|----|-------------| |
| 33 | +| `AS_OFF` | 0 | Autonomous system inactive | |
| 34 | +| `AS_READY` | 1 | Armed and waiting for "Go" signal | |
| 35 | +| `AS_DRIVING` | 2 | Autonomous driving active | |
| 36 | +| `AS_FINISHED` | 3 | Mission complete, vehicle stopped | |
| 37 | +| `AS_EMERGENCY` | 4 | Emergency braking activated | |
| 38 | + |
| 39 | +--- |
| 40 | + |
| 41 | +## cmd_vel Mux Logic |
| 42 | + |
| 43 | +The state machine selects which velocity command reaches the actuators: |
| 44 | + |
| 45 | +| Mission | AS State | Output | Why | |
| 46 | +|---------|----------|--------|-----| |
| 47 | +| `manual` / `remote_control` | *any* | Manual cmd_vel | Operator has direct control | |
| 48 | +| `throttle_test` | *any* | Fixed 50% throttle | Hardware test, no perception | |
| 49 | +| Any autonomous | `AS_DRIVING` | Autonomous cmd_vel | Controller drives the kart | |
| 50 | +| Any autonomous | *anything else* | Zero (stopped) | Safety: no motion unless AS_DRIVING | |
| 51 | + |
| 52 | +!!! info "Key insight" |
| 53 | + AS state only matters for autonomous missions. Manual and throttle_test bypass it entirely -- the operator is always in control. |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +## State Transitions |
| 58 | + |
| 59 | +```mermaid |
| 60 | +stateDiagram-v2 |
| 61 | + classDef off fill:#6c757d,color:#fff |
| 62 | + classDef ready fill:#ffc107,color:#000 |
| 63 | + classDef driving fill:#28a745,color:#fff |
| 64 | + classDef finished fill:#17a2b8,color:#fff |
| 65 | + classDef emergency fill:#dc3545,color:#fff |
| 66 | +
|
| 67 | + [*] --> AS_OFF |
| 68 | +
|
| 69 | + AS_OFF --> AS_READY : Select autonomous mission |
| 70 | + AS_READY --> AS_DRIVING : "start" command |
| 71 | + AS_DRIVING --> AS_FINISHED : "finish" command |
| 72 | + AS_DRIVING --> AS_READY : "stop" (auto mission) |
| 73 | + AS_READY --> AS_OFF : Switch to manual |
| 74 | +
|
| 75 | + AS_FINISHED --> AS_OFF : "reset" command |
| 76 | + AS_EMERGENCY --> AS_OFF : "reset" command |
| 77 | +
|
| 78 | + AS_READY --> AS_EMERGENCY : "ebs" command |
| 79 | + AS_DRIVING --> AS_EMERGENCY : "ebs" command |
| 80 | + AS_FINISHED --> AS_EMERGENCY : "ebs" command |
| 81 | +
|
| 82 | + AS_DRIVING --> AS_READY : Select new auto mission |
| 83 | + AS_FINISHED --> AS_READY : Select new auto mission |
| 84 | +
|
| 85 | + class AS_OFF off |
| 86 | + class AS_READY ready |
| 87 | + class AS_DRIVING driving |
| 88 | + class AS_FINISHED finished |
| 89 | + class AS_EMERGENCY emergency |
| 90 | +``` |
| 91 | + |
| 92 | +### Transition Details |
| 93 | + |
| 94 | +| Trigger | From | To | Notes | |
| 95 | +|---------|------|----|-------| |
| 96 | +| Select autonomous mission | `AS_OFF`, `AS_DRIVING`, `AS_FINISHED` | `AS_READY` | Auto-arms the system | |
| 97 | +| Switch to manual | Any (except `AS_OFF`) | `AS_OFF` | Fully disarms | |
| 98 | +| `start` | `AS_READY` | `AS_DRIVING` | Begin autonomous driving | |
| 99 | +| `stop` (auto mission active) | `AS_READY`, `AS_DRIVING`, `AS_FINISHED`, `AS_EMERGENCY` | `AS_READY` | Stays armed | |
| 100 | +| `stop` (manual mission) | Any | `AS_OFF` | Fully disarms | |
| 101 | +| `ebs` | Any (except `AS_OFF`) | `AS_EMERGENCY` | Emergency braking | |
| 102 | +| `finish` | `AS_DRIVING` | `AS_FINISHED` | Mission complete | |
| 103 | +| `reset` | `AS_FINISHED`, `AS_EMERGENCY` | `AS_OFF` | Clear error/completion | |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## ASSI (Autonomous System Status Indicator) |
| 108 | + |
| 109 | +The ASSI communicates the AS state visually, as required by FS rules: |
| 110 | + |
| 111 | +| State | ASSI Signal | |
| 112 | +|-------|-------------| |
| 113 | +| `AS_OFF` | Off | |
| 114 | +| `AS_READY` | Yellow continuous | |
| 115 | +| `AS_DRIVING` | Yellow flashing (2-5 Hz) | |
| 116 | +| `AS_FINISHED` | Blue continuous | |
| 117 | +| `AS_EMERGENCY` | Blue flashing (2-5 Hz) | |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## Formula Student Competition Context |
| 122 | + |
| 123 | +These states map to the **FS T14.8 AS Status** (Figure 15 in FS Rules 2026). See also the [rules reference](../rules/as_state_machine.md) for the full FS decision tree and hardware requirements. |
| 124 | + |
| 125 | +In a real competition, additional checks gate each transition: |
| 126 | + |
| 127 | +- **AS_READY** requires: mission selected + ASMS on + ASB checks OK + TS active + brakes engaged |
| 128 | +- **AS_DRIVING** (R2D) is triggered only via the RES (Remote Emergency System) "Go" signal, after 5 seconds in AS_READY |
| 129 | +- The vehicle must not move until 3 seconds after entering AS_DRIVING |
| 130 | + |
| 131 | +!!! warning "Current limitations" |
| 132 | + 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**. |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## ROS Topics |
| 137 | + |
| 138 | +### Subscriptions (inputs) |
| 139 | + |
| 140 | +| Topic | Type | Source | Purpose | |
| 141 | +|-------|------|--------|---------| |
| 142 | +| `/dashboard/mission` | `String` | Dashboard | Mission selection | |
| 143 | +| `/dashboard/state_cmd` | `String` | Dashboard | Commands: start, stop, ebs, finish, reset | |
| 144 | +| `/kart/cmd_vel` | `Twist` | Controller | Autonomous velocity command | |
| 145 | +| `/kart/cmd_vel_manual` | `Twist` | Joystick / Dashboard | Manual velocity command | |
| 146 | + |
| 147 | +### Publications (outputs) |
| 148 | + |
| 149 | +| Topic | Type | Rate | Purpose | |
| 150 | +|-------|------|------|---------| |
| 151 | +| `/kart/cmd_vel_muxed` | `Twist` | 100 Hz | Final muxed velocity command | |
| 152 | +| `/kart/state` | `String` | 10 Hz | Current AS state name (heartbeat) | |
| 153 | +| `/orin/machine_state` | `Frame` | On change | AS state ID to ESP32 | |
| 154 | +| `/orin/mision` | `Frame` | On change | Mission ID to ESP32 | |
| 155 | +| `/orin/steer_mode` | `Frame` | On change | Steering mode (PID/PWM) to ESP32 | |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +## Implementation Notes |
| 160 | + |
| 161 | +The node runs two timers: |
| 162 | + |
| 163 | +- **100 Hz mux timer** (`_mux_tick`): Reads the current mission and state, selects the appropriate `cmd_vel` source, and publishes to `/kart/cmd_vel_muxed`. |
| 164 | +- **10 Hz heartbeat** (`_publish_state`): Publishes the current state name so other nodes and the dashboard can monitor it. |
| 165 | + |
| 166 | +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. |
| 167 | + |
| 168 | +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. |
0 commit comments