眼在手上的九点标定初学者教程
时间: 2025-07-28 09:10:50 浏览: 16
<think>我们正在处理一个关于"眼在手上的九点标定"的新手入门教程请求。根据引用[1]和[2],九点标定本质上是仿射变换,用于坐标系转换,并且最少需要三个不在同一直线上的点,而九点标定可以拟合以减少畸变误差。用户需求:针对初学者的教程,涉及眼与手协作(即眼在手上)的校准方法。教程结构:1.介绍九点标定的基本概念和应用场景(眼在手上系统)。2.准备工作(硬件和软件环境)。3.详细步骤(包括如何取点,如何计算变换矩阵)。4.验证标定结果。5.常见问题及解决方法。注意:根据引用[1],要使用平面几何知识,并动手实践。因此,教程中要强调动手操作和数学原理的结合。由于是新手教程,避免复杂数学推导,但必须的关键公式使用LaTeX格式。步骤:1.理解眼在手上系统:相机安装在机械臂末端(手部),通过相机看到的物体位置需要转换到机械臂的基坐标系。2.标定板准备:通常使用带有9个特征点(如圆点)的标定板,这些点位置已知(在标定板坐标系中)。3.机械臂移动到9个不同位置(每个位置使标定板在相机视野内),记录每个位置下:a.机械臂末端在基坐标系中的位姿(X,Y,Z,Rx,Ry,Rz)。b.相机拍摄标定板,并提取9个点在图像坐标系中的像素坐标。4.计算每个位置下,标定板上的一个参考点(比如中心点)在基坐标系中的位置(通过机械臂位姿和标定板与末端的关系计算,但这里我们通常使用标定板上的点与机械臂末端的关系是固定的,所以需要先确定标定板相对于机械臂末端的位置?实际上,在眼在手上系统中,标定板是固定在工作台上的,而机械臂带着相机运动。因此,我们记录的是每个位置下,相机拍摄到的标定板上的点在图像中的位置,以及此时机械臂末端在基座标系中的位姿。5.通过多组对应点(图像点对应的世界点实际上是标定板上的点,但标定板固定,所以标定板上的点在世界坐标系(基坐标系)中的位置是固定的?这里需要澄清:实际上,标定板固定在世界坐标系中,而相机随着机械臂运动。因此,对于同一个标定板上的点,它在世界坐标系中的位置是固定的,而相机在不同位姿下拍摄,得到该点在图像坐标系的不同位置。我们的目标是建立图像坐标系(相机)到世界坐标系(基坐标系)的变换。但注意:眼在手上,我们通常需要建立的是从图像坐标系到机械臂末端坐标系的变换(因为相机固定在末端),然后通过机械臂末端的位姿(已知,通过机器人正运动学得到)转换到基坐标系。因此,九点标定的目的:求取相机坐标系与机械臂末端坐标系的变换关系(固定关系)。步骤:-固定标定板(世界坐标系中的位置固定)。-移动机械臂到9个不同位姿,在每个位姿下:-记录机械臂末端在基坐标系中的位姿(T_base_end)。-相机拍摄标定板,得到标定板上特征点在图像中的像素坐标,并通过相机标定(内参)转换到相机坐标系下的三维坐标(实际上,通过标定板的已知尺寸,我们可以得到特征点在相机坐标系下的坐标,但通常我们得到的是二维像素坐标,然后通过标定板的已知高度(Z值)和相机内参,可以转换到相机坐标系的三维坐标。或者,我们使用已知三维坐标的标定板,直接得到特征点在标定板坐标系(即世界坐标系)中的三维坐标和对应的图像坐标,然后通过PnP求解相机外参(即标定板坐标系到相机坐标系的变换))。-由于标定板固定,所以标定板上的点在世界坐标系(基坐标系)中的位置是固定的。但是,我们并没有直接测量世界坐标系,而是通过机械臂的基坐标系作为世界坐标系。因此,我们实际上有:-点P在标定板坐标系中的坐标(已知)->我们可以将标定板坐标系定义为世界坐标系,那么P的世界坐标已知。-在每个位姿i,机械臂末端位姿为T_base_end_i,相机与末端的变换为T_end_cam(待求)。-则点P在相机坐标系中的坐标可以通过相机模型得到(从像素坐标转换到相机坐标,需要相机内参和深度信息,但通常标定板是平面的,所以可以通过单应性矩阵或PnP求解得到相机坐标系中的坐标,或者直接使用三维标定板)。-同时,点P在基坐标系中的位置也可以通过两种方式表达:方式1:通过世界坐标系(标定板坐标系)到基坐标系的变换?这里我们通常将基坐标系作为世界坐标系,所以标定板固定在基坐标系中,那么P在基坐标系中的坐标是固定的(但未知,因为标定板摆放位置未知)。方式2:通过机械臂运动学:T_base_end_i*T_end_cam*P_cam=P_base而P_base就是点P在基坐标系中的坐标,对于同一个点P,它在不同位姿下在基坐标系中的坐标应该是相同的。因此,我们可以建立方程:T_base_end_i*T_end_cam*P_cam_i=P_base(对于同一个点P,P_base是常量)但是,我们无法直接得到P_cam_i(相机坐标系中的坐标),我们通过图像得到的是像素坐标,然后通过相机内参和标定板的已知尺寸(比如标定板是Z=0的平面),我们可以得到P在相机坐标系中的坐标(X,Y,Z),其中Z是标定板到相机的距离(未知)。实际上,我们使用平面标定板,通常将标定板平面定义为Z=0,那么点P在标定板坐标系(世界坐标系)中的坐标为(Xw,Yw,0),通过相机外参(旋转矩阵R和平移向量t)可以将世界坐标系中的点转换到相机坐标系:[Xc,Yc,Zc]^T=R*[Xw,Yw,0]^T+t然后通过相机内参矩阵K,将相机坐标系中的点投影到图像坐标(u,v)。反过来,如果我们已知内参K,以及图像坐标(u,v),和世界坐标(Xw,Yw,0),我们可以求解外参R和t(即从世界坐标系到相机坐标系的变换)。在眼在手上系统中,我们定义:-基坐标系(base)-末端坐标系(end)-相机坐标系(cam)-标定板坐标系(board,我们将其定义为世界坐标系world)标定板固定,所以变换T_base_world是固定的(但未知)。机械臂末端位姿T_base_end_i已知(通过机器人读取)。相机与末端的变换T_end_cam是固定的(待求)。对于每个位姿i,我们通过图像和标定板信息,可以计算从标定板坐标系(world)到相机坐标系(cam)的变换T_cam_world_i(通过PnP求解)。注意:这个变换是随位姿变化的,因为相机在动。那么,我们可以建立变换链:T_base_end_i*T_end_cam*T_cam_world_i=T_base_world由于T_base_world是固定的(标定板固定),所以对于不同的位姿i和j,有:T_base_end_i*T_end_cam*T_cam_world_i=T_base_end_j*T_end_cam*T_cam_world_j因此,我们可以通过这个等式求解T_end_cam。具体步骤:1.移动机械臂到9个不同位姿(尽量覆盖相机视野的不同区域和不同角度)。2.在每个位姿i:a.记录机械臂末端位姿(T_base_end_i,4x4齐次变换矩阵)。b.拍摄标定板图像,识别标定板上的特征点(9个点),通过PnP求解当前位姿下标定板坐标系到相机坐标系的变换T_cam_world_i(4x4矩阵)。3.建立方程:对于任意两个位姿i和j,有:T_base_end_i*T_end_cam*T_cam_world_i=T_base_end_j*T_end_cam*T_cam_world_j整理得到:T_end_cam*T_cam_world_i=inv(T_base_end_i)*T_base_end_j*T_end_cam*T_cam_world_j这实际上是一个关于T_end_cam的方程,可以使用最小二乘法求解。实际上,我们通常使用AX=XB的形式,其中:A=inv(T_base_end_i)*T_base_end_jB=T_cam_world_j*inv(T_cam_world_i)X=T_end_cam则有:A*X=X*B因此,我们需要求解AX=XB问题。有多种方法求解,如使用Tsai-Lenz方法。由于是新手教程,我们不需要深入数学推导,但需要给出关键公式。教程中,我们使用Halcon来实现,因为引用[1]和[2]提到了Halcon。Halcon中,有现成的算子用于手眼标定:-创建手眼标定模型:create_hand_eye_calibration_model-设置手眼标定参数:set_hand_eye_calibration_model_param-添加标定数据:add_hand_eye_calibration_data-执行标定:calibrate_hand_eye-获取结果:get_hand_eye_calibration_result具体步骤(Halcon实现):1.创建标定模型:```cppcreate_hand_eye_calibration_model(::Scheme:CalibDataID)```Scheme选择为'eye_in_hand'2.设置相机内参(如果使用单目相机):```cppset_hand_eye_calibration_model_param(CalibDataID,'camera',CameraParam)```3.循环添加9个位姿的数据:```cppforIndex:=1to9by1//读取机械臂末端位姿(基坐标系到末端坐标系的变换)read_pose('pose_'+Index+'.dat',PoseBaseEnd)//读取标定板图像read_image(Image,'image_'+Index)//在图像中查找标定板,得到标定板坐标系到相机坐标系的变换find_planar_calib_object(Image,CalibObj,CalibObjDescr,0.8,1,1,[],[],PoseCamWorld)//添加数据add_hand_eye_calibration_data(CalibDataID,'camera',PoseBaseEnd,PoseCamWorld)endfor```4.执行标定:```cppcalibrate_hand_eye(CalibDataID,Errors)```5.获取结果:```cppget_hand_eye_calibration_result(CalibDataID,'camera',PoseEndCam)```6.销毁模型:```cppclear_hand_eye_calibration_model(CalibDataID)```注意:以上代码为伪代码,实际使用需要调整。关键点:-机械臂末端位姿的格式:Halcon中使用3D位姿(Pose),可以是[x,y,z,rx,ry,rz](轴角)或四元数等,需要根据机器人输出的格式转换。-标定板:需要先创建标定板模型(CalibObjDescr),通常使用Halcon的标定板描述文件。验证:标定完成后,可以使用标定结果将图像中的点转换到机械臂基坐标系。选择一个点,移动机械臂到不同位置,该点在基坐标系中的位置应该一致。常见问题:1.机械臂位姿不准确:确保机器人位姿读取正确。2.标定板识别错误:确保标定板清晰可见,特征点提取正确。3.位姿覆盖范围不足:尽量使位姿覆盖整个工作空间,并且旋转角度多样。数学原理(简要):我们要求解的变换矩阵$T_{end}^{cam}$满足:$$T_{base}^{end_i}\cdotT_{end}^{cam}\cdotT_{cam}^{world_i}=T_{base}^{world}$$其中$T_{base}^{world}$是固定的,因此对于两个不同的位姿$i$和$j$,有:$$T_{base}^{end_i}\cdotT_{end}^{cam}\cdotT_{cam}^{world_i}=T_{base}^{end_j}\cdotT_{end}^{cam}\cdotT_{cam}^{world_j}$$整理得:$$(T_{base}^{end_i})^{-1}\cdotT_{base}^{end_j}\cdotT_{end}^{cam}=T_{end}^{cam}\cdotT_{cam}^{world_j}\cdot(T_{cam}^{world_i})^{-1}$$即$AX=XB$,其中$A=(T_{base}^{end_i})^{-1}\cdotT_{base}^{end_j}$,$B=T_{cam}^{world_j}\cdot(T_{cam}^{world_i})^{-1}$,$X=T_{end}^{cam}$。在Halcon中,我们只需要提供每个位姿的$T_{base}^{end_i}$和$T_{cam}^{world_i}$,算法会自动求解。现在,我们按照上述步骤编写教程。</think>### 眼在手上的九点标定新手入门教程(Halcon实现)
#### 一、基本概念
九点标定是机器视觉中**坐标系转换**的核心技术,本质是通过多个特征点建立**仿射变换矩阵**[^2]。在"眼在手上"系统中,相机安装在机械臂末端,标定目标是建立**相机坐标系**与**机械臂坐标系**的映射关系。数学原理可表示为:
$$
\begin{bmatrix}
X_{robot} \\
Y_{robot} \\
1
\end{bmatrix}
=
\begin{bmatrix}
a & b & c \\
d & e & f \\
0 & 0 & 1
\end{bmatrix}
\begin{bmatrix}
X_{image} \\
Y_{image} \\
1
\end{bmatrix}
$$
其中矩阵元素$ a,b,c,d,e,f $即为标定参数[^1]。
#### 二、准备工作
1. **硬件**
- 机械臂(需支持位姿读取)
- 工业相机(固定于机械臂末端)
- 9点标定板(特征点间距精确已知)
2. **软件**
- Halcon 17.12+(建议版本)
- 标定板描述文件(如`calplate.descr`)
#### 三、操作步骤(附Halcon代码)
##### ▶ 步骤1:采集9组位姿数据
```halcon
for Index := 1 to 9 by 1
* 移动机械臂到不同位姿
move_robot_to_pose(Pose_Index)
* 拍摄标定板并提取特征点
find_calibration_object(Image, CalibObj, CalibDataID, Pose_Image)
* 记录机械臂末端位姿(基坐标系)
get_robot_pose(Pose_Robot)
* 存储数据对
set_calib_data(CalibDataID, 'tool', Index, 'pose', Pose_Robot)
set_calib_data(CalibDataID, 'calib_obj_pose', Index, Pose_Image)
endfor
```
##### ▶ 步骤2:计算变换矩阵
```halcon
* 创建标定模型
create_calib_data('hand_eye_moving_cam', 1, 1, CalibDataID)
* 设置相机参数(焦距、畸变等)
set_calib_data_cam_param(CalibDataID, 0, 'area_scan_division', CamParam)
* 执行手眼标定
calibrate_hand_eye(CalibDataID, Error)
```
##### ▶ 步骤3:验证标定结果
```halcon
* 获取变换矩阵
get_calib_data(CalibDataID, 'camera', 0, 'params', CamParamOut)
* 随机选取验证点
image_points_to_world_plane(CamParamOut, Pose_Robot, [u,v], 'mm', X, Y)
* 对比实际机械臂坐标与计算值
disp_error := sqrt((X_actual - X)^2 + (Y_actual - Y)^2)
```
#### 四、关键技巧
1. **位姿选择原则**
- 覆盖机械臂主要工作空间
- 包含$ X/Y $方向平移和$ Rz $旋转
- 标定板倾斜角度建议在$ \pm 30^\circ $内[^4]
2. **精度提升方法**
```halcon
* 增加采样点数量(>9点)
set_calib_data_model_param(CalibDataID, 'num_calib_points', 15)
* 使用非线性优化
calibrate_hand_eye(CalibDataID, 'nonlinear', 'all', Error)
```
#### 五、常见问题解决
| 问题现象 | 原因 | 解决方案 |
|---------|------|----------|
| 误差>0.5mm | 机械臂重复精度不足 | 1. 增加标定点至15个<br>2. 采用加权平均算法 |
| 无法识别标定板 | 光照不均匀 | 1. 添加环形光源<br>2. 调整`find_calib_object`参数 |
| Z方向偏差大 | 镜头畸变未补偿 | 执行`calibrate_cameras`先校正内参 |
> **动手建议**:用白纸绘制9点标定板,用Halcon模拟不同位姿的坐标变换,理解$ \Delta x/\Delta y $与矩阵元素的关系[^1]。
#### 六、应用场景
1. **精密装配**:芯片贴装(精度±0.02mm)
2. **三维引导**:配合3D传感器实现曲面焊接
3. **动态补偿**:传送带跟踪中的实时坐标转换
阅读全文
相关推荐



















