Skip to content

Xsens MTi-680G IMU + GNSS (Formula Student driverless race car)

Platform: Formula Student / FSAE driverless race car (Ackermann kinematics) Status: Validation in progress — contributed by UniNa Corse, Università degli Studi di Napoli Federico II, 2nd place FSAE Italy 2025 driverless category. Field validation results will be published after competition season.


Sensors

Sensor Model Notes
IMU + GNSS Xsens MTi-680G 9-axis IMU (accel + gyro + mag) with integrated GNSS (RTK capable). Single unit.
Wheel / vehicle model Custom RK4 bicycle model Provides velocity odometry via encoder. Not a standard nav_msgs/Odometry topic.
VSLAM KISS-ICP Provides pose odometry in GPS-denied areas (e.g., tunnel sections).

IMU datasheet specs: - Gyro ARW: 0.01°/√hr → σ ≈ 0.0005 rad/s at 100 Hz - Accel VRW: 0.003 m/s/√hr → σ ≈ 0.003 m/s² at 100 Hz - This is a high-end tactical-grade MEMS IMU. Noise values are 6-14x lower than a BNO085.

GNSS specs: - Integrated u-blox GNSS receiver with RTK support - RTK fixed: CEP ~1cm - Standard GPS: CEP ~1.5m


Config

This configuration targets a high-vibration Ackermann vehicle with a high-quality IMU and RTK GPS. If you are running standard GPS (no RTK corrections), change gnss.base_noise_xy and gnss.min_fix_type as noted in the comments.

fusioncore:
  ros__parameters:
    base_frame: base_link
    odom_frame: odom
    publish_rate: 100.0
    publish.force_2d: false         # race car: 3D mode, surface is not perfectly flat

    motion_model: "Ackermann"       # front-wheel steering: cannot turn in place

    # Xsens MTi-680G: high-end tactical MEMS IMU.
    # Has a magnetometer but race car environment has strong magnetic interference
    # from motors and motor controllers. Leave false unless field-calibrated.
    imu.has_magnetometer: false
    imu.gyro_noise: 0.0005          # rad/s : ARW 0.01 deg/sqrt(hr) at 100 Hz
    imu.accel_noise: 0.003          # m/s^2 : VRW 0.003 m/s/sqrt(hr) at 100 Hz
    imu.remove_gravitational_acceleration: false  # Xsens driver publishes raw specific force
    imu.frame_id: "imu_link"

    # Wheel / bicycle model odometry.
    # The MTi-680G also outputs velocity from its integrated GNSS.
    # Tune vel_noise based on your encoder resolution and wheel slip characteristics.
    # Race cars have minimal wheel slip on dry track; loosen for wet conditions.
    encoder.vel_noise: 0.05         # m/s : conservative starting value
    encoder.yaw_noise: 0.03         # rad/s : slightly looser for high-speed cornering

    # Xsens MTi-680G integrated GNSS (RTK mode for competition).
    # Competition circuits typically have good sky view: use RTK fixed when available.
    # Near buildings or in tunnel sections: outlier gate handles GPS degradation.
    #
    # RTK fixed (open track sections):
    gnss.base_noise_xy: 0.015       # m : RTK fixed CEP ~1cm, conservative floor
    gnss.min_fix_type: 4            # 4=RTK_FIXED
    #
    # To fall back to RTK float if fixed is unavailable:
    # gnss.base_noise_xy: 0.5
    # gnss.min_fix_type: 3
    #
    # Standard GPS (no NTRIP corrections available):
    # gnss.base_noise_xy: 1.5
    # gnss.min_fix_type: 1

    gnss.base_noise_z: 0.1          # m : RTK Z accuracy is better than standard GPS
    gnss.max_hdop: 3.0
    gnss.min_satellites: 4

    # MTi-680G is a single-antenna unit. No dual-antenna heading.
    # Heading initializes from GNSS motion after ~5m of travel.
    gnss.heading_topic: ""
    gnss.azimuth_topic: ""

    # Lever arm: distance from base_link to GNSS antenna phase center.
    # On a race car this is significant and must be measured accurately.
    # x=forward, y=left, z=up (meters).
    gnss.lever_arm_x: 0.0
    gnss.lever_arm_y: 0.0
    gnss.lever_arm_z: 0.0

    # Outlier rejection: tighter threshold appropriate for RTK accuracy.
    # A 5-sigma GPS outlier with RTK fixed (CEP 1cm) is still a very small deviation.
    # Standard chi2(3, 0.999) gate handles this correctly.
    outlier_rejection: true
    outlier_threshold_gnss: 16.27   # chi2(3, 0.999)
    outlier_threshold_enc: 11.34    # chi2(3, 0.999)
    outlier_threshold_imu: 15.09    # chi2(6, 0.999)

    # Coast mode: for GPS-denied sections (tunnel, underground pit area).
    gnss.coast_n: 3
    gnss.coast_q_factor: 10.0
    gnss.coast_timeout_s: 10.0      # tighter than default: race cars move fast

    # KISS-ICP VSLAM: provides absolute pose during GPS-denied sections.
    # Uncomment and set to your actual KISS-ICP output topic.
    # vslam.topic: "/kiss_icp/odometry"
    # vslam.pose_noise: 0.05

    adaptive.imu: true
    adaptive.encoder: true
    adaptive.gnss: true
    adaptive.window: 50
    adaptive.alpha: 0.01

    # High-quality IMU: tighter orientation process noise than generic configs.
    ukf.q_position: 0.01
    ukf.q_orientation: 1.0e-10     # tighter: MTi-680G orientation is very stable
    ukf.q_velocity: 0.1
    ukf.q_angular_vel: 0.05        # tighter: low gyro noise
    ukf.q_acceleration: 1.0
    ukf.q_gyro_bias: 1.0e-6        # tighter: tactical MEMS bias stability
    ukf.q_accel_bias: 1.0e-6
    ukf.q_encoder_wz_bias: 1.0e-7

    input.gnss_crs: "EPSG:4326"
    output.crs: "EPSG:4978"
    output.convert_to_enu_at_reference: true
    reference.use_first_fix: true

Topic remaps

The Xsens MTi-680G uses the official xsens_ros_mti_driver package. Default topics:

ros2 launch fusioncore_ros fusioncore.launch.py \
  fusioncore_config:=/path/to/this-config.yaml \
  --ros-args \
  -r /imu/data:=/imu/data \          # xsens driver default: already /imu/data
  -r /gnss/fix:=/gnss \              # xsens driver publishes NavSatFix at /gnss
  -r /odom/wheels:=/vehicle/odom      # your bicycle model odometry topic

Check your xsens_ros_mti_driver configuration for the exact topic names. The driver can output sensor_msgs/Imu and sensor_msgs/NavSatFix simultaneously from the same unit.


Adapting this config for standard GPS

If you do not have RTK corrections (NTRIP base station or corrections from the MTi-680G's GNSS), use standard GPS values:

gnss.base_noise_xy: 1.5        # m : MTi-680G autonomous GPS CEP
gnss.min_fix_type: 1
gnss.base_noise_z: 3.0

Deployer

Pasquale Cannavacciuolo (@pakyCannavacciuolo05), UniNa Corse — Università degli Studi di Napoli Federico II. FSAE Italy 2025 driverless category, 2nd place overall.

Running FusionCore with this config on your Xsens platform? Open a pull request to update the status and add your validation results.