1.制作模板
dev_update_off ()dev_set_color ('green')dev_close_window ()WindowHeight:=740WindowWidth :=740dev_open_window(0, 0, 540, 540, 'black', WindowHandle)Instruction := ['Rotate: Left button','Zoom: Shift + left button','Move: Ctrl + left button']read_object_model_3d('./model/modelcalib3.om3','mm', [], [],ObjectModel3D, Status)triangulate_object_model_3d(ObjectModel3D, 'greedy', [], [], \Tri3D, Information)create_surface_model (Tri3D, 0.02, [], [], SurfaceModelID)Message := 'Surface model to be searched'pra_name:=['color_0','point_size_0','disp_pose']pra_value:=['magenta',1.0,'true']visualize_object_model_3d (WindowHandle, Tri3D, [], [], pra_name,pra_value, Message, [], Instruction, PoseOut)NumCalibrationScenes := 20
2.模板匹配
20組左右
dev_update_off ()dev_set_color ('green')dev_close_window ()WindowHeight:=740WindowWidth :=740dev_open_window(0, 0, 540, 540, 'black', WindowHandle)Instruction := ['Rotate: Left button','Zoom: Shift + left button','Move: Ctrl + left button']read_object_model_3d('./model/modelcalib3.om3','mm', [], [],ObjectModel3D, Status)triangulate_object_model_3d(ObjectModel3D, 'greedy', [], [], \Tri3D, Information)create_surface_model (Tri3D, 0.02, [], [], SurfaceModelID)Message := 'Surface model to be searched'pra_name:=['color_0','point_size_0','disp_pose']pra_value:=['magenta',1.0,'true']
* visualize_object_model_3d (WindowHandle, Tri3D, [], [], pra_name,pra_value, Message, [], Instruction, PoseOut)NumCalibrationScenes := 20ObjInCamPose5:=[]ObjInCamPose6:=[]ObjInCamPose7:=[]ObjInCamPose8:=[]ObjInCamPose9:=[]for I := 0 to 20 by 1read_object_model_3d('./scene/calib_scene/Object'+I, 'm', \[], [], ObjectScene, Status1)select_points_object_model_3d(ObjectScene, 'point_coord_z', \0.5, 700, ObjectZ)* find_surface_model(SurfaceModelID, ObjectZ, 0.02, 0.3, 0.6,\'false', [], [], ObjInCamPose, Score, SurfaceMatchingResultID)if(|Score|>=1)rigid_trans_object_model_3d(ObjectModel3D, ObjInCamPose, ObjectdTrans)pra_name:=['color_0','color_1','point_size_0','disp_pose']pra_value:=['green','magenta',1.0,'true']Message:=I+'/20'visualize_object_model_3d (WindowHandle, [ObjectZ,ObjectdTrans], [], [], \pra_name,pra_value, Message, [], Instruction, PoseOut)write_pose(ObjInCamPose, './calib/ObjInCamPose/ObjInCamPose'+I+'.dat')endif* stop()endfor
3.標定
dev_update_off ()dev_get_window(WindowHandle)* The number of files. 不要低于16, 低于16達不到精度NumCalibrationScenes :=20* 創建句柄 HECCalibDataID占內存,最終要銷毀create_calib_data ('hand_eye_stationary_cam', 0, 0, HECCalibDataID)*設置標定句柄的初始參數set_calib_data (HECCalibDataID, 'model', 'general', \'optimization_method', 'nonlinear')for I := 1 to 20 by 1*1.寫數據進入到標定句柄try*拍照點坐標Filename :='./calib/handeye/Pose' + (I)$'01d' + '.dat'read_pose (Filename, ToolInBasePose)ToolInBasePose[6]:=2convert_pose_type(ToolInBasePose, 'Rp+T', 'gba', 'point',ToolInBasePose1)*匹配點坐標read_pose('./calib/ObjInCamPose/ObjInCamPose' + I$'01d' + '.dat',ObjInCamPose)*兩個pose 都扔到句柄里面去,扔20次 機器人的歐拉角 轉換為 halcon 格式的歐拉角set_calib_data (HECCalibDataID, 'tool', I, 'tool_in_base_pose', ToolInBasePose)set_calib_data_observ_pose (HECCalibDataID, 0, 0, I, ObjInCamPose)catch (Exception)message:='第'+I+'個數據不存在'disp_message(WindowHandle, message, 'window', 12, 12, 'black', 'true')endtryendfor
stop()*2. 循環20次 分別向標定句柄 存放 ToolInBasePose和ObjInCamPose,20次, 注意一一對應關系,*ToolInBasePose*匹配全部結束 了 ,終于拿到了句柄HECCalibDataID!dev_clear_window ()disp_message (WindowHandle, 'Performing the hand-eye calibration', 'window', -1, -1, 'black', 'true')*3.計算標定*拍照點 ToolInBasePose1*工件在相機的坐標 ObjInCamPosecalibrate_hand_eye (HECCalibDataID, HECPoseError)*4.1獲取結果-兩個pose的保存get_calib_data (HECCalibDataID, 'camera', 0, 'base_in_cam_pose', BaseInCamPose)get_calib_data (HECCalibDataID, 'calib_obj', 0, 'obj_in_tool_pose',ObjInToolPose)*測試 ---動的pose是 計算不出來!*標定的結果, 通過20組 移動的ToolInBasePose,ObjInCamPose 標定出*兩個相對 不動的 BaseInCamPose ,0bjInToolPosewrite_pose(BaseInCamPose, './calib/BaseInCamPose.dat')write_pose(ObjInToolPose, './calib/ObjInToolPose.dat')*4.2 打印出來標定精度 誤差多少,量化的一個結果dev_clear_window ()Message := 'Quality of the results:'Message[1] := ' 'Message[2] := 'Translation errors in mm: 'MeanTransError := HECPoseError[0]MaxTransError := HECPoseError[2]MeanHECPoseError:=HECPoseError[1]MaxHECPoseError:=HECPoseError[3]Message[3] := 'root mean square ' + MeanTransError$'6.4f'Message[4] := 'maximum ' + MaxTransError$'6.4f'Message[5] := ' 'Message[6] := 'Rotation error in degrees: 'Message[7] := 'root mean square ' + HECPoseError[1]$'6.4f'Message[8] := 'maximum ' + HECPoseError[3]$'6.4f'stop ()disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')disp_continue_message (WindowHandle, 'black', 'true')query_calib_data_observ_indices (HECCalibDataID, 'camera', 0, CalibObjIdx, PoseIds)stop()
4.走點
* 使用 標定的時候 第一個點云*先得到點云 +匹配 read_pose('calib/ObjInCamPose/ObjInCamPose1.dat', ObjInCamPose)*固定拍照點*調取 兩個標定結果姿態read_pose('./calib/BaseInCamPose.dat', BaseInCamPose)
read_pose('./calib/ObjInToolPose.dat', ObjInToolPose)pose_invert(BaseInCamPose, CamInBasePose)
pose_invert(ObjInToolPose, ToolInObjPose)pose_compose(ObjInCamPose,ToolInObjPose,ToolInCamPose)
pose_compose(CamInBasePose, ToolInCamPose,ToolInBasePose)
*ToolInBasePose--- 驗證 旋轉軸是0
*換算成為機器人坐標系
convert_pose_type(ToolInBasePose, 'Rp+T', 'abg', 'point',ToolInBasePose2)if(ToolInBasePose2[3]>180)ToolInBasePose2[3]:=ToolInBasePose2[3]-360
endif
if(ToolInBasePose2[4]>180)ToolInBasePose2[4]:=ToolInBasePose2[4]-360
endif
if(ToolInBasePose2[5]>180)ToolInBasePose2[5]:=ToolInBasePose2[5]-360
endifstop()*[-264.325, -521.181, 138.24, -161.487, -1.92762, -167.703, 2]
*[-263.446, -521.104, 138.067, -161.598, -1.86336, -167.656, 2]*拍照值
read_pose('calib/handeye/Pose1.dat', CapToolInBasePose)*計算出抓取點
眼在手外:相機固定不動,機械臂夾住標定板來回變換
機械臂拍照點ToolInBasePose1
匹配點ObjInCamPose
通過手眼標定文件,找出兩個不動的點??? BaseInCamPose 和 0bjInToolPose
最后給出匹配點,通過兩個不動的點
求解出機械臂抓取點 ToolInBasePose2