Skip to main content
Version: 1.0.2

IMU

Hardware​

AutomatePro includes an onboard BNO085 9-axis MEMS IMU. The IMU combines a 3-axis accelerometer, 3-axis gyroscope, and 3-axis magnetometer. The driver publishes ROS 2 IMU data and, when enabled, magnetic-field and accuracy data.

The arrows on the device indicate the IMU vector directions:

AutomatePro IMU axis directions

IMU Specifications​

ParameterValue
SensorBNO085
Sensing types3-axis gyroscope, 3-axis magnetometer, 3-axis accelerometer
Rotation vector error (dynamic)13.5 deg
Accelerometer accuracy10.3 m/s2
Gyroscope accuracy13.1 deg/s
Magnetometer accuracy11.4 uT
Default IMU sample rate100 Hz
Configurable IMU rateUp to 400 Hz, hardware dependent
Info

1 Based on IC manufacturer tests. Results on AutomatePro can vary by mounting, calibration, and magnetic environment. See the BNO080/BNO085 datasheet for manufacturer details.

ROS API​

Node: automatepro_imu_driver​

Publishers​

TopicTypeDescription
/sensor/imu/datasensor_msgs/msg/ImuOrientation, angular velocity, and linear acceleration.
/sensor/imu/magnetic_fieldsensor_msgs/msg/MagneticFieldMagnetic field data, when magnetometer publishing is enabled.
/sensor/imu/accuracyautomatepro_imu_driver/msg/ImuAccuracyAccuracy levels for orientation, accelerometer, gyroscope, and magnetic-field reports.

Services​

ServiceTypeDescription
/sensor/imu/save_tarestd_srvs/srv/TriggerPersists the current tare to sensor flash.
/sensor/imu/save_calibrationstd_srvs/srv/TriggerSaves Dynamic Calibration Data (DCD) to sensor flash.
/sensor/imu/reinitstd_srvs/srv/TriggerReinitializes the IMU driver and sensor.

Verify IMU Data​

Run these checks from AutomatePro over SSH:

source /opt/ros/humble/setup.bash
ros2 node list | grep automatepro_imu_driver
ros2 topic echo /sensor/imu/data --once --qos-reliability best_effort

If accuracy publishing is enabled, check calibration state:

ros2 topic echo /sensor/imu/accuracy --once

Accuracy levels use:

ValueMeaning
0Unreliable
1Low
2Medium
3High
255Unknown

Configuration​

Driver: automatepro_imu_driver
Container: automatepro-core-driver

info

Runtime ROS configuration is stored in /opt/automatepro/config/ros. Packaged defaults are stored in /opt/automatepro/defconfig/ros.

Edit the IMU parameter file:

sudo nano /opt/automatepro/config/ros/imu_params.yaml

Important parameters:

