Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file
CONTRIBUTING
Repository Summary
| Checkout URI | https://github.com/manankharwar/fusioncore.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-04-10 |
| Dev Status | MAINTAINED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Packages
| Name | Version |
|---|---|
| compass_msgs | 0.1.1 |
| fusioncore_core | 0.1.1 |
| fusioncore_gazebo | 0.1.1 |
| fusioncore_ros | 0.1.1 |
README
FusionCore
ROS 2 sensor fusion SDK. Combines IMU, wheel encoders, and GPS into one reliable position estimate. Zero manual tuning. Apache 2.0.
What problem does this solve?
Every mobile robot needs to know where it is. It gets this from multiple sensors: IMU, wheel encoders, GPS: each of which is imperfect in its own way. IMUs drift. Wheels slip. GPS jumps. You need software that intelligently combines all three into one trustworthy position estimate.
That software is called a sensor fusion package. The standard one for ROS, robot_localization, was officially deprecated in September 2023. Its designated replacement (fuse) still doesn’t support GPS properly as of early 2026. At ROSCon UK 2025 the official workshop was still teaching both tools because no clear accessible replacement existed.
FusionCore is that replacement.
Why FusionCore
| Capability | robot_localization | Fuse | FusionCore |
|---|---|---|---|
| Core filter | EKF | Factor graph | UKF |
| 3D support | Partial | PR open 1+ year | Full 3D, native |
| IMU bias estimation | None | Complex | Automatic |
| GPS fusion | UTM workaround | Not implemented | ECEF, proper |
| Dual antenna heading | Hack required | Not supported | Native |
| IMU frame transform | Manual | Manual | Automatic via TF |
| Message covariances | Ignored | Partial | Full 3x3 GNSS + odometry |
| GNSS antenna offset | Ignored | Ignored | Lever arm with observability guard |
| Outlier rejection | None | None | Mahalanobis chi-squared gating |
| Adaptive noise | None | None | Automatic from innovation sequence |
| TF validation | Silent failure | Silent failure | Startup check + exact fix commands |
| Multiple sensor sources | No | No | Yes: 2x GPS, multiple IMUs |
| compass_msgs/Azimuth | No | No | Yes: ROS 2 native port |
| Delay compensation | No | No | Yes: full IMU replay retrodiction up to 500ms |
| Ground constraint | No | No | Yes: VZ=0 pseudo-measurement for wheeled robots |
| Sensor dropout detection | Silent | Silent | Per-sensor staleness with SensorHealth enum |
| Maintenance | Abandoned | Slow | Active, issues answered in 24h |
| License | BSD-3 | BSD-3 | Apache 2.0 |
| ROS 2 Jazzy | Ported | Native | Native, built from scratch |
| Working examples | Minimal | None | Real robot configs |
Installation
Prerequisites
- ROS 2 Jazzy Jalisco (primary) or ROS 2 Kilted (community tested)
- A colcon workspace (
~/ros2_ws)
Clone into your workspace
cd ~/ros2_ws/src
git clone https://github.com/manankharwar/fusioncore.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
colcon build --packages-select fusioncore_core fusioncore_ros
source install/setup.bash
Running the tests
cd ~/ros2_ws
source /opt/ros/jazzy/setup.bash
colcon build --packages-select fusioncore_core --cmake-args -DBUILD_TESTING=ON
colcon test --packages-select fusioncore_core
colcon test-result --verbose
Expected output: 42 tests, 0 errors, 0 failures, 0 skipped
Running FusionCore
# Terminal 1
ros2 launch fusioncore_ros fusioncore.launch.py
# Terminal 2
ros2 lifecycle set /fusioncore configure
ros2 lifecycle set /fusioncore activate
# Verify
ros2 topic hz /fusion/odom
# expected: average rate: 100.000
FusionCore uses a ROS 2 lifecycle node. Configure first (load parameters, validate TF tree, check transforms), then activate (start processing sensor data). This prevents the filter from starting with bad initial values or missing transforms.
WSL2 note: If
ros2 lifecycle setreturns “Node not found”, use the launch file’s built-in auto-configure instead. The Gazebo launch file (fusioncore_gazebo.launch.py) configures and activates the node automatically viaEmitEvent(ChangeState(...))12 seconds after startup, bypassing DDS discovery latency that affects WSL2.
Sensor topics
File truncated at 100 lines see the full file