一. SCARA机械手介绍
Scara机械手包括3个平移+1个旋转,共计4个自由维度,动作会受到限制,它不能倾斜,但它能提供更快,更精确的性能。
二.SCARA手眼标定注意事项
1.SCARA机器人必须提前对摄像机进行校准,然后再对手眼系统进行校正,对于6轴关节机器人,手眼标定前的摄像机标定是可选择的,在后面可以直接通过手眼标定来校准摄像机。
2.为SCARA机器人确定Z轴方向的平移.
遇到问题:在校准SCARA机器人时,不可能明确地确定所有姿态参数,当相机移动拍照的时候,无法确定机器人基础坐标系下的校正对象的位姿中的Z偏移量,所以Z偏移量会设置为0;当相机固定拍照的时候,无法确定机器人工具坐标系下校正对象的位姿中的Z偏移量,所以Z偏移量会设置为0;当我们手眼标定结束后,需要确定这个Z偏移量,将手眼标定的结果平移Z单位;
如何确定Z偏移量:
相机固定拍照:
2.1校准板(未连接到机器人)放置在任意位置,以便摄像机可以观察到。从而获取摄像机坐标系下校准板的位姿。
2.2将机器人的工具手动移动到校准板的原点,然后查询机器人工具位姿。
2.3通过以上两个位姿和手眼标定结果里的摄像机坐标系下的机器人位姿,从而获取Z偏移量;
相机移动拍照:
2.4 校准板放置在任意位置。然后移动机器人,使得照相机可以观察校准板,从图像中可以获取摄像机坐标系中校准板的位姿,同时通过机器人软件查询当前机器人位姿;
2.5 将机器人的工具手动移动到校准板的原点,然后再次查询机器人姿态;
2.6 通过三个姿势和手眼标定结果里摄像机坐标系下机器人工具位姿,从而确定Z偏移量;
下面给出眼在手上和固定相机两种手眼标定的例子。
注意请安装halcon12后再运行例子,不然示例图片找不到。
示例:SCARA固定相机手眼标定
求摄像机坐标系下的机械人基础坐标系的位置
errors是标定后的精度。
*标定板 CalibObjDescr := 'calibrate_hand_eye_scara_setup_01_calplate.cpd' *标定板厚度 CalibrationPlateThickness := 0.003 *摄像机内部参数 CameraParam := [0.0165251,-642.277,4.65521e-006,4.65e-006,595.817,521.75,1280,1024] *待抓取物体的厚度 ObjectThickness := 0.001 *关闭打开的窗口 dev_close_window () *打开一个新窗口 dev_open_window_fit_size (0, 0, 1280, 1024, 640, -1, WindowHandle) *设置字体信息:字体大小14,字体类型:mono,粗体 set_display_font (WindowHandle, 14, 'mono', 'true', 'false') *关闭程序计数器,变量窗口更新,图形窗口图形更新 dev_update_off () //////////////////////////////////////获取校准图像和相应的机器人姿势/////////////////////////////////////////// * 创建手眼标定模型 create_calib_data ('hand_eye_scara_stationary_cam', 1, 1, CalibDataID) * 对手眼标定模型设置摄像机内部参数 set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', CameraParam) * 对手眼标定模型设置标定板描述文件 set_calib_data_calib_object (CalibDataID, 0, CalibObjDescr) for Index := 1 to 10 by 1 *读取含标定板的图像 read_image (CalibImage, '3d_machine_vision/handeye/scara_stationary_cam_setup_01_calib_' + Index$'02') *读取标定板图像对应的机器人的位姿 read_pose ('scara_stationary_cam_setup_01_tool_in_base_pose_' + Index$'02' + '.dat', ToolInBasePose) * 将机器人基座坐标系下机器人工具位姿设置到手眼标定模型里 set_calib_data (CalibDataID, 'tool', Index, 'tool_in_base_pose', ToolInBasePose) *寻找标定板对象 find_calib_object (CalibImage, CalibDataID, 0, 0, Index, [], []) dev_display (CalibImage) *从标定模型里获取摄像机坐标系下标定板位姿 get_calib_data_observ_pose (CalibDataID, 0, 0, Index, ObjInCameraPose) disp_caltab (WindowHandle, CalibObjDescr, CameraParam, ObjInCameraPose, 1) disp_message (WindowHandle, 'Calibration image ' + Index + ' of 10', 'window', 12, 12, 'black', 'true') wait_seconds (0.2) endfor disp_continue_message (WindowHandle, 'black', 'true') stop () * //////////////////////////////////////执行手眼标定//////////////////////////////////////////////////////////////// *执行手眼标定 calibrate_hand_eye (CalibDataID, Errors) *获得校准结果,即获取摄像机坐标系下机器人位姿 get_calib_data (CalibDataID, 'camera', 0, 'base_in_cam_pose', BaseInCamPosePre) *释放校正模型使用的内存 clear_calib_data (CalibDataID) disp_preliminary_result (WindowHandle, BaseInCamPosePre, Errors) disp_continue_message (WindowHandle, 'black', 'true') stop () //////////////////////////////////////将手眼标定结果平移Z//////////////////////////////////////////////////////////////// *读取标定板图像 read_image (ImageRef, '3d_machine_vision/handeye/scara_stationary_cam_setup_01_calib_ref') *获取摄像机坐标系下校正对象的位姿 get_calib_plate_pose (ImageRef, CameraParam, CalibObjDescr, ObjInCamPoseRef) *读取机器人坐标系下机器人工具的位姿 read_pose ('scara_stationary_cam_setup_01_tool_in_base_pose_ref.dat', ToolInBasePoseRef) *修复Z的歧义 fix_scara_ambiguity_stationary_cam (BaseInCamPosePre, ToolInBasePoseRef, ObjInCamPoseRef, ZCorrection) *沿着Z轴转换摄像机坐标系下的机器人坐标的位姿 set_origin_pose (BaseInCamPosePre, 0, 0, ZCorrection, BaseInCamPose) * * 显示手眼标定结果,获取摄像机坐标系下机器人底座的位姿 disp_final_results (WindowHandle, BaseInCamPosePre, BaseInCamPose) disp_end_of_program_message (WindowHandle, 'black', 'true') //////////////////////////////////////获取摄像机坐标系下测量平面的位姿//////////////////////////////////////////////////////////////// *将摄像机坐标系下机器人坐标的位姿反转,从而得到机器人坐标下摄像机的位姿 pose_invert (BaseInCamPose, CamInBasePose) * 确定测量平面的姿态 set_origin_pose (ObjInCamPoseRef, 0, 0, CalibrationPlateThickness - ObjectThickness, MPInCamPose) //////////////////////////////////////保存手眼标定结果//////////////////////////////////////////////////////////////// *将机器人坐标系下摄像机位姿写入本地硬盘 write_pose (CamInBasePose, 'cam_in_base_pose.dat') *将相机摄像机内参写入本地硬盘 write_cam_par (CameraParam, 'camera_parameters.dat') *摄像机坐标系下测量平面的位姿写入本地硬盘 write_pose (MPInCamPose, 'measurement_plane_in_cam_pose.dat')
示例:SCARA移动相机手眼标定
*标定板 CalibObjDescr := 'calibrate_hand_eye_scara_setup_01_calplate.cpd' *摄像机内部参数 CameraParam := [0.004938,-10379.136,4.65138e-006,4.65e-006,617.294,534.687,1280,1024] *关闭打开的窗口 dev_close_window () *打开一个新窗口 dev_open_window_fit_size (0, 0, 1280, 1024, 640, -1, WindowHandle) *设置字体信息:字体大小14,字体类型:mono,粗体 set_display_font (WindowHandle, 14, 'mono', 'true', 'false') *关闭程序计数器,变量窗口更新,图形窗口图形更新 dev_update_off () //////////////////////////////////////获取校准图像和相应的机器人姿势/////////////////////////////////////////// * 创建手眼标定模型 create_calib_data ('hand_eye_scara_moving_cam', 1, 1, CalibDataID) * 对手眼标定模型设置摄像机内部参数 set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', CameraParam) * 对手眼标定模型设置标定板描述文件 set_calib_data_calib_object (CalibDataID, 0, CalibObjDescr) for Index := 1 to 10 by 1 *读取含标定板的图像 read_image (CalibImage, '3d_machine_vision/handeye/scara_moving_cam_setup_01_calib_' + Index$'02') *读取标定板图像对应的机器人的位姿 read_pose ('scara_moving_cam_setup_01_tool_in_base_pose_' + Index$'02' + '.dat', ToolInBasePose) * 将机器人基座坐标系下机器人工具位姿设置到手眼标定模型里 set_calib_data (CalibDataID, 'tool', Index, 'tool_in_base_pose', ToolInBasePose) *寻找标定板对象 find_calib_object (CalibImage, CalibDataID, 0, 0, Index, [], []) dev_display (CalibImage) *从标定模型里获取摄像机坐标系下标定板位姿 get_calib_data_observ_pose (CalibDataID, 0, 0, Index, ObjInCameraPose) disp_caltab (WindowHandle, CalibObjDescr, CameraParam, ObjInCameraPose, 1) disp_message (WindowHandle, 'Calibration image ' + Index + ' of 10', 'window', 12, 12, 'black', 'true') wait_seconds (0.2) endfor disp_continue_message (WindowHandle, 'black', 'true') stop () //////////////////////////////////////执行手眼标定//////////////////////////////////////////////////////////////// *执行手眼标定 calibrate_hand_eye (CalibDataID, Errors) *获得校准结果,即获取摄像机坐标系下机器人工具位姿 get_calib_data (CalibDataID, 'camera', 0, 'tool_in_cam_pose', ToolInCamPosePre) *释放校正模型使用的内存 clear_calib_data (CalibDataID) disp_preliminary_result (WindowHandle, ToolInCamPosePre, Errors) disp_continue_message (WindowHandle, 'black', 'true') stop () //////////////////////////////////////将手眼标定结果平移Z//////////////////////////////////////////////////////////////// *读取标定板校正图像 read_image (ImageRef1, '3d_machine_vision/handeye/scara_moving_cam_setup_01_calib_ref_1') *通过标定板图像获取摄像机坐标系下校正对象的位姿 get_calib_plate_pose (ImageRef1, CameraParam, CalibObjDescr, ObjInCamPoseRef1) *第一次手动移动机器人,使照相机可以观察到标定板,然后通过机器人控制软件读取当前机器人位姿。 read_pose ('scara_moving_cam_setup_01_tool_in_base_pose_ref_1.dat', ToolInBasePoseRef1) *第二次手动移动机器人到校准板的原点,然后通过机器人控制软件读取当前机器人位姿。 read_pose ('scara_moving_cam_setup_01_tool_in_base_pose_ref_2.dat', ToolInBasePoseRef2) *获取Z平移量 fix_scara_ambiguity_moving_cam (ToolInCamPosePre, ObjInCamPoseRef1, ToolInBasePoseRef1, ToolInBasePoseRef2, ZCorrection) *对摄像机坐标系下机器人工具位姿进行平移ZCorrection偏移量 set_origin_pose (ToolInCamPosePre, 0, 0, ZCorrection, ToolInCamPose) * * Visualize disp_final_results (WindowHandle, ToolInCamPosePre, ToolInCamPose) disp_end_of_program_message (WindowHandle, 'black', 'true') //////////////////////////////////////获取机器人坐标系下校正对象的位姿//////////////////////////////////////////////////////////////// pose_invert (ToolInCamPose, CamInToolPose) ObjInCamPose := [-0.0043,0.0085,0.087,0.445,0.068,355.9,0] ToolInBasePose := [0.2612,0.084,0.1731,0,0,178.128,0] pose_compose (CamInToolPose, ObjInCamPose, ObjInToolPose) pose_compose (ToolInBasePose, ObjInToolPose, ObjInBasePose)
上面的程序仍然嫌复杂了一点,勇哥摘抄了一篇简单点的,如下:
=======================================
手眼标定基于Tsai的两步法标定,是经典的Ax = xB 求解模型。
Tsai的两步法标定是基于径向校正约束;第一步:利用最小二乘法求解线性方程组,得出相机的外参数;
第二步:根据获得的相机外参数,求取相机的内参数;如果无透视畸变,可以使用一个线性方程求出。
罗第6、7章;特别:P164-166)
1.手眼标定就是对机械手和相机的位置关系进行标定,这样根据识别得到的像素位置去引导机械手去抓取。
2.eye-in-hand:通过相机标定确定相机坐标系和世界坐标系之间的关系;即P&&R。
这时如果知道相机坐标系和机械手基础坐标系之间的关系,即可得到物体在机械手坐标系中的坐标。
3.eye-to-hand:通过相机标定确定相机坐标系和世界坐标系之间的关系;即P&&R;
因为相机和机械手基础坐标系之间的关系是固定的,即:只要求出相机坐标系在基础坐标系中的位置,即可获得物体在机械手基础坐标系中的位置。
****************手眼标定执行流程 **创建数据模型 create_calib_data ('calibration_object', 1, 1, CalibDataID) ***设置相机参数 set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', []) **设置标定板描述文件 set_calib_data_calib_object (CalibDataID, 0, 'calplate.cpd') **循环读取标定板图像 for index := 1 to 10 by 1 read_image (Image, 'fabrik') *读取机械手法兰盘在基础坐标系中的位置姿态 read_pose ('campose.dat', Pose) *将机械手法兰盘在基础坐标系中的位置姿态添加到标定数据模型中 set_calib_data (CalibDataID, 'model', 'general', 'reference_camera', Pose) **获取标定对象,并添加到数据模型中 find_calib_object (Image, CalibDataID, 0, 0, 0, [], []) *获得世界坐标系和相机坐标系的相对位置关系 get_calib_data_observ_pose (CalibDataID, 0, 0, 0, ObjInCameraPose) endfor calibrate_hand_eye (CalibDataID, Errors) *获得机械手基础坐标系在摄像机坐标系下的坐标 get_calib_data (CalibDataID, 'camera', 0, 'params', DataValue) **获得摄像机坐标系在机械手基础坐标系下的坐标 pose_invert (ObjInCameraPose, PoseInvert) *根据摄像机在机械手基础坐标系下的姿态和目标在摄像机坐标系下的姿态,求解目标在摄像机基础坐标系下的姿态 pose_compose (PoseInvert, PoseInvert, PoseCompose)