ParameterDefaultDescription
log_levelinfoDriver log level. Launch accepts debug, info, warn, error, or fatal.
frame_idlm450_imu_linkFrame ID stamped on published IMU messages.
rotation_vector_modegame_rotation_vectorOrientation report type. Use rotation_vector for magnetic absolute heading, game_rotation_vector for relative heading without magnetometer, or geomagnetic_rotation_vector for geomagnetic heading.
tare.on_startupfalseApplies one-shot tare when the node starts. Leave disabled after commissioning.
tare.axesxyzAxes included in tare.
tare.persistfalseSaves tare to flash when enabled.
tare.use_persistedfalseComposes the tare saved in the sensor with the mounting orientation. When false, the driver ignores the saved tare and uses the mounting orientation as the absolute reorientation.
tare.orientation.enabledtrueApplies the configured chip-to-body orientation mapping at startup and watchdog reinitialization.
tare.orientation.roll_deg/pitch_deg/yaw_deg0.0/0.0/0.0Mounting orientation in degrees when use_quaternion is false.
tare.orientation.use_quaternionfalseUses qx, qy, qz, and qw instead of roll, pitch, and yaw when enabled.
tare.orientation.qx/qy/qz/qw0/0/0/1Quaternion orientation mapping when use_quaternion is true.
calibration.accelerometer.enabledfalseEnables BNO08x accelerometer dynamic calibration.
calibration.accelerometer.planarfalseEnables planar accelerometer calibration mode.
calibration.gyroscope.enabledfalseEnables BNO08x gyroscope dynamic calibration.
calibration.gyroscope.on_tablefalseEnables stationary on-table gyroscope calibration assist.
calibration.magnetic_field.enabledfalseEnables BNO08x magnetometer dynamic calibration. Enable only when magnetic heading is required and the environment is suitable.
calibration.save_dcdfalsePeriodically saves Dynamic Calibration Data to flash.
i2c.enabledtrueUses I2C communication.
i2c.bus/dev/i2c-7I2C bus path.
i2c.address0x4BBNO08x I2C address.
uart.enabledfalseUses UART communication instead of I2C when enabled and i2c.enabled is false.
uart.device/dev/ttyACM0UART device path when UART transport is enabled.
publish.accuracy.enabledtruePublishes /sensor/imu/accuracy.
publish.imu.enabledtruePublishes /sensor/imu/data.
publish.imu.rate100Requested IMU report rate in Hz.
publish.magnetic_field.enabledfalsePublishes /sensor/imu/magnetic_field. Use --qos-reliability best_effort when echoing this topic from the CLI.
publish.magnetic_field.rate100Requested magnetometer report rate in Hz.
publish.imu.orientation_offset.enabledfalseApplies a software quaternion offset before publishing orientation.
publish.imu.orientation_offset.qx/qy/qz/qw0/0/0/1Software orientation offset quaternion.
Important

Restart automatepro-core-driver after changing the configuration. Configuration values are loaded when the driver container starts and are only applied after the service restarts.

sudo systemctl restart automatepro-core-driver

Default Configuration Shape​

automatepro_imu_driver:
ros__parameters:
log_level: "info"
frame_id: "lm450_imu_link"
rotation_vector_mode: "game_rotation_vector"
tare:
on_startup: false
axes: "xyz"
persist: false
use_persisted: false
orientation:
enabled: true
roll_deg: 0.0
pitch_deg: 0.0
yaw_deg: 0.0
use_quaternion: false
qx: 0.0
qy: 0.0
qz: 0.0
qw: 1.0
calibration:
accelerometer:
enabled: false
planar: false
gyroscope:
enabled: false
on_table: false
magnetic_field:
enabled: false
save_dcd: false
i2c:
enabled: true
bus: "/dev/i2c-7"
address: "0x4B"
uart:
enabled: false
device: "/dev/ttyACM0"
publish:
accuracy:
enabled: true
magnetic_field:
enabled: false
rate: 100
imu:
enabled: true
rate: 100
orientation_offset:
enabled: false
qx: 0.0
qy: 0.0
qz: 0.0
qw: 1.0

Example​

This example prints IMU and magnetic field messages, each at most once per second, by subscribing to /sensor/imu/data and /sensor/imu/magnetic_field; the driver publishes the magnetic field only when publish.magnetic_field.enabled is true. The tutorial package is available in the AutomatePro tutorials repository, and its README explains how to build and run the examples.

Source: imu.py

import rclpy
from rclpy.executors import ExternalShutdownException
from rclpy.node import Node
from sensor_msgs.msg import Imu, MagneticField

LOG_PERIOD_S = 1.0


class ImuSubscriber(Node):

def __init__(self):
super().__init__('imu_subscriber')
self.imu_subscription = self.create_subscription(
Imu,
'/sensor/imu/data',
self.imu_callback,
10)
self.magnetic_field_subscription = self.create_subscription(
MagneticField,
'/sensor/imu/magnetic_field',
self.magnetic_field_callback,
10)

def imu_callback(self, msg):
self.get_logger().info(
'Received IMU message: orientation=%s, angular_velocity=%s, '
'linear_acceleration=%s' % (
msg.orientation, msg.angular_velocity, msg.linear_acceleration),
throttle_duration_sec=LOG_PERIOD_S)

def magnetic_field_callback(self, msg):
self.get_logger().info(
'Received MagneticField message: magnetic_field=%s' % msg.magnetic_field,
throttle_duration_sec=LOG_PERIOD_S)


