ARTICLE DETAIL

资讯详情

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

ROS2 Humble摄像头标定避坑指南:CALIBRATE不变绿与保存失败全解析

ROS2 Humble摄像头标定避坑指南:CALIBRATE不变绿与保存失败全解析 1. 摄像头标定到底在标什么为什么ROS2 Humble下格外容易翻车摄像头标定这件事说白了就是给相机配一副合适的眼镜。相机出厂时的镜头畸变、焦距、光心位置这些参数厂商给的标称值往往和实际有偏差尤其是那些几十块钱的USB摄像头或者广角镜头畸变能大到让直线看起来像香蕉。标定的目的就是通过拍摄一组已知图案通常是棋盘格或圆点板反推出相机的内参矩阵和畸变系数让后续的图像去畸变、测距、SLAM、三维重建这些活儿能算得准。在ROS2 Humble这个版本上做标定用的是camera_calibration这个功能包底层还是那套经典的张正友标定法。流程听起来不复杂启动标定节点、把棋盘格在相机前晃一晃、等CALIBRATE按钮变绿、点一下、保存。但真正上手你会发现从第一步开始就处处是坑。CALIBRATE按钮死活不变绿是最经典的好不容易变绿了点完保存又发现/tmp目录下空空如也或者保存出来的文件路径根本找不到。我前后在Humble上标过七八个不同型号的相机从普通的USB免驱摄像头到工业级的全局快门相机踩过的坑基本能凑齐一套标定错误大全。这篇就把这些错误按出现频率从高到低捋一遍每个问题都给出排查思路和具体操作尽量让你少走弯路。不管你是刚装完ROS2 Humble的新手还是从Foxy迁过来的老用户只要你在做摄像头标定这篇内容应该都能帮上忙。需要提前说明的是Humble和Foxy在标定这块的差异其实不大核心的camera_calibration包接口基本一致但Humble对Python版本3.10和某些依赖库的版本要求更严加上Ubuntu 22.04默认的Qt环境变化导致一些在Foxy上能跑通的命令在Humble上会报奇怪的错。这也是为什么很多人明明照着老教程做却卡在莫名其妙的地方。2. 标定前的环境准备与参数确认2.1 安装camera_calibration包的正确姿势很多人以为装了ROS2 Humble桌面版就自带标定工具其实不一定。camera_calibration属于image_pipeline的一部分桌面完整版desktop-full通常包含但如果你装的是ros-humble-desktop或者更精简的版本就需要单独装。sudo apt install ros-humble-camera-calibration sudo apt install ros-humble-camera-calibration-parsers sudo apt install ros-humble-image-proc装完之后验证一下ros2 pkg executables camera_calibration正常应该输出camera_calibration cameracalibrator。如果这条命令报package not found说明包没装上或者你的ROS2环境变量没source。这里有个新手常犯的错装了包但忘了source /opt/ros/humble/setup.bash然后到处找问题。建议直接把source写进~/.bashrc省得每次开终端都要手动敲。注意如果你用的是鱼香ROS的一键安装脚本它默认装的是desktop版本camera_calibration可能不在里面需要手动补装。别问我怎么知道的。2.2 棋盘格标定板的制作与尺寸测量标定板是标定的基准它的精度直接决定标定结果的可信度。常见做法是打印一张棋盘格A4纸贴在硬纸板上但这里有个致命细节你必须用尺子实际测量打印出来后每个格子的边长而不是用打印文件里标注的尺寸。原因很简单打印机在缩放、边距处理上会有偏差你告诉程序格子是25mm实际打印出来可能是24.3mm这个误差会直接传导到焦距计算里。我一般用游标卡尺量三个格子取平均精确到0.1mm。棋盘格参数在启动标定节点时通过--size和--square两个参数传入--size内部角点数量格式是列数x行数。注意是内部角点不是格子数。一个8x6的棋盘格8列6行格子内部角点是7x5。--square每个格子的实际边长单位米。ros2 run camera_calibration cameracalibrator \ --size 7x5 \ --square 0.025 \ --ros-args \ -r image:/camera/image_raw \ -r camera:/camera这里--size 7x5对应的是内部角点--square 0.025表示25mm。如果你把这两个搞反了或者角点数算错了标定节点要么找不到角点要么算出来的参数离谱。2.3 相机话题与QoS配置检查标定节点订阅的是图像话题默认是/camera/image_raw。但你的相机发布的话题名可能不一样比如/usb_cam/image_raw、/image_raw或者带命名空间的/my_camera/image_raw。先用ros2 topic list确认实际话题名再用-r image:实际话题名做重映射。更隐蔽的坑是QoS。ROS2默认的QoS是RELIABLE但很多相机驱动尤其是基于image_transport的发布图像时用的是SENSOR_DATAQoS也就是BEST_EFFORT。如果标定节点用RELIABLE去订阅一个BEST_EFFORT的话题QoS不兼容结果是订阅成功但一帧图像都收不到标定窗口一片漆黑。排查方法ros2 topic info /camera/image_raw --verbose看输出里的QoS Profile。如果是BEST_EFFORT你需要在启动标定节点时指定QoS或者临时把相机驱动的QoS改成RELIABLE。Humble下camera_calibration对QoS的处理比Foxy好一些但仍有概率出问题。我遇到过一次折腾了半小时才发现是QoS不匹配图像话题明明有数据标定窗口就是不出图。3. CALIBRATE按钮不变绿的六大原因逐个拆解这是被问得最多的问题没有之一。按钮不变绿本质上是标定节点认为当前采集到的样本还不够好不满足计算条件。它内部有几个硬性门槛任何一个不达标都会卡住。3.1 样本数量与姿态覆盖不足标定节点需要足够多的样本而且这些样本要覆盖不同的位置和角度。具体来说它要求X方向左右平移覆盖足够范围Y方向上下平移覆盖足够范围Size方向远近覆盖足够范围Skew方向倾斜角度覆盖足够范围标定窗口右侧有四个进度条分别对应这四个维度。只有当四个条都填满或者接近填满CALIBRATE才会变绿。很多人只在一个小范围内晃棋盘格X和Y填满了但Size和Skew一直是空的按钮自然不变绿。实操技巧把棋盘格拿到画面四个角各停一下再拿到画面中心远近各来一次最后把棋盘格倾斜成不同角度绕X轴、Y轴、Z轴都转一转。每个姿态保持静止一两秒让节点稳定采集。我一般会做20到30个有效姿态进度条基本就满了。3.2 棋盘格检测失败或角点识别不准如果棋盘格在画面里太小、太模糊、反光严重或者背景太杂乱标定节点可能检测不到角点。这时候你晃再多也没用因为根本没采集到有效样本。判断方法标定窗口里棋盘格上会叠加彩色角点标记。如果标记正常显示说明检测成功如果棋盘格上什么都没有或者标记乱跳说明检测有问题。常见原因和对策问题现象可能原因解决办法棋盘格上无角点标记格子太小或太模糊靠近相机或换更高分辨率角点标记跳动不稳光照不足或反光增加均匀照明避免直射反光只识别出部分角点棋盘格被遮挡或出画确保整个棋盘格完整在画面内角点标记错位棋盘格不平整贴在硬板上压平3.3 图像分辨率与话题类型不匹配标定节点对图像分辨率有隐含要求。如果分辨率太低比如320x240棋盘格角点检测精度不够样本质量差进度条很难填满。建议至少640x480有条件上1280x720。另一个坑是图像编码格式。标定节点期望的是mono8或bgr8。如果你的相机发布的是yuv422、rgb8或者压缩格式compressed标定节点可能无法正确处理。用ros2 topic echo /camera/image_raw --once看一下encoding字段不对的话在相机驱动里改或者加一个image_proc节点做转换。3.4 标定板参数与实际不符前面说过--size和--square要准确。如果--size写错了比如实际是7x5你写成8x6标定节点会一直试图找8x6的角点找不到就永远采集不到样本。这个错误很隐蔽因为窗口不会报错只是默默不工作。验证方法启动标定节点后看终端有没有输出类似[WARN] [xxx]: Unable to detect checkerboard的警告。如果有八成是参数错了。3.5 相机内参初值问题有些相机驱动会发布camera_info话题里面带有默认的内参。如果这些默认值偏差太大标定节点在计算时可能无法收敛导致按钮不变绿。这种情况在廉价USB摄像头上比较常见它们往往发布一个全零或者随便填的camera_info。解决办法在启动标定节点时加--no-service-check参数跳过服务检查或者临时把camera_info的发布关掉。不过更稳妥的做法是先用一个粗略的内参初值标定一次后再用结果更新。3.6 计算资源不足导致卡顿标定节点在后台做角点检测和优化计算如果CPU占用太高比如同时跑着Gazebo、RViz2、SLAM可能导致处理延迟进度条更新缓慢甚至卡死。我遇到过在虚拟机上标定按钮死活不变绿换到物理机上同样的操作几秒就绿了。排查用htop看一下CPU占用。如果标定节点所在的核心一直100%考虑关掉其他不相关的节点或者给标定节点设置更高的优先级。4. 保存文件找不到的排查与解决按钮终于变绿了点一下CALIBRATE等进度条走完再点SAVE然后……文件呢这是第二高频的问题。4.1 默认保存路径与文件命名规则camera_calibration默认把标定结果保存到/tmp目录下文件名格式是/tmp/calibrationdata.tar.gz对就是一个tar.gz压缩包不是直接的yaml文件。很多人去/tmp找yaml当然找不到。这个压缩包里包含ost.yaml左右相机如果是双目或单目的标定参数ost.txt同样内容的文本格式一堆left-xxx.png、right-xxx.png标定时采集的样本图像解压命令cd /tmp tar -xzvf calibrationdata.tar.gz解压后就能看到ost.yaml。这个文件才是你要的标定结果。4.2 权限问题导致保存失败/tmp目录一般都有写权限但如果你在Docker容器里跑标定或者/tmp被挂载成了只读保存就会静默失败。表现是点了SAVE按钮没反应终端也没有明显报错。排查手动测试/tmp是否可写touch /tmp/test_write echo OK rm /tmp/test_write如果这条命令失败说明/tmp不可写。解决办法是修改/tmp权限或者在启动标定节点前设置TMPDIR环境变量指向一个可写目录export TMPDIR/home/yourname/calib_tmp mkdir -p $TMPDIR然后重新启动标定节点保存的文件就会出现在$TMPDIR下。4.3 保存按钮点击时机与状态确认SAVE按钮只有在CALIBRATE完成之后才有效。如果你在标定计算还没结束时就点SAVE它不会做任何事。正确流程是四个进度条填满CALIBRATE变绿点击CALIBRATE等待下方出现标定结果重投影误差等数值确认结果合理后点击SAVE终端会输出保存路径如果点了SAVE终端没有任何输出说明保存没触发。检查一下是不是标定计算还没完成或者窗口焦点不在标定窗口上。4.4 标定结果质量判断与重投影误差保存之前强烈建议看一眼重投影误差Reprojection Error。这个值在标定完成后会显示在窗口下方。一般来说小于0.5像素优秀0.5到1.0像素可接受大于1.0像素建议重新标定误差大的原因通常是样本质量差、棋盘格不平整、或者姿态覆盖不够。别急着保存一个误差2.0的结果用这种参数做去畸变图像边缘会扭曲得亲妈都不认识。4.5 标定文件的后续使用与验证拿到ost.yaml后怎么用在ROS2里你可以把它作为camera_info的参数加载。常见做法是写一个launch文件用camera_info_manager加载这个yamlfrom launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( packageusb_cam, executableusb_cam_node_exe, parameters[{ camera_info_url: file:///home/yourname/calib/ost.yaml, video_device: /dev/video0, image_width: 640, image_height: 480, }] ) ])验证标定效果启动image_proc节点订阅去畸变后的图像话题/camera/image_rect看看直线是不是真的直了。如果边缘还有明显弯曲说明标定参数有问题回去重标。5. 常见问题速查表与独家避坑技巧5.1 问题速查表问题最可能原因快速排查命令/操作CALIBRATE不变绿姿态覆盖不足看四个进度条哪个没满CALIBRATE不变绿棋盘格检测失败看窗口里有无角点标记CALIBRATE不变绿参数size/square错误重新测量并核对图像窗口全黑QoS不匹配ros2 topic info --verbose图像窗口全黑话题名不对ros2 topic list保存后找不到文件默认存到/tmpls /tmp/calibrationdata.tar.gz保存失败/tmp不可写touch /tmp/test标定误差大棋盘格不平重新贴板压平标定误差大样本太少增加姿态到20去畸变效果差分辨率不匹配标定和运行时用同一分辨率5.2 独家避坑技巧技巧一标定前先录一段bag。与其在现场反复晃棋盘格不如先用ros2 bag record把图像话题录下来然后对着bag做标定。这样你可以反复回放慢慢调整姿态不用担心现场光线变化或者相机移动。回放命令ros2 bag play my_calib_bag --loop配合标定节点可以无限次重试效率高很多。技巧二用--no-service-check跳过服务检查。有些相机驱动不提供set_camera_info服务标定节点启动时会卡在服务检查上。加这个参数可以跳过ros2 run camera_calibration cameracalibrator \ --size 7x5 --square 0.025 --no-service-check \ --ros-args -r image:/camera/image_raw技巧三标定板背景要干净。棋盘格放在花床单、木纹桌面上角点检测容易受干扰。找一面白墙或者铺一张白纸做背景检测成功率会高很多。技巧四光照均匀比亮度重要。不要用单侧强光会产生阴影和反光。用两个灯从不同角度打光或者干脆在阴天的窗边做漫射光效果最好。技巧五保存后立刻备份。/tmp目录在系统重启后会被清空标定完第一时间把ost.yaml复制到你的工作空间里。我吃过这个亏标定了一下午重启后文件没了只能重来。技巧六Humble下用Python 3.10的注意点。如果你自己写标定相关的脚本注意Humble用的是Python 3.10某些老库可能不兼容。camera_calibration本身没问题但如果你要调用OpenCV做后续处理确保cv_bridge版本匹配。5.3 从Foxy迁移到Humble的标定差异如果你之前用Foxy迁到Humble后标定出问题重点检查这几处Qt版本Humble用Qt5Foxy也是Qt5但Humble的默认主题和字体渲染有变化标定窗口的按钮位置可能略有不同别点错了。QoS默认值Humble对QoS的默认处理更严格Foxy上能跑的RELIABLE订阅在Humble上可能失败。Python版本Foxy是3.8Humble是3.10如果你有自定义的标定脚本注意语法和库兼容性。launch文件格式Humble推荐用Python launchXML launch虽然还支持但某些新特性只在Python launch里有。6. 标定之后的验证与参数调优标定不是保存完yaml就结束了验证环节同样重要。我一般会做两步验证一是看去畸变后的图像二是用标定参数做一次实际测距看看误差是否在可接受范围。去畸变验证最简单启动image_proc对比原始图像和去畸变图像。找画面里明显的直线比如门框、桌边看它在去畸变后是不是变直了。如果边缘还有弯曲说明畸变系数没标好。测距验证稍微麻烦一点在相机前方放一个已知尺寸的物体比如A4纸297mm x 210mm用去畸变后的图像计算它的像素尺寸再根据焦距换算实际距离和卷尺量的值对比。误差在5%以内算合格。如果验证不通过别急着重新标定先检查这几个参数image_width和image_height是否和标定时一致camera_matrix里的焦距值是否合理一般在几百到几千像素之间distortion_coefficients是否在合理范围k1通常在-0.5到0.5之间调参是个细活有时候微调一下camera_info里的参数效果比重新标定还好。但前提是你得理解每个参数的含义别瞎调。最后分享一个我个人的习惯每次标定完把标定时的环境光照、分辨率、棋盘格参数、标定结果重投影误差、内参矩阵、验证结果去畸变效果、测距误差都记在一个文本文件里和yaml一起存档。下次再标同一个相机可以对比参考快速判断这次标定是否靠谱。这个习惯帮我省了很多重复劳动也让我对不同相机的标定特性有了更直观的认识。
返回列表