ARTICLE DETAIL

资讯详情

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

Kalibr相机IMU联合标定:VIO外参与时延优化全指南

Kalibr相机IMU联合标定:VIO外参与时延优化全指南 做视觉惯性方案这些年我踩得最深的坑往往不在算法本身而在“还没开始跑VIO设备就先标歪了”。一台相机、一枚IMU装在机器人或无人机上两者坐标系并不重合时间戳也对不齐甚至几毫秒的时钟偏差都会被后端优化放大成轨迹漂移。要解决这个问题目前最成熟也最主流的工具就是ETH Zurich ASL实验室开源的Kalibr它能一次性把相机内参、IMU噪声参数、相机与IMU之间的外参以及时延全部估计出来。这篇博文我会把Kalibr联合标定的原理、数据采集、配置编写、运行和排障完整讲一遍适合正在做视觉惯性测距、SLAM、无人机避障、机器人导航的开发者参考。1. 相机IMU联合标定为什么会成为VIO的第一道门槛1.1 外参两个传感器之间的“坐标转换口诀”先想清楚一件事相机输出像素和灰度IMU输出三个轴的角速度与加速度一个在光心一个在器件几何中心安装角度也可能差上十几度。算法里所有“把图像特征变换到IMU坐标系再预积分”的操作都需要一个精确的4x4齐次变换矩阵通常记做T_ic下标表示从IMU到相机的坐标映射。它的结构是一个旋转矩阵加一个平移向量旋转矩阵负责把IMU的三个轴转到相机坐标系的姿态平移向量负责补偿两个传感器中心之间的空间距离。别小看这六个数如果旋转偏差达到5度以上特征点的投影误差就会直接爆掉后端的视觉惯性束调整再怎么优化也不可能把系统误差救回来。所以外参标定不是“锦上添花”而是整个视觉惯性系统成立的前提。我见过不少同学买来现成的算法跑通demo然后直接把外参设置为单位矩阵心想“反正两边位置很接近”。这种做法的后果是在室内缓慢运动时或许勉强能看一旦加速、转向剧烈IMU预积分和视觉观测就开始互相打架轨迹要么飘要么跳。后面再回头标定发现数据采集时又没有故意激发IMU的六自由度场景纹理也不够结果标定反而失败。所以第一个心得是标定跟算法训练一样输入数据质量决定最终效果上限这一点后面专门展开。1.2 时间戳偏差比外参更隐蔽的“隐形杀手”除了空间关系时间轴也要对齐。相机图像从曝光中心到驱动发布中间经过传感器读取、ISP处理、驱动封装、ROS话题传输动辄几毫秒到几十毫秒IMU虽然延迟小但如果分别由不同芯片打时间戳两边的时钟基准并不严格同步。Kalibr把这种时间偏移time offset也作为待优化量加到外参旁边一起估计。很多人标定时只看空间外参忽略了输出的时延结果这是不对的。如果bag里IMU频率是200Hz一帧图像“慢”了10ms等效于IMU数据整体晚了两拍参与预积分。你可以试试在VIO里手动把IMU数据平移20个时刻点轨迹误差就会显著增大可见这几毫秒的影响有多大。Kalibr估计出的时延通常是一个很小的浮点数比如-0.0032秒。正负号表示相对关系如果结果是负值意味着图像时间戳晚于IMU的等效观测时刻反过来同理。实际工程里如果这个值超过10ms并且很不稳定我建议先检查驱动是不是用了软件时间戳或者图像话题有没有经过压缩、中转节点这些都会引入额外延迟。解决完时间戳一致性再回来标定时延结果就会稳定很多。1.3 为什么偏偏用Kalibr而不是手测或九点法可能会有朋友问空间外参我也量过尺寸角度用水平尺大致估一下不行吗坦白说只有在你对精度要求极低的时候才行。VIO对旋转外参的敏感度极高1度的旋转误差在10米外的特征点就会产生约17厘米的投影偏差这对机器人避障来说已经完全不可接受。而手眼标定、九点标定解决的是机械臂末端和相机关系的问题张正友标定解决的是单目内参问题它们和“相机-IMU这两类异源传感器的时空对齐”根本不是同一个问题。Kalibr的核心优势在于它用连续时间的B样条拟合传感器运动轨迹把离散的相机观测和IMU采样放到同一条连续曲线里做联合优化。这样即使没有外部运动捕捉系统只需手持设备在Aprilgrid标定板前做六自由度晃动也能把外参、时延、噪声密度统一估计出来。开源、成熟、社区案例多这是我坚持用它跑通整套流程的根本原因。2. 准备工作决定标定上限IMU内参、标定板与数据采集2.1 先把IMU内参测准确别把烂参数扔给联合优化Kalibr在联合标定时会同时估计IMU的噪声密度和随机游走但前提是初值不能差太远。如果一开始就把某个噪声参数给成0优化器可能会走进死胡同。因此我的习惯是先采集一段2小时左右的静止IMU数据用imu_utils包跑Allan方差分析得到陀螺仪和加速度计的噪声密度与随机游走再填到IMU的yaml里。操作上并不复杂写一个roslaunch文件把IMU消息录成bag然后调用imu_utils的节点处理最后读取allan输出的yaml文件里面的gyro/accel相关参数就是连续时间下的噪声密度和随机游走可以直接复制。这里有个非常容易踩的坑Kalibr的IMU参数单位默认是连续时间下的不能用短时间窗口的标准差估计去替代。很多初学者从IMU手册里抄离散采样噪声填进yaml结果联合标定时残差形状异常。另外Allan方差分析的时长不能太短10分钟勉强能用最好1小时以上。静止采集时把设备放在稳定台面上避免有人走动、窗口风、震动桌面等环境干扰。这一步看似耗时但后面联合标定会少折腾很多。2.2 标定板选Aprilgrid精度、配置与打印Kalibr默认推荐的标定板是Aprilgrid而不是OpenCV传统棋盘格原因在于它的每个格子自带编码ID允许部分遮挡和部分视野观测算法在优化时依然能正确识别角点并匹配到世界坐标系。在标定板的yaml文件里需要明确target_type为aprilgrid同时指定行列数tagCols/tagRows、单个标签边长tagSize单位米和标签间距tagSpacing相对边长的比例。例如6x6的板子边长0.1米间距比例0.15意味着相邻两个tag中心的距离是0.1×(10.15)米。这两个数字必须量得非常准确哪怕有1毫米误差也会直接进入外参估计的误差项。板子打印时不要在普通纸上打最好用哑光相纸或贴在平面硬板/铝板上避免弯曲、反光。我实测发现表面轻微弯曲的标定板会让边缘角点重投影误差始终居高不下。2.3 数据采集动作设计晃动、时长与bag录制联合标定对数据的要求我总结成四个关键词激发、覆盖、清晰、静止。具体操作是设备手持或安装在简单云台上在标定板前做缓慢但幅度充分的旋转和平移尽量覆盖IMU每个轴的正负方向避免纯旋转或纯平移因为那样外参会退化优化解不唯一。整个过程建议控制在30到90秒太短了IMU激励不充分太长了容易手抖导致图像模糊、特征点丢失。采集前让设备静止1到2秒采集结束时也静止几秒这会给初始化阶段提供比较好的角速度偏置基础。bag录制时话题名称必须与后面配置文件的rostopic字段一致例如/cam0/image_raw和/imu0。图像话题建议使用原始未压缩图像分辨率、帧率不要中途切换。录制过程中始终观察标定板占据画面比例理想情况是板子占图像四分之一以上并且始终完整或大部分出现在视野中。光照要均匀避免强光直射造成标定板局部过曝或者反光形成高光斑。关于IMU频率联合标定一般建议至少100Hz以上如果设备只有50Hz也能算但时延估计的不确定性会明显变大。我在实际项目里还发现标定板的背景不要太杂乱最好是一面均匀的白墙背景中的纹理容易干扰Aprilgrid的检测结果导致偶发误识别的角点。3. Kalibr联合标定完整实操配置文件、命令行与结果解读3.1 环境安装用ROS工作空间编译KalibrKalibr主要面向ROS推荐在Ubuntu 18.04ROS Melodic或Ubuntu 20.04ROS Noetic环境下使用。安装之前确保ceres-solver、opencv、eigen等依赖齐备然后克隆代码并编译大致命令为cd ~/catkin_ws/src git clone https://github.com/ethz-asl/kalibr.git cd .. catkin_make -DCMAKE_BUILD_TYPERelease source devel/setup.bash编译过程中最常见的麻烦是依赖版本冲突尤其是OpenCV和Ceres版本。如果遇到找不到库的问题优先检查是否有多个OpenCV版本混用建议用系统自带的OpenCV配合ROS自带的依赖来编译。编译完成后敲kalibr_calibrate_imu_camera --help能正常打出帮助信息就说明环境没问题。另外很多朋友会遇到“明明编译好了命令却找不到”的情况这是因为没有source工作空间或者没有把kalibr的路径加入.bashrc。这里顺便提醒用rosrun或直接执行可执行文件均可但最好在工作空间环境下操作避免不同版本ROS环境串扰。安装过程我踩过最值的一个坑是不要试图在Python3环境中直接装旧版Kalibr的Python依赖它的很多脚本是Python2的用ROS Noetic时要注意兼容方案社区里有对应的更新分支确保运行环境与脚本匹配再继续。3.2 编写三个配置文件target、camchain、imu标定之前先整理三个yaml。第一个是标定板描述文件命名如april_6x6.yaml内容为target_type: aprilgrid tagCols: 6 tagRows: 6 tagSize: 0.1 tagSpacing: 0.15第二个是相机参数文件如果相机内参还没有可以用kalibr_calibrate_cameras先做一次内参标定也可以直接给一个比较合理的初值Kalibr联合标定过程中会继续优化相机内参。camchain.yaml的常见格式cam0: camera_model: pinhole distortion_model: radtan distortion_coeffs: [0.1, -0.02, 0.001, 0.0005] intrinsics: [460.0, 460.0, 320.0, 240.0] resolution: [640, 480] rostopic: /cam0/image_raw其中intrinsics对应fx、fy、cx、cydistortion_coeffs对应k1、k2、p1、p2。像素坐标系原点、主点这些初值不重要反正后面会迭代优化但fx、fy的数量级要合理1000以内的值和10000的值能给优化器完全不同的起点。第三个是IMU配置文件imu.yaml内容类似imu0: update_rate: 200.0 gyroscope_noise_density: 1.7e-04 gyroscope_random_walk: 1.3e-05 accelerometer_noise_density: 2.0e-03 accelerometer_random_walk: 3.1e-04update_rate要与bag里IMU消息的真实频率对齐可以直接用rostopic hz /imu0测量。噪声密度、随机游走从上一步Allan方差结果中拿注意单位Kalibr内部按连续时间处理不要额外除以采样频率。配置写好后把三个yaml和录好的bag都放到同一个目录方便后面输入路径。3.3 运行标定命令学会看输出和结果文件在目录下执行联合标定kalibr_calibrate_imu_camera \ --target april_6x6.yaml \ --cam camchain.yaml \ --imu imu.yaml \ --bag dataset.bag如果希望固定或放开相机内参可以用--cam-num-cams、--show-extraction、--time-calibration等开关控制。运行开始后工具会先提取标定板角点然后做IMU预积分接着是连续的优化迭代。中途会弹出窗口显示角点提取效果如果发现很多帧没有检测到标定板或者检测点位错乱建议立即CtrlC检查数据质量而不是等它跑完。标定正常跑完后主要产出两个文件一个是camchain-imu.yaml里面有估计出的相机内参和IMU外参另一个是results-imu-cam0.txt里面记录了外参T_ic的数值、时延time offset以及重投影误差、IMU残差等统计。这里我会重点看三个指标图像重投影误差一般小于0.5像素算非常好小于1像素算合格如果大于2像素说明角点检测或内参初值有问题IMU残差应该大致平稳没有明显趋势时延结果应当稳定不随标定初始化变化大跳。读取T_ic时注意它表示的坐标变换方向把IMU坐标系里的向量左乘这个矩阵才能变换到相机坐标系实际使用外参时方向搞反是工程里最常见的问题。4. 标定过程避坑实录故障排查与结果验证4.1 标定失败与数值异常速查表这部分内容是我反复踩坑后的小结直接用表格整理方便大家遇到问题时对照现象可能原因解决办法角点检测率极低光照过曝、标定板太小/太远、图像模糊重新采集调整距离和光照确保标定板占画面1/4以上优化不收敛或发散外参初值给得离谱、IMU参数错误用手持静态初始化或粗校准给初值检查IMU yaml单位重投影误差1像素标定板弯曲、相机内参初值差、图像畸变模型不对换平整板子重新做单目内参标定调整distortion_model时延估计跳动大图像时间戳来自软件、imu频率低改用传感器硬件时间戳提高IMU频率特征点边角误差大标定板边缘透视过大、拖影减少运动速度增大标定板尺寸输出外参与手量差太多数据激励不足、外参可观测性差补充六个自由度的晃动轨迹每个案例背后都有细节。比如“时延估计跳动大”我遇到过一次是因为图像话题经过了低通缩放节点导致延迟随机变化后来直接把原始图像话题作为输入就好了。另一次“重投影误差1像素”排查半天发现是标定板打印后贴在泡沫板上轻微弯弧换铝板之后立竿见影。所以看到异常数值不要急着调迭代参数先检查物理设备和数据链路。4.2 标定结果是否可信三种验证手段标定完毕不等于万事大吉。我一般会做三个层面的验证。第一静态一致性检查把设备静置在桌上采集一段静止图像和IMU数据用标定出的外参把IMU重力方向投影到相机图像坐标系看垂直方向是否与画面中实际水平线对齐偏差大说明旋转外参有问题。第二动态轨迹一致性以纯视觉跑一段短轨迹再以视觉惯性融合跑同一段观察轨迹形状是否一致特别关注转弯和加减速期间是否出现系统性拉伸。第三重复性实验同样的设备连续标定两次对比T_ic的旋转欧拉角和平移向量如果两次结果相差很大说明这次标定不稳定需要重新采集数据。这里再分享一个工程小技巧把标定出的外参交给VIO系统后不要把外参完全锁死。可以在一小段数据里把外参作为优化变量放开观察优化后的外参与标定值是否收敛到很接近的位置。如果两者差异很小说明标定可信如果差异超过几度说明标定质量不高应该回到数据端排查。这个技巧在后端漂移排查时也很有用。4.3 思路扩展从相机IMU到lidar-IMU的标定迁移Kalibr的思路并不局限在相机与IMU之间。现在越来越多的设备同时装了激光雷达和IMU需要lidar与IMU的外参。虽然lidar和相机特性不同但标定问题的本质是相同的建立异源传感器之间的空间变换和时间关系。社区里出现了很多受Kalibr启发的lidar-imu外参标定工具利用连续时间轨迹的框架将点云配准残差与IMU预积分残差联合计算。我自己试过用类似框架给一体化的雷达-IMU设备做标定发现最大的经验依然是先保证IMU内参准确再保证运动激励充分最后再来谈算法。这个通用经验是所有多传感器时空标定的共性基础。有一点要提前说明讲lidar标定不是偏离主题而是因为很多做机器人感知的读者会把“相机IMU”和“雷达IMU”放在同一条选型链路上。Kalibr的经验完全可以迁移到lidar方案里但lidar标定对初值更敏感并且雷达点云在不同场景下的特征可观测性差异更大所以更依赖场景结构化程度。如果暂时没有条件做雷达标定先在相机IMU上把Kalibr吃透绝对值得。5. 写在最后标定的本质是让数据自己说话最后分享几个我个人的习惯供参考。一是每次采集完bag我都会先跑一遍kalibr的角点提取或IMU可视化确认数据质量后再进入标定绝不拿垃圾数据去碰运气。二是标定结果我会随手存档记录设备型号、串号、采集日期、标定板尺寸方便后续复标时对比漂移。Kalibr确实不是完美的工具它也有对rolling shutter支持不佳、对光照敏感等问题但在我接触过的标定方案里它依然是解决相机-IMU时空对齐最可靠、最值得先跑通的选择。如果你正在被VIO初始漂移折磨不妨从检查最基础的外参和时延开始——很多时候误差审到了源头算法问题就已经解决了一大半。
返回列表