Hi peci1!! Thank you again for the detailed review. I spent the last few days working through your list properly.
Here’s what’s been fixed:
IMU frame transform: the node now reads frame_id from the IMU message, looks up the TF rotation to base_link, and transforms angular velocity and linear acceleration before fusing. If the transform is missing, it prints the exact static_transform_publisher command to fix it and falls back gracefully.
GNSS antenna offset: implemented with a proper observability guard. The lever arm correction only activates when heading has been independently validated from a real source. Specifically, heading_validated_ is only set true when: a dual antenna heading message is received, an AHRS/IMU with magnetometer publishes orientation, or the robot has traveled >= 5 meters at sufficient speed with low yaw rate. Before any of these, lever arm is disabled regardless of what yaw variance says…. so the filter cannot fake its way into applying the correction.
Message covariances: GNSS now uses the full 3x3 covariance matrix when position_covariance_type == 3, including off-diagonal elements. Wheel odometry reads twist.covariance per-axis when available. Both fall back to config params when covariance is zero or unknown. Config params still work as overrides for sensors with bogus covariance.
IMU orientation: accepted as a direct measurement. Added imu.has_magnetometer config flag…. when false (default, 6-axis IMUs), orientation fuses roll/pitch but does not validate heading. When true (9-axis: BNO08x, VectorNav, Xsens), heading is validated. This prevents gyro drift from silently activating lever arm correction.
Multiple sources: second GNSS receiver configurable via gnss.fix2_topic. Multiple IMU sources via separate TF-aware callbacks.
Dual antenna heading: fully wired to a ROS topic (gnss.heading_topic, default /gnss/heading).
Uses sensor_msgs/Imu orientation quaternion: acknowledged this is slightly awkward but it’s what most u-blox and Septentrio drivers publish.
compass_msgs/Azimuth: added support. The upstream package is ROS 1 only so I ported the identical message definition to ROS 2 Jazzy natively. FusionCore now accepts compass_msgs/Azimuth on a configurable topic, handles ENU/NED convention conversion, RAD/DEG units, and warns when magnetic north reference is used instead of geographic.
Happy to contribute the ROS 2 port back upstream if that’s useful to you.
Do you mind testing it out and/or if you have any questions or if you spot any red flags then please let me know…