ROS 2 Jazzy driver for the TDK InvenSense ICM-20948 9-axis IMU (3-axis accelerometer + 3-axis gyroscope + AK09916 3-axis magnetometer) over I2C.
- Publishes
sensor_msgs/Imuon theimu/data_rawtopic (no orientation fusion,orientation_covariance[0] = -1) - Publishes
sensor_msgs/MagneticFieldon theimu/magtopic - Publishes
sensor_msgs/Temperatureon theimu/temptopic - Fake mode — generates random 9-axis IMU data without physical hardware
- Register bank switching (Bank 0-3) for full ICM-20948 register access
- AK09916 magnetometer access via I2C secondary bus (auto-read)
- Configurable accel/gyro full-scale ranges, publish rate, and covariance values
- Proper SI unit output: acceleration in m/s², angular velocity in rad/s, magnetic field in Tesla
- ROS 2 Jazzy
- Python 3
smbus2(only required whenfake_modeisfalse)
pip3 install smbus2cd ~/ros2_ws
colcon build --packages-select icm20948_imu
source install/setup.bashros2 launch icm20948_imu icm20948_launch.pyros2 run icm20948_imu icm20948_node.py --ros-args -p fake_mode:=trueros2 run icm20948_imu icm20948_node.py --ros-args -p fake_mode:=falseros2 launch icm20948_imu icm20948_launch.py params_file:=/path/to/your_params.yamlros2 topic echo /imu/data_raw
ros2 topic echo /imu/mag
ros2 topic echo /imu/temp| Parameter | Type | Default | Description |
|---|---|---|---|
fake_mode |
bool | true |
true: generate random data, false: read from real I2C device |
i2c_bus |
int | 1 |
I2C bus number (/dev/i2c-N) |
device_address |
int | 0x68 |
ICM-20948 I2C address (0x68 AD0=LOW, 0x69 AD0=HIGH) |
publish_rate |
double | 100.0 |
Publishing rate in Hz (runtime changeable) |
frame_id |
string | imu_link |
TF frame ID in message headers |
accel_range |
int | 0 |
Accelerometer full-scale: 0=±2g, 1=±4g, 2=±8g, 3=±16g |
gyro_range |
int | 0 |
Gyroscope full-scale: 0=±250, 1=±500, 2=±1000, 3=±2000 dps |
accel_covariance |
double | 0.04 |
Diagonal acceleration covariance (m²/s⁴) |
gyro_covariance |
double | 0.02 |
Diagonal angular velocity covariance (rad²/s²) |
mag_covariance |
double | 0.01 |
Diagonal magnetic field covariance (T²) |
| Service | Type | Description |
|---|---|---|
imu/calibrate |
std_srvs/Trigger |
Collect gyro data for 2 seconds and compute bias offset |
imu/reset |
std_srvs/Trigger |
Clear bias and reinitialize the sensor |
icm20948_imu/
├── CMakeLists.txt
├── package.xml
├── config/
│ └── icm20948_params.yaml
├── launch/
│ └── icm20948_launch.py
├── icm20948_imu/
│ ├── __init__.py
│ └── icm20948_driver.py
├── nodes/
│ └── icm20948_node.py
└── test/
└── test_icm20948_node.py
Tested on Ubuntu 24.04 (WSL2) with fake_mode: true.
$ colcon test --packages-select icm20948_imu
$ colcon test-result --verbose
Summary: 217 tests, 0 errors, 0 failures, 0 skipped
| Test Category | Test | Result |
|---|---|---|
| Topics | imu/data_raw publishes sensor_msgs/Imu |
PASS |
| Topics | imu/mag publishes sensor_msgs/MagneticField |
PASS |
| Topics | imu/temp publishes sensor_msgs/Temperature |
PASS |
| Topics | frame_id == "imu_link" |
PASS |
| Topics | orientation_covariance[0] == -1.0 (no fusion) |
PASS |
| Topics | Temperature in range 10-40 °C | PASS |
| Services | imu/calibrate returns success=True |
PASS |
| Services | imu/reset returns success=True |
PASS |
| Parameters | publish_rate runtime change to 20.0 Hz |
PASS |
| Shutdown | Clean exit (code 0, -2, or -15) | PASS |
| Linting | pep257, flake8, copyright, xmllint | PASS |
This project is licensed under the MIT License. See LICENSE for details.