TL;DR:
A state machine says what the robot is doing now (the state), what can happen (events) and where each event leads (transitions).
Draw the diagram before writing code. Every state needs a way out, and every event needs an answer in every state.
Keep each state's code small. A safety stop should work from every state.
A robot that patrols a room, chases something that moves and goes home when it loses it can quickly turn into a tangle of if statements. One flag for "chasing", another for "returning", a timer that is never reset, and a bug that appears only when two things happen at once. A state machine replaces the tangle with a short list of situations the robot can be in.
What a state machine does on a robot
At any moment the robot is in exactly one state, such as PATROL or CHASE. Each state has a small job: the code that runs while you are in it. Events are things that happen: the camera sees a target, a timer runs out, a button is pressed. A transition is a rule that says "in this state, when this event happens, move to that state."
The pattern is clear to read, easy to test and it stops contradictory behavior, because the robot cannot be in two states at once.
Draw it first
Before you write code, sketch circles for the states and arrows for the transitions, and write the event on each arrow. If you cannot draw it, you cannot yet code it. For the example below, the sketch looks like this:
target seen
+--------> CHASE <---------+
| | |
| target lost for 3 s | target seen
| v |
PATROL <------ RETURN -------+
reached start pointWorked example: a robot that patrols, chases and returns
The robot starts at a home point. It has three states:
PATROL: drive slowly around a square route and scan for a target.
CHASE: steer toward the target using the camera.
RETURN: drive back to the home point.
The events are target_seen, target_lost_3s (no sighting for 3 seconds) and at_home. The transitions:
State | Event | Next state |
|---|---|---|
PATROL | target_seen | CHASE |
CHASE | target_lost_3s | RETURN |
RETURN | target_seen | CHASE |
RETURN | at_home | PATROL |
Trace a run. The numbers are times in seconds.
t = 0: robot is in PATROL, driving the route.t = 12: the camera sees the target. Eventtarget_seen, PATROL leads to CHASE.t = 12 to 20: in CHASE, the robot steers toward the target.t = 20: the target goes behind a wall and the sightings stop.t = 23: three seconds with no target. Eventtarget_lost_3s, CHASE leads to RETURN.t = 23 to 40: in RETURN, the robot drives home.t = 40: robot reaches home. Eventat_home, RETURN leads to PATROL.
Notice what the table makes you decide. What if the target shows up again while the robot is returning? The table says RETURN goes to CHASE. What if at_home happens during PATROL? No row, so it is ignored. A table forces you to ask these questions.
Here is a minimal version in Python:
state = "PATROL"
def step(state, events):
if state == "PATROL" and "target_seen" in events:
return "CHASE"
if state == "CHASE" and "target_lost_3s" in events:
return "RETURN"
if state == "RETURN" and "target_seen" in events:
return "CHASE"
if state == "RETURN" and "at_home" in events:
return "PATROL"
return state # no matching rule: stay put
# each loop: read sensors, make events, step, then run the state's actionEach loop does three things: read the sensors and turn them into events, call step, and then run the code for the current state. The states themselves can call feedback controllers, for example the steering in CHASE could use a PID (see feedback vs open-loop control).
Where it goes wrong
Missing transitions. The robot gets stuck in a state because no event leads out. Check every state has a way out.
Flicker. If
target_seenflips on and off every frame, the robot jumps between states. Add a delay or a condition that must hold for a short time, like the 3 seconds above.State explosion. Adding more flags like "carrying" and "low battery" doubles the number of states. Use a hierarchy: a top-level state machine, with a small one inside a state when needed.
Hidden variables. If behavior depends on a global flag that is not a state, you have rebuilt the tangle. Put it into the state.
Blocking code. A
sleep(5)inside a state freezes sensor reading. Use timers and let the loop keep running.
Safety: Treat the emergency stop as something outside the state machine. A hardware stop or a top-priority check that cuts motor power must work whatever the state is, even if the code is stuck. Limit speed in CHASE and RETURN so that a robot that suddenly changes state cannot hit someone before they react.
How real robots use them
State machines run the behavior of robot vacuums (clean, return to dock, charge), warehouse robots, game characters, and the sequences in industrial machines. Larger robots often use behavior trees, which organize the same decisions in a different way. The idea is the same: break behavior into named modes with clear rules for switching. An arm program might have states like WAIT, REACH, GRASP, LIFT, each using its own kinematics (see forward kinematics of a two-joint arm).
Try it yourself
Pick a task, such as "wait for a button, drive 1 m, turn around, drive back, stop." Draw the circles and arrows on paper. List each state's action and each event. Then code the step function from your table and test it by feeding in made-up events before you connect motors. Wheels off the ground for the first run.
Frequently asked questions
What is the difference between a state and an event?
A state is a mode the robot stays in for a while, like PATROL. An event is something that happens at a moment, like a button press. Events cause transitions between states.
Why draw the diagram first?
It shows missing exits and missing cases before they become bugs, and it gives everyone on the team the same picture of how the robot should behave.