def main(args=None):
rclpy.init(args=args)
node = ImuSubscriber()
try:
rclpy.spin(node)
except (KeyboardInterrupt, ExternalShutdownException):
pass
finally:
node.destroy_node()
rclpy.try_shutdown()


if __name__ == '__main__':
main()

Run the node using the following command:

ros2 run automatepro_python_tutorials imu_node

Orientation Commissioning​

Use this workflow when the IMU is remounted, when the reference orientation changes, or when a system needs a known rest pose.

Important

Perform tare and calibration only when the device is in its final mounting position and away from motors, steel structures, strong magnets, and current-carrying wires.

  1. Complete dynamic calibration.

    Dynamic calibration is off in the packaged configuration, because slow yaw turns during operation mis-calibrate the gyroscope. For a calibration session, set calibration.accelerometer.enabled and calibration.gyroscope.enabled to true, and calibration.magnetic_field.enabled only if magnetic heading is required, then restart the core driver.

    Move the device through several stable orientations for accelerometer calibration, leave it stationary for gyroscope calibration, and perform magnetic rotations only if magnetic-field calibration is enabled. Save the calibration:

    ros2 service call /sensor/imu/save_calibration std_srvs/srv/Trigger

    Set the calibration flags back to false and restart the core driver.

  2. Tare the reference pose (optional).

    With the packaged tare.use_persisted: false, the driver ignores a tare saved in the sensor and uses the mounting orientation from step 3 as the absolute reorientation, so a tare does not survive a restart. A saved tare does not apply to game_rotation_vector, the default mode; use steps 3 and 4 instead.

    To use a saved tare with rotation_vector, place AutomatePro in the desired zero orientation and temporarily set:

    tare:
    on_startup: true
    axes: "xyz"
    persist: true
    use_persisted: true

    Restart the core driver and wait for tare completion in logs:

    sudo systemctl restart automatepro-core-driver
    sudo journalctl -u automatepro-core-driver -f

    After tare completes, set tare.on_startup: false so it is not applied on every boot. Keep tare.use_persisted: true.

  3. Set mounting orientation.

    Use tare.orientation.roll_deg, pitch_deg, and yaw_deg to map the chip axes to the device body frame. This orientation mapping is re-applied on startup and watchdog recovery.

  4. Apply software heading offset when needed.

    If the device in the rest pose should publish identity orientation (0, 0, 0, 1), capture the current quaternion:

    ros2 topic echo /sensor/imu/data --field orientation --once

    Set publish.imu.orientation_offset.* to the conjugate of that quaternion and enable publish.imu.orientation_offset.enabled.

  5. Verify the final output.

    Restart the core driver and verify that the rest pose and motion directions match your robot frame:

    sudo systemctl restart automatepro-core-driver
    ros2 topic echo /sensor/imu/data --field orientation --once
Developer Notes: rotation modes and persistence

rotation_vector_mode selects which BNO08x SH-2 report is enabled. game_rotation_vector does not use the magnetometer and reports relative heading. rotation_vector and geomagnetic_rotation_vector use magnetic information for heading.

Dynamic tare runs only on initial node startup when tare.on_startup is enabled. The fixed mounting orientation is re-applied on every sensor initialization, including watchdog recovery. The software orientation offset is applied as q_published = q_offset * q_sensor.

Troubleshooting​

IMU Topic Is Missing​

Check that the driver is enabled:

grep ROS_DRIVER_IMU /opt/automatepro/.env

Check logs:

sudo journalctl -u automatepro-core-driver -n 100 --no-pager

Automatic Recovery​

The driver watches the sensor data stream and reinitializes the sensor when no data arrives for two seconds. This is the same action as the /sensor/imu/reinit service, and the period and timeout are fixed in the driver.

The mounting orientation configured under tare.orientation is applied again on every reinitialization. A dynamic tare is not, as described in Orientation Commissioning.

Orientation Is Correct After Startup but Wrong After Recovery​

Verify tare.orientation.enabled: true. The fixed orientation mapping is the part reapplied on every sensor initialization.

Heading Drifts or Jumps​

Check the rotation-vector mode and magnetic environment. If the system does not require magnetic absolute heading, game_rotation_vector is less sensitive to magnetic disturbances. If magnetic heading is required, calibrate in the deployment environment and monitor /sensor/imu/accuracy.