ROS摄像头标定实战:Ubuntu20.04下从原理到精度的完整指南
1. 项目概述与核心价值
最近在折腾一个基于ROS的移动机器人项目,核心的视觉导航模块死活调不准,建图总是有漂移。排查了一圈,最后发现问题的根源出在摄像头标定上——内参矩阵的几个像素误差,在几米外的距离上被放大成了十几厘米的定位偏差。这让我重新审视了“Ubuntu20.04在ROS中使用摄像头标定”这个看似基础,实则至关重要的环节。很多朋友,尤其是刚接触ROS和机器视觉的新手,容易把标定当作一个“一次性”的、按教程走完流程就完事的任务。但实际上,标定的精度直接决定了你后续所有视觉算法(如SLAM、目标检测、三维重建)的上限。一个粗糙的标定结果,会让再高级的算法都像是在沙地上盖楼。
这个项目标题看似简单,但它串联起了Ubuntu20.04系统环境、ROS(Robot Operating System)框架、摄像头驱动、标定工具链以及最终的参数应用,是一个典型的机器人感知层基础工程。无论你是做机械臂的视觉引导、无人车的避障,还是服务机器人的交互,只要用到摄像头,标定就是绕不开的第一步。而且,在Ubuntu20.04这个长期支持版(LTS)与ROS Noetic这个“最后一代ROS1”的经典组合下,这个过程既有成熟的方案,也藏着一些版本适配的“坑”。接下来,我就结合自己多次实操的经验,从环境准备、原理理解、实操步骤到避坑指南,完整地拆解一遍,目标是让你不仅能“跑通”流程,更能“吃透”每一个参数背后的意义,拿到一份可靠的内外参。
2. 环境准备与工具链解析
工欲善其事,必先利其器。在Ubuntu20.04上进行ROS摄像头标定,整个工具链的搭建和选择是关键。这里我们主要针对ROS Noetic版本。
2.1 系统与ROS基础环境
首先确保你的Ubuntu20.04系统已经安装了ROS Noetic Desktop-Full版本。这是最省心的选择,包含了我们后续需要的几乎所有可视化工具和基础功能包。如果你之前安装的是更精简的版本,可能需要手动补一些包。
安装完成后,一个必做的动作是初始化rosdep。很多依赖问题都出在这里。打开终端,依次执行:
sudo rosdep init rosdep update这个步骤会为系统安装ROS包所需的系统依赖定义,后续在安装一些摄像头驱动或标定包时,它能自动帮你解决libxxx-dev之类的依赖缺失问题。
2.2 摄像头驱动与接口选择
这是第一个容易卡住的地方。你的摄像头能否被ROS识别并发布图像话题,完全取决于驱动。市面上摄像头主要分两大类:
USB摄像头(如普通的网络摄像头、罗技C920等):这是最常用的。在ROS中,标准驱动包是
usb_cam。你可以通过以下命令安装:sudo apt-get install ros-noetic-usb-cam安装后,驱动节点会将摄像头数据发布到
/usb_cam/image_raw等话题上。这个包的优点是稳定、简单,但功能相对基础,一些高级参数(如曝光、白平衡)可能需要通过v4l2-ctl命令行工具调节。工业相机或特定品牌相机(如Intel Realsense, ZED, 海康威视等):这类相机通常有厂商提供的专用ROS驱动包。例如,对于Intel Realsense D435i,你需要安装
librealsense2和ros-noetic-realsense2-camera包。这类驱动的功能更强大,可以直接在ROS参数服务器中设置相机参数,并且通常支持点云、IMU等更多数据流。
选择建议:对于学习和大多数移动机器人应用,一个普通的USB摄像头完全足够。优先选择免驱、支持UVC协议的型号,兼容性最好。在购买或选用前,可以插上Ubuntu试试,用cheese或guvcview这类图形化工具能正常打开,那么在ROS里大概率也没问题。
2.3 标定工具包:camera_calibration
ROS官方提供的标定工具是camera_calibration包。它本质上是一个Python脚本,配合一个图形化界面(GUI),通过识别棋盘格图案来自动计算相机内参和畸变系数。
在ROS Noetic中,它通常已经随Desktop-Full版本安装了。如果没有,可以通过以下命令安装:
sudo apt-get install ros-noetic-camera-calibration这个包是我们本次标定的核心。它的工作原理是:你手持一个打印的棋盘格标定板(Checkerboard)在相机前移动、旋转,GUI界面会实时检测角点并采集数据。采集足够多(通常建议50-100张)不同位置、不同姿态的图片后,工具会利用这些二维图像点与三维世界点(已知的棋盘格物理尺寸)的对应关系,通过张正友标定法等算法,解算出相机的5个内参(fx, fy, cx, cy, skew)和5个畸变系数(k1, k2, p1, p2, k3)。
注意:
camera_calibration包主要针对单目普通相机(Monocular)。如果你使用的是双目相机或RGB-D相机(如Realsense),标定流程和工具会有所不同,通常涉及双目标定(Stereo Calibration)和深度标定,需要用到camera_calibration的扩展功能或其他专用包(如kalibr用于高精度多传感器标定)。
3. 标定前关键准备:棋盘格与话题验证
在启动标定程序前,有两件至关重要的事情需要准备妥当:一是棋盘格标定板,二是确保相机图像话题能被正确订阅。
3.1 棋盘格标定板的制作与参数
标定板是标定的尺子,它的精度直接影响结果。camera_calibration包默认使用棋盘格(Checkerboard)图案。
生成与打印:你可以在网上搜索“棋盘格标定板生成器”,或者使用ROS自带的工具。但更推荐自己用代码(如OpenCV)生成一个高精度的PDF。关键参数有两个:
- 方格数量(size):指的是内部角点的数量。例如,一个8x6的棋盘格,指的是内部有8列、6行黑色方格的交点,所以角点数是7x5(因为边缘的角点不算内部角点)。在启动标定程序时,你需要输入的是内部角点数,比如
7x5。 - 方格尺寸(square):指每个黑色或白色方格的实际物理边长,单位是米。常用的是0.024米(24毫米)或0.03米(30毫米)。这个值必须精确测量,最好用游标卡尺测量打印出来后的实际尺寸,而不是直接用设计尺寸,因为打印可能存在缩放。
一个简单的OpenCV生成脚本示例:
import cv2 import numpy as np # 定义参数 squares_x = 7 # 内部角点列数 squares_y = 5 # 内部角点行数 square_size = 0.024 # 单位:米 dpi = 300 # 打印DPI margin = 20 # 边缘留白(像素) # 计算图像尺寸(每个方格像素数 = 英寸每米 * 米每格 * DPI) inch_per_meter = 39.3701 pixels_per_square = int(square_size * inch_per_meter * dpi) width_px = squares_x * pixels_per_square + 2 * margin height_px = squares_y * pixels_per_square + 2 * margin # 创建白色画布 board = np.ones((height_px, width_px), dtype=np.uint8) * 255 # 绘制棋盘格 for i in range(squares_y + 1): # 需要画方格,所以是+1 for j in range(squares_x + 1): if (i + j) % 2 == 0: start_x = margin + j * pixels_per_square start_y = margin + i * pixels_per_square end_x = start_x + pixels_per_square end_y = start_y + pixels_per_square board[start_y:end_y, start_x:end_x] = 0 # 保存 cv2.imwrite('checkerboard_7x5_24mm.png', board)将生成的PNG打印在硬质、平整、无反光的材料上,如相纸或亚光覆膜的卡纸。贴在硬板(如亚克力板)上效果更佳,可以防止弯曲。
- 方格数量(size):指的是内部角点的数量。例如,一个8x6的棋盘格,指的是内部有8列、6行黑色方格的交点,所以角点数是7x5(因为边缘的角点不算内部角点)。在启动标定程序时,你需要输入的是内部角点数,比如
使用建议:
- 确保棋盘格平整,拍摄时不要有褶皱或反光。
- 棋盘格区域要充满相机视野的1/3到1/2,并且要在视野的不同位置(中心、四角、边缘)和不同姿态(平面倾斜、旋转)进行拍摄。
- 光照要均匀,避免阴影覆盖角点。
3.2 摄像头话题验证与驱动启动
在开始标定前,必须确保相机驱动已经正确运行,并且发布了标定工具所需的话题。
启动摄像头驱动:
- 对于
usb_cam,启动命令如下:
默认会发布roslaunch usb_cam usb_cam-test.launch/usb_cam/image_raw话题。你可以通过rqt_image_view来查看图像是否正常。 - 对于其他相机,请参考对应驱动的启动方式,例如Realsense可能是
roslaunch realsense2_camera rs_camera.launch。
- 对于
检查话题与图像信息: 打开一个新终端,使用
rostopic list查看当前发布的话题列表。你应该能找到类似/camera/image_raw或/usb_cam/image_raw的话题。 进一步,使用rostopic echo /usb_cam/image_raw/header(请替换为你的实际话题名)可以快速查看图像的帧率、时间戳等信息。更重要的,使用rostopic hz /usb_cam/image_raw可以查看图像发布的实际频率。标定过程中,稳定的帧率(如30Hz)比超高帧率更重要,太高的帧率可能导致采集的图像序列变化太小,不利于标定。验证图像编码: 标定工具
camera_calibration默认订阅的话题类型是sensor_msgs/Image。你需要确认你的摄像头驱动发布的是否是原始(raw)或压缩(compressed)图像。通常,usb_cam发布的image_raw是原始Bayer格式或RGB格式,这需要与相机本身的传感器输出匹配。一个常见的错误是,驱动发布了image_raw,但它的编码(encoding)是yuv422或bgr8,而标定工具可能对bgr8或rgb8支持最好。如果标定工具无法识别图像,可以在启动驱动时尝试设置参数,例如对于usb_cam,可以在launch文件中设置pixel_format为yuyv或mjpeg,并确保image_raw的编码是标定工具可读的。
4. 标定实操流程与参数采集
当环境、标定板和摄像头都准备好后,我们就可以开始正式的标定流程了。这个过程是交互式的,需要人工配合。
4.1 启动标定节点与GUI
标定需要启动两个核心部分:标定节点和校准GUI。最方便的方式是使用一个launch文件,但为了理解过程,我们分步进行。
首先,在一个终端中启动你的摄像头驱动,确保图像话题正常发布。假设话题名为/usb_cam/image_raw。
然后,打开第二个终端,启动标定节点。命令格式如下:
rosrun camera_calibration cameracalibrator.py \ --size 7x5 \ # 内部角点尺寸,根据你的棋盘格填写 --square 0.024 \ # 方格物理边长,单位:米 image:=/usb_cam/image_raw \ # 图像话题名 camera:=/usb_cam # 相机命名空间,用于存储标定结果执行这条命令后,会弹出一个图形化窗口。窗口左侧是相机实时画面,右侧是标定控制面板。
4.2 数据采集技巧与界面解读
GUI界面右侧有四个条形指示器:X,Y,Size,Skew。它们代表了当前采集到的数据在哪些维度上是丰富的。
- X:表示棋盘格在图像水平方向上的移动范围。
- Y:表示棋盘格在图像垂直方向上的移动范围。
- Size:表示棋盘格在图像中的远近(尺度)变化范围。
- Skew:表示棋盘格的倾斜(非共面旋转)程度。
你的目标就是通过移动棋盘格,让这四个条形都变成绿色。当数据足够时,右下角的CALIBRATE按钮会从灰色变为可点击状态。
采集数据时的实操技巧:
- 慢速平稳移动:手持标定板,在相机前缓慢、平稳地移动和旋转。避免快速晃动,否则图像模糊会导致角点检测失败。
- 覆盖整个视野:将棋盘格移动到画面的左上、右上、左下、右下四个角落,并确保整个棋盘格都在视野内。
- 变化距离和角度:将棋盘格靠近摄像头(填满画面)和远离摄像头(只占画面一小部分)。同时,不仅绕X、Y轴旋转(像翻书一样),也要绕Z轴旋转(像转方向盘一样),并尝试一些非对称的倾斜姿态,以充分激发
Skew维度。 - 观察角点检测:在GUI的实时画面上,当棋盘格被成功识别时,会在每个内部角点处画出一个彩色圆圈,并且角点之间会用线连接起来。确保所有预期的内部角点都被正确检测到。如果某个角点没被识别,可能是光照不均、棋盘格不平整、或者部分角点出了画面。
- 采集数量:通常每个姿态稳定停留1-2秒,工具会自动采集多帧。总共采集50-100组有效数据(即右侧
Images计数器)后,各个条形应该会变绿或接近全绿。数据并非越多越好,关键是姿态的多样性和覆盖度。
4.3 计算与保存标定结果
当X,Y,Size,Skew四个条形都变绿后,点击CALIBRATE按钮。此时程序会开始计算,界面可能会卡住几秒到几十秒(取决于数据量和电脑性能),这是正常的。
计算完成后,右侧面板下方会出现SAVE和COMMIT两个按钮。
SAVE:将标定结果保存到本地磁盘。默认会保存到/tmp/calibrationdata.tar.gz这个压缩包中。这个压缩包内包含了所有用于标定的原始图像、角点数据,以及一个名为ost.yaml或ost.txt的标定结果文件。务必点击SAVE进行备份!COMMIT:将标定结果(一个yaml文件)保存到ROS参数服务器,并写入相机驱动指定的默认路径(通常是~/.ros/camera_info/目录下)。这个操作会将标定参数与相机的唯一标识(通过camera_info_url机制)绑定,以后每次启动该相机节点时,会自动加载这些参数。
重要操作顺序:建议先点击SAVE备份原始数据,然后再点击COMMIT。点击COMMIT后,你可以关闭标定窗口。
5. 标定结果解析与应用
标定完成后,我们得到了一个YAML文件。理解这个文件里的每一个参数,比单纯完成标定更重要。
5.1 标定文件参数详解
我们打开COMMIT后生成的文件(通常位于~/.ros/camera_info/,以相机名命名,如usb_cam.yaml),会看到类似以下内容:
image_width: 640 image_height: 480 camera_name: usb_cam camera_matrix: rows: 3 cols: 3 data: [fx, 0, cx, 0, fy, cy, 0, 0, 1] distortion_model: plumb_bob distortion_coefficients: rows: 1 cols: 5 data: [k1, k2, p1, p2, k3] rectification_matrix: rows: 3 cols: 3 data: [1, 0, 0, 0, 1, 0, 0, 0, 1] projection_matrix: rows: 3 cols: 4 data: [fx, 0, cx, 0, 0, fy, cy, 0, 0, 0, 1, 0]camera_matrix(内参矩阵 K):fx,fy:相机在x和y方向上的焦距,单位是像素。这两个值理论上应该接近,如果相差很大(比如超过10%),可能标定板移动不够充分或图像存在严重非线性畸变。cx,cy:主点坐标,即光心在图像像素坐标系中的位置,理想情况应在图像中心(width/2, height/2)附近。如果偏离中心很远,需要检查标定过程。
distortion_coefficients(畸变系数):k1,k2,k3:径向畸变系数。普通镜头通常k1为负值(桶形畸变),k2,k3较小。鱼眼镜头这些值会很大。p1,p2:切向畸变系数。通常由镜头安装与传感器不平行导致,值一般很小。distortion_model: plumb_bob:这是ROS常用的畸变模型,即“布朗-康拉德”模型,适用于大多数普通针孔相机。
rectification_matrix(矫正矩阵):对于单目相机,这通常是一个单位矩阵,在立体标定中才有实际意义。projection_matrix(投影矩阵):由内参矩阵扩展而来,用于将三维点投影到二维图像,在单目情况下,其前三列与内参矩阵相同。
5.2 标定结果验证与可视化
拿到参数后,不能直接相信,必须进行验证。
重投影误差(Reprojection Error):在标定GUI点击
CALIBRATE后,终端会输出平均重投影误差,单位是像素。这个值是衡量标定精度的黄金标准。一般来说,误差小于0.5像素说明标定非常优秀,在0.5-1.0像素之间可以接受,大于1.0像素则需要考虑重新标定或检查标定板、拍摄过程。误差过大的常见原因是标定板不平、角点检测不准或数据姿态不够丰富。使用
image_proc节点进行实时去畸变验证:这是最直观的验证方法。image_proc是image_pipeline包中的一个节点,可以实时应用标定参数对图像进行去畸变处理。- 首先确保已安装:
sudo apt-get install ros-noetic-image-proc - 启动摄像头驱动(确保已
COMMIT标定参数)。 - 在一个新终端运行:
ROS_NAMESPACE=usb_cam rosrun image_proc image_proc。这个命令会在/usb_cam命名空间下启动image_proc节点。 - 现在,除了原始的
/usb_cam/image_raw话题,还会出现一个新的话题/usb_cam/image_rect。使用rqt_image_view订阅这个话题。 - 观察
image_rect图像。找一些直线物体(如门框、桌子边缘)放在画面边缘。在原始图像中,这些直线可能会因为畸变而弯曲。在矫正后的图像中,它们应该变得笔直。这是检验畸变系数是否正确的直接方法。
- 首先确保已安装:
在RViz中可视化:你可以在RViz中添加一个
Camera显示类型,将Image Topic设置为/usb_cam/image_rect。如果标定正确,你看到的画面应该是去畸变后的。同时,可以观察图像坐标系下的网格是否横平竖直。
6. 常见问题排查与深度优化
在实际操作中,你几乎一定会遇到一些问题。这里汇总了最常见的“坑”及其解决方案。
6.1 标定过程中的典型故障
GUI无法启动或闪退:
- 可能原因:缺少Python图形库依赖。尝试安装:
sudo apt-get install python3-tk python3-pil.imagetk。 - 可能原因:图像话题不存在或话题类型不对。使用
rostopic list和rostopic type /your_image_topic确认话题存在且类型为sensor_msgs/Image。
- 可能原因:缺少Python图形库依赖。尝试安装:
棋盘格角点无法检测(没有彩色圆圈):
- 检查棋盘格参数:
--size参数输入的是内部角点数,不是方格数。一个8x6的棋盘格,内部角点是7x5。 - 检查图像话题:确保GUI订阅的话题名正确,且图像正在正常发布。可以用
rqt_image_view先看看画面。 - 改善拍摄条件:确保光照充足均匀,棋盘格平整且完全在视野内,避免反光和阴影。尝试调整相机焦距(如果是可变焦镜头),让棋盘格线条清晰。
- 尝试单色通道:有时彩色图像干扰角点检测。可以在启动摄像头驱动时,尝试发布灰度图像。对于
usb_cam,可以在launch文件中设置pixel_format为gray或yuyv,并确保image_raw的编码是mono8。
- 检查棋盘格参数:
标定条形(X, Y, Size, Skew)迟迟不变绿:
- 姿态不够丰富:这是最常见原因。你需要在三维空间内大幅度移动和旋转棋盘格,特别是绕光轴(Z轴)旋转和大幅度的倾斜(Skew),这两个姿态最难采集。尝试将棋盘格几乎侧对摄像头。
- 数据质量差:虽然采集了很多张,但可能很多张的角点检测不准(圆圈闪烁或位置跳动),这些数据会被算法自动剔除。确保每次采集时,所有角点都稳定、清晰地被识别。
点击
CALIBRATE后程序卡死或报错:- 数据量太少或质量太差:算法无法收敛。回到上一步,采集更多样化的高质量数据。
- 内存不足:如果采集了非常大量的高分辨率图像,可能导致内存不足。可以尝试先
SAVE,然后重启标定程序,用--load参数加载之前保存的数据文件进行标定。
6.2 标定结果不理想的优化策略
重投影误差过大(>1像素):
- 重新测量方格尺寸:用更精确的游标卡尺测量打印后棋盘格的实际方格尺寸,并更新到
--square参数中。这是最常见的误差来源。 - 检查标定板平整度:将标定板贴在更硬的基板上,确保拍摄时绝对平整。
- 剔除异常数据:在采集过程中,如果某些帧的角点检测明显有偏移(比如圆圈没对准交点),可以在采集后、计算前,在GUI中通过点击某张缩略图来删除该组数据。
- 使用更大的棋盘格或更多角点:更多的角点可以提供更多的约束方程,理论上可以提高标定精度。可以尝试9x7或10x8的棋盘格。
- 重新测量方格尺寸:用更精确的游标卡尺测量打印后棋盘格的实际方格尺寸,并更新到
内参(fx, fy)不合理:
- fx和fy相差悬殊:这通常意味着在X和Y方向采集的数据不均衡。例如,只做了水平移动,没有做垂直移动。确保
X和Y条形都变绿。 - 焦距值异常:根据公式
fx = F / dx,其中F是物理焦距,dx是像元尺寸。对于一款已知摄像头,可以估算其焦距像素值的大致范围。如果计算出的fx远大于图像宽度,那肯定是错误的。
- fx和fy相差悬殊:这通常意味着在X和Y方向采集的数据不均衡。例如,只做了水平移动,没有做垂直移动。确保
主点(cx, cy)偏离图像中心过远:
- 理想情况下,主点应在图像中心。如果偏离超过图像尺寸的10%,可能需要检查相机传感器的安装是否居中,或者标定过程是否存在系统误差。有时,相机自身的数字校正(如电子防抖)也会影响主点。可以尝试在相机驱动中关闭所有数字增强功能(如自动对焦、数码变焦、图像稳定等)后重新标定。
6.3 标定参数的持久化与使用
成功标定并COMMIT后,ROS的相机驱动会在启动时自动从~/.ros/camera_info/目录下寻找对应的标定文件。为了确保万无一失,建议:
- 手动备份:将生成的
yaml文件复制到你的项目目录中,例如~/catkin_ws/src/your_project/config/。 - 在Launch文件中显式指定:在启动相机节点的launch文件里,显式设置
camera_info_url参数,指向你的标定文件。这样即使换了电脑或环境,也能确保加载正确的参数。<launch> <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen"> <param name="video_device" value="/dev/video0" /> <param name="image_width" value="640" /> <param name="image_height" value="480" /> <!-- 关键:指定标定文件路径 --> <param name="camera_info_url" value="file://$(find your_project)/config/usb_cam.yaml" /> </node> </launch> - 在代码中加载:在你的ROS节点(C++或Python)中,可以使用
camera_info_manager来加载标定信息,或者直接使用sensor_msgs/CameraInfo消息,该消息会自动从参数服务器加载。
7. 进阶话题:从标定到实际应用
完成一次精准的标定只是第一步。在实际的机器人项目中,如何管理和使用这些参数,同样充满挑战。
7.1 多相机与传感器联合标定
如果你的机器人上有多个摄像头(比如双目、前视+后视),或者摄像头与激光雷达、IMU等其他传感器需要融合,就需要进行联合标定。
- 双目相机标定:除了各自的内参和畸变,还需要标定出两个相机之间的旋转矩阵和平移向量(外参)。ROS的
camera_calibration包也支持双目模式,需要同时订阅左右目的图像话题。标定结果会额外给出rotation和translation矩阵。这个外参的精度直接影响立体匹配和深度计算的准确性。 - 相机-激光雷达(Camera-LiDAR)标定:这是一个更复杂的问题。你需要找到一个同时能被相机和激光雷达观测到的标定物(如带有特定图案的木板、ArUco码板等)。通过提取标定物在图像中的像素坐标和在点云中的三维坐标,来求解两者之间的变换矩阵。常用的工具有
autoware的calibration_toolkit或lidar_camera_calibration等。 - 相机-IMU标定:对于VIO(视觉惯性里程计)应用,需要标定相机和IMU之间的时间戳延迟(time offset)以及空间变换。这是一个非常专业的领域,通常使用
kalibr这样的高精度标定工具箱。
7.2 标定参数的在线标定与自适应
在长期运行的机器人上,相机可能会因为震动、温度变化或机械结构松动而导致内参发生微小变化(称为内参漂移)。对于高精度应用,需要考虑在线标定或自适应方法。
- 基于自然特征的标定:利用环境中稳定的自然特征点(如墙角、窗框),在机器人运行过程中持续跟踪,并以此反推相机参数的变化。这属于SLAM(同步定位与建图)研究的前沿领域。
- 使用主动标定板:在机器人工作环境中固定放置一个高精度的标定板(如高精度打印的棋盘格或LED点阵板),机器人定期“看”一眼这个板子,自动完成标定参数的重计算和更新。这种方法简单可靠,适用于结构化环境。
7.3 标定流程的自动化脚本
对于需要频繁标定或批量处理多个相机的团队,手动操作GUI效率太低。你可以将上述流程脚本化。
核心思路是:使用camera_calibration包的Python API(即cameracalibrator.py脚本背后的模块),或者直接调用OpenCV的calibrateCamera函数,编写一个自动采集图像、检测角点、计算参数的脚本。你可以设定一个固定的动作序列(如让机械臂手持标定板移动到预设位置),实现全自动标定。这不仅能提高效率,还能减少人为操作引入的误差,保证标定过程的一致性。
一个简单的自动化思路是:订阅图像话题,使用OpenCV的findChessboardCorners函数实时检测角点。当检测到角点且棋盘格姿态符合预设条件(如位于视野某区域、倾斜角度在范围内)时,自动保存该帧图像和角点数据。采集足够数量后,调用calibrateCamera函数计算参数,并自动保存结果文件。这个脚本可以集成到你的机器人启动或维护流程中。