1. 棋盘格手眼标定基础概念
手眼标定是机器人视觉系统中的关键步骤,特别是在"眼在手外"(Eye-to-Hand)配置下。这种配置下,相机固定在机器人工作空间外,独立于机械臂运动。想象一下,这就像你站在桌子旁边观察机械臂的动作——你的眼睛(相机)不动,而手臂(机械臂)在移动。
棋盘格标定板是这个过程中的重要工具,它就像一把精确的尺子。标定板上规则排列的黑白方格提供了大量可识别的特征点。当机械臂带着标定板移动时,相机从不同角度拍摄这些图案,就像从多个视角测量同一把尺子,从而建立坐标系之间的转换关系。
在实际操作中,我们需要解决两个核心问题:一是确定相机坐标系与标定板坐标系的关系(通过图像处理实现),二是确定机械臂末端坐标系与基座坐标系的关系(通过机器人运动学获得)。最终目标是找到相机坐标系与机器人基座坐标系之间的固定变换关系。
2. 准备工作与环境搭建
2.1 硬件配置要点
我建议使用至少6x4的棋盘格标定板(内角点数量),每个方格边长建议15-30mm。在实际项目中,我发现方格尺寸过小会导致角点检测困难,过大则可能超出相机视野。相机分辨率最好在200万像素以上,固定安装时要确保在整个机械臂运动范围内都能清晰拍摄到标定板。
机械臂方面,需要确保末端执行器能牢固固定标定板。我常用3D打印的专用夹具,比胶带固定更可靠。记得检查机械臂的重复定位精度,一般工业级机械臂在±0.1mm以内就足够。
2.2 软件环境配置
推荐使用Python 3.8+和OpenCV 4.5+的组合。安装依赖很简单:
pip install opencv-python numpy transforms3d特别提醒:transforms3d库在欧拉角转换时非常实用。我在早期项目中尝试自己实现这些转换,结果发现边界条件处理特别容易出错,后来改用这个成熟库省去了很多麻烦。
3. 数据采集实战技巧
3.1 机械臂位姿规划
采集数据时,机械臂需要移动到多个不同位姿。根据我的经验,15-20个位姿比较理想,太少会影响精度,太多则增加不必要的工作量。位姿选择有几个技巧:
- 让标定板在相机视野中呈现明显不同的角度,建议俯仰角变化超过30度
- 尽量让标定板占据相机视野的主要部分(60%-80%面积为佳)
- 避免对称位姿,比如正对相机时旋转180度的情况
记录位姿时,我习惯使用欧拉角表示旋转。注意统一角度单位(度或弧度),我在一个项目中混用了两种单位,导致标定结果完全错误,排查了很久才发现。
3.2 图像采集注意事项
拍摄时要注意光照均匀,避免反光。我遇到过棋盘格黑色方块反光变成白色,导致角点检测失败的情况。建议使用漫射光源,或者在不同角度布置多个光源。
保存图像时,建议使用无损格式如PNG。有次使用JPEG压缩过度,角点像素值发生变化,导致标定误差增大。文件命名最好包含位姿序号,方便后期对应。
4. 核心算法代码解析
4.1 位姿数据处理
def pose_vectors_to_base2end_transforms(pose_vectors): R_base2ends = [] t_base2ends = [] for pose_vector in pose_vectors: # 欧拉角转旋转矩阵 R_end2base = euler_to_rotation_matrix(pose_vector[3], pose_vector[4], pose_vector[5]) t_end2base = pose_vector[:3] # 构建齐次变换矩阵 pose_matrix = np.eye(4) pose_matrix[:3, :3] = R_end2base pose_matrix[:3, 3] = t_end2base # 求逆得到基座到末端的变换 pose_matrix_inv = np.linalg.inv(pose_matrix) R_base2end = pose_matrix_inv[:3, :3] t_base2end = pose_matrix_inv[:3, 3].reshape(3, 1) R_base2ends.append(R_base2end) t_base2ends.append(t_base2end) return R_base2ends, t_base2ends这个函数处理机械臂的位姿数据。实际使用中我发现,不同品牌的机械臂可能使用不同的欧拉角顺序(ZYX、XYZ等),这点要特别注意。我曾经因为顺序搞错,导致标定结果完全不可用。
4.2 棋盘格检测与相机标定
# 准备3D对象点 pattern_size = (6, 4) # 内角点数量 square_size = 15.0 # 方格实际尺寸(mm) objp = np.zeros((np.prod(pattern_size), 3), dtype=np.float32) objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) * square_size # 检测角点 obj_points = [] img_points = [] for image in glob.glob('./images/*.png'): img = cv2.imread(image) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, pattern_size) if ret: # 亚像素级精确化 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria) obj_points.append(objp) img_points.append(corners)这里我添加了亚像素级角点检测,这是很多教程中容易忽略的细节。实测发现这能提高约15%的标定精度。参数(11,11)是搜索窗口尺寸,对于200万像素图像比较合适,更高分辨率可以适当增大。
5. 手眼标定实现与验证
5.1 核心标定过程
# 计算标定板到相机的变换 R_board2cameras = [] t_board2cameras = [] for i in range(len(obj_points)): ret, rvec, t = cv2.solvePnP(obj_points[i], img_points[i], K, dist_coeffs) R, _ = cv2.Rodrigues(rvec) R_board2cameras.append(R) t_board2cameras.append(t) # 手眼标定 R_camera2base, t_camera2base = cv2.calibrateHandEye( R_base2ends, t_base2ends, R_board2cameras, t_board2cameras ) # 构建变换矩阵 T_camera2base = np.eye(4) T_camera2base[:3, :3] = R_camera2base T_camera2base[:3, 3] = t_camera2base.reshape(3)OpenCV的calibrateHandEye函数支持多种算法(Tsai、Park等)。我对比发现,在眼在手外配置下,Tsai算法通常表现最好。可以通过参数cv2.CALIB_HAND_EYE_TSAI来指定。
5.2 结果验证方法
标定完成后,我常用的验证方法是:
- 选择一个测试位姿,记录机械臂末端实际位置
- 使用标定结果将相机看到的标定板位置转换到基座坐标系
- 比较计算值与实际值的差异
好的标定结果,位置误差通常在机械臂重复定位精度的2-3倍以内。如果误差过大,建议检查:
- 位姿数据单位是否一致
- 角点检测是否准确
- 机械臂运动时标定板是否有晃动
6. 常见问题排查
在实际项目中,我遇到过各种奇怪的问题。比如有一次标定结果完全不对,最后发现是机械臂的零点漂移导致的。后来我在每次标定前都先执行回零操作。
另一个常见问题是图像模糊。可以通过以下代码检测:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) lap_var = cv2.Laplacian(gray, cv2.CV_64F).var() if lap_var < 50: # 阈值可根据实际情况调整 print("图像模糊,建议重新拍摄")还有一次遇到标定结果不稳定,发现是机械臂不同位姿下电缆拉扯导致轻微位移。后来改用无线通信解决了这个问题。
7. 性能优化建议
对于需要频繁标定的场景,我总结了几点优化经验:
- 并行计算:图像处理部分可以使用多进程,特别是当图像数量较多时
from multiprocessing import Pool def process_image(image_path): # 图像处理代码 pass with Pool(4) as p: # 4个进程 results = p.map(process_image, image_paths)缓存机制:对于不变的相机内参,可以保存为文件避免重复计算
增量标定:当新增位姿数据时,可以只处理新数据,而不是全部重新计算
自动筛选:通过程序自动剔除角点检测不准确的图像,提高标定稳定性
8. 实际应用案例
在最近的一个拆垛项目中,我们需要让机械臂根据视觉系统定位抓取箱子。使用这套标定方法后,抓取成功率从最初的70%提升到了98%。关键是在传送带两侧安装了多个相机,通过手眼标定建立了统一的坐标系。
另一个应用是在焊接场景,通过标定使视觉系统能准确识别焊缝位置。这里特别要注意防眩光处理,我们最终采用了偏振滤镜配合特殊打光方案。
在医疗机器人项目中,标定精度要求更高(0.1mm级)。我们采用了高分辨率工业相机和特殊设计的标定板,同时在温度稳定的实验室内进行操作,避免热变形影响。