Sensor Fusion’s First Decision: Loosely or Tightly Coupled GNSS?
A practical framework for choosing loose versus tight IMU-GNSS fusion, including calibration priorities, an innovation-gating example, covariance reporting, and replay-based verification.
29 May 2026, 19:59 UTC

A robot or vehicle usually has an inertial measurement unit (IMU) updating at 100 Hz and GNSS updating at 10 Hz. The engineering problem is not simply choosing a filter: it is deciding what GNSS information the filter receives, how sensor errors are modeled, and what happens when a measurement is bad. The practical takeaway is to start with a loosely coupled extended Kalman filter (EKF) unless you can access raw satellite observations and implement integrity monitoring.
Choose the coupling before choosing the filter
A loosely coupled EKF consumes the GNSS receiver’s position or velocity solution. A tightly coupled EKF consumes individual observations such as pseudorange, carrier phase, and Doppler. Coupling changes both the information available to the filter and the amount of validation the team must own.
| Design | Main benefit | Main burden |
|---|---|---|
| Loosely coupled | Simple receiver interface and straightforward failure handling | Usually cannot inspect individual satellite measurements |
| Tightly coupled | Can use raw observations and satellite geometry directly | Requires receiver access, careful measurement modeling, and integrity checks |
Choose loose coupling when the receiver exposes only a finished navigation solution or when satellite-level monitoring is outside the project’s scope. Choose tight coupling when raw measurements are available and the team can distinguish a multipath-affected observation from a valid one. An unscented or particle filter may handle stronger nonlinearity, but it also increases CPU and memory use; that trade-off is secondary to calibration, timing, and measurement integrity.
Calibration and clocks constrain every design
Fusion assumes the IMU and GNSS describe the same motion at the same instant. Extrinsic calibration establishes the rigid transform between their coordinate frames, including the receiver’s lever arm from the vehicle’s navigation reference point. Time synchronization establishes when each measurement was taken. Neither error is automatically removed by the filter.
For scale, a 50 ms timestamp offset on a vehicle moving at 20 m/s creates a 1 m displacement before filtering begins. A similarly small mounting error can become a heading-dependent bias. Measure both with calibrated fixtures rather than estimating them from the same live trajectory the filter will process.
Worked example: reject one implausible GNSS fix
Consider an illustrative configuration for an EKF process. Replace every value with one characterized for the actual receiver, vehicle, and environment.
filter_config:
imu_rate_hz: 100
gnss_rate_hz: 10
gnss_position_variance_m2: [9.0, 9.0, 25.0]
innovation_gate_sigma: 3.0
fallback: propagate_with_increasing_covariance
The variance row represents the GNSS measurement noise matrix, not the filter’s prediction uncertainty. At each GNSS epoch, compute the innovation, the difference between the measured position and the EKF’s predicted position. Evaluate it against the combined uncertainty:
S = H * P_predicted * H_transpose + R
normalized_innovation = innovation / sqrt(S)
Suppose the horizontal innovation is 12 m, the predicted horizontal variance is 4 m², and the GNSS horizontal variance is 9 m². Then S = 13 m², and the normalized innovation is 12 / sqrt(13) = 3.33. With a three-sigma gate, that update should be rejected. The expected check is that the state and covariance remain unchanged at that GNSS epoch, while the next valid fix can still be accepted.
The gate is a diagnostic decision, not a universal constant. A gate that is too tight rejects valid measurements during aggressive maneuvers; one that is too loose admits multipath. If updates are repeatedly rejected, report degraded localization and enter a defined fallback rather than silently propagating an increasingly uncertain estimate.
Publish covariance, not just a position
A fused pose without uncertainty forces downstream code to treat every estimate as equally trustworthy. Publish the pose together with its covariance so a planner can widen an obstacle margin, slow down, or request localization assistance. The covariance also helps operators distinguish a smooth drift from a single rejected jump.
Do not treat filter covariance as a safety certificate. It describes estimated uncertainty under the configured model, not proof that the system meets a functional-safety requirement. Also avoid permanently hardcoding nominal noise values: IMU bias and GNSS error can change with temperature, age, and operating conditions.
Verify the system with synchronized replays
Record synchronized IMU and GNSS data, then replay it through the filter and compare the result with an independent reference such as RTK-GNSS or motion capture. Cover multiple routes, speeds, and urban or open-sky conditions. The implementation-independent checks below apply to conventional EKF software, although quaternion conventions and covariance frames vary by library and should be confirmed in its documentation.
- Confirm that timestamps share a clock domain and that the extrinsic transform came from a calibrated fixture.
- Check that attitude quaternions remain normalized after every update.
- Inspect innovation residuals and rejected-update counts across repeated runs.
- Compare estimated uncertainty with observed error using normalized estimation error squared when independent ground truth is available.
- Exercise GNSS denial, delayed measurements, and sustained rejection to verify the fallback behavior.
The decision is therefore straightforward: begin with loose coupling, make calibration and timing explicit, add innovation gating and covariance reporting, and move to tight coupling only when raw observations and integrity monitoring are genuinely available. If the replay shows divergence during sharp maneuvers, investigate linearization and sensor modeling before blaming the filter class.