Behavior Trees in Robotics

Disclosure: some links on this page are affiliate links. If you buy through them we may earn a commission at no extra cost to you.

Behavior trees were born in games, but their second career is arguably bigger: they’ve become a standard task-orchestration architecture in robotics. The ROS 2 Nav2 navigation stack — running on thousands of real robots — is driven by behavior trees, and BehaviorTree.CPP has become the de-facto C++ library for robot mission logic.

If you’re coming from gamedev, the concepts transfer directly (intro here if you need it). This guide covers what’s different on real hardware, and the concrete stack you’d use today.

Why robotics switched from state machines

Robot task logic was traditionally FSMs (SMACH, FlexBE in ROS 1). The pain points that drove the migration mirror the gamedev comparison, plus two robotics-specific ones:

BehaviorTree.CPP: the workhorse

BehaviorTree.CPP (by Davide Faconti) is a C++ library where trees are defined in XML and leaf nodes are C++ classes registered by name:

<root BTCPP_format="4">
  <BehaviorTree ID="PickAndPlace">
    <Sequence>
      <Fallback>
        <Condition ID="IsHoldingObject"/>
        <Sequence>
          <Action ID="MoveToObject"/>
          <RetryUntilSuccessful num_attempts="3">
            <Action ID="GraspObject"/>
          </RetryUntilSuccessful>
        </Sequence>
      </Fallback>
      <Action ID="MoveToTarget"/>
      <Action ID="PlaceObject"/>
    </Sequence>
  </BehaviorTree>
</root>

Note the dialect: robotics says Fallback where games say Selector/Priority, and BT.CPP distinguishes synchronous actions from long-running stateful/async actions (equivalent to returning Running). It ships with Groot2, a visual editor/monitor that can watch a live tree over a network connection — the robotics equivalent of a debugger, and something you’ll want from day one.

▶ Explore this pick-and-place tree interactively

ROS 2 and Nav2: behavior trees in production

Nav2, the ROS 2 navigation framework, is the highest-profile BT deployment in robotics. Its default “navigate to pose” logic is a behavior tree XML you can read and customize: compute a path (with retries and rate throttling), follow it, and on failure run recovery branches — clear costmaps, spin in place, back up, wait — in fallback order.

The practical superpower: changing robot behavior means editing an XML tree, not recompiling a node graph. Want the robot to try re-planning five times before backing up? Edit the tree. Fleet operators tune per-site behavior this way.

For manipulation and full-mission logic (patrol → inspect → dock → charge), teams compose BT.CPP subtrees the same way — subtree reuse maps naturally onto “skills” a robot exposes.

Game trees vs robot trees: what actually differs

AspectGamesRobotics
Tick sourceFrame loop (30–60 Hz)Explicit rate, often 10–100 Hz per tree
Leaves talk toEngine/gameplay codeROS actions/services, hardware drivers
FailureA design caseThe common case — recovery is the point
Long actionsAnimation-lengthSeconds to minutes (async is mandatory)
Authoring formatEditor-specific JSON / engine assetsXML (BT.CPP), often hand-edited
VerificationPlaytestingSimulation + formal analysis culture

Learning path

  1. The book: Behavior Trees in Robotics and AI: An Introduction by Michele Colledanchise and Petter Ögren is the definitive text — rigorous but readable, and the authors maintain a free preprint on arXiv (print edition on Amazon).
  2. Hands-on: work through the BehaviorTree.CPP tutorials, then read Nav2’s default behavior tree XMLs — they’re short and production-grade.
  3. Design practice: sketch your mission logic in the free online behavior tree editor before committing it to XML — structure mistakes are much cheaper to fix in a sketch.

Recommended reading

Books that go deeper on behavior trees and game AI.

As an Amazon Associate, behaviortrees.com earns from qualifying purchases.