When to Use What
You've learned state machines and behavior trees. Now the question is: which should you use?
The answer: it depends on the task. And often, the best solution is both.
Comparison Table
| State Machine | Behavior Tree | |
|---|---|---|
| Mental model | "What mode is the robot in?" | "What task is the robot doing?" |
| Structure | Flat or hierarchical states | Tree of nodes |
| Execution | Event-driven (transitions fire on events) | Polled (ticked every frame) |
| Best for | Discrete modes (idle, charging, error) | Composable tasks (search, approach, grasp) |
| Parallel execution | Difficult (need concurrent states) | Easy (parallel nodes) |
| Reusability | Hard (transitions are context-specific) | Easy (subtrees are self-contained) |
| Visual tools | Good (statechart editors) | Excellent (drag-and-drop BT editors) |
| Complexity scaling | Exponential (transitions grow as O(n²)) | Linear (tree depth grows slowly) |
State Machines: When to Use
Use a state machine when:
-
Your robot has distinct modes
If you can describe your robot as "it's in the charging state" or "it's in the error state," a state machine fits naturally.
-
Transitions are event-driven
If transitions happen when something occurs (user presses button, sensor triggers, message received), state machines model this cleanly.
-
You need guaranteed behavior in each state
State machines are deterministic. If you're in state A and event E occurs, you always transition to state B. This is critical for safety-critical systems.
-
You have a small number of states (< 20)
Beyond that, state diagrams become unreadable and transitions explode in number.
Example: Motor controller
A motor controller has clear modes:
IDLE → RUNNING (on start command)
RUNNING → IDLE (on stop command)
RUNNING → ERROR (on overcurrent)
ERROR → IDLE (on reset command)
This is a perfect fit for a state machine.
Behavior Trees: When to Use
Use a behavior tree when:
-
You have many small, reusable behaviors
If your robot needs to search, approach, grasp, retreat, and you want to compose these in different ways, BTs shine.
-
Tasks need to be prioritized
A selector naturally expresses "try the high-priority task first, then fall back to lower priorities."
-
Behaviors run in parallel
A BT can tick "move to goal" and "publish status" simultaneously without complex concurrency logic.
-
You need visual editing
BT editors let non-programmers (designers, domain experts) build behavior by dragging nodes in a GUI.
-
Complexity is high (many conditions and tasks)
BTs scale linearly. A tree with 100 nodes is still readable. A state machine with 100 states is a nightmare.
Example: Warehouse robot
A warehouse robot picks items from shelves. Its behavior tree might look like:
Root (Selector)
├─ Sequence: Handle Emergency
│ ├─ Condition: EmergencyStopPressed?
│ └─ Action: StopAllMotors
├─ Sequence: Charge If Low
│ ├─ Condition: BatteryLow?
│ ├─ Action: NavigateToCharger
│ └─ Action: Dock
└─ Sequence: Pick and Deliver
├─ Action: GetNextOrder
├─ Action: NavigateToShelf
├─ Action: PickItem
├─ Action: NavigateToDropoff
└─ Action: ReleaseItem
This is a BT because it's a complex, prioritized set of tasks that need to be composed and reused.
A good rule of thumb: if you're drawing circles (states) and arrows (transitions), use a state machine. If you're drawing boxes (tasks) in a tree, use a behavior tree.
Mixing Both
Real robots often use both in a hierarchy:
High-level mission planner: Behavior Tree
├─ Task: "Deliver Package"
│ Uses state machine: NAVIGATING → DELIVERING → RETURNING
├─ Task: "Avoid Obstacle"
│ Uses state machine: DETECTING → PLANNING → AVOIDING
└─ Task: "Charge Battery"
Uses state machine: SEEKING → DOCKING → CHARGING
The behavior tree decides which high-level task to execute (based on priorities and conditions).
Each task is implemented as a state machine with its own internal states.
This gives you the best of both worlds:
- BT's composability and reusability at the task level
- State machine's clarity and event-driven transitions at the behavior level
Common Pitfalls
Using a state machine when you need composability
If you find yourself copy-pasting states across multiple state machines ("every mission needs a low-battery state"), you probably want a BT with shared subtrees.
Using a BT when you need event-driven transitions
If your robot needs to react immediately to a sensor event (e.g., emergency stop), polling a BT at 10 Hz might not be fast enough. A state machine with interrupt-driven transitions is better.
Overcomplicating simple robots
If your robot has 3 states and 5 transitions, you don't need a 200-node behavior tree. A simple state machine or even a few if statements will do.
The right tool depends on the complexity of your problem.
What's Next?
You now know when to use state machines, when to use behavior trees, and when to use both. But what happens when things go wrong? In the next lesson, we'll cover error handling and recovery — how to make your robot gracefully handle failures instead of freezing or crashing.