IMU biasNEORACER DOCS
NEORACER DOCS
These docs are public and open source.Edit on GitHub
CALIBRATION / IMU BIAS

IMU BIAS CALIBRATION.

A raw QMI8658A reads a small, steady offset even when the car is dead still, and the QMC6309 magnetometer reads a field warped by the metal around it. Two scripts measure those once and write the corrections to a pair of YAML files the driver loads at launch, so rc.physics gives you honest numbers.

~0 minutesIntermediateWrites real YAMLLoaded at launch
01 / TWO CALIBRATIONS

THE TWO CALIBRATIONS.

The IMU node reads three sensors off one chip: accelerometer, gyroscope, and magnetometer. The first two are corrected by sitting still; the third needs you to turn the car through every direction so the script can map the field. They are two separate scripts and two separate YAML files.

01

Accel + gyro bias

calibrate_imu.py, car still.
Held flat and motionless, the script averages the readings and stores the offset as accelerometer.bias and gyroscope.bias.
imu_cal.yaml
02

Magnetometer fit

calibrate_mag.py, car rotating.
Turning the car through all orientations, it fits a and a so the field reads as a clean sphere, not a tilted egg.
mag_cal.yaml
02 / YOU'LL NEED

WHAT YOU'LL NEED.

01

The driver running

So /imu and /mag publish.
Both scripts subscribe to the live topics, so the IMU node has to be up first. Launch the driver before you start either one.
02

A level surface

For the accel and gyro pass.
A flat, vibration-free spot for the still pass. The accelerometer learns which way is down from it, so a tilted table bakes the tilt into the bias.
03

Space to rotate

For the magnetometer pass.
Clear room to slowly turn the car through pitch, roll, and yaw. Away from motors, laptops, and steel desks, which warp the very field you are measuring.
FIG. A / FIVE STEPS, START TO FINISH
1
$_
SSH in
to the Jetson
2
Driver up
/imu, /mag publishing
3
Still + level
accel + gyro bias
4
Rotate
magnetometer fit
5
Save YAML
config/imu_cal · mag_cal
Bring the driver up, run the still pass, run the rotating pass, and the two YAML files are written for the IMU node to load next launch.
03 / ACCEL + GYRO

THE ACCEL + GYRO PASS.

bash
# Driver running (teleop), car flat and motionless on a level surface. python3 ~/racecar_ws/src/racecar_neo/scripts/calibrate_imu.py # It connects to /imu, collects a window of samples, and averages them. # The mean is the bias: what the sensor reports when nothing is moving. # When it finishes, it writes imu_cal.yaml.
04 / MAGNETOMETER

THE MAGNETOMETER FIT.

bash
# Driver running. Pick the car up and be ready to rotate it. python3 ~/racecar_ws/src/racecar_neo/scripts/calibrate_mag.py # While it collects, slowly tumble the car through every orientation: # nose up and down, roll left and right, spin through a full yaw. # It fits a hard-iron offset and a soft-iron matrix to the cloud of # points, plots them as a sphere so you can see the coverage, and # writes mag_cal.yaml.

The goal is even coverage of the sphere. Gaps mean a direction the field was never sampled, which leaves the fit guessing there. Keep turning until the plotted points wrap the whole ball.

05 / WHERE IT LIVES

THE OUTPUT YAML.

This is the one calibration that is a real config file, not a source constant. The launch file hands both YAMLs to the IMU node as parameters, so the corrections apply the next time you bring the driver up. The parameter names are documented on the ROS 2 parameters page.

yaml
# config/imu_cal.yaml, written by calibrate_imu.py imu_node: ros__parameters: accelerometer: bias: [0.013, -0.021, 0.004] # m/s^2, per axis gyroscope: bias: [0.0011, 0.0006, -0.0009] # rad/s, per axis # config/mag_cal.yaml, written by calibrate_mag.py imu_node: ros__parameters: magnetometer: hard_iron_bias: [1.2e-5, -8.0e-6, 3.1e-6] # T, offset soft_iron_matrix: data: [1.02, 0.01, 0.0, 0.01, 0.98, 0.0, 0.0, 0.0, 1.0] # row-major 3x3
  • Relaunch the driver after calibrating so the IMU node reloads the files.
  • The values above are an illustration; yours come out of the two scripts.
  • Keep the YAMLs with your workspace so a re-image does not drop them back to identity.