FixTheRobot Explore Robotics / Systems Engineering / Engineering Guides / Module 12

Engineering Guides · Module 12

Covariance-aware estimator handover

Weight each source by one over its variance. The handover is then a consequence of the covariances, not a switch.

  • Intermediate
  • Module 12: Outdoor-to-Indoor Localization & GNSS-Denied Navigation
  • Written for ROS 2 Jazzy where ROS 2 is used
  • Sources checked 2026-11-06

Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.

1. Engineering problem

A hard switch between GNSS and map localisation can jump at the instant it flips. If both sources report honest covariances, combining them weights the better one more and the handover happens gradually as GNSS degrades.

2. When is this needed?

  • Fusing GNSS with a map-based estimate near entrances.
  • When mode switching causes pose jumps.
  • When choosing covariance values.

3. Selection and design decisions

For two independent estimates of the same quantity with variances σ₁² and σ₂² the minimum-variance combination weights each by 1/σ², and the fused variance is 1/(1/σ₁² + 1/σ₂²). A Kalman filter such as the one in robot_localization does this recursively, and its documentation states that covariances in the input messages are used, that a measurement can be rejected with Mahalanobis thresholds, and that a sensor can time out, after which the filter predicts without correction (read 2026-11-06). The result is only as honest as the covariances: the NavSatFix covariance type says whether it is unknown, approximated, diagonal-known or known.

Overview
SituationWhat the weights doRisk
GNSS good (σ small)GNSS dominatesIf the map estimate is biased, it is ignored
GNSS degradingWeight moves to the map estimateNeeds an honest GNSS covariance
GNSS covariance too optimisticGNSS keeps dominating wronglyJumps and metre-level errors indoors
Both uncertainFused σ stays largeSlow down or stop (see the sensor-failure guide)

4. Advantages and disadvantages

  • Smooth fusion avoids jumps and depends on covariance quality; switching is robust to bad covariances and can jump.
  • Gating (Mahalanobis) protects from glitches that covariance alone does not show.
  • Inflate covariances rather than removing a source when you doubt it.

5. Requirements and constraints

  • Each source’s covariance is consistent with its actual error (checked on logs).
  • Sources are independent, or their correlation is handled.
  • Time stamps are aligned before fusing.

6. Architecture

GNSS (σ_g) ─┐
            ├─ inverse-variance weights ─▶ fused pose, σ_f
map (σ_m) ──┘

7. Implementation

  1. Measure the actual error of each source against a reference on logs.
  2. Set the covariances from that error, with a floor.
  3. Fuse (below) or use a filter that does it.
  4. Add gating for glitches and a timeout for lost sources.
  5. Check that the fused covariance matches the error in a crossing test.
def weights(sig_gnss, sig_map):
    wg, wm = 1 / sig_gnss ** 2, 1 / sig_map ** 2
    return wg / (wg + wm), wm / (wg + wm)
for t, sg in enumerate((0.05, 0.3, 1.0, 3.0, 10.0)):
    wg, wm = weights(sg, 0.15)
    fused = 1 / (1 / sg ** 2 + 1 / 0.15 ** 2) ** 0.5
    print(f"GNSS sigma {sg:5.2f} m: weight GNSS {wg:.3f}, map {wm:.3f}, fused sigma {fused:.3f} m")

Printed (checked by the site’s tests):

GNSS sigma  0.05 m: weight GNSS 0.900, map 0.100, fused sigma 0.047 m
GNSS sigma  0.30 m: weight GNSS 0.200, map 0.800, fused sigma 0.134 m
GNSS sigma  1.00 m: weight GNSS 0.022, map 0.978, fused sigma 0.148 m
GNSS sigma  3.00 m: weight GNSS 0.002, map 0.998, fused sigma 0.150 m
GNSS sigma 10.00 m: weight GNSS 0.000, map 1.000, fused sigma 0.150 m

Reading it: with a map-based estimate of σ = 0.15 m, GNSS at 0.05 m gets 90 % of the weight; at 0.30 m it gets 20 %; at 1.0 m only 2 %, and above that essentially none. The fused standard deviation never exceeds the better source. The handover therefore happens as GNSS degrades from 0.3 to 1 m, without any switch. Values are illustrative.

8. Real examples

  • Entrance: GNSS covariance grows from 0.05 m to metres within a few seconds; the weight moves to the map-based estimate over the same period.

9. Failure scenarios

  • Reporting a fixed small GNSS covariance whatever the fix quality.
  • Fusing two estimates that share the same raw data and treating them as independent.
  • No gating, so one glitch moves the pose.

10. Troubleshooting

  1. Plot the weights and the covariances over a crossing.
  2. Compare the fused error with the reference.
  3. Check the covariance type of the GNSS messages.

11. Validation

  • The example prints the lines shown (executed by the site tests).
  • The fused pose error in a crossing stays within its reported covariance.

12. Engineering checklist

13. Further references

Related on FixTheRobot