Recovery Behaviors
Even with a great planner and controller, robots get stuck. A person suddenly blocks the aisle. The robot wedges itself into a tight corner. The path momentarily disappears. Recovery behaviors keep the robot from freezing in place and instead give it a way to self-rescue.
Failure Drops into the Recovery Branch
As shown in the Behavior Tree post, when FollowPath fails the BT immediately falls through to its recovery branch.
Rendering diagram…
Each behavior has a clear purpose.
- Spin — rotates in place to rescan with LiDAR. Effective when the robot believed it was stuck but a gap actually exists.
- BackUp — reverses ~0.5 m. Useful for breaking free of a corner or doorway wedge.
- Wait — pauses to let a person or another robot pass.
After recovery, the robot replans and retries. Rather than hammering the same command until it works, the system changes the physical situation before trying again.
How Does It Know It Is Stuck?
Recovery does not trigger on every hiccup. A progress monitor watches whether the robot is advancing. If no forward progress is detected within a threshold time (e.g., 30 seconds), the robot is declared stuck and recovery is invoked.
💡 Recovery can also fail — if the local costmap is broken and the robot is in an "Off Grid" state, even spin and backup fail. When recovery does not work, investigate costmap coverage rather than the recovery behavior itself.
What Actually Fired in Our Runs
That is the textbook. Searching our own warehouse run logs, however, Nav2's spin, backup and wait never fired once. A layer we built above Nav2 resolved the blockage instead.
[PASS-GATE] HO_A: gap ahead is 1.10 m, passing needs 1.97 m, HO_B has priority, stop before entry
[PASS-ALIGN] HO_A: lateral error to the centreline +0.61 m, align before entering (tolerance 0.10 m)
[PASS-RESUME] HO_A: re-issuing the same goal, attempt 1 of 4, stopped 9.2 s having moved 0.05 m, aisle clear
On the left, the textbook recovery branch (FollowPath fails, then spin/backup/wait, then retry) — which fired zero times in our warehouse runs. On the right is what actually unblocked the robot: having moved only 0.05 m in 9.2 s it is declared stuck (thresholds: under 0.25 m in 8 s), the aisle is checked as clear, and the same goal is re-issued (at most four times).
The difference lies in what counts as evidence of being stuck. Nav2's recovery keys off the failure of an action — FollowPath returning failure. The log above keys off the outcome instead: time passed and distance did not. A controller can report that it is still succeeding while the robot sits still; the first signal stays silent there, the second one fires.
⚠️ When recovery exists in two layers, the logs must say which layer ran. Reading "recovery worked" as "Nav2's recovery works" means claiming to have validated a feature that never executed. We only discovered the zero-fire count by going back through the logs while writing this post.
Fleet-Level Stops — STOP as Collision Avoidance
In multi-robot deployments there is a higher-level recovery mechanism. When a collision risk is detected, the fleet manager issues a STOP to a specific robot. This must cancel the Nav2 goal — not merely halt the wheels.
⚠️ If you stop the wheels but leave the goal alive, Nav2 continues issuing drive commands asking "why aren't you moving?" For a collision-avoidance stop to work, the goal must be cancelled so the controller stops pushing entirely.
In a nutshell
📌 Recovery behaviors — spin (rescan), backup (break free), wait (yield) — change the physical situation and retry, and execute through the Behavior Tree's recovery branch. If recovery fails, investigate the costmap. For fleet STOP events, cancel the Nav2 goal — do not merely halt the wheels.
References
See standard test results with videos and verdict evidence on the imSim Portal.
View public results →