此页面由 AI 自动翻译。查看英文原版

本页目录

  • 如何放置它
  • 输入和输出
  • Pipeline 流
  • 限制
  • 请求的报告速率
  • 示例中使用的高速率原始流
  • 批处理
  • 数据包字段和报告语义
  • 用法
  • 按硬件报告可用性
  • 校准和外参
  • 处理后的输出变换
  • 读取多个 IMU 流
  • 功能示例
  • 参考

IMU

Supported on:RVC2RVC4
IMU(惯性测量单元)节点可用于接收设备上 IMU 芯片的数据。Luxonis 设备根据平台代系使用不同的 IMU 堆栈:IMU 芯片通过 SPI 连接到 RVC。请参阅 OAK 硬件文档,查看您的 OAK 相机是否集成了 IMU。

如何放置它

Python

Python
1pipeline = dai.Pipeline()
2imu = pipeline.create(dai.node.IMU)

C++

C++
1dai::Pipeline pipeline;
2auto imu = pipeline.create<dai::node::IMU>();

输入和输出

Pipeline 流

典型的 IMU 节点流是:
  1. 创建 dai::node::IMU
  2. 以请求的速率启用一个或多个 IMUSensor 报告
  3. 使用 setBatchReportThreshold()setMaxBatchReports() 配置批处理
  4. 从主机输出队列中消耗 IMUData 数据包

限制

  • 在使用 BNO08X 的 RVC2 设备上,由于传感器硬件限制,陀螺仪频率高于 400 Hz 可能会产生偶尔的抖动。

请求的报告速率

imu.enableIMUSensor(..., reportRate) 接受以 Hz 为单位的请求报告速率。实际运行时行为取决于 IMU 和平台:
  • 在使用 BNO08X 的 RVC2 设备上,请求的速率会向上舍入到下一个支持的速率。
  • 在使用 BMI270 的 RVC2 设备上,请求的速率会向下舍入到下一个支持的速率。高于 400 Hz 的请求目前最高约为 250 Hz。
  • 在使用 LSM6DSV + AK09919 的 RVC4 设备上,请将已验证的运行时速率视为特定于平台的,而不是假设芯片的最大 ODR 直接映射到主机流速率。
有关详细的每个传感器运行时行为和硬件特性,请参阅 IMU 硬件参考

示例中使用的高速率原始流

当前的 depthai-core IMU 示例和测试使用以下原始流速率进行高速捕获:
  • ACCELEROMETER_RAW,速率为 480 Hz
  • GYROSCOPE_RAW,速率为 400 Hz

批处理

IMU 节点在将数据包发送到主机之前对其进行批处理。
  • setBatchReportThreshold(N) 设置设备允许发送批次所需的最小 IMU 数据包数量
  • setMaxBatchReports(M) 设置一个批次中包含的最大数据包数量
更高的批处理可以减少主机开销,并在 USB 带宽或主机调度成为瓶颈时提供帮助。

数据包字段和报告语义

每个 IMUData 消息包含一个或多个 IMUPacket 条目。每个数据包仅包含在节点配置中启用的报告的字段。典型字段包括:
  • acceleroMeter
  • gyroscope
  • magneticField
  • rotationVector
使用报告系列如下:
  • *_RAW:传感器原生坐标系中的直接传感器输出
  • *_UNCALIBRATED:使用 imuExtrinsics 旋转到 Luxonis RDF 坐标系中,未应用 IMU 校准参数
  • *_CALIBRATED:旋转到 Luxonis RDF 坐标系中,并使用 IMU 校准参数进行校正
  • 融合输出,如 ROTATION_VECTORGAME_ROTATION_VECTOR:从传感器的内部处理路径转发

用法

Python

Python
1pipeline = dai.Pipeline()
2imu = pipeline.create(dai.node.IMU)
3
4# 以 100 Hz 的速率启用 ACCELEROMETER_RAW 和 GYROSCOPE_RAW
5imu.enableIMUSensor([dai.IMUSensor.ACCELEROMETER_RAW, dai.IMUSensor.GYROSCOPE_RAW], 100)
6# 达到此阈值后,如果主机未被阻塞且 USB 带宽可用,数据包将以 X 的批次发送
7imu.setBatchReportThreshold(1)
8# 一个批次中的最大 IMU 数据包数量,如果达到此数量,设备将阻止发送,直到主机可以接收它
9# 如果低于或等于 batchReportThreshold,则发送将始终在设备端阻塞
10# 有助于减少设备 CPU 负载和丢失的数据包数量,如果设备端由于多个节点导致 CPU 负载很高
11imu.setMaxBatchReports(10)

C++

C++
1dai::Pipeline pipeline;
2auto imu = pipeline.create<dai::node::IMU>();
3
4// 以 100 Hz 的速率启用 ACCELEROMETER_RAW 和 GYROSCOPE_RAW
5imu->enableIMUSensor({dai::IMUSensor::ACCELEROMETER_RAW, dai::IMUSensor::GYROSCOPE_RAW}, 100);
6// 达到此阈值后,如果主机未被阻塞且 USB 带宽可用,数据包将以 X 的批次发送
7imu->setBatchReportThreshold(1);
8// 一个批次中的最大 IMU 数据包数量,如果达到此数量,设备将阻止发送,直到主机可以接收它
9// 如果低于或等于 batchReportThreshold,则发送将始终在设备端阻塞
10// 有助于减少设备 CPU 负载和丢失的数据包数量,如果设备端由于多个节点导致 CPU 负载很高
11imu->setMaxBatchReports(10);

按硬件报告可用性

