ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

IMU标定实战:从误差模型到VIO应用,手把手教你使用imu_tk

IMU标定实战:从误差模型到VIO应用,手把手教你使用imu_tk 1. 项目缘起为什么IMU标定是VIO的“必修课”搞VIO视觉惯性里程计的朋友估计没人能绕开IMU标定这个坎。你可能已经调通了ORB-SLAM3或者VINS-Mono跑起来感觉也还行但总在某些场景下——比如快速旋转、剧烈晃动或者长时间运行后——轨迹就开始飘误差累积得让你怀疑人生。很多时候问题的根源并不在算法本身有多复杂而在于最基础的一环被忽略了你用的那个IMU惯性测量单元它的数据真的准吗IMU说白了就是个“感觉器官”它通过加速度计和陀螺仪来感知自身的运动和姿态变化。但理想很丰满现实很骨感。工厂里出来的IMU尤其是消费级的MEMS微机电系统IMU比如我们常用的MPU6050、MPU9250、BMI088乃至一些内置在手机里的型号都存在各种误差。这些误差不是随机的噪声而是有规律、有偏置的“系统误差”。最要命的就是零偏Bias和尺度因子Scale Factor它们会像慢性毒药一样悄无声息地污染你的数据。陀螺仪的零偏如果不准角速度积分得到的角度就会随时间线性漂移加速度计的尺度因子不准比力测量值就失真重力对齐和速度积分全都会出问题。所以IMU标定标的就是这些内在的、不随外界环境变化的参数。它不是一次性的“校准”而是在使用前必须完成的“标定”。你可以把它理解为给这个“感觉器官”做一次全面的“体检”和“矫正”建立它的误差模型。只有拿到了准确的误差参数才能在后续的预积分、ESKF误差状态卡尔曼滤波或者优化过程中把这些误差补偿掉让IMU说“真话”。网上关于IMU标定的工具不少imu_tk是其中比较经典和常用的一款。它源自西班牙马拉加大学代码开源原理清晰特别适合研究和理解标定的全过程。但说实话它的文档和上手体验对新手并不友好很多细节藏在代码里参数设置不对或者操作顺序错了结果可能南辕北辙。我最近在为一个项目搭建VIO原型重新梳理了一遍imu_tk的使用流程把过程中踩的坑、悟到的门道都记了下来。这篇内容就是一份给实干者的“备忘”目标不是复述论文公式而是让你能真正动手把一坨原始的IMU数据变成一组可靠的标定参数。2. 标定前的核心认知IMU到底有哪些“毛病”要治在动手操作imu_tk之前我们必须先搞清楚我们要标定的对象是什么。这就像医生看病得先知道病因。对于MEMS IMU其误差模型通常包括确定性误差和随机误差两大类。imu_tk主要对付的是确定性误差。2.1 确定性误差模型零偏、尺度、轴失准这是标定的核心目标。我们通常用一个线性模型来近似描述对于陀螺仪Gyroscope和加速度计Accelerometer通用模型测量值 尺度因子矩阵 * (真实值 零偏) 测量噪声把它拆开看主要有三个部分零偏Bias 这是最关键的参数。即使IMU完全静止不动它的输出也不是零而是一个稳定的偏移量这就是零偏。零偏不是固定的它会随时间缓慢变化随机游走也会受温度影响。标定得到的是某一时刻或某段标定数据期间的“平均零偏”。在VIO的ESKF中我们通常把零偏作为状态量进行估计而标定得到的零偏初始值就是给滤波器一个靠谱的起点。这里就关联到一个热搜词“imu静止初始化得到的测量方差和eskf中的过程噪声中q之间关系”。简单说静止初始化时计算的测量方差噪声方差反映了传感器短时间内的噪声水平而ESKF过程噪声中的Q矩阵尤其是对应零偏随机游走的部分描述的是零偏随时间变化的“速度”。前者是观测的“瞬时抖动”后者是状态零偏本身的“变化趋势”两者共同决定了滤波器对零偏的估计置信度。尺度因子Scale Factor 理想情况下传感器读数变化1个单位对应的物理量度/秒 或 m/s²也变化1个单位。但现实是这个比例系数往往不是1。尺度因子误差会导致读数被放大或缩小。它是一个对角矩阵每个轴独立。轴失准Misalignment和非正交性Non-orthogonality 这是最容易被忽略但影响深远的部分。我们假设IMU的X、Y、Z轴是完美正交的并且与芯片封装的外壳严格对齐。实际上制造工艺会导致轴之间不完全是90度并且传感器芯片的敏感轴与模块的物理边框也可能存在夹角。imu_tk将这两者合并为一个“标定矩阵”这是一个3x3的下三角矩阵。这个矩阵同时包含了尺度因子和轴间耦合关系。修正了这个矩阵就相当于把传感器的“身体”摆正了。2.2 标定策略为什么需要特定的“舞蹈动作”知道了要标什么下一步就是怎么标。imu_tk采用的方法是多位置静态标定法。它的核心思想是利用地球重力场这个天然的、已知的、稳定的参考基准。对于加速度计当IMU静止时它测量到的是重力加速度在三个轴上的投影。如果我们让IMU以多个不同的、已知的姿态静止放置那么理论上所有静止测量值的模长都应该等于当地的重力加速度g约9.8 m/s²。由于零偏、尺度因子和轴失准的存在实际测得的向量模长会偏离g。通过收集数十个不同姿态下的静止数据就可以构建一个优化问题求解出使得所有静止测量值模长最接近g的那组标定参数。对于陀螺仪imu_tk通常需要依赖一个外部的、更精确的旋转参考源比如高精度的转台来提供“真实角速度”这在一般实验室条件下很难实现。因此常见的做法是只标定加速度计然后假设陀螺仪与加速度计共享同一个“标定矩阵”即两者的轴失准关系一致再通过一些方法比如温度建模或简单估计来标定陀螺仪的零偏和尺度因子。这也是很多开源VIO方案如Kalibr的默认策略。所以你的标定流程本质上就是让IMU跳一段“静止芭蕾”把它放在一个平面上保持静止几十秒记录数据然后换个姿态比如绕某个轴旋转90度再静止几十秒再记录如此重复覆盖尽可能多的姿态空间。3. 实战准备硬件、软件与数据采集理论清楚了我们进入实战环节。使用imu_tk你需要准备好三样东西硬件平台、编译好的软件、以及符合要求的数据。3.1 硬件与数据采集设置硬件选择 任何能输出原始加速度计和陀螺仪数据的IMU模块都可以。常见的有MPU6050 (I2C)、MPU9250 (I2C/SPI)、BMI088 (SPI)等。你需要一个微控制器如STM32、ESP32或开发板如树莓派来读取数据并通过串口发送到电脑。确保你的读取频率如100Hz, 200Hz是稳定的。关键参数记录 在采集数据前必须明确并记录两个参数它们将直接用于标定采样频率 (acq_rate): 你的IMU数据实际输出的频率单位Hz。务必准确它影响静止检测的阈值计算。重力加速度 (g_value): 你所在地区的重力加速度值。通常取9.805或9.81精确值可以查询当地重力图。这个值用于计算加速度计的模长误差。数据采集“舞蹈”指南预热 上电后让IMU静止运行至少5-10分钟使其内部温度稳定零偏相对稳定。姿态规划 你需要让IMU在三维空间中取多个静止姿态。一个经典且简单有效的方案是利用立方体的六个面。将IMU模块平放在一个平整的桌面上以它的物理外壳为参考分别让它的X, -X, Y, -Y, Z, -Z 轴指向天或地。这样你就得到了6个姿态。增加多样性 仅在6个正交姿态下标定矩阵中的非对角元素轴失准可能无法被充分观测。因此你还需要增加一些倾斜的姿态。例如将IMU倾斜约45度放置或者绕某个轴旋转45度。总共准备20-50个不同的静止姿态是比较稳妥的。采集流程将IMU放置到预定姿态。保持绝对静止这是最重要的要求。任何微小的振动或移动都会污染数据。可以将IMU放在厚重的书本上或使用夹具固定。保持静止至少30-60秒。时间越长平均效果越好越能抑制随机噪声。在这段静止期内以稳定的频率采集并保存数据。数据格式通常为timestamp(秒), gx, gy, gz, ax, ay, az。注意单位陀螺仪通常是度/秒(deg/s)加速度计是米/秒²(m/s²)。平稳地切换到下一个姿态重复上述过程。数据文件 将整个采集过程的所有数据保存到一个文本文件中例如imu_data.txt。imu_tk要求数据是按时间顺序连续记录的中间包含了静止段和运动段切换姿态时的短暂移动。3.2 imu_tk 环境搭建与编译imu_tk依赖一些第三方库。假设你已经在Ubuntu系统上18.04或20.04比较常见可以按以下步骤操作# 1. 安装依赖 sudo apt-get update sudo apt-get install cmake libboost-dev libeigen3-dev # 2. 克隆代码库注意官方imu_tk可能已不再维护有一些fork版本修复了问题 git clone https://github.com/Kyle-ak/imu_tk.git # 这是一个常用的维护版本 cd imu_tk # 3. 创建并进入构建目录 mkdir build cd build # 4. 编译 cmake .. make -j4编译成功后在build/bin/目录下你会得到两个可执行文件test_imu_calib 用于加速度计标定的主程序。test_imu_calib_gyro 用于陀螺仪标定需要转台数据一般不用。4. 核心操作运行标定与参数解读环境就绪数据在手现在开始最关键的一步。4.1 运行加速度计标定imu_tk的标定过程是自动的但它依赖于几个重要的启动参数。我们需要准备一个参数配置文件比如命名为params.calib内容如下# 标定参数文件示例 acq_rate 100.0 # 你的数据采样频率 (Hz) gyro_dps 2000.0 # 陀螺仪量程 (±dps)根据你的IMU型号设置如MPU6050可选250, 500, 1000, 2000 accel_g 4.0 # 加速度计量程 (±g)根据你的IMU型号设置如MPU6050可选2, 4, 8, 16 g_value 9.805 # 当地重力加速度然后在build/bin/目录下运行命令./test_imu_calib -input imu_data.txt -params params.calib -output accel_calib_result.txt -bias 500 -gn 0.8 -gm 1.2 -gb 0.01这个命令看起来有点复杂我们来拆解每一个参数-input: 你的原始数据文件路径。-params: 参数配置文件路径。-output: 标定结果输出文件路径。-bias 500:静止检测初始化窗口大小。这是第一个关键参数。程序会先用前500个采样点根据你的采样频率比如100Hz就是前5秒的数据来初始估计静止状态下的零偏。如果你的数据开头不是静止段这个值需要调整。-gn 0.8 -gm 1.2:静止检测的加速度模长阈值。这是第二个关键参数。程序认为静止状态下加速度计读数的模长应该在g_value附近波动。-gn是下限系数-gm是上限系数。阈值范围是[gn * g_value, gm * g_value]。这里[0.8*9.805, 1.2*9.805]即[7.844, 11.766]。这个范围要设得合理宽松以容纳由于初始零偏和尺度误差导致的模长偏差但又不能太宽以免把运动数据误判为静止。如果发现程序识别出的静止段太少或太多需要调整这两个值。-gb 0.01:静止检测的陀螺仪阈值度/秒。静止时陀螺仪读数应该接近零只有噪声和零偏。这个参数设置角速度的绝对值阈值所有轴的角速度都低于此值才被认为是静止。0.01是一个很严格的值适用于高质量IMU。如果IMU噪声大可以适当放宽到0.05或0.1。运行后程序会输出识别出的静止段信息并最终将标定结果写入accel_calib_result.txt。4.2 解读标定结果打开accel_calib_result.txt你会看到类似下面的内容Calibration parameters (Accelerometer): Misalignment Matrix (Tau): [ 1.002345, -0.001234, 0.000567; -0.000123, 0.998765, 0.002345; 0.000456, -0.000789, 1.001234 ] Bias Vector: [ 0.0123, -0.0234, 0.0456 ] (m/s^2)如何理解这些矩阵和向量标定矩阵Misalignment Matrix, Tau 这是一个3x3的下三角矩阵。它包含了尺度因子和轴失准的联合修正信息。对角线元素 近似为尺度因子的倒数。例如Tau[0,0]1.002345意味着原始X轴读数偏小需要乘以约1.002345来修正。非对角线元素 表示轴之间的耦合。例如Tau[1,0]-0.000123表示Y轴的读数中混入了一小部分X轴的信号负相关需要被减去。修正公式accel_corrected Tau * (accel_raw - bias)零偏向量Bias Vector 三个轴各自的零偏值单位是 m/s²。在修正时需要先从原始读数中减去这个零偏。验证标定效果 一个快速的验证方法是用标定后的参数处理你的原始静止段数据然后计算每个静止段加速度向量的模长。理想情况下所有模长都应该非常接近你设定的g_value(如9.805)其标准差应该比标定前小很多。你可以写个简单的Python脚本来做这个验证。4.3 陀螺仪标定的“曲线救国”如前所述没有转台我们很难高精度地标定陀螺仪的尺度因子和轴失准。一个实践中的常用假设是陀螺仪与加速度计共享相同的安装和轴失准关系。也就是说我们可以把加速度计标定得到的Tau矩阵直接用于陀螺仪。那么陀螺仪的零偏和尺度因子怎么办零偏 可以让IMU在静止状态下长时间数分钟采集数据计算这段时间内陀螺仪三个轴读数的平均值作为初始零偏。这就是“静止初始化”。这个零偏会被输入到VIO的ESKF中作为状态估计的初始值。尺度因子 对于消费级IMU如果要求不高有时会假设其尺度因子误差很小比如1%或者从数据手册中获取一个典型值。更精细的做法可能需要通过已知角速度的运动如精确旋转90度、180度来拟合但这需要精密的实验装置。因此一套完整的标定参数可能包括accel_Tau(3x3),accel_bias(3x1)gyro_Tau(3x3通常取accel_Tau或单位矩阵)gyro_bias(3x1通过静止初始化获得)在VIO的配置文件中这些参数会分别填入加速度计和陀螺仪的标定矩阵和零偏项中。5. 避坑指南那些让结果跑偏的细节使用imu_tk的过程绝不会一帆风顺。下面是我总结的几个最常见的坑和解决方案。5.1 静止段识别失败或错误这是最常见的问题。现象是程序运行后很快结束输出结果异常或者识别出的静止段数量为0。检查-gn/-gm参数 这是首要怀疑对象。先用一个简单的脚本读取你的原始数据文件计算每个数据点加速度的模长sqrt(ax^2ay^2az^2)并绘制出来。观察在静止时段这个模长值是多少。你会发现由于未标定模长可能严重偏离9.8。根据这个观察到的范围重新设置-gn和-gm。例如如果静止模长在8.0到11.5之间那么可以设置为-gn 0.82 -gm 1.17相对值或直接使用绝对值如果程序支持。检查-gb参数 同样检查静止时段陀螺仪三个轴读数的绝对值。如果IMU噪声较大静止时角速度读数可能在 ±0.1 dps 内波动那么-gb 0.01就太严格了需要放宽到-gb 0.1。检查数据开头-bias参数指定的初始窗口必须是静止的。如果你的数据文件一开头IMU就在运动程序初始零偏估计错误会导致后续所有静止检测失败。确保数据文件以一段静止数据开始或者调整-bias到一个肯定处于静止状态的采样点位置。数据单位 确保imu_tk读取的数据单位是你预期的。加速度计应为 m/s²陀螺仪应为 deg/s。如果单位是 rad/s需要转换。5.2 标定结果不合理有时程序能跑完但输出的标定矩阵数值非常夸张如对角线元素远大于1.5或小于0.5或者修正后效果反而变差。姿态覆盖不足 这是根本原因之一。如果你的静止姿态都集中在很小的角度范围内例如只是平放稍微倾斜那么标定问题就是“病态”的有很多组参数都能使这些姿态下的模长接近9.8算法无法找到唯一正确解。必须确保姿态在三维空间中有充分的分布特别是要包含绕不同轴的大角度旋转。立方体六个面是基础45度倾斜姿态是关键补充。静止数据质量差 静止时段内存在振动或缓慢漂移。确保IMU放在非常稳固的平台上远离风扇、电机等振源。采集时间足够长30秒以上让随机噪声平均掉。量程参数错误gyro_dps和accel_g必须与你的IMU硬件设置和数据实际范围匹配。如果你设置的量程是±4g但实际数据已经出现了超过4g的数值可能由于冲击标定就会出错。检查你的数据最大值和最小值。5.3 如何与VIO系统对接标定出参数只是第一步正确地用到VIO里才是目的。参数格式转换imu_tk输出的Tau矩阵是下三角的且修正公式为corrected Tau * (raw - bias)。但不同的VIO库可能采用不同的参数化和公式。例如有的库使用上三角矩阵有的使用“尺度因子轴失准”的分离表示公式可能是corrected scale_matrix * misalignment_matrix * raw bias。你必须仔细阅读你所用的VIO框架如VINS-Mono, OKVIS, SVO等的配置文件说明了解它期望的标定矩阵格式和含义并进行必要的数学转换。一个常见的做法是将imu_tk的Tau矩阵进行QR分解或直接求逆来得到其他形式表示的参数。噪声参数 VIO的配置文件通常还需要加速度计和陀螺仪的噪声参数accel_n,gyro_n和零偏随机游走参数accel_w,gyro_w。这些不能通过imu_tk的静态标定得到。它们需要通过艾伦方差Allan Variance分析来估计或者使用传感器数据手册中的典型值或者从VIO论文的推荐值开始调试。这就是另一个话题了。6. 进阶思考离线、在线与联合标定掌握了imu_tk的基本使用你可能会有更进一步的疑问这也正好对应了几个热搜词。“相机和IMU的联合标定怎么做”imu_tk只做IMU的内参标定。而相机和IMU之间还存在一个外参即两者坐标系的变换关系旋转矩阵和平移向量。这就是联合标定要解决的问题。目前最流行的工具是Kalibr。它通过一个棋盘格或AprilTag标定板让相机-IMU系统共同经历一系列激励运动充分激励所有自由度同时录制图像和IMU数据。Kalibr会联合优化求解相机内参、IMU内参包括零偏和尺度因子但模型可能不同、以及相机与IMU之间的时空外参旋转、平移、以及时间戳延迟。这是一个更复杂但也更完备的标定流程。通常的步骤是先单独标定相机内参然后用Kalibr进行联合标定。“相机和IMU离线外参标定原理”其核心原理是基于优化的手眼标定。由于相机和IMU刚性连接它们在运动时两者感知到的运动应该满足一定的几何约束。通过多组时间同步的相机位姿从视觉SLAM或标定板得到和IMU预积分得到的相对运动可以构建一个最小二乘问题来求解两者之间的固定变换关系。Kalibr就是实现了这一套算法并考虑了时间同步误差的估计。“双目VIO”和“Lidar IMU标定”双目VIO 它使用两个相机能直接恢复出尺度信息因此对IMU加速度计尺度因子的依赖比单目VIO要低一些。但IMU的零偏和陀螺仪参数依然至关重要标定流程和本文所述一致。Lidar IMU标定 其原理与相机-IMU联合标定类似只不过将相机换成了激光雷达。也需要通过充分的运动利用点云匹配得到的雷达位姿与IMU预积分位姿之间的约束来优化求解外参。有一些专门工具如lidar_imu_calib。最后关于“imu预积分”它正是VIO中高效使用IMU数据的关键技术。预积分将一段时间内的IMU测量值积分起来得到一个相对的运动增量这个增量只依赖于这段时间内的IMU读数与状态初值无关。而一个准确的IMU标定参数是保证预积分结果准确性的基石。如果标定参数误差大预积分的结果就会带有系统误差进而污染整个VIO的优化结果。IMU标定看似是VIO流水线中一个前置的、枯燥的环节但它却是整个系统稳健运行的底层保障。花上几个小时严谨地完成一次标定可能比你后面调几天算法参数都管用。希望这份详尽的备忘能帮你跨过这个基础但至关重要的门槛。
返回列表