ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

IMU标定工具选型:kalibr_allan、imu_utils、imu_tk实战指南

IMU标定工具选型:kalibr_allan、imu_utils、imu_tk实战指南 上周有个项目让我印象很深对方用 D435i 跑 VINS-Fusion视觉跟踪看着很稳但定位轨迹就是慢慢飘。我打开配置一看IMU 噪声参数是从网上一份教程里复制的默认值加计和陀螺的随机游走跟实际传感器根本不是一回事。后来用 imu_utils 重标了一遍把 noise density 和 random walk 换成真实测量值问题立刻缓解。类似的场面我遇到过不止一次。所以这篇东西我想聊聊 kalibr_allan、imu_utils、imu_tk 这三个开源 IMU 标定工具包到底怎么选、怎么用。它们解决的都不是IMU 装没装正这种外参问题而是更底层、更隐蔽的噪声特性问题。如果你在做 lidar imu 标定前置准备、RGB-D 相机配合 IMU 的紧耦合、或者手眼标定之后要评估 IMU 数据质量这篇文章应该能帮你少走不少弯路。1. 标定到底在标什么五个参数把 IMU 的坏脾气说清楚1.1 先看一个真实翻车场景很多人对 IMU 标定的理解停留在标完就能消除漂移这是个挺常见的误区。IMU 的漂移来自两个层面一个是每次开机都不一样的零偏另一个是运行中随时间缓慢变化的随机游走。前者靠上电后静止初始化能解决一部分后者只能靠统计建模让算法知道这个传感器大约以多大的速率在随机漂移。我见过最典型的问题是这样的VINS-Mono 里默认的加计噪声参数是0.01陀螺是0.001很多移植项目直接沿用。但不同型号 MEMS IMU 的噪声水平可能差一个数量级一个 D435i 的实测加计 noise density 可能在0.005到0.02之间一颗工业级光纤陀螺可能只有0.0001。拿别人的参数套自己的传感器滤波器对 IMU 的信任程度就是错的表现就是视觉明明没崩轨迹却在慢慢漂。1.2 随机误差、确定性误差、安装误差要分开看这里把 IMU 标定涉及的东西拆开避免三种东西混在一起随机误差陀螺的角度随机游走Angle Random WalkARW、加计的速度随机游走Velocity Random WalkVRW对应的就是 Allan 方差曲线里的白噪声段还有长期工作的偏置随机游走Bias Instability / Rate Random Walk。它们是概率意义上的统计量没法用一个固定值消掉只能建模成滤波器过程噪声。确定性误差包括常值零偏bias、尺度因子误差scale factor、轴间非正交误差misalignment。这部分是可以用六位置法或连续旋转法标定出来、然后在数据预处理阶段直接减掉的。安装误差IMU 和相机/雷达/机械臂末端之间的旋转和平移外参一般靠手眼标定或联合标定解决和上面的传感器自身标定不是一回事。kalibr_allan、imu_utils 主要做随机误差imu_tk 在随机误差之外还能做一部分确定性误差。这一点决定了你当前项目该先碰哪个工具。1.3 标定参数在 VIO 里到底被谁消费以 VINS-Fusion 这类紧耦合方案为例IMU 的噪声参数用于预积分协方差传播。简单说后端优化时会用noise density和random walk去构造过程噪声矩阵决定每一帧 IMU 测量值在状态估计里有多少话语权。参数给小了滤波器会过分相信 IMU 短时积分结果视觉观测稍有延迟或遮挡姿态就被带偏参数给大了IMU 提供的信息几乎不被信任系统在纯视觉退化场景比如白墙、暗光里就直接飘了。所以标定不是为了好看而是给滤波器一个诚实的传感器模型。这就像你知道一个人跑步时会喘不能让算法假设他是机器人、恒定输出配速否则后面的配速预测全都会错。2. 三大工具的定位差异同是 Allan 方差三种不同姿势2.1 共同的数学地基kalibr_allan、imu_utils 的核心算法都建立在 Allan 方差分析上。Allan 方差的思路很朴素把一段长时间静止的 IMU 数据按不同的时间窗口长度切块统计相邻窗口均值的差异方差然后画出聚类时间-方差的双对数曲线。曲线不同段的斜率对应不同误差源斜率约 -0.5 的段对应白噪声曲线在纵轴上的截距换算成 noise density曲线最低点对应零偏不稳定性斜率约 0.5 的段对应速率随机游走也就是 random walk。理解这个原理很重要因为后面无论哪个工具跑完你都要能在图形上判断结果可不可信。如果采集数据时长不够曲线根本不会走到斜率 0.5 的段工具拟合出来的 random walk 可能只是外推值要用时心里得有数。2.2 三款工具的定位差异工具主要功能输入形式依赖输出kalibr_allanAllan 方差分析、随机噪声参数拟合ROS bagROS通常配合 Kalibr 生态YAML 格式噪声参数、Allan 曲线imu_utilsAllan 方差分析、一键化封装ROS bagROS、code_utilsYAML 格式噪声参数、PNG 曲线图imu_tk确定性误差标定 Allan 方差分析文本文件timestamp, acc, gyr无 ROS 强依赖C 库解析解形式输出偏差、尺度、轴间误差kalibr_allan 来自 ETHZ Kalibr 生态风格偏研究向适合本来就准备用 Kalibr 做相机-IMU 联合标定的团队。它的好处是和后续工具链自洽坏处是需要自己编译、配置对只想快速拿到一组参数学会有点重。imu_utils 是社区里流传最广的轻量方案日常最常用。它把 Allan 方差分析包成了一个 ROS 节点播放 bag 就能出结果我在这篇里会重点写它的实操。imu_tk 则走的是另一条路它有个相当实用的多位置静态标定方法可以估计加计和陀螺的零偏、尺度因子、轴间非正交误差同时也能做 Allan 方差分析。它对没有 ROS 环境的嵌入式项目特别友好输入是纯文本部署在 ARM 板上也能跑。2.3 选型速判如果按使用场景推荐我的习惯是正在用或准备用 Kalibr 做联合标定 → 先上 kalibr_allan保持整条链路的格式一致只想要一份可用的随机噪声参数、越快越好 → imu_utils晚上录两小时数据第二天早上出结果要用在嵌入式 / 无 ROS 环境或者想顺便修掉确定性偏差 → imu_tk追求严谨、用于论文级精度 → kalibr_allan imu_tk 双跑交叉验证。3. kalibr_allan 实操记录从 rosbag 到 imu.yaml3.1 环境准备与依赖kalibr_allan 一般以源码形式放进你的 ROS catkin 工作区。我常用的做法是建一个imu_ws单独容纳标定相关包不要跟业务工程混在一起。需要准备的东西包括一个可用 ROS 环境、编译 Kalibr 生态所需的基础依赖以及你最终想用的那个 IMU 驱动。这里最容易忽略的是把 IMU 的采样率固定下来。很多传感器驱动默认值比较随意我建议统一设置成传感器原生最高频率比如 200 Hz 或 400 Hz并且在录制期间不要修改参数。编译顺序也有讲究。如果是从源码拉取 Kalibr 相关包建议严格按照仓库文档里的依赖顺序来避免同时拉了很多没用的可视化依赖。遇到 Eigen、Sophus 版本冲突是常见事建议用一个干净的 Ubuntu ROS 环境单独编译。3.2 数据录制时长、静止、采样率kalibr_allan 需要的是长时间静止数据。我实际测试下来的经验是用于工程估计1 到 2 小时基本够用要求严谨一点最好录 2.5 到 3 小时。太短的数据会让 Allan 曲线在长聚类时间区间没有足够的统计样本random walk 的拟合误差很大。录制的具体做法把 IMU 固定在一个刚性的台面上不要放桌上因为桌子本身可能有低频振动关掉电机、风扇等明显振源传感器电源保持稳定不要用那种电压波动明显的 USB 口否则会在陀螺上看到明显的异常峰录制前先上电预热几分钟让偏置从冷启动状态稳定下来。录制命令很简单rosbag record -O imu_static.bag /imu/data但要注意/imu/data这个名字只是示例实际操作前要确认自己驱动发布的话题名称和消息类型。录制期间我一般每隔几分钟看一眼rostopic hz确保频率没有掉。3.3 跑标定并获取输出kalibr_allan 的典型运行方式是通过 ROS 节点把 bag 路径、IMU 话题作为参数传进去。不同版本入口略有差异这里的关键是运行后它会读整个 bag 的 IMU 数据计算 Allan 方差并做拟合。rosrun kalibr_allan kalibr_allan --bag imu_static.bag --imu /imu/data跑完之后工作目录里会出现结果文件。常见命名类似imu.yaml或者带时间戳的 YAML里面包含了陀螺和加计的 noise density、random walk 以及部分 Allan 曲线数据。我第一次跑这个工具的时候有个困惑它输出的是 rad/s 单位下的功率谱密度还是离散时间下的参数这需要仔细阅读头注释。现在比较常见的做法是输出连续时间噪声密度后续在 kalibr 联合标定时直接用如果你要转成 VINS 里的离散时间噪声别忘了除以sqrt(采样周期)。这个换算我后面专门讲。3.4 输出文件长什么样一份典型输出的 YAML 内容大概是这样的结构gyroscope_noise_density: 1.5833e-04 gyroscope_random_walk: 2.4600e-05 accelerometer_noise_density: 3.6087e-03 accelerometer_random_walk: 3.2917e-03这几个值后续可以直接喂给 Kalibr 的相机-IMU 联合标定。需要强调的是不同工具的单位约定可能不同最好以单位注释为准。如果某些输出没有写单位可以画 Allan 曲线验证noise density 对应曲线左端平直段的高度random walk 对应右侧斜率 0.5 段的延伸值。4. imu_utils 实操记录5 分钟拿结果的轻量方案4.1 安装 code_utils 与 imu_utilsimu_utils 是我在实际项目里用得最多的工具因为它足够轻。安装时有个先后顺序问题先编译code_utils再编译imu_utils因为后者依赖前者。很多人一上来把所有包扔进 catkin_make结果 code_utils 还没编译完就报找不到头文件。建议分开编译catkin_make -DCMAKE_BUILD_TYPERelease source devel/setup.sh如果你在用较新版本的 ROS可能还需要处理一些 C 标准兼容问题。社区里常见的做法是给 CMakeLists 加-stdc14这个按报错信息调整即可不算大坑。4.2 修改 launch 文件并播放 bagimu_utils 的 launch 文件核心参数大致是这些launch node pkgimu_utils typeimu_an nameimu_an outputscreen param nameimu_topic typestring value/imu/data/ param nameimu_name typestring valueimu/ param namedata_src typestring valuebag路径/ param nametime_start typeint value0/ param nametime_timespan typeint value180/ /node /launch这里的time_timespan单位是秒表示从 bag 里取多少秒数据做分析。我有次偷懒只录了 20 分钟设了 1200 秒出来的曲线后半段毛刺特别多那就是数据量不足的信号。后来统一按 90 分钟以上录制曲线干净很多。数据播放方式有两种一种是用rosbag play imu_static.bag在线播放同时启动 imu_utils 节点另一种是把 bag 路径直接写进 launch 文件。我更推荐后者省得两个终端同步。运行结束后工作目录会出现imu_utils输出目录里面是 YAML 和 PNG 曲线图。4.3 结果怎么看imu_utils 输出的 YAML 通常按陀螺和加计分别列%YAML:1.0 --- type: IMU name: imu Gyr: unit: rad/s avg-axis: gyr_n: 1.2696e-04 gyr_w: 1.5920e-05 Acc: unit: m/s^2 avg-axis: acc_n: 5.9863e-03 acc_w: 5.1989e-03gyr_n对应角度随机游走噪声密度gyr_w对应陀螺随机游走acc_n是加计速度随机游走密度acc_w是加计偏置随机游走。它还会按 x、y、z 单轴分别输出一份最后给一个 avg-axis 用于平均值。同时输出的 PNG 曲线是判断数据质量的重要依据。曲线应该呈现典型的先下后上形态左侧白噪声段接近斜率 -0.5中间最低点平缓右侧上升。如果你看到的曲线一直在抖或根本没有低谷说明数据里有振动或传感器在采集期间发生了位移建议重新录。5. imu_tk 实操记录六面位置法标定确定性误差5.1 数据格式与采集方法imu_tk 对输入格式有明确要求通常是一个文本文件每一行包括时间戳、三轴加计、三轴陀螺用逗号或空格分隔。它不关心你的 ROS 话题也不要求你装 ROS所以特别适合在嵌入式或无 ROS 环境里用。采集方式上imu_tk 常用的确定性误差标定法是多位置静态法也就是我们常说的六面法。把 IMU 固定在台面上依次让 x、y、z 轴分别朝上和朝下每个姿态保持 30 到 60 秒同时记录数据。这样一共 6 个位置每个位置的重力矢量在传感器坐标下指向已知方向算法就能拟合出加计的零偏、尺度因子和非正交误差。实际执行的时候要注意朝向要尽可能准。你可以用水平尺、直角块或者干脆在 3D 打印的定位块上做标记。如果朝向差个几度标定出来的轴间误差里会掺入人为误差反而比不标还差。我自己试过把 IMU 用双面胶贴在手机屏上用手机角度计辅助摆正效果比随手放强很多。陀螺的确定性误差标定通常还需要配合角速度激励典型做法是让 IMU 绕某轴做匀速或已知轨迹的旋转。如果没有转台只做零偏部分也能接受。5.2 运行标定并查看输出imu_tk 的可执行程序通常由仓库提供的示例代码编译而来主程序输入数据文件输出标定结果。典型的命令类似./imu_tk_calibrate imu_data.txt运行时会输出加计和陀螺的零偏、尺度因子、轴间误差矩阵。这些输出的含义比较直接加计的 bias 就是三个轴上的常值零偏scale 是各轴灵敏度偏差misalignment 是三轴不正交导致的交叉耦合。我个人的建议是把这些确定性参数先手动加在数据处理的前端然后在已经做过失真误差修正的数据上再跑一轮 Allan 方差这样拿到的随机噪声参数才更干净。否则确定性误差混在 Allan 方差里零偏不稳定性会被抬高。5.3 为什么确定性标定和随机噪声标定要分开做很多人会问既然 imu_tk 也能算 Allan 方差为什么还要再单独跑 imu_utils我的理解是两个工具的重心不同。Allan 方差分析的前提是消除确定性趋势后的平稳随机过程如果数据里还有明显的常值零偏和尺度误差Allan 曲线形态会偏移拟合得到的随机游走参数会偏大。所以在我的工作流里顺序是固定的先用 imu_tk 粗标确定性误差把数据里的固定偏差和尺度问题清理掉再对这些去偏后的数据跑 Allan 方差得到随机噪声参数。如果项目时间紧确定性误差不严重也可以直接跑 Allan但心里要清楚结果里混着一定确定性成分。6. 90% 的标定误差来自采集环节时长、静止、温度、数据连续性6.1 时长不是越长越好而是越稳越好很多人以为 Allan 方差分析就是数据越多越好于是录了好几个小时结果曲线反而乱糟糟。问题通常不是时长而是长时间录制中环境发生了变化桌面的空调风直吹、设备发热、人的走动引起地面振动这些都会变成长聚类时间段的异常方差。我在实践中对时长的理解是至少 1 小时最好 2 小时但必须在稳定的实验环境下做。如果现场条件嘈杂宁愿拆成多次短采集也不要强求一次录够。多次采集后可以把结果对比一下看各次标定参数的离散程度如果两次的 gyr_n 差超过 20%说明采集环境有问题。6.2 静止姿态和振动控制对 Allan 方差分析来说传感器必须绝对静止。这里的静止不是放桌上不动这么简单有些桌面本身会因为楼上走动、空调共振而微振动高档 MEMS 陀螺完全能感受到。我吃过一次亏把 IMU 用双面胶粘在金属台面上台面下方刚好有个排风扇结果 Allan 曲线在中等聚类时间段上出现了明显峰值怎么拟合都对不上。后来换到一块厚橡胶垫上问题就消失了。对六面法标定确定性误差来说还要保证每个姿态的静止时间足够长让传感器内部的零偏稳定下来。我一般每个姿态放 60 秒前 10 秒数据不用只用后 50 秒。6.3 温度影响数据开始前先预热MEMS 陀螺的零偏对温度非常敏感冷启动和热机状态下的 bias 可能差好几倍。如果你一上电就录标定数据Allan 方差里的零偏不稳定性会偏大因为温度漂移被当成了偏置随机游走。我在项目里的习惯是传感器上电后至少预热 5 到 10 分钟再开始录数据同时尽量保证录制过程中的环境温度没有剧烈变化。冬天在室外调试尤其要注意手一靠近传感器红外辐射都会在温度曲线上留下痕迹。6.4 检查数据质量的三个命令录制完成后先不要急着跑工具花一分钟做数据质量检查rostopic hz /imu/data rostopic echo /imu/data --noarr第一看频率是不是稳定第二看是否有 NaN 或者跳变。还可以用rqt_bag拉一段数据看看整体趋势确认传感器没有在录制中被人挪动。这三个检查做完再跑标定不然工具再精确也救不了脏数据。7. 把标定结果喂进 VINS-Fusion 与 Kalibr参数转换与验证7.1 从 Allan 输出到 VINS-Fusion 配置imu_utils 和 kalibr_allan 输出的通常是连续时间噪声参数但很多 VIO 框架里期望的噪声参数是离散时间步下的协方差值。以 VINS-Mono/VINS-Fusion 常见的配置文件为例它需要四类参数加计噪声密度、陀螺噪声密度、加计随机游走、陀螺随机游走。如果你手头是 imu_utils 的输出可以直接把它那四个量填进去imu_acc_noise: 5.9863e-03 imu_gyr_noise: 1.2696e-04 imu_acc_random_walk: 5.1989e-03 imu_gyr_random_walk: 1.5920e-05有的版本里还需要除以sqrt(dt)这个要看具体框架内部是连续模型还是离散模型。我的建议不是去背公式而是从原理上确认如果框架里的协方差传播是在离散时间步上进行采样那么噪声密度往往是功率谱密度形式需要除以sqrt(dt)如果框架里已经给了连续模型接口就不需要额外处理。出现疑问时直接标定一次后做仿真对比看静止时姿态方差是否合理。7.2 在 Kalibr 联合标定中的二次使用如果你用的是 Kalibr 做相机-IMU 联合标定那标定出来的噪声参数要以 yaml 文件形式提供给kalibr_calibrate_imu_camera。格式大致是# 该文件用于 kalibr 联合标定 imu: update_rate: 200.0 gyroscope_noise_density: 1.2696e-04 gyroscope_random_walk: 1.5920e-05 accelerometer_noise_density: 5.9863e-03 accelerometer_random_walk: 5.1989e-03注意update_rate一定要写实际发布频率不要写标称值。我有一次把 D435i 的 IMU 标注成 400 Hz实际驱动只发了 200 Hz联合标定结果里的时间戳对齐就一直有残差。7.3 标定结果验证方法标定完不能直接就用我习惯先做一个快速验证静止漂移测试把 IMU 固定静止记录 10 分钟姿态解算结果看积分出来的姿态角漂移速率是否在合理范围直线往返测试把 IMU 装在机器人上沿直线走一个来回看回到起点时位置误差是否在预期范围与另一款工具交叉对比同一份数据用 imu_utils 和 kalibr_allan 各跑一遍结果应该接近。如果静止漂移测试里角度还是在快速跑说明噪声模型还是不对或者零偏没有处理好。别急着继续联调回去查数据采集环节更有效。8. 实测对比表与选型建议我的最终结论维度kalibr_allanimu_utilsimu_tk安装难度中高依赖较多低依赖 code_utils中C 编译数据输入ROS bagROS bag文本文件核心输出YAML 噪声参数YAML 噪声参数 PNG 曲线零偏/尺度/轴间误差 Allan 分析是否需 ROS是是否适合场景科研、Kalibr 联合标定工程快速标定嵌入式、无 ROS、确定性误差标定典型耗时准备 1 天运行 0.5 小时准备 0.5 天运行 5 分钟准备 1 天含六面位运行 0.5 小时我的实际选择标准很简单默认先用 imu_utils 拿随机噪声参数因为它的曲线输出最直观、结果文件最通用如果项目里 Kalibr 明显要长期用就改用 kalibr_allan 保持链路一致一旦发现传感器存在明显的尺度或轴间误差问题再引入 imu_tk 做确定性标定。最后分享一个习惯每次标定完我会在工程里同时保留三样东西——数据 bag、标定参数 yaml、当时的环境记录室温、预热时间、安装方式、录制时长。这样后续如果发现标定结果存疑能快速回溯是哪一步出了问题。这个习惯让我省了大量重复采集的时间也建议你试试。
返回列表