ARTICLE DETAIL

资讯详情

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

Realsense D455相机与IMU联合标定:Kalibr完整实战指南

Realsense D455相机与IMU联合标定:Kalibr完整实战指南 标定这种事做过一次基本就不会忘。尤其是Realsense D455这种自带IMU的相机它在出厂时虽然做了内参和IMU的工厂标定但相机和IMU之间的外参、时间延时、以及IMU自身的噪声特性这些参数拿到手通常是没法直接用的。做视觉惯性SLAM、VIO、或者多传感器融合第一步就是要把这些参数算清楚否则后面跑算法全是玄学。我这次就用Kalibr把Realsense D455的彩色相机和内藏IMU做了一遍完整的联合标定从环境配置、数据采集、内参标定到最后的IMU-相机联合求解整个过程踩了不少坑。这篇文章把完整流程和常见报错都整理出来了适合刚入门视觉惯性导航、或者搞了几天Kalibr还没跑通的兄弟直接“抄作业”。1. 标定前先把原理和准备搞明白1.1 Kalibr联合标定到底在算什么Kalibr是ETH Zurich开源的相机标定工具箱它最强的能力就是能够同时估计相机与IMU之间的外参旋转和平移、时间延迟以及IMU的噪声参数。联合标定的本质是通过相机观测到的视觉特征和IMU测量到的角速度、加速度对同一段运动轨迹进行一致性优化。简单理解就是让“IMU说的运动”和“相机看到的运动”能对得上。D455内置的IMU是博世的BMI0556轴包含3轴陀螺仪和3轴加速度计最高输出频率可以到400Hz。Realsense驱动默认把IMU按照200Hz或者400Hz发布取决于你启动参数怎么配而彩色图像通常是30Hz。两种传感器频率差了十好几倍要融合就必须知道它们之间的坐标系转换关系。这个关系如果不对后面的VINS-Fusion、ORB-SLAM3、OpenVINS这些算法跑起来轻则轨迹漂移重则直接发散。另外还要明确一点联合标定是建立在相机内参已知的基础上。Kalibr的imu-camera标定流程会先做相机内参标定得到相机的焦距、主点和畸变模型参数然后再把IMU数据加进去做外参和噪声参数的估计。别跳步老老实实按顺序来成功率能高很多。1.2 环境与工具链怎么搭先说我的环境这个版本组合实测问题最少Ubuntu 18.04 ROS MelodicRealsense SDK 2.50.0 realsense-ros 2.3.2Kalibr源码编译安装用的是master分支Ubuntu 20.04 ROS Noetic其实也能跑但Kalibr依赖的老版本Python库在Noetic下容易出幺蛾子报错概率明显高一些。如果你非要用Noetic建议用版本比较新的Kalibr分支并且做好和Python 3兼容的准备网上很多教程都是基于Python 2写的老古董照抄大概率报错。Kalibr的编译安装步骤很简单mkdir -p ~/kalibr_workspace/src cd ~/kalibr_workspace/src git clone https://github.com/ethz-asl/kalibr.git cd .. catkin_make source devel/setup.bash这里有个编译依赖需要提前装好尤其是python-igraph和wxPython很多时候Kalibr运行报错就是它们没装sudo apt-get install python-igraph python-wxgtk3.0 python-pip python-scipy python-matplotlib python-numpy python-opencv如果装wxpython的时候找不到包多半是Ubuntu源的问题换一下或者用pip装就行实测不影响主流程。Realsense那边的驱动如果是按照官方realsense-ros的方法装的启动节点的时候要注意把IMU话题发出来。我用的启动方式是roslaunch realsense2_camera rs_camera.launch enable_imu:true unite_imu_method:linear_interpolationunite_imu_method:linear_interpolation这个参数很关键它会把IMU的角速度和加速度数据用线性插值的方式对齐到图像时间戳附近统一封装发布这样录包的时候时间戳一致性会好很多。启动之后先确认话题列表rostopic list至少需要看到/camera/color/image_raw或者infra图像和/camera/imu这两个话题。IMU话题如果需要确认帧率和数据是否正常可以用rostopic echo /camera/imu -n 5看一眼角速度和加速度的数值范围是否合理如果静止状态下加速度应该是约等于重力加速度9.8附近角速度接近0。数值离谱的话先解决硬件或驱动问题再往下走。2. 数据采集是整个标定的命门2.1 标定板的准备绝不是随便打印一张纸Kalibr的IMU相机联合标定需要视觉特征来做运动的参照。标定板是重中之重。Kalibr支持三种标定板Aprilgrid、Checkerboard、Circlegrid。我强烈推荐Aprilgrid也就是带二维码编码的棋盘格。它比普通棋盘格强在每一个角点都有唯一ID即使部分被遮挡也不影响角点检测和对应而且检测算法对模糊和光照变化的鲁棒性明显更好。我用Kalibr自带的工具生成标定板PDFkalibr_create_target_pdf --type apriltag --nx 6 --ny 6 --tsize 0.088 --tspace 0.3参数含义是生成6x6的Aprilgrid每个格子边长0.088米格子间距是边长的0.3倍。生成之后打印到A4纸然后一定要用尺子实测标定板的实际尺寸。打印机的缩放比例会造成尺寸误差这玩意儿在视觉标定里是直接进入优化方程的差一毫米结果就差一截。实测完把真实值记下来后面写target配置文件要用。配置文件内容大概是这样的target_type: aprilgrid tag_cols: 6 tag_rows: 6 tag_size: 0.088 tag_spacing: 0.3tag_size一定要填实测值。我习惯每次打印都重新量一次不要偷懒复用旧值。2.2 录包不是随便晃晃就行数据采集的套路直接决定标定结果的好坏。Kalibr对采集动作有一个核心要求IMU的三轴加速度计和陀螺仪必须被充分激励。说得直白一点你拿着相机运动的时候动作要包含旋转、平移、加速、减速六个自由度都动到不要单轴旋转或者匀速平移。我总结了一套自己用着很顺手的动作模式手持相机先静止保持约2秒让IMU有一个初始重力参考开始运动动作大概像在空中画“8”字同时身体缓缓转动过程中不断变换姿态方向正着、侧着、倒着、斜着尽量让相机视野始终对着标定板偶尔快速转动一下手腕做几个急促的加减速故意刺激IMU最后停止运动静止2秒录包时长建议控制在2到3分钟录太短数据量不够录太长文件巨大而且容易混入大量无效数据。我每个标定数据大概录2500到3000帧彩色图像对应大约100秒到120秒对IMU来说已经是几十万帧了足够联合标定用了。录包命令rosbag record -O d455_calib.bag /camera/color/image_raw /camera/imu有几个关键点值得强调录包全程保持室内光照稳定不要开自动曝光手动固定曝光比较好。光照突变会导致图像模糊或过曝角点检测失败直接污染数据。标定板要始终出现在视野里但不要全程死板地占满画面。画面里标定板占比在20%到60%之间摆动是比较理想的太大会导致运动信息不足太小则角点检测不稳定。不要一边录包一边走动手持相机的运动幅度足够人身体不要有大位移不然容易给IMU引入不必要的重力分离误差。别把镜头正对着窗户或者强光源那样很容易产生镜头光晕对称特征被破坏后检测质量直线下降。2.3 录完先检查再标定录完包不要急着跑Kalibr先做一次数据质量检查。我常用的笨办法rosbag info d455_calib.bag看两个话题的帧数是否匹配。如果IMU数据明显缺失比如图像3000帧但IMU只有几千帧说明驱动配置有问题重录比硬跑靠谱。更直观的方式是用rqt_bag或者直接写个Python脚本把IMU的角速度曲线画出来确认运动轨迹里确实有大幅度的角速度变化而不是像条直线一样平缓。曾经有一次我偷懒随便挥了几下录了2分钟结果标定出来的外参残差巨大浪费一下午排查最后重录一遍就好了。数据质量差后面所有努力都是白给。3. 相机内参标定3.1 为什么先单独标定相机内参网上有些人图省事直接用工厂标定的内参去做联合标定结果Kalibr收敛得很差。原因是相机内参的任何微小偏差都会在联合优化时被“分摊”到外参和IMU参数里导致所有的结果都不准。所以Kalibr的官方流程就是先单独标定相机内参把这个环节固定在最优值再去做IMU联合标定。D455的彩色相机使用的是RGB传感器内参模型一般用pinhole-equi或者pinhole-radtan。到底用哪个模型没有定论直接用Kalibr跑出来的结果里看哪个模型的残差小就选哪个。一般情况下D455的广角镜头用equidistant等距畸变模型效果更好但我实测过radtan也能用关键在于畸变系数不要出现特别离谱的大数值。3.2 相机内参标定的完整命令先写一个相机标定的topic配置文件告诉Kalibr订阅哪个图像话题cam0: topic: /camera/color/image_raw cam_model: pinhole-equi然后运行相机内参标定kalibr_calibrate_cameras --target /path/to/april_6x6_88mm.yaml --models pinhole-equi --topics /camera/color/image_raw --bag d455_calib.bag这一步会检测标定板角点并做内参优化整个过程几分钟。运行结束后会生成一个以日期命名的yaml文件里面就是相机内参结果。重点关注重投影误差正常情况应该小于0.5像素如果大于1像素检查图像清晰度和标定板尺寸配置。生成的yaml就是联合标定需要的内参文件但这个文件里畸变模型的关键字可能和联合标定要求的格式不完全一致需要稍微改一下。我的经验是直接把相机内参文件里的camera_model、intrinsics、distortion_coeffs复制到联合标定的camchain配置里确保模型命名字段一致就行。4. 相机IMU联合标定的完整流程4.1 IMU的噪声参数从哪里来联合标定还需要一个imu.yaml文件里面写IMU的噪声密度和随机游走等参数。很多新手在这里卡住不知道数值该填什么。这个参数其实可以从IMU芯片的数据手册查也可以先用经验值。D455内置的BMI055芯片可以参考博世官方datasheet里的参数Kalibr配置文件中一般需要给出以下四项imu0: update_rate: 200.0 accelerometer_noise_density: 0.0038 accelerometer_random_walk: 0.0003 gyroscope_noise_density: 0.0002 gyroscope_random_walk: 0.00002update_rate要和你录包时IMU的实际发布频率一致。如果你用rostopic hz /camera/imu查出来是400那这里就填400填错会导致后续优化时方程里的IMU测量数量对不上。这组参数不一定要非常精确Kalibr在优化过程中会把这些值作为先验权重。原则上噪声密度和随机游走的数量级对了就行精确值是标定完之后的结果里会重新给出的。所以你不用担心初始值不准导致失败真正导致失败的是数据质量差或者外参初始值错得太离谱。4.2 生成camchain配置并运行联合标定准备好三个文件相机内参yaml、imu.yaml、目标板yaml。然后运行kalibr_calibrate_imu_camera --bag d455_calib.bag --cam camchain.yaml --imu imu.yaml --target april_6x6_88mm.yaml --time-calibration--time-calibration参数一定要带上让Kalibr去估计图像和IMU之间的时间偏移。D455驱动虽然已经做了时间同步但实际仍然存在几个毫秒级别的偏差这个偏差对高动态标定影响很大必须要在优化里估计掉。整个联合标定运行时间较长数据量大的话可能需要10到20分钟。运行过程中Kalibr会经历多个阶段角点检测、IMU预积分、外参初始化、非线性优化。中间如果报错中断先别慌看一眼是哪个环节挂了绝大多数都能从下文的报错列表里找到答案。4.3 标定结果怎么解读运行完成后Kalibr会输出一系列文件camchain-imucam-d455_calib.yaml最终相机内参和相机到IMU的外参imu-imucam-d455_calib.yaml优化后的IMU噪声参数report-imucam-d455_calib.pdf标定报告PDF报告是判断标定质量的核心依据。重点看三张图相机重投影误差应围绕0值随机分布没有明显漂移、IMU残差应该是一条在0附近的噪声带没有大尖峰、以及运动轨迹可视化。在camchain文件里T_ci就是相机到IMU的外参变换矩阵。比如可以得到类似这样的结果T_ci: - [0.014, -0.999, 0.001, 0.021] - [0.999, 0.014, 0.000, -0.005] - [0.000, -0.004, -1.000, -0.018] - [0.0, 0.0, 0.0, 1.0]其中前面 3x3 是旋转矩阵第4列前三个元素是平移向量。看到这个平移向量的数值D455的相机坐标系和IMU光心之间确实有大概1到2厘米的偏移这符合硬件结构。5. 常见报错与排查实录我这一路下来把Kalibr联合标定过程中最常见的报错几乎都踩了一遍下面列出的都是真实出现过的、能让你原地卡一天的问题分类整理成速查表后面详细展开。报错类型典型特征常见原因环境类ModuleNotFoundError、command not found缺Python库、环境没source消息类bag file does not contain topics话题名写错、驱动没发IMU数据类ValueError、cannot reshapeIMU数据量不足、时间戳异常算法类优化发散、残差巨大内参没标准、动作激励不够资源类Segmentation fault、内存爆炸数据量过大、系统内存不足5.1 环境类报错No module named igraph或者No module named wx这是Kalibr最出名的报错之一。办法就是补装依赖pip install python-igraph sudo apt-get install python-wxgtk3.0Ubuntu 20.04以上可能没有wxgtk3.0的包可以改用pip install wxpython不过wxPython这货编译安装非常痛苦建议优先用apt装实在不行再折腾pip。kalibr_calibrate_imu_camera: command not found这个几乎都是因为忘了source工作空间。source ~/kalibr_workspace/devel/setup.bash或者干脆写进~/.bashrc省得每次新终端都要手动source。我早期就是经常忘了source一报这个错就怀疑是不是编译出问题了检查半天发现只是没source环境纯浪费时间。5.2 话题与数据类报错bag file does not contain these topics: /camera/color/image_raw, /camera/imu说明你录制的话题名和配置文件对不上。先看话题名再写配置不要凭记忆。我习惯用一条命令直接把需要的字段拉出来rosbag info d455_calib.bag | grep -E topic|/cameraValueError: cannot reshape array of size X into shape (N, 2)这个报错表面看是Python数组问题实际90%是IMU数据的时间同步出问题了。Kalibr在读取IMU数据时需要把IMU时间戳和图像时间戳进行对齐。如果IMU的话题里的时间戳跳变严重或者数据有大量重复值就会导致reshape失败。遇到这个报错先用rosbag工具检查IMU话题的时间戳是否有规律rostopic echo -b d455_calib.bag -p /camera/imu | head -20输出里如果时间戳出现明显跳跃或者乱序就要回炉重录。另外一个常见原因是IMU的发布频率设置得和imu.yaml里的update_rate不一致导致Kalibr初始化IMU数据序列的长度时对不上。cam0: Using message filter with target delay ...或者卡在角点检测阶段大概率是图像话题里有用时间戳和IMU时间戳不在同一个时钟域的情况。这种多数是驱动配置的问题回看启动时im数据是否正常更新必要时重新启动realsense节点。5.3 算法报错与标定发散标定结果出来了但外参里的旋转矩阵不是正交阵或者平移量是好几米这种明显不合理的数值这就是典型的标定发散。发散的最核心原因就是运动激励不足。我之前有一版数据集始终用相对缓慢的动作绕着一个轴转自认为拍够了2分钟结果标定出来的T_ci里平移量是1.8米。后来重录了一个大幅度、多方向动作的数据同一套参数跑出来就是正常的2厘米。这个教训非常深刻。还有一个小概率情况--time-calibration这一项不开启的时候如果真实的时间偏差比较大Kalibr也容易输出异常结果。建议一律开启时间标定。5.4 资源崩溃与卡死Segmentation fault (core dumped)。这类崩溃多发生在角点检测阶段尤其是数据量大、图像分辨率高的情况下。D455的彩色图是1280x720如果录包时间又长Kalibr在把所有图像一次性读入内存时直接爆掉。我的建议是录包时长控制在2到3分钟图像帧率用15到30Hz不要贪多。如果机器内存确实小可以用更低的图像帧率录制联合标定对图像帧率要求没有想象中高15Hz配200Hz的IMU同样能抖出不错的标定结果。Process crashed或者电脑直接卡死无响应多半是优化阶段矩阵维度过大。检查IMU数据时长过长的录制文件会生成超大协方差矩阵优化慢到怀疑人生。跑之前用free -h看看内存余量至少留4G以上空闲内存。6. 实操心得与后续使用建议6.1 怎么进一步提升标定精度我的经验是任何一次标定结果都不要直接用至少重复采集两组数据分别跑出结果然后对比外参的一致性。如果两组结果里平移量偏差在3毫米以内、旋转误差在0.5度左右那说明标定可信度较高。如果两组结果差很多那多半是其中一组数据有问题老老实实重录。另一个提升精度的小技巧是录包时先把标定板放在画面中央保持相机不动3秒然后开始运动。这个静止初始段能让IMU的重力方向初始化更准对后续优化很关键。6.2 标定结果怎么给VINS等算法用Kalibr输出的T_ci是“相机到IMU”的变换但很多VIO算法比如VINS-Fusion需要的是“IMU到相机”的变换即T_ic。直接用的时候别忘了求逆这个坑我见人踩过无数次。T_ic inv(T_ci)如果你的算法用的还是4元数格式把旋转矩阵转成四元数之后再填入配置。Kalibr输出的报告里也会有四元数形式直接用就可以。我通常会在标定完成后做一个快速验证把相机和IMU绑在手里在室内走一个小圈录一段数据喂给VINS-Fusion跑一次。如果起点和终点基本重合、地面没有明显翘曲那说明外参标定是靠谱的。如果轨迹发飘优先检查外参标定结果而不是怀疑SLAM算法本身。最后再说一个实用习惯标定数据、配置文件、输出结果一定要存放在同一个文件夹并且在文件名里备注日期和标定板尺寸。我见过太多人半年后想重新标定或排查问题时对着一堆没有标注的yaml和bag发呆完全想不起来当时用的是哪块板子、哪套参数。标注清晰能省下大量重复劳动。这套流程跑下来Kalibr也就那么回事关键是把每个环节都做扎实尤其是数据采集这部分投入再多时间都不冤枉。
返回列表