报告系列IMUSensorBNO08XBMI270LSM6DSVAK09919备注
原始加速度ACCELEROMETER_RAW原始加速度流
Luxonis 坐标系下的加速度计(无 IMU 校准参数)ACCELEROMETER_UNCALIBRATEDRAW -> UNCALIBRATED 应用 imuExtrinsics。这是统一的 IMU 坐标系加速度计路径。
Luxonis 坐标系下的加速度计(有 IMU 校准参数)ACCELEROMETER_CALIBRATED需要在运行时校准负载中存在 IMU 校准参数。
原始角速度GYROSCOPE_RAW原始陀螺仪流
Luxonis 坐标系下的陀螺仪(无 IMU 校准参数)GYROSCOPE_UNCALIBRATEDRAW -> UNCALIBRATED 应用 imuExtrinsics。在旧设备上,这应该可以开箱即用。
Luxonis 坐标系下的陀螺仪(有 IMU 校准参数)GYROSCOPE_CALIBRATED需要在运行时校准负载中存在 IMU 校准参数。
原始磁场MAGNETOMETER_RAW在 RVC4 上,原始磁力计数据来自 AK09919 伴随传感器。
处理后的磁场MAGNETOMETER_CALIBRATED, MAGNETOMETER_UNCALIBRATED在目标硬件上验证公共枚举/文档字符串对于处理后的磁力计输出仍然是 BNO08X 形状的。
派生加速度输出LINEAR_ACCELERATION, GRAVITY在目标硬件上验证BNO08X 直接公开这些。对于非 BNO 路径,请在目标设备上验证可用性并进行分支。
融合方向输出ROTATION_VECTOR, GAME_ROTATION_VECTOR, GEOMAGNETIC_ROTATION_VECTOR, ARVR_STABILIZED_ROTATION_VECTOR, ARVR_STABILIZED_GAME_ROTATION_VECTOR在目标硬件上验证否,独立这些是传感器融合输出,而不是由 IMU 节点在主机端进行的融合。

校准和外参

使用 device.readCalibration() 从设备读取出厂校准负载。在使用运行时校准覆盖时,请使用 device.getCalibration()device.setCalibration()对于处理后的惯性输出,请使用此模型:
  • RAW -> UNCALIBRATED:使用 imuExtrinsics 将传感器原生坐标系对齐到 Luxonis RDF 坐标系
  • UNCALIBRATED -> CALIBRATED:应用在 IMU 校准参数中设置的加速度计或陀螺仪校准
  • 因此,ACCELEROMETER_UNCALIBRATEDGYROSCOPE_UNCALIBRATED 共享统一的 IMU 坐标系路径
  • ACCELEROMETER_CALIBRATEDGYROSCOPE_CALIBRATED 在此基础上增加了运行时校准修正

处理后的输出变换

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 @ raw

UNCALIBRATED -> CALIBRATED

Python
1import depthai as dai
2import numpy as np
3
4imu_calibration = [
5    [1.0, 0.0, 0.0, 0.125],
6    [0.0, 1.0, 0.0, 0.000],
7    [0.0, 0.0, 1.0, 0.000],
8]
9
10with dai.Pipeline() as pipeline:
11    imu = pipeline.create(dai.node.IMU)
12    imu.enableIMUSensor(dai.IMUSensor.ACCELEROMETER_UNCALIBRATED, 100)
13    imu_q = imu.out.createOutputQueue(maxSize=10, blocking=False)
14
15    pipeline.start()
16    pkt = imu_q.get().packets[0]
17    uncalibrated = np.array([pkt.acceleroMeter.x, pkt.acceleroMeter.y, pkt.acceleroMeter.z])
18
19    calibration = np.array(imu_calibration)
20    calibrated = calibration[:, :3] @ uncalibrated + calibration[:, 3]

读取多个 IMU 流

如果目标硬件公开了所选报告,您可以启用多个 IMU 报告系列,并且只读取请求的字段。

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.magneticField

C++

C++
1#include "depthai/depthai.hpp"
2
3int main() {
4    dai::Pipeline pipeline;
5    auto imu = pipeline.create<dai::node::IMU>();
6
7    imu->enableIMUSensor(dai::IMUSensor::ACCELEROMETER_RAW, 100);
8    imu->enableIMUSensor(dai::IMUSensor::GYROSCOPE_RAW, 100);
9    imu->enableIMUSensor(dai::IMUSensor::MAGNETOMETER_RAW, 100);
10
11    imu->setBatchReportThreshold(1);
12    imu->setMaxBatchReports(10);
13
14    auto imuQ = imu->out.createOutputQueue(50, false);
15
16    pipeline.start();
17    while(pipeline.isRunning()) {
18        auto data = imuQ->get<dai::IMUData>();
19        for(const auto& pkt : data->packets) {
20            const auto& a = pkt.acceleroMeter;
21            const auto& g = pkt.gyroscope;
22            const auto& m = pkt.magneticField;
23        }
24    }
25}

功能示例

参考

class

dai::node::IMU

#include IMU.hpp
variable
Output out
Outputs IMUData message that carries IMU packets.
variable
Input mockIn
Mock IMU data for replaying recorded data
function
void enableIMUSensor(IMUSensorConfig sensorConfig)
Enable a new IMU sensor with explicit configuration
function
void enableIMUSensor(const std::vector< IMUSensorConfig > & sensorConfigs)
Enable a list of IMU sensors with explicit configuration
function
void enableIMUSensor(IMUSensor sensor, uint32_t reportRate)
Enable a new IMU sensor with default configuration
function
void enableIMUSensor(const std::vector< IMUSensor > & sensors, uint32_t reportRate)
Enable a list of IMU sensors with default configuration
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)
Maximum number of IMU packets in a batch report
function
std::int32_t getMaxBatchReports()
Maximum number of IMU packets in a batch report
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)

需要帮助?

请前往 Discussion Forum 获取技术支持或提出您可能有的任何其他问题。