Repository navigation
Add localization GPS/IMU fusion with bias estimation and outage simulation - #1448
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The implementation, documentation, links, and comprehensive tests are consistent and no blocking issues were identified.
Review effort: Balanced
Findings: None
What changed in this PR
Adds a documented planar GPS/IMU EKF example with bias estimation and simulated GPS outages.
Changes:
- Implements eight-state sensor fusion, simulation, and animation.
- Adds comprehensive numerical and rendering tests.
- Integrates the example into project documentation and README.
| File | Description |
|---|---|
Localization/gps_imu_fusion/gps_imu_fusion.py |
Implements the EKF, simulation, and animation. |
tests/test_gps_imu_fusion.py |
Tests models, covariance, outages, and rendering. |
docs/modules/2_localization/gps_imu_fusion/gps_imu_fusion_main.rst |
Documents assumptions and equations. |
docs/modules/2_localization/localization_main.rst |
Adds the documentation entry. |
README.md |
Adds the example overview and links. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
GPS/IMU Fusion Localization with Bias Estimation The upper panels compare GPS/IMU fusion with bias estimation (blue), fusion without bias estimation (red dashed), and IMU-only dead reckoning (orange dotted), using the same sensor measurements.
For the default seed 0, ground truth lies inside the bias-estimating EKF's position ellipse and all three bias bands at all 1,001 samples. The no-bias-estimation EKF's true position falls outside its ellipse during parts of the run. These are synthetic demonstration results, not a guarantee of coverage for other data. The bias 3σ half-widths shrink from 0.300 → 0.0339 m/s² (x), 0.300 → 0.0296 m/s² (y), and 3.000 → 0.458 deg/s (gyro). Position RMSE: 0.66 m with bias estimation, 2.58 m without bias estimation, and 15.74 m for IMU-only dead reckoning. Updated animation: PythonRoboticsGifs#17. |

Reference issue
Addresses #603 with a planar GPS/IMU fusion example.
What does this implement/fix?
Add an eight-state extended Kalman filter that predicts from body-frame accelerometer/gyroscope readings at 20 Hz and corrects with GPS positions at 1 Hz. It estimates position, velocity, heading and three IMU biases, continuing prediction during a simulated 10-second GPS outage.
An independently generated analytic figure-eight trajectory lets the animation compare GPS/IMU fusion with bias estimation, a five-state GPS/IMU EKF without bias estimation, and IMU-only dead reckoning. All three use the same biased, noisy IMU samples; both EKFs receive the same GPS fixes and outage schedule. The five-state EKF assumes zero bias while still correcting position, velocity and heading with GPS. The sample includes analytic motion Jacobians, sample-noise propagation, bias random walk and a Joseph-form GPS covariance update.
The documentation and README use the title GPS/IMU Fusion Localization with Bias Estimation. The animation includes three additional panels comparing estimated accelerometer x/y biases (m/s²) and gyroscope bias (deg/s) against ground truth, with covariance-derived ±3σ bands and GPS outages shaded. The path plot shows current 3σ position ellipses for both EKFs, including x/y cross-covariance; the error plot also tracks the bias-estimating EKF's ellipse semi-major axis.
The documentation states the planar, gravity-compensated, local-metric-frame assumptions and the need for approximately known initial heading/velocity. It includes the equations and code links. README and localization contents link to the example.
Companion animation: PythonRoboticsGifs#17. The documentation uses its immutable commit URL so the image is available before merging.
Additional information
Validated on Python 3.13.2 with the repository's pinned runtime and documentation dependencies:
MPLBACKEND=Agg bash runtests.sh: 156 passed, including 19 tests for the new example, Ruff and mypy.cd docs && make html: passed with warnings treated as errors.CheckList