02 · 2025
Autonomous Mobile Robot Navigation Stack
A full ROS 2 autonomy stack for a warehouse AMR, with a learned traversability costmap replacing hand-tuned heuristics.
- ROS 2
- C++
- Nav2
- SLAM Toolbox
- PyTorch
- PREEMPT_RT
- Docker
Demo video
Add a 30–60 second clip of this running in the manager, under this project’s Demo video URL.
The problem
The fleet needed an operator intervention roughly once every X hours. Most were the same failure: the planner treated a hand-tuned inflation radius as ground truth, so pallet wrap, floor drains, and low-hanging shrink film were either invisible or treated as walls.
What I built
An end-to-end autonomy stack: 2D LiDAR SLAM for localisation, Nav2 for global and local planning, and a learned traversability costmap trained on field data that replaced the inflation heuristic. A behaviour tree handles recovery so the robot degrades gracefully instead of stopping dead.
How it works
- C++17 ROS 2 nodes; the control path runs on a PREEMPT_RT kernel with the executor and node composition tuned to hold the latency budget.
- SLAM Toolbox for mapping and localisation, with a re-localisation routine for the docking approach.
- Traversability model in PyTorch, trained on labelled LiDAR + camera field recordings, exported to ONNX and served on the robot.
- Nav2 with a custom controller plugin and a BehaviorTree.CPP recovery tree.
- Sensor fusion (EKF) over wheel odometry, IMU, and LiDAR scan matching.
How it was tested
A hardware-in-the-loop rig replays recorded field rosbags on every merge and fails the build on a regression in intervention-triggering events. Controller changes are checked against a fixed set of simulated scenarios before they reach a robot.
Results
- Operator interventions cut from 1 per X hours to 1 per Y, across N customer sites.
- Docking accuracy held under Z cm.
- Perception-to-planning latency reduced from X ms to Y ms after restructuring the executor.
- Migrated ROS 1 → ROS 2 with zero fleet downtime.
What I learned
- The learned costmap was only trustworthy once I added a floor on it. A model that is confidently wrong about a drain is worse than a crude inflation radius, so the planner now clamps how much it will trust the network.
- Most of the real work was data, not modelling — the active-learning loop over field failures moved the metric far more than any architecture change.
- I underestimated how much the HIL rig would pay for itself. It should have been the first thing built, not the third.
My role
I owned the perception-to-planning interface and the costmap model, and led the ROS 2 migration. Two other engineers worked on the docking and fleet-management sides.