对于标定来说,一般常见的有用于测量的线性与非线性标定,另一类就是和运动相关的标定,手眼标定。
勇哥写过许多epson机器人的手眼标定,也有halcon仿制这种方式的实现方法。
但是halcon有自己的手眼标定。
CalibObjDescr := 'calibrate_hand_eye_scara_setup_01_calplate.cpd' CalibrationPlateThickness := 0.003 gen_cam_par_area_scan_division (0.0165251, -642.277, 4.65521e-006, 4.65e-006, 595.817, 521.75, 1280, 1024, CameraParam) ObjectThickness := 0.001 dev_close_window () dev_open_window_fit_size (0, 0, 1280, 1024, 640, -1, WindowHandle) set_display_font (WindowHandle, 14, 'mono', 'true', 'false') dev_update_off () //创建标定模型,注意这个地方第一个参数输入的是手眼标定固定相机模式 create_calib_data ('hand_eye_scara_stationary_cam', 1, 1, CalibDataID) //设置相机参数和相机类型为area_scan_division,这里是面扫,同时相机输入参数为CameraParam set_calib_data_cam_param (CalibDataID, 0, [], CameraParam) //在标定模型中指定标定板所使用的标定板描述文件 set_calib_data_calib_object (CalibDataID, 0, CalibObjDescr) for Index := 1 to 10 by 1 read_image (CalibImage, '3d_machine_vision/hand_eye/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 () check_hand_eye_calibration_input_poses (CalibDataID, 0.05, 0.005, Warnings) if (|Warnings| != 0) dev_inspect_ctrl (Warnings) stop () endif //创建一个手眼标定 calibrate_hand_eye (CalibDataID, Errors) //得到相机外参数,也就是CCD坐标系和机械手基础坐标系之间在的关系。 //即旋转矩阵和平移矢量,就是在CCD坐标系下机械手的姿态, //这也是我们手眼标定要得到的参数,有了各个坐标系之间的这种转换关系 //就可以算出将来识别目标在机械手坐标系下的坐标。 get_calib_data (CalibDataID, 'camera', 0, 'base_in_cam_pose', BaseInCamPosePre) disp_preliminary_result (WindowHandle, BaseInCamPosePre, Errors) disp_continue_message (WindowHandle, 'black', 'true') stop () read_image (ImageRef, '3d_machine_vision/hand_eye/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) //设置3D坐标原点,BaseInCamPose为新的3D位置,也就是在CCD坐标系下 //机械手基础坐标系的姿态 set_origin_pose (BaseInCamPosePre, 0, 0, ZCorrection, BaseInCamPose) disp_final_results (WindowHandle, BaseInCamPosePre, BaseInCamPose) disp_end_of_program_message (WindowHandle, 'black', 'true') //姿态转换函数,因为前面求解的是机械手在CCD坐标系下的位置,这里 //转换成CCD在机械坐标下的姿态,并且赋值给变量CamInBasePse pose_invert (BaseInCamPose, CamInBasePose) //创建目标在CCD坐标系下的姿态信息 create_pose (0.0035, -0.0128, 0.7981, 1.345, 356.158, 180.194, 'Rp+T', 'gba', 'point', ObjInCamPose) //根据CCD在机械手基础坐标系下的姿态和目标在CCD坐标系下的姿态求解目标 //在机械手基础坐标系下的姿态,有了这个姿态就可以控制机械手去抓取这个目标 //这就是我们要进行手眼标下的最终目的 pose_compose (CamInBasePose, ObjInCamPose, ObjInBasePose) //设置3D坐标原点,MPInCamPose为新的3D位置,也就是在CCD坐标系下 //测量板的姿态 set_origin_pose (ObjInCamPoseRef, 0, 0, CalibrationPlateThickness - ObjectThickness, MPInCamPose) //保存在机械手下CCD的姿态 write_pose (CamInBasePose, 'cam_in_base_pose.dat') //保存相机的内参 write_cam_par (CameraParam, 'camera_parameters.dat') //保存在CCD坐标系下的测量板的姿态 write_pose (MPInCamPose, 'measurement_plane_in_cam_pose.dat')
可以看到,板定板的类型不是halcon那种玻璃标定板。
关于标定板的支持什么样的类型,还值得再研究一下。
2020.5.22 勇哥注:
halcon12开始支持下图所示的蜂窝标定板。
之前和之后的的halcon版本都支持阵列标定板。
即halcon12之后都支持两种类型的标定板。
本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:


