Unit 06 · lesson
State Machines Beat Spaghetti Logic
Robot code becomes difficult when behavior is described only as a growing collection of conditions.
Consider:
if button:
run_motor
if sensor:
stop_motor
if timer:
reverse_motor
if not sensor:
run_motor
Which rule owns the mechanism? What happens if several are true?
The problem is not syntax. The behavior has no explicit state model.
Name the states
A state machine makes the robot's current mode visible.
For an intake mechanism:
IDLE
│ start
▼
INTAKING
│ object detected
▼
HOLDING
│ release requested
▼
EJECTING
│ timer complete
└────────→ IDLE
Each state can define:
- allowed outputs;
- conditions for leaving;
- timeout or failure behavior;
- sensor expectations.
Why this helps
If the mechanism is in HOLDING, the code should not simultaneously behave as if it is EJECTING.
State machines reduce accidental combinations.
They also improve debugging because a log can say:
state=INTAKING → transition=object_detected → state=HOLDING
That is more useful than "motor changed."
Add a failure state
Real robots need a path for things that do not happen.
What if the object sensor never triggers?
INTAKING
│ timeout
▼
FAULT
Now the robot can stop, notify the operator, or try a bounded recovery.
Without a timeout, the code may run the mechanism forever.
Trace the machine
Create a state machine for one behavior:
- elevator homing;
- door opening;
- line-following start/stop;
- object pickup;
- docking.
Include:
- at least three states;
- a condition on every transition;
- one timeout or fault path;
- outputs associated with each active state.
Then run one scenario on paper and record the sequence of states.
If you cannot explain which state owns the output, the logic is not finished.
State makes behavior inspectable
Consider a robot that should wait, drive forward, stop when it reaches a marker, and then signal completion.
A state model makes the sequence explicit:
WAIT
│ start
▼
DRIVE
│ marker seen
▼
STOP
│ velocity = 0
▼
DONE
Each state has a limited job. Each transition has a condition.
Compare that with scattered conditionals:
if start:
drive()
if marker:
stop()
if not moving:
done = True
The code may work in a simple test, but relationships are hidden. What happens if marker is already true when start arrives? What if done remains true on the next run? What outputs are guaranteed while waiting?
Define state invariants
An invariant is something that must remain true while a state is active.
For example:
| State | Required invariant |
|---|---|
| WAIT | drive output is zero |
| DRIVE | stop condition is checked every cycle |
| STOP | commanded motion is zero |
| DONE | no automatic restart occurs |
Those statements are easier to test than "the robot behaves correctly."
When behavior becomes complicated, resist adding another Boolean flag first. Ask whether the system now has a state that deserves a name.