← Emre Girgin

Camera–IMU Calibration with Kalibr

Calibrating a camera you mounted on a robot against the robot's IMU, and checking whether the result is any good.

1. Convert the ROS2 bag to ROS1

Kalibr runs on ROS1, so convert the recording first. Exclude topics with custom message types (on Unitree robots, /lowstate); the converter cannot read them.

pip3 install "rosbags>=0.9.12"
rosbags-convert --src <ros2_bag> --dst <name>.bag --exclude-topic <custom_topic>

2. Describe the IMU and the target

imu.yaml. Take the noise values from an Allan variance run on your own IMU; the ones below are only a starting point:

rostopic: /imu

accelerometer_noise_density: 0.01
accelerometer_random_walk: 0.0002
gyroscope_noise_density: 0.005
gyroscope_random_walk: 4.0e-06

update_rate: 500   # your IMU rate; check with `ros2 topic hz`

april_6x6.yaml for a 6×6 AprilGrid:

target_type: 'aprilgrid'
tagCols: 6
tagRows: 6
tagSize: 0.088     # edge to edge, metres
tagSpacing: 0.3    # gap / tagSize
codeOffset: 0

3. Build Kalibr in Docker

git clone https://github.com/ethz-asl/kalibr.git
cd kalibr
docker build -t kalibr_noetic -f Dockerfile_ros1_20_04 .   # 5–10 minutes

Put imu.yaml, april_6x6.yaml and the ROS1 bag in one folder and start the container from there:

xhost +local:root
docker run -it --rm \
    -e "DISPLAY" -e "QT_X11_NO_MITSHM=1" \
    -v "/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    -v "$(pwd):/data" \
    kalibr_noetic /bin/bash

4. Camera intrinsics

rosrun kalibr kalibr_calibrate_cameras \
    --bag /data/<name>.bag \
    --target /data/april_6x6.yaml \
    --models pinhole-radtan \
    --topics /camera/image_raw \
    --verbose

This writes <name>-camchain.yaml, <name>-results-cam.txt and <name>-report-cam.pdf.

5. Camera–IMU extrinsics

source /catkin_ws/devel/setup.bash
rosrun kalibr kalibr_calibrate_imu_camera \
    --bag /data/<name>.bag \
    --cam /data/<name>-camchain.yaml \
    --imu /data/imu.yaml \
    --target /data/april_6x6.yaml \
    --verbose

Excite every axis while recording: tilt, roll, yaw and translate the robot in front of the board, including forward and back. Too little translation is the most common reason the extrinsics come out wrong.

6. Is the result any good?

Five things to check:

Camera–IMU translation

Time shift

Reprojection error

Accelerometer bias

Gravity magnitude

7. Using the result in OpenVINS

The full VIO setup is in Odometry on a Quadruped.