ARTICLE DETAIL

资讯详情

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

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

Kalibr联合标定Realsense D455相机与IMU完整实操指南 最近接手了一个带视觉惯性融合的机器人项目调试VINS-Fusion的时候被外参坑到怀疑人生——明明相机和IMU都是同一颗D455结果系统初始化反复飘后来才发现是标定环节偷懒了。做视觉SLAM、VIO或者多传感器融合定位的朋友应该都有体会相机和IMU之间的外参标定这一步绕不过去外参差一点后面的紧耦合优化、预积分全都会连锁出错。这篇我完整梳理一遍用Kalibr对Realsense D455做相机加IMU联合标定的实操流程包含环境配置、标定板生成、数据采集、两步标定命令解读和常见的报错解决直接照着抄就能跑通。在开始之前先说明一下整套流程我是在Ubuntu 20.04加ROS Noetic环境下实测完成的理论上18.04加Melodic也完全兼容。适合正在做VINS、ORB-SLAM3、FAST-LIVO这类视觉惯性系统的同学参考也适合刚入手D455想验证IMU精度的朋友。文章里所有命令和配置文件我都会贴出来并解释为什么这么写方便你理解之后按自己项目情况改。1. 联合标定到底在标什么为什么绕不过去1.1 相机内参、IMU内参和外参各自负责什么很多刚接触这个领域的朋友会把“标定”理解成一个笼统的动作觉得跑个工具输出个yaml文件就完事了。实际上联合标定至少包含三层含义。第一层是相机内参也就是针孔模型下的焦距fx、fy主点cx、cy以及畸变系数。D455的彩色相机视野不算特别广默认用radtan径向切向畸变模型就足够了。内参决定了像素坐标和相机坐标系下光线的对应关系如果内参不准哪怕外参再准整个投影残差也会很大。第二层是IMU内参包括加速度计和陀螺仪的尺度因子、安装误差、零偏以及噪声密度和随机游走。Kalibr的imu-cam标定流程里其实也会估计IMU的尺度误差和安装误差矩阵但前提是你至少给一个合理的初值。D455内部IMU的理论参数在官方手册里有但每颗芯片都有个体差异有条件的话先用imu_utils这类工具单独标定一下更好。第三层就是整个联合标定最核心的部分——相机和IMU之间的外参也就是从相机坐标系到IMU坐标系的旋转矩阵和平移向量通常写作r_ci和t_ci。外参的物理意义非常直观IMU测到的角速度和加速度要转换到相机坐标系下去和视觉特征形成约束如果这个变换错了等于一个系统里两套传感器在说两套语言融合结果自然发散。除了外参Kalibr还会估计一个时间偏移timeoffset用来补偿图像和IMU消息之间的时间戳对齐误差。1.2 为什么必须用数据驱动的方式标理论上外参可以通过机械图纸量出来但实际根本不可行。相机的光学中心和IMU的测量中心都不是可以直接用卡尺量到的物理点你得靠“看”和“感受”去反推它们之间的相对位置。人工量测误差动不动就是厘米级而视觉惯性系统的外参误差容忍度通常在毫米级和毫弧度级稍微差一点就会导致初始化失败或轨迹漂移。更重要的是随着设备温度变化、安装时轻微位移外参在每次重新安装之后都可能变化这意味着标定不是一劳永逸的而是跟着设备状态走的。所以一套可重复执行的标定工具链就是刚需。1.3 为什么选Kalibr这个方案标定工具箱其实不少OpenCalib、Aircraft、basalt这些也都能做但我最终选择Kalibr主要看中三点。第一是生态成熟Kalibr是苏黎世联邦理工ASL实验室开源的老牌工具从2013年左右开始维护积累了大量的使用案例和踩坑帖遇到问题搜索一下基本都有答案。第二是算法鲁棒Kalibr用Aprilgrid而不是普通棋盘格这种标签自带编码即使部分遮挡也能解算出ID意味着标定板边缘被切出画面也不会导致检测崩溃。第三是一站式解决Kalibr既能做单目、双目、多目相机内参标定也能做相机与多个IMU的外参联合标定虽然UI简陋、依赖老旧但在“把事办成”这件事上非常靠得住。对于D455这种内置IMU的消费级深度相机来说Kalibr完全够用不需要上工业级设备。2. 环境准备把Kalibr和Realsense D455跑起来2.1 系统依赖与Kalibr编译安装Kalibr目前官方支持ROS Melodic和Noetic两个版本我建议直接用NoeticPython3的支持更干净。系统装好Ubuntu 20.04和ROS Noetic之后先把依赖补齐再编译Kalibr。sudo apt update sudo apt install python3-catkin-tools python3-igraph python3-pip python3-scipy python3-numpy pip3 install pyyaml然后创建工作空间并克隆Kalibr源码mkdir -p ~/kalibr_ws/src cd ~/kalibr_ws/src git clone https://github.com/ethz-asl/kalibr.git cd ~/kalibr_ws catkin_make编译过程正常情况下几分钟完成如果遇到pip安装igraph速度很慢或者失败我踩过的一个坑是直接换用系统源指定的版本sudo apt install python3-igraph会比pip install更稳。还有个常见问题是Kalibr源码本身对numpy版本比较敏感Noetic环境下默认的numpy版本太高有可能会在运行时报ValueError或者类型转换错误。我的处理办法是给Kalibr单独建一个Python2/3兼容的虚拟环境或者在kalibr仓库里指定一个兼容版本的分支比如noetic分支。2.2 Realsense D455驱动安装与话题确认D455用的是Intel RealSense SDK也就是librealsense我们还要安装对应的ROS功能包realsense-ros。librealsense建议直接从Intel的apt源装这样固件升级和动态库都比较省心。sudo apt install ros-noetic-realsense2-camera装完驱动后启动相机节点时要注意默认launch不一定把IMU打开。realsense2-camera默认是会发布IMU话题的但需要确认一下。roslaunch realsense2_camera rs_camera.launch unite_imu_method:linear_interpolation加入unite_imu_method参数后驱动会额外发布一个融合后的/camera/imu话题这个参数含义是把IMU的角速度和线加速度做线性插值使消息时间戳更平滑。对于Kalibr来说这个选项很有帮助因为原始IMU话题时间戳偶尔会出现不小跳动。启动之后用工具确认话题状态这一步非常关键后面Kalibr只认bag里录制的话题名和频率rostopic hz /camera/color/image_raw rostopic hz /camera/imu正常情况下彩色图30FPSIMU 200Hz左右。如果你发现IMU频率只有100Hz别担心D455的IMU默认是200Hz但某些固件版本下需要手动在launch里加imu_framer_rate:200参数。提示录制bag之前一定要先确认图像和IMU的话题时间戳使用相同的时间基准。D455驱动发布的话题时间戳默认都是采集板时钟如果你之前在launch里加了external_cam之类的参数可能会导致时间错乱。2.3 常见坑LibRealSense与ROS包版本不匹配如果是自己编译安装的librealsense很容易出现realsense2_camera启动后报找不到固件或者驱动版本太旧的问题。我的建议是先运行realsense-viewer打开图形界面确认固件已经升级到最新再启动ROS节点。realsense-viewer里能看到IMU数据是否正常滚动这一步能过滤掉很大一部分硬件层面的问题。3. 标定板与数据采集决定成品的80%3.1 生成并打印Aprilgrid标定板Kalibr官方推荐使用Aprilgrid而不是传统棋盘格。棋盘格虽然也能检测但存在对称性问题会导致标定板方向判断模糊而Aprilgrid每个tag都有独一无二的编码甚至遮挡住一半也能恢复出完整位姿。生成标定板直接用Kalibr自带的命令kalibr_create_target_pdf --type apriltag --nx 6 --ny 6 --tsize 0.024 --tspace 0.3这几个参数的含义我需要额外解释一下。nx和ny是内部角点数量不是tag的数量比如6x6的tag网格内部有5x5个角点Kalibr会以tag之间的交点作为特征点。tsize是每个黑色方块的实际边长单位米这里0.024代表24mm。tspace是方块间距与边长的比值0.3表示间距是边长的30%这个值不能设太大因为标定板需要保持紧凑也不能太小否则tag间的边框信息不足。打印出来之后一定要用尺子量实际尺寸因为打印机的缩放比例不一定是100%。如果实测边长是23.5mm而非24mm就把yaml文件里的tagSize改成0.0235这个微小差异对内参影响不大但对联合标定中的外参平移误差影响不小。3.2 标定板target yaml文件的写法在运行标定命令之前需要手写一个描述标定板参数的yaml文件内容按实际标定板来填。target_type: aprilgrid tagCols: 6 tagRows: 6 tagSize: 0.024 tagSpacing: 0.3这和生成PDF时的参数一一对应。注意tagSize单位是米填错了整个标定结果会等比例错掉。3.3 数据采集动作规范与时长控制很多人标定失败的原因不在算法而在数据采集太随意。Kalibr对数据的运动激励有一定要求简单说就是让IMU充分感受到角速度和线加速度的变化让相机充分看到不同姿态下的标定板。录制的具体动作我总结了一套比较高效的模式。开始时让相机正对标定板保持静止半秒然后依次绕相机坐标系的X轴、Y轴、Z轴缓慢旋转旋转过程中手腕不要僵硬保持小幅度平移。每个轴旋转几轮之后再做一些“8”字形的摆动保证角速度和线加速度方向不断变化。整个动作持续120到180秒就足够太长的数据反而会导致优化时间过久。需要注意避免的几种情况纯旋转没有平移。相机在纯旋转运动下观测到的视差变化不够内参标定会退化外参标定也一样。动作太剧烈。D455的运动曝光模式下图像容易模糊Aprilgrid角点检测失败率会直线上升。宁可动作慢一点稳一点也不要甩来甩去。标定板太小或离得太远。标定板在画面中占比太低角点提取精度就会下降。我建议标定板宽度占到画面宽度的三分之一到二分之一。标定板超出画面。虽然有tag编码但大量角点丢失会让优化不稳定尽量保持标定板在画面内。3.4 固定曝光与图像参数设置D455的自动曝光在标定时必须关掉不然室内走动时亮度突变会导致部分帧的Aprilgrid检测失败。可以在launch里加参数也可以用dynamic_reconfigure在线设置rosrun dynamic_reconfigure dynparam set /camera/color exprosure 200 rosrun dynamic_reconfigure dynparam set /camera/color gain 100exposure的取值根据实际环境亮度调室内光源稳定时我一般取100到300。总之原则就是让画面亮度稳定、不过曝、不欠曝。录制bag的命令如下rosbag record -O d455_calib.bag /camera/color/image_raw /camera/imu录完以后顺手做一个检查确保bag里有图像有IMUrosbag info d455_calib.bag看到类似/camera/color/image_raw: 4000 messages和/camera/imu: 30000 messages就说明数据量是够的。3.5 采集过程中还有一个容易忽略的要点D455的彩色相机分辨率在标定的时候建议直接用1280x720不要为了省计算量降到640x480。因为内参标定依赖角点提取精度分辨率越低像素量化误差对重投影误差的影响越大。到了联合标定阶段如果嫌处理慢可以先用图像抽取工具对bag做减帧而不要降分辨率。4. 相机内参标定迈过第一道坎4.1 相机模型选择与launch参数解析在开始内参标定之前先明确一下使用的相机模型。Kalibr里最常用的两个是pinhole-radtan和pinhole-equi。radtan模型适合普通视角相机畸变被建模为径向畸变加切向畸变D455的彩色相机正好适用。如果用的是鱼眼镜头或者纯深度相机标定才需要考虑equi等全景模型。内参标定的命令格式如下kalibr_calibrate_cameras --target my_april.yaml \ --bag d455_calib.bag \ --topics /camera/color/image_raw \ --models pinhole-radtan \ --show-extraction--show-extraction参数会弹出一个窗口动态显示当前帧检测到的Aprilgrid角点建议第一次标定的时候打开看一眼。如果画面中大量帧显示提取失败就不要让命令继续跑下去了直接CtrlC终止改曝光或者换数据。命令跑完后会生成三个文件camchain-d455_calib.yaml包含相机模型的畸变系数和焦距等内参后续联合标定要直接用。result-cam-d455_calib.txt重投影误差统计。report-cam-d455_calib.pdf可视化报告。4.2 内参结果判读标准打开result-cam-d455_calib.txt重点关注重投影误差的均值。正常情况下所有角点的重投影误差均值应该小于0.3像素如果超过0.5像素就要怀疑数据质量了。我的个人标准是0.2以内优秀0.2到0.5能用大于0.5果断重录。重投影误差偏大的常见原因一是标定板不平整纸贴在硬纸板上有褶皱二是图像运动模糊降低了角点检测精度三是标定板距离相机太远角点定位精度下降。碰到误差大的情况优先检查这三个方向而不是去调Kalibr参数。4.3 内参标定的翻车点检测不到Aprilgrid最常见的报错是No valid tag found或者日志里出现大量Detection failed。先排查标定板参数是否正确再检查图像是否过曝。还有一个很多人不知道的点Aprilgrid对光照比较敏感如果标定板表面有反光白色区域和黑色区域对比度不足检测解码会失败。所以打印标定板尽量用哑光纸不要用光面铜版纸。4.4 内参标定的一个实用技巧kalibr_calibrate_cameras每次运行结果会有微小差异这是正常的。如果你希望结果更稳定可以一次性录制多条bag分别标定几次然后对比结果。如果几次标定出的焦距波动在0.2%以内说明标定置信度高。如果波动超过1%说明数据质量不行不是算法不稳定。5. 相机IMU联合标定核心实操5.1 编写IMU参数yaml文件联合标定需要两个输入文件一个是上一步内参标定生成的camchain-d455_calib.yaml另一个是描述IMU话题和噪声参数的yaml。下面是我在D455上使用的模板# d455_imu.yaml imu_topics: [/camera/imu] update_rate: 200 accelerometer_noise_density: 0.000467 accelerometer_random_walk: 0.00019 gyroscope_noise_density: 0.000237 gyroscope_random_walk: 0.000003update_rate必须和实际IMU发布频率一致建议用rostopic hz /camera/imu测一下再填。噪声密度和随机游走的初值可以先从D455官方手册或者imu_utils标定结果里取Kalibr在联合优化时会把它们作为先验如果数值差几个数量级会导致优化发散。我给的这组数值是从多块D455标定统计出来的常见范围如果你没有imu_utils的标定结果直接用这个作为初值问题不大。5.2 联合标定命令和参数详解一切准备就绪后运行核心命令kalibr_calibrate_imu_camera --target my_april.yaml \ --cam camchain-d455_calib.yaml \ --imu d455_imu.yaml \ --bag d455_calib.bag \ --max-iter 300参数含义如下--target标定板yaml。--cam相机内参标定结果。--imuIMU参数yaml。--bag数据bag。--max-iter最大迭代次数默认可能只有200数据质量好的话几十步就收敛了如果数据较差可以适当调大我一般给500。运行期间终端会输出每轮迭代的代价(cost)变化。正常情况cost应该单调下降并趋于平稳这个过程通常几分钟。如果cost在几百轮后还在剧烈震荡大概率是外参初值给得太差或者数据里的IMU噪声模型填得太离谱。5.3 联合标定结果文件解读运行结束后会生成camchain-imucam-d455_calib.yaml和report-imucam-d455_calib.pdf。打开yaml文件最核心的内容在camchain部分cam0: T_cam_imu: - [0.015, -0.999, -0.001, 0.014] - [0.999, 0.015, 0.001, -0.001] - [-0.001, 0.001, -0.999, -0.012] ... timeoffset: 0.0032这个T_cam_imu就是外参矩阵的前面几列旋转加平移4x4齐次变换矩阵。timeoffset单位是秒表示IMU时间戳相对于图像时间戳的偏移。D455的SDK内部已经做了同步timeoffset通常很小在毫秒量级但如果这个值超过10毫秒就要去检查ROS时间同步机制是否正常。注意T_cam_imu的含义是从IMU坐标系到相机坐标系的变换。用的时候要搞清楚你的VIO系统需要的是T_ic还是T_ciVINS-Fusion里读取的外参是T_ic也就是相机到IMU的变换需要在Kalibr输出结果的基础上取逆这个方向搞反了是新手最常见的错误之一。5.4 联合标定后如何快速验证标定结果不是拿到yaml文件就算完事我每次都会做一个快速验证。方法很简单把Kalibr输出的外参替换到VINS-Fusion或ORB-SLAM3的配置里然后跑一段之前录好的测试数据看系统能否正常初始化、位姿轨迹是否平滑。如果初始化阶段相机静止时IMU bias能快速收敛且在快速运动时定位没有明显漂移说明外参是可靠的。如果初始化一直失败先把外参方向调换一下再试。6. 高频报错与排查实录6.1 报错速查表下面是我和几个朋友在整套流程里遇到过的典型报错按现象、原因、解决方式整理成一张速查表。报错现象可能原因解决方式No valid tag found标定板检测失败检查曝光、标定板尺寸和表面反光降低动作速度Initialization failed数据激励不足或IMU噪声参数错误检查采集动作是否覆盖充分旋转检查imu.yaml噪声数量级ImportError: No module named igraph缺少Python依赖sudo apt install python3-igraph或pip install python-igraphThe relative pose cannot be determined标定板静止了太长时间增加平移和旋转幅度让相机持续运动std::bad_alloc或内存溢出bag数据量过大用rosbag filter按帧抽取减小bag体积No imu messages in bag录制时IMU话题没发布在launch中开启IMU相关参数确认rostopic hz有频率Topic not found话题名写错用rosbag info查看实际话题名cost持续震荡不收敛IMU内参初值和实际偏差太大用imu_utils先标定IMU内参更新噪声参数标定完成但重投影误差巨大标定板不平整或尺寸填错换硬板支撑标定板核对tagSize实测值内参结果每次漂移很大标定板占画面比例太小靠近标定板增大目标占比6.2 报错排查思路先检查数据再检查参数很多人一看到Kalibr报错就到处改参数我不建议这么做。Kalibr的算法本身经过充分验证绝大多数报错的根源在输入数据而不是参数。排查顺序我建议固定成这样先用rosbag info确认话题名、消息数量、时长。用rqt_bag或者Python脚本抽取几帧图像肉眼确认标定板清晰可见。打开IMU话题画出角速度和加速度曲线确认没有长时间零值或者突跳。再回到yaml参数从target尺寸、噪声参数开始核对。6.3 内存不足导致std::bad_alloc的处理彩色720P视频录制两三分钟bag文件可能达到几百MB甚至上GBKalibr读入bag后要建立视觉特征轨迹和IMU样条内存占用会翻好几倍。8GB内存的笔记本在标定过程中容易直接崩溃。我的做法是先用rosbag filter把bag拆短保留中间运动最充分的一段60到90秒已经足够标定。也完全可以降低图像帧率到15Hz再标定代价只是角点观测数量少一些。rosbag filter d455_calib.bag d455_short.bag t.to_sec() 30.0 and t.to_sec() 120.06.4 时间戳同步和timeoffset异常有时候联合标定跑完其他结果都正常唯独timeoffset估算出来是几十毫秒甚至几百毫秒这就是在提醒你数据时间基准出问题了。D455驱动虽然自带时间同步但如果你在launch中启用了多个realsense相机或者使用了网络时钟同步时间戳可能会出现偏移。解决方法是检查rostopic hz输出里的时间戳稳定度还不行就换一台没有外接PTP等时钟服务的机器重录。卡尔曼滤波。标定本身是个一次性投入但回报是长期的定位精度稳定性。如果你标完一次之后发现系统还是容易飘不用急着怀疑算法回头看看本文提到的这几个检查点多半是数据采集环节埋了雷。
返回列表