Skip to main content
All projects

Monte Carlo localisation

A ROS 2 particle filter whose tuning is measured rather than asserted — every number below comes out of an offline harness that re-runs from a seed.

  • Personal project
  • Solo
  • C++17, ROS 2 Humble/Jazzy
Green: ground truth. Red: the filter’s estimate. Blue: the particle cloud.

Green: ground truth. Red: the filter’s estimate. Blue: the particle cloud.

Problem

Particle-filter implementations usually document their tuning with a recorded bag and a screenshot of RViz, which says nothing about whether the numbers hold on a different seed or a different floorplan. I wanted an MCL implementation where every claim about accuracy was reproducible.

Approach

  • Implemented the odometry motion model, a likelihood-field range-finder model and adaptive low-variance resampling over a known 2D occupancy grid, following Thrun, Burgard and Fox.
  • Kept the core free of any ROS dependency: the node translates messages into plain structs at the boundary, which is what makes the models unit-testable.
  • Computed the likelihood field with an O(n) exact distance transform rather than a per-beam ray cast.
  • Shipped an offline evaluation harness that drives a simulated robot through the map against known ground truth, so accuracy is reported per seed instead of per screenshot.
  • Ran the same harness over six floorplans to find where the tuning stops transferring.

Results

  • 0.055 m mean final error over a 20.25 m route, 8/8 seeds converged within 0.50 m, against odometry drifting 0.31–0.95 m.
  • 8/8 seeds on every one of six floorplans, 0.055–0.132 m mean final error.
  • 200 particles for tracking; 5,000 for global localisation on the shipped map.
  • 83 GoogleTest cases, building and running without ROS.

My role and context

Personal project, solo, in the same repository as the DWA local planner. This page is built from my own report; the derivations and every measurement behind the tuning are in the repository docs.

Limitations and next steps

  • Global localisation is tuned to the shipped map: unreliable at 2,000 particles and below, and on five other floorplans 5,000 particles converge only 3–6 times out of 8.
  • KLD-adaptive sampling and random particle injection are not implemented, so the filter cannot recover if it locks onto a wrong mode.
  • The reported pose is the mean over all particles, not the dominant cluster, so it is meaningless while the cloud is multi-modal. The published covariance is what makes that detectable.
  • No scan matching or motion-model adaptation, so fast rotation or wheel slip beyond the noise model will lose the lock.
  • Measurement updates run on the latest scan at a fixed rate without interpolating odometry to the scan timestamp: fine at walking speed, a source of bias at speed.
  • Single-threaded, O(particles × beams) per update.

Links