nav2_amcl package, also departs from the textbook in how it combines the beams of a scan.
The parts appear here in the order the filter uses them: the map and the likelihood of one beam, the way AMCL combines the beams of a scan, the adaptive number of particles, and the recovery mechanism. A table at the end maps Nav2’s parameters to the symbols.
The map and the likelihood field
The map is an occupancy grid with 5 cm cells. AMCL’s default sensor model is the likelihood field (Thrun, Burgard and Fox, 2005, Section 6.4 and Table 6.3), not the beam model. The beam model casts a ray through the map for every beam of every particle. The likelihood field does no ray casting. It projects the endpoint of each beam into the map and looks up how far that point lies from the nearest occupied cell. These distances are computed once, when the map is loaded, and stored in a second grid. Nav2 stops the computation atlaser_likelihood_max_dist, 2 m by default, so every cell farther away reads 2 m.
Take a particle at and beam of the scan, with measured range and bearing . With the LIDAR at the center of the robot, the endpoint of the beam is
If is the distance from to the nearest occupied cell, the likelihood of the beam is
The first term is large when the endpoint falls on a wall of the map. The second is a floor for readings the map cannot explain. AMCL names the mixture weights and , where the beam model section writes and . The textbook Gaussian has the factor in front, and AMCL leaves it out. A beam that returns has no endpoint and is skipped.
The code below builds a map of four rooms around a corridor, its distance grid, and a simulated LIDAR with the parameters of the TurtleBot3’s LDS-01: 360 beams, a 3.5 m range and 1 cm range noise. The simulator finds the true ranges by stepping along each beam through the grid. The filter never calls it.
Prediction with odometry
AMCL moves every particle by a sample from the odometry motion model, described in the particle filter section. The relative motion between two odometry poses is split into a turn , a straight drive and a second turn , and each particle draws its own noisy version of the three. The noise parameters to are 0.2 by default in Nav2. AMCL does not update on every scan. It waits until the odometry reports that the robot has movedupdate_min_d, 0.25 m, or turned update_min_a, 0.2 rad. The simulated robot below therefore drives in steps of 0.25 m and turns in place in steps of 0.2 rad, and each step is one filter update. Its odometry has a 3% error in distance and about 0.6° of noise in each turn.
Combining the beams of a scan
The particle filter needs one weight per particle for the whole scan. With beams that are independent given the pose and the map, that weight is the product of the beam likelihoods, as in the beam model: AMCL computes something else. It uses at mostmax_beams beams, 60 by default, evenly spaced through the scan. The product is in its source, commented out. In its place the code adds the cubes of the beam likelihoods to 1:
A comment in the source calls this an ad hoc weighting scheme. The code below computes both weights for 2000 particles scattered around the true pose, with a spread of 30 cm in position and 6° in heading, and reports the effective sample size of the normalized weights. It counts how many particles carry the weight in practice.
The number of particles
A particle filter needs many particles when the belief is spread over the whole map and few when it is concentrated around one pose. KLD sampling (Fox, 2003) chooses the number while it resamples. It divides the state space into bins, 50 cm by 50 cm by 10° in AMCL, and draws particles one at a time. After each draw it counts the number of bins that hold at least one particle and stops once the number of particles exceeds Fox derives the bound for a particle set whose histogram over the bins should differ from the true posterior by at most in Kullback-Leibler divergence, with probability . The constant is then the upper quantile of the standard normal distribution. The more bins the particles occupy, the more particles the bound requires. AMCL clips to the range [min_particles, max_particles], 500 to 2000 by default.
In Nav2, is pf_err, 0.05 by default, and is pf_z, 0.99 by default. The code uses pf_z directly as the quantile , and the Nav2 documentation notes that 2.33 is the 99% quantile. The default of 0.99 therefore corresponds to , not 0.01.
The resampler below follows AMCL. Each draw is a resampled particle or, with probability , a random pose in free space. The second case is the recovery mechanism of the last part.
Global localization
The filter loop puts the parts together. Each update moves the particles with the odometry, weights them with the scan and resamples them with KLD sampling. It also keeps the two averages and that the recovery mechanism needs. Like AMCL, it reports the mean pose of the heaviest cluster. After resampling, AMCL groups the occupied bins of its KD-tree into clusters, where bins that touch, diagonally included, belong to the same cluster. It adds up the weights of the particles in each cluster and reports the mean pose of the cluster with the largest sum. Every resampled particle has the same weight, so this is the cluster with the most particles. The mean of all particles would fall between the modes of a spread-out belief. Nav2 can start without an initial pose. Itsreinitialize_global_localization service spreads max_particles particles uniformly over the free space of the map, and the run below starts that way.
Recovery after the robot is moved
A robot that is picked up and set down elsewhere, the kidnapped robot of Thrun, Burgard and Fox (2005, Section 7.2), leaves the particle filter with no particles near the new pose. Odometry does not see the move. Resampling only copies existing particles, so on its own the filter cannot find the robot again. Augmented MCL (Thrun, Burgard and Fox, 2005, Table 8.3) adds random poses during resampling. It tracks two exponential averages of the mean weight of the particles, with . Each resampled particle is replaced by a random pose with probability While the scans fit the particles, the two averages agree and is 0. When the fit gets suddenly worse, drops faster than and random poses enter the set. In Table 8.3, is the mean of the measurement likelihoods. AMCL computes it from the particle weights before it normalizes them. Each of those weights is the particle’s previous weight times its scan score, and after resampling every previous weight is . AMCL’s is therefore the mean score divided by the number of particles . Because KLD sampling changes , also falls when the particle set grows, even if the scores stay the same. Nav2 sets bothrecovery_alpha_slow and recovery_alpha_fast to 0, which turns the mechanism off. Its documentation suggests 0.001 and 0.1. AMCL also does one thing that Table 8.3 does not: after any update that injects random poses it sets both averages to zero, so that the next update restarts them from the current mean weight.
The run below starts from a known pose, as after you set the initial pose in Nav2, and carries the robot from the upper middle room to the lower left room after 60 updates. It runs three times: with Nav2’s defaults, with the suggested values, and with the suggested values but without the reset, as in Table 8.3.
reinitialize_global_localization and let the robot drive until the particles converge, as in the previous part.
Nav2 parameters and their symbols
The defaults are from the
nav2_amcl source. The likelihood_field_prob model adds beam skipping: when most particles disagree with a beam, the beam is ignored, which helps with objects that are not in the map.
References
- Fox, D. (2003). Adapting the sample size in particle filters through KLD-sampling. International Journal of Robotics Research, pp. 985 to 1003.
- Nav2 documentation. AMCL configuration guide.
- Nav2 source.
nav2_amclpackage. - Thrun, S., Burgard, W., and Fox, D. (2005). Probabilistic Robotics. MIT Press.
Found an error on this page? Report an issue.

