- RVC2 devices use either BNO08X or BMI270
- RVC4 devices use LSM6DSV together with an AK09919 magnetometer.
Looking for the conceptual docs?
For sensor families, output semantics, reference frames, factory calibration, and noise characterization, see the IMU hardware reference. For practical usage, see the IMU examples below.
How to place it
Python
Python
1pipeline = dai.Pipeline()
2imu = pipeline.create(dai.node.IMU)Inputs and Outputs
Pipeline flow
- Create
dai::node::IMU - Enable one or more
IMUSensorreports at a requested rate - Configure batching with
setBatchReportThreshold()andsetMaxBatchReports() - Consume
IMUDatapackets from the host output queue
Limitations
- On RVC2 devices with BNO08X, gyroscope frequencies above 400 Hz can produce occasional jitter due to sensor hardware limitations.
Requested report rate
imu.enableIMUSensor(..., reportRate) accepts a requested report rate in Hz.Actual runtime behavior depends on the IMU and platform:- On RVC2 devices using BNO08X, requested rates round up to the next supported rate.
- On RVC2 devices using BMI270, requested rates round down to the next supported rate. Requests above 400 Hz currently top out around 250 Hz.
- On RVC4 devices using LSM6DSV + AK09919, treat validated runtime rates as platform-specific rather than assuming the silicon max ODR maps directly to the host stream rate.
High-rate raw streaming used in examples
depthai-core IMU examples and tests use the following raw-stream rates for high-rate capture:ACCELEROMETER_RAWat480 HzGYROSCOPE_RAWat400 Hz
Batching
setBatchReportThreshold(N)sets the minimum number of IMU packets that should be ready before the device is allowed to send a batchsetMaxBatchReports(M)sets the maximum number of packets included in one batch
Packet fields and report semantics
IMUData message contains one or more IMUPacket entries. Each packet only carries the fields for the reports that were enabled in the node configuration.Typical fields include:acceleroMetergyroscopemagneticFieldrotationVector
*_RAW: direct sensor output in the sensor-native frame*_UNCALIBRATED: rotated into the Luxonis RDF frame usingimuExtrinsics, without IMU calibration parameters applied*_CALIBRATED: rotated into the Luxonis RDF frame and corrected using IMU calibration parameters- fused outputs such as
ROTATION_VECTORandGAME_ROTATION_VECTOR: forwarded from the sensor's internal processing path
Usage
Python
Python
1pipeline = dai.Pipeline()
2imu = pipeline.create(dai.node.IMU)
3
4# enable ACCELEROMETER_RAW and GYROSCOPE_RAW at 100 hz rate
5imu.enableIMUSensor([dai.IMUSensor.ACCELEROMETER_RAW, dai.IMUSensor.GYROSCOPE_RAW], 100)
6# above this threshold packets will be sent in batch of X, if the host is not blocked and USB bandwidth is available
7imu.setBatchReportThreshold(1)
8# maximum number of IMU packets in a batch, if it's reached device will block sending until host can receive it
9# if lower or equal to batchReportThreshold then the sending is always blocking on device
10# useful to reduce device's CPU load and number of lost packets, if CPU load is high on device side due to multiple nodes
11imu.setMaxBatchReports(10)Report availability by hardware
Current public API scope
The current
depthai-core IMU enum and docstrings are still BNO08X-oriented. In the bindings, the node is still documented as IMU node for BNO08X, so fused and processed report coverage should be read together with the hardware docs and validated on the target device when the sensor path is not BNO08X.| Report family | IMUSensor values | BNO08X | BMI270 | LSM6DSV | AK09919 | Notes |
|---|---|---|---|---|---|---|
| Raw acceleration | ACCELEROMETER_RAW | Yes | Yes | Yes | No | Raw accelerometer stream |
| Accelerometer in Luxonis frame, without IMU calibration parameters | ACCELEROMETER_UNCALIBRATED | Yes | Yes | Yes | No | RAW -> UNCALIBRATED applies imuExtrinsics. This is the unified IMU-frame accelerometer path. |
| Accelerometer in Luxonis frame, with IMU calibration parameters | ACCELEROMETER_CALIBRATED | Yes | Yes | Yes | No | Requires IMU calibration parameters to be present in the runtime calibration payload. |
| Raw angular velocity | GYROSCOPE_RAW | Yes | Yes | Yes | No | Raw gyroscope stream |
| Gyroscope in Luxonis frame, without IMU calibration parameters | GYROSCOPE_UNCALIBRATED | Yes | Yes | Yes | No | RAW -> UNCALIBRATED applies imuExtrinsics. On older devices this is expected to work out of the box. |
| Gyroscope in Luxonis frame, with IMU calibration parameters | GYROSCOPE_CALIBRATED | Yes | Yes | Yes | No | Requires IMU calibration parameters to be present in the runtime calibration payload. |
| Raw magnetic field | MAGNETOMETER_RAW | Yes | No | No | Yes | On RVC4, raw magnetometer data comes from the AK09919 companion sensor. |
| Processed magnetic field | MAGNETOMETER_CALIBRATED, MAGNETOMETER_UNCALIBRATED | Yes | No | No | Validate on target hardware | Public enum/docstrings are still BNO08X-shaped for processed magnetometer outputs. |
| Derived acceleration outputs | LINEAR_ACCELERATION, GRAVITY | Yes | No | Validate on target hardware | No | BNO08X exposes these directly. For non-BNO paths, validate availability on the target device and branch. |
| Fused orientation outputs | ROTATION_VECTOR, GAME_ROTATION_VECTOR, GEOMAGNETIC_ROTATION_VECTOR, ARVR_STABILIZED_ROTATION_VECTOR, ARVR_STABILIZED_GAME_ROTATION_VECTOR | Yes | No | Validate on target hardware | No standalone | These are sensor-fusion outputs, not host-side fusion done by the IMU node. |
Calibration and extrinsics
device.readCalibration() to read the factory calibration payload from the device. Use device.getCalibration() and device.setCalibration() when working with runtime calibration overrides.For the processed inertial outputs, use this model:RAW -> UNCALIBRATED: align the sensor-native frame into the Luxonis RDF frame usingimuExtrinsicsUNCALIBRATED -> CALIBRATED: apply the accelerometer or gyroscope calibration set in the IMU calibration parametersACCELEROMETER_UNCALIBRATEDandGYROSCOPE_UNCALIBRATEDtherefore share the unified IMU-frame pathACCELEROMETER_CALIBRATEDandGYROSCOPE_CALIBRATEDadd the runtime calibration correction on top of that
Processed output transforms
RAW -> UNCALIBRATED
Python
1import depthai as dai
2import numpy as np
3
4with dai.Pipeline() as pipeline:
5 imu = pipeline.create(dai.node.IMU)
6 imu.enableIMUSensor(dai.IMUSensor.ACCELEROMETER_RAW, 100)
7 imu_q = imu.out.createOutputQueue(maxSize=10, blocking=False)
8
9 device = pipeline.getDefaultDevice()
10 calib = device.readCalibration()
11 imu_to_cam = np.array(calib.getImuToCameraExtrinsics(dai.CameraBoardSocket.CAM_A, False))
12 R_imu_to_cam = imu_to_cam[:3, :3]
13
14 pipeline.start()
15 pkt = imu_q.get().packets[0]
16 raw = np.array([pkt.acceleroMeter.x, pkt.acceleroMeter.y, pkt.acceleroMeter.z])
17 uncalibrated = R_imu_to_cam @ rawReading multiple IMU streams
Python
Python
1import depthai as dai
2
3with dai.Pipeline() as pipeline:
4 imu = pipeline.create(dai.node.IMU)
5
6 imu.enableIMUSensor(dai.IMUSensor.ACCELEROMETER_RAW, 100)
7 imu.enableIMUSensor(dai.IMUSensor.GYROSCOPE_RAW, 100)
8 imu.enableIMUSensor(dai.IMUSensor.MAGNETOMETER_RAW, 100)
9
10 imu.setBatchReportThreshold(1)
11 imu.setMaxBatchReports(10)
12
13 imu_q = imu.out.createOutputQueue(maxSize=50, blocking=False)
14
15 pipeline.start()
16 while pipeline.isRunning():
17 imu_data = imu_q.get()
18 for pkt in imu_data.packets:
19 a = pkt.acceleroMeter
20 g = pkt.gyroscope
21 m = pkt.magneticFieldExamples of functionality
Reference
class
dai::node::IMU
variable
variable
function
void enableIMUSensor(IMUSensorConfig sensorConfig)function
void enableIMUSensor(const std::vector< IMUSensorConfig > & sensorConfigs)function
void enableIMUSensor(IMUSensor sensor, uint32_t reportRate)function
void enableIMUSensor(const std::vector< IMUSensor > & sensors, uint32_t reportRate)function
void setBatchReportThreshold(std::int32_t batchReportThreshold)Above this packet threshold data will be sent to host, if queue is not blocked
function
std::int32_t getBatchReportThreshold()Above this packet threshold data will be sent to host, if queue is not blocked
function
void setMaxBatchReports(std::int32_t maxBatchReports)function
std::int32_t getMaxBatchReports()function
void enableFirmwareUpdate(bool enable)Whether to perform firmware update or not. Default value: false.
inline function
DeviceNodeCRTP()inline function
DeviceNodeCRTP(const std::shared_ptr< Device > & device)inline function
DeviceNodeCRTP(std::unique_ptr< Properties > props)inline function
DeviceNodeCRTP(std::unique_ptr< Properties > props, bool confMode)inline function
DeviceNodeCRTP(const std::shared_ptr< Device > & device, std::unique_ptr< Properties > props, bool confMode)Need assistance?
Head over to Discussion Forum for technical support or any other questions you might have.