视觉自动化检测主要针对钢卷、瓷器、钢轨、铸件、锂电池壳、反光镜、瓶体、金属、木材生产线中产品表面划痕、表面缺陷及颜色检测。
热线电话:13655163735/025-66018619
首页 > 公司动态 > 技术动态
工业机器人3D视觉手眼标定代码实战指南
2025-08-17 02:30:37

想象一下:汽车装配线上,搭载3D相机的机械臂精准抓取悬空的变速箱零件——这令人惊叹的精准协同背后,核心秘密正是 “手眼标定” 。当机器人需要“看懂”并“操作”三维世界时,手眼标定代码就是那双为其赋予空间感知与精度的无形之手。

为何手眼标定是3D视觉的基石?

在机器人3D视觉系统中,相机如同机器人的“眼睛”,机械臂是其“手臂”。然而,相机安装在机械手末端(Eye-in-Hand)或固定支架上(Eye-to-Hand)时,它所“看到”的三维点云坐标(相机坐标系)与机器人控制器“认为”的末端工具位置(工具坐标系)或基座位置(基坐标系)天然存在坐标系的鸿沟

  • 核心矛盾: 相机识别到一个物体的精确3D坐标(Xc, Yc, Zc)。但机器人手臂要移动过去抓取,它需要知道这个点在*自己*的工具坐标系或基坐标系下的位置(Xr, Yr, Zr)。
  • 标定的使命: 手眼标定就是要找到相机坐标系与机器人工具坐标系(Eye-in-Hand)或基坐标系(Eye-to-Hand)之间那个精确的变换矩阵。这个矩阵编码了旋转R平移T关系。有了它,系统就能将视觉感知无缝转化为机器人可执行的精准动作指令。

手眼标定背后的数学与流程

手眼标定的核心数学模型是一个经典的矩阵方程:AX = XB

  • A: 机器人末端从位置1移动到位置2时,其工具坐标系(或基坐标系)的相对变换(通过机器人控制器读取关节角度正运动学计算得到)。
  • B: 相机在机器人位于位置1和位置2时,观测同一个固定目标(如标定板)的相对姿态变换(通过对拍摄的标定板图像解算得到)。
  • X: 就是我们要求解的手眼变换矩阵(相机坐标系到工具坐标系的变换,即 T_tool_cam 或相机到基坐标系的变换 T_base_cam)。

标准标定流程(以Eye-in-Hand为例):

  1. 固定高精度标定板: 在机器人工作空间内稳固放置一个已知几何尺寸的标定板(如棋盘格、Charuco板、点阵板)。
  2. 安装相机: 将3D相机(如结构光、双目、ToF)牢固安装在机器人末端法兰盘上。
  3. 多姿态数据采集: 控制机器人末端携带相机移动,从多个(通常20-50个)、不同(覆盖足够旋转和平移)的姿态拍摄标定板。每个姿态记录:
  • robot_pose_i 机器人当前末端工具中心点(TCP)在基坐标系下的位姿(齐次变换矩阵 T_base_tool_i)。
  • cam_pose_i 通过图像处理和对标定板的PnP求解计算出的标定板在当前相机坐标系下的位姿(齐次变换矩阵 T_cam_board_i)。因为标定板固定,它在基坐标系下的位姿 T_base_board *应*是常量(忽略微小振动)。
  1. 构建方程: 取两次不同的运动i和j。
  • 机器人运动的相对变换 A_ij = inv(T_base_tool_i) * T_base_tool_j (从i到j,工具坐标系视角)。
  • 相机观测的相对变换 B_ij = inv(T_cam_board_i) * T_cam_board_j (从i到j,相机坐标系视角)。
  • A_ij * X = X * B_ij (其中 X = T_tool_cam)。
  1. 求解X: 采集足够多的(i, j)对(通常通过多组运动构建方程组),使用高效的数值算法(如OpenCV中的 calibrateHandEye 函数提供多种解法:
  • Tsai (经典稳定)
  • Park (另一种解析法)
  • Horaud (基于旋转向量)
  • Andreff (基于激光跟踪仪等外置设备数据,精度高但复杂)
  • Daniilidis (四元数法)求解这个超定方程组,得到最优的 T_tool_cam (X)。
  1. 验证精度: 使用未参与标定的姿态,计算理论目标点位置与实际机器人运动到达位置之间的误差。

核心代码实现要点(概念性伪代码)

”`python

1. 读取标定参数和机器人位姿数据

calibration_data = load_data(‘calibration_data.h5’) # 包含所有姿态的 robot_pose_i 和 cam_pose_i (标定板在相机坐标系下的位姿)

2. 初始化用于存储相对变换A和B的列表

R_gripper2base = [] # 存储机器人运动旋转部分 (A_ij 的旋转) t_gripper2base = [] # 存储机器人运动平移部分 (A_ij 的平移) R_target2cam = [] # 存储相机运动旋转部分 (B_ij 的旋转) t_target2cam = [] # 存储相机运动平移部分 (B_ij 的平移)

3. 遍历数据,生成运动对 (i, j),计算相对变换

注意:通常使用时序上连续的运动,或所有可能的组合(计算量大)

for i in range(0, len(calibration_data) - 1): for j in range(i + 1, len(calibration_data)):

计算机器人工具坐标系变化的相对位姿 A_ij = (T_base_tool_i)^{-1} * T_base_tool_j

T_base_tool_i = calibration_data[i][‘robot_pose’] T_base_tool_j = calibration_data[j][‘robot_pose’] T_tool_i_tool_j = np.linalg.inv(T_base_tool_i) @ T_base_tool_j # 工具坐标系从i到j的运动

提取A_ij的旋转(R_A)和平移(t_A)

R_A = T_tool_i_tool_j[:3, :3] t_A = T_tool_i_tool_j[:3, 3] R_gripper2base.append(R_A) t_gripper2base.append(t_A)

计算相机观测的相对位姿 B_ij = (T_cam_i_board)^{-1} * T_cam_j_board

T_cam_i_board = calibration_data[i][‘cam_pose’] # 标定板在姿态i时的相机坐标 T_cam_j_board = calibration_data[j][‘cam_pose’] # 标定板在姿态j时的相机坐标 T_board_cam_i = np.linalg.inv(T_cam_i_board) # 相机在姿态i时相对于标定板的位姿 T_board_cam_j = np.linalg.inv(T_cam_j_board) # 相机在姿态j时相对于标定板的位姿 T_cam_i_cam_j = T_board_cam_i @ np.linalg.inv(T_board_cam_j)