上篇讲了RGB-D数据处理的几个核心环节——深度图空洞填充、RGB-D对齐、深度转点云、坐标变换。从这篇开始,我们转到惯性传感器。IMU是机器人感知系统中不可或缺的组成部分,不管你是做SLAM、做导航还是做控制,都得跟IMU打交道。
面试时候被问"IMU输出什么数据",很多人会说"加速度和角速度"。但面试官想听的不止这些——他想知道你理解IMU的工作原理吗?知道加速度计和陀螺仪的物理机制吗?知道它们的误差来源吗?
IMU的基本组成
一个典型的IMU(Inertial Measurement Unit,惯性测量单元)包含两类传感器:加速度计(Accelerometer)和陀螺仪(Gyroscope)。高级的IMU还包含磁力计(Magnetometer),组成9轴IMU。
加速度计测量的是线性加速度(单位:m/s²),三个轴各一个,输出(ax, ay, az)。
陀螺仪测量的是角速度(单位:rad/s或deg/s),三个轴各一个,输出(ωx, ωy, ωz)。
磁力计测量的是磁场方向(单位:μT或Gauss),三个轴各一个,输出(mx, my, mz)。磁力计可以用来确定"北"的方向,但容易受铁磁物质干扰。
在ROS2中,IMU数据通过sensor_msgs/Imu消息发布:
# sensor_msgs/Imu消息结构 header # 时间戳 + 坐标系ID orientation # 四元数 (x, y, z, w) —— 部分IMU直接输出姿态 angular_velocity # 角速度 (x, y, z) —— 陀螺仪原始数据 linear_acceleration # 线加速度 (x, y, z) —— 加速度计原始数据 # 每个量都有对应的协方差矩阵注意:很多IMU驱动会内置一个姿态估计算法(通常是互补滤波或者EKF),直接输出orientation。但原始的IMU数据只有角速度和加速度,姿态需要你自己积分计算。面试时候要分清这两种情况。
加速度计的工作原理
加速度计的核心原理是牛顿第二定律:F = ma。传感器内部有一个微小的质量块(proof mass),通过弹簧或者电容悬挂。当传感器加速时,质量块因为惯性会产生相对位移,测量这个位移就能算出加速度。
MEMS加速度计(手机、机器人里用的都是这种)通常用电容式检测。质量块和固定电极之间形成电容,加速度导致质量块移动,电容值变化,通过电路测量电容变化就能算出加速度。
一个关键概念:加速度计测量的是比力(specific force),不是真正的加速度。比力 = 真实加速度 - 重力加速度。也就是说,当IMU静止放在桌面上时,加速度计输出的不是0,而是(0, 0, 9.81)——它在测量重力。
这个特性非常重要。在SLAM和导航中,你需要从加速度计的输出中减去重力分量,才能得到真实的运动加速度。如果搞反了,整个惯性导航就全错了。
import numpy as np # 从加速度计输出中提取真实加速度 def get_true_acceleration(accel_raw, orientation_quat): """去除重力分量""" gravity_world = np.array([0, 0, 9.81]) # 根据当前姿态,把世界坐标系下的重力变换到IMU坐标系 R = quat_to_rotation_matrix(orientation_quat) gravity_body = R.T @ gravity_world # 真实加速度 = 测量值 - 重力 return accel_raw - gravity_body加速度计的实际应用和注意事项
在实际项目中,加速度计的数据处理有几个容易踩的坑。
第一个坑是坐标系约定。不同厂家的IMU,坐标系定义可能不同。有的用NED(北-东-地),有的用ENU(东-北-天),有的用FRD(前-右-下)。ROS2的标准是ENU(REP-103),如果你的IMU驱动输出的是NED坐标系,需要做坐标变换。这个变换很简单:x_ned = y_enu, y_ned = x_enu, z_ned = -z_enu。但如果搞混了,重力方向就反了,整个惯性导航就废了。
第二个坑是振动干扰。机器人运行时,电机和减速器会产生高频振动。这些振动会耦合到加速度计的输出中,形成很大的噪声。处理方法是在加速度计数据上加重力方向,导致姿态估计完全错误。所以IMU安装时要尽量远离振动源(电机、轮子),并且用减振材料(比如橡胶垫)隔离。
第三个坑是量程选择。加速度计有不同的量程(±2g, ±4g, ±8g, ±16g等)。量程越大,分辨率越低。如果你的机器人运动比较平缓(比如AGV),用±2g的量程就够了,分辨率最高。如果是无人机或者剧烈运动的机器人,可能需要±8g或±16g。选型的时候要根据最大预期加速度来选,留一定的余量。
第四个坑是采样率匹配。IMU的采样率要和你的算法需求匹配。做姿态估计通常需要200Hz以上的采样率,做运动补偿可能需要500Hz甚至1000Hz。但采样率越高,数据量越大,对通信带宽和处理能力的要求也越高。SPI接口的IMU通常能支持更高的采样率,I2C接口的带宽有限,高速场景可能跟不上。实际项目中,我见过有团队用I2C接口跑1kHz采样率,结果数据丢包严重,最后换成SPI才解决。
面试中怎么聊
面试官问IMU工作原理,按这个顺序回答:先说IMU的组成(加速度计+陀螺仪+磁力计),再说加速度计的原理(电容式检测比力,注意重力问题),然后说陀螺仪的原理(科里奥利效应,角速度积分得角度),最后说误差来源(零偏、噪声、温漂)。
如果面试官追问"为什么IMU不能单独做姿态估计",你可以说:陀螺仪的零偏经过积分会累积成角度漂移,加速度计短期噪声大但长期不漂移。两者互补(互补滤波或EKF)才能得到短期和长期都可靠的姿态估计。
如果面试官追问"加速度计能测重力,那怎么区分重力和运动加速度",你可以说:单靠加速度计无法区分。这就是为什么需要陀螺仪——陀螺仪提供的角速度信息可以帮助估计重力方向,从而从加速度计输出中分离出重力分量。
如果面试官追问"IMU怎么选型",你可以从几个维度分析。精度等级:消费级IMU(手机、游戏手柄)精度最低,工业级IMU(机器人、无人机)精度中等,战术级IMU(军事、航天)精度最高但价格昂贵。对于地面移动机器人,工业级IMU(比如BMI088、ICM-42688)通常够用。对于高精度SLAM或自动驾驶,可能需要更高级的IMU(比如ADIS16470、VectorNav VN-100)。接口方面,SPI比I2C快很多,适合高采样率场景。功耗方面,电池供电的机器人需要关注IMU的功耗,有些高性能IMU功耗较大。
另外,很多IMU模块集成了加速度计、陀螺仪和磁力计(比如MPU9250、BNO085),使用方便但磁力计容易受干扰。如果对磁力计精度要求高,建议把磁力计单独放置,远离电机和电源线。
分享一个我在项目中做IMU数据积分的踩坑经历。当时需要把陀螺仪的角速度积分成姿态角,一开始直接用简单的欧拉积分:angle += omega * dt。跑了几秒钟发现角度漂移得厉害,静止时每分钟能漂好几度。后来换了四元数积分,漂移好了一些但还是有问题。最后发现最大的问题不是积分方法,而是零偏没校准——陀螺仪静止时的输出不是零,而是有一个大约0.02 rad/s的固定偏差。这个偏差积分10秒就是0.2弧度(约11度),难怪漂移那么厉害。校准零偏后(静止5秒取平均值作为零偏),再配合四元数积分,漂移降到了每分钟1度以内。当然这个精度对SLAM来说还是不够,最终还是上了EKF做传感器融合。但这个经历让我深刻理解到:IMU数据处理的每一步都不能马虎,零偏校准是基础中的基础。
下一篇讲IMU误差模型——零偏、噪声、温漂和校准方法。把误差的来源和特性搞清楚,才能在实际项目中正确处理IMU数据。
如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。
「机器人软件开发面试·从入门到精通」连载系列
上一篇:第155篇 RGB-D数据处理——深度图空洞填充、对齐和坐标转换
下一篇预告:第157篇 IMU误差模型——零偏、噪声、温漂和校准方法
有任何问题欢迎评论区留言,我会尽量回复。