Halcon之根据SCARA手眼标定来执行拾取和放置

Halcon之根据SCARA手眼标定来执行拾取和放置

  这个示例展示了如何使用SCARA机器人根据SCARA手眼校准确定的校准信息来执行拾取和放置应用程序。其主要分为两个部分:
  一是利用模型图像来定义目标的形状;
  二是根据形状模型,在每幅图像中寻找目标,对于选中的目标,计算机器人坐标,然后进行抓取。

(为了使示例适用于实际应用程序,必须通过摄像机获取图像,而不能从文件中读取)

* 为了使用提供的示例图像运行例程,必须将校正图像设置为true。
*
RectifyImages := true
* 
* 读取HDevelop示例程序中的calibrate_hand_eye_scara_stationary_cam和align_hand_eye_scara_stationary_cam.hdev之一提供的校准信息。

try
    * 读出手眼标定的结果
    * 从文本文件中读取相机外部的3D位姿
    read_pose ('cam_in_base_pose.dat', CamInBasePose)
    * 读取被抓取物体的位姿估算所需的数据
    * 从文本文件中读取相机内部参数
    read_cam_par ('camera_parameters.dat', CameraParam)
    * 读取在相机3D位姿上测量平面的的3D位姿,MPInCamPose为测量平面的3D位姿
    read_pose ('measurement_plane_in_cam_pose.dat', MPInCamPose)
catch (Exception)
    * 当文件的校准信息不能获取,则使用标注的校准信息代替
    * 要提供文件上的校准信息,运行halcon例程中的 calibrate_hand_eye_scara_stationary_cam.hdev
    * 或者 align_hand_eye_scara_stationary_cam.hdev
    CamInBasePose := [0.05592166548,0.19497621789,0.48025117245,180.09816119,29.85593363,179.94389014,0]
    CameraParam := [0.0165251,-642.277,4.65521e-006,4.65e-006,595.817,521.75,1280,1024]
    MPInCamPose := [0.0045679683065,-0.0028695297318,0.4088853425,359.78658429,29.732027579,0.22946472765,0]
endtry
* 
* 准备校准map以消除图像失真
if (RectifyImages)
    * 将测量平面的3D位姿的点坐标转换为摄像机坐标系的齐次3D变换矩阵
    prepare_rectification_map (Map, CameraParam, MPInCamPose, MappingScale, MPInCamPoseMapping)
    * 将图像点转换为z=0的世界坐标系平面
    image_points_to_world_plane (CameraParam, MPInCamPoseMapping, 0, 0, 'm', MapUpperLeftX, MapUpperLeftY)
endif
* 
dev_update_off ()
* 设置HALCON系统参数,border_shape_models利用多个算子寻找形状模型
set_system ('border_shape_models', 'true')
* 
* 此处, 应建立与机器人的连接,并将机器人移动到一个确定的备用位姿
* 以允许获取测量平面的无遮挡图像
* 
* 确定被抓去对象的形状模型

* - 获取用于模型生成的图像
read_image (Image, '3d_machine_vision/handeye/scara_stationary_cam_setup_01_metal_parts_04')
* 图像校正
if (RectifyImages)
    * 对图像进行一般变换
    map_image (Image, Map, ModelImage)
else 
    * 如果不需要校正,则复制图像并为它分配一个新内存
    copy_image (Image, ModelImage)
endif
* 
dev_close_window ()
dev_open_window_fit_image (ModelImage, 0, 0, 600, 600, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_clear_window ()
dev_display (ModelImage)
dev_set_line_width (2)
*
* - 创建形状模型
*
* 创建一个平行于坐标轴的矩形(也可以用算子画任意方向的矩形)
draw_rectangle1 (WindowHandle, Row1, Column1, Row2, Column2)
gen_rectangle1 (ModelROI, Row1, Column1, Row2, Column2)
* 使用离散高斯函数平滑图像
gauss_filter (ModelImage, ImageGauss, 5)
* 缩小图像的域,即将ROI区域分割出来 
reduce_domain (ImageGauss, ModelROI, ImageReduced)
* 为匹配准备一个形状模型
* use_polarity:图像中的物体和模型必须具有相同的对比度。例如,如果模型是暗背景上的亮物体,那么只有当物体比背景亮时才会被发现。
create_shape_model (ImageReduced, 'auto', rad(0), rad(360), 'auto', 'auto', 'use_polarity', [10,50], 'auto', ModelID)
* 获取形状模型的面积和中心坐标
area_center (ModelROI, ModelROIArea, ModelROIRow, ModelROIColumn)
* 显示基于形状匹配的结果
dev_display_shape_matching_results (ModelID, 'green', ModelROIRow, ModelROIColumn, 0, 1, 1, 0)
*
* - 确定物体上的抓取点,可以通过在图像中标识(仅当工具能够以任何方向抓取物体时)
*   也可以通过用机器人抓取并记录各个机器人的位姿
*   

DefineGraspingPointByRobot := true
* 通过机器人确定抓取点
if (DefineGraspingPointByRobot)
    dev_set_colored (12)
    * 抓取点模型的基本位姿(这里的参数都是提前设置好的,是关于模型图像中目标的坐标及角度)
    GraspingPointModelInBasePose := [0.26745,0.1645,0.1229,0,0,20.5672,0]
    * 将相机3D位姿中的每一个位姿进行反转
    pose_invert (CamInBasePose, BaseInCamPose)
    * 将反转后的3D位姿转换为齐次变换矩阵(进一步转换位姿)
    pose_to_hom_mat3d (BaseInCamPose, BaseInCamHomMat3D)
    * 将进一步转换后的位姿进行任意的放射变换
    affine_trans_point_3d (BaseInCamHomMat3D, GraspingPointModelInBasePose[0], GraspingPointModelInBasePose[1], GraspingPointModelInBasePose[2], Qx, Qy, Qz)
    * 把3D点投射到()像素图像坐标中
    project_3d_point (Qx, Qy, Qz, CameraParam, GraspingPointModelRow, GraspingPointModelColumn)
    * 抓取点模型的角度
    GraspingPointModelAngle := GraspingPointModelInBasePose[5]
    if (RectifyImages)
        * 计算校正后的图像坐标
        * 将图像点转换为z=0的世界坐标系平面 
        image_points_to_world_plane (CameraParam, MPInCamPoseMapping, GraspingPointModelRow, GraspingPointModelColumn, MappingScale, GraspingPointModelXMP, GraspingPointModelYMP)
        GraspingPointModelRow := GraspingPointModelYMP - MapUpperLeftY / MappingScale
        GraspingPointModelColumn := GraspingPointModelXMP - MapUpperLeftX / MappingScale
        * 在修正后的模型图像中显示抓取姿态
        get_image_size (ModelImage, WidthM, HeightM)
        CamParamRect := [0,0,MappingScale,MappingScale,-MapUpperLeftX / MappingScale,-MapUpperLeftY / MappingScale,WidthM,HeightM]
        GraspingPointModelXMP := MapUpperLeftX + GraspingPointModelColumn * MappingScale
        GraspingPointModelYMP := MapUpperLeftY + GraspingPointModelRow * MappingScale
        PoseCoordSystemVis := [GraspingPointModelXMP,GraspingPointModelYMP,0,0,0,GraspingPointModelAngle,0]
        dev_set_colored (12)
        disp_3d_coord_system (WindowHandle, CamParamRect, PoseCoordSystemVis, 0.02)
    else
        * 如果没有校正图像,则在原来的模型图像中显示抓取位姿 
        pose_invert (CamInBasePose, BaseInCamPose)
        * 组合两个元组中给出的3D位姿
        pose_compose (BaseInCamPose, GraspingPointModelInBasePose, PoseCoordSystemVis)
        dev_set_colored (12)
        disp_3d_coord_system (WindowHandle, CameraParam, PoseCoordSystemVis, 0.02)
    endif
    disp_message (WindowHandle, 'Model contours and grasping pose', 'window', 12, 12, 'black', 'true')
* 在图像中标识
else
    * 使用二值阈值分割图像
    binary_threshold (ImageReduced, Region, 'max_separability', 'light', UsedThreshold)
    * 填补区域的漏洞
    fill_up (Region, RegionFillUp)
    * 侵蚀具有矩形结构元素的区域
    erosion_rectangle1 (RegionFillUp, RegionErosion, 160, 1)
    * 确定区域的最小周边矩形,即包含该区域的所有矩形中面积最小的矩形
    smallest_rectangle2 (RegionErosion, GraspingPointModelRow, GraspingPointModelColumn, Phi, Length1, Length2)
    * 为输入的点生成一个十字形的XLD轮廓线
    gen_cross_contour_xld (GraspingPointModel, GraspingPointModelRow, GraspingPointModelColumn, 25, 0.785398)
    dev_set_color ('yellow')
    dev_display (GraspingPointModel)
    disp_message (WindowHandle, 'Model contours and grasping point', 'window', 12, 12, 'black', 'true')
endif
area_center (ModelROI, ModelROIArea, ModelROIRow, ModelROIColumn)
* 设置形状模型的原点(参考点)
set_shape_model_origin (ModelID, GraspingPointModelRow - ModelROIRow, GraspingPointModelColumn - ModelROIColumn)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
* 循环遍历图像中要被机器人抓取的物体
*
* 参数MPInCamPoseMapping的位姿变换 将测量平面的点坐标转换为摄像机坐标系的齐次三维变换矩阵
pose_to_hom_mat3d (MPInCamPoseMapping, MPInCamHomMat3DMapping)
for ImageIdx := 2 to 6 by 1
    * 获取下一张图像
    read_image (Image, '3d_machine_vision/handeye/scara_stationary_cam_setup_01_metal_parts_' + ImageIdx$'02d')
    * 
    * 对图像进行校正,以允许使用基于标准形状的匹配来搜索对象的实例
    *
    if (RectifyImages)
        map_image (Image, Map, SearchImage)
    else
        copy_image (Image, SearchImage)
    endif
    dev_clear_window ()
    dev_display (SearchImage)
    * 
    * 寻找对象实例
    * 在图像中寻找形状模型的最佳匹配(如果应该找到图像中所有超过MinScore的模型实例,则必须将NumMatches设置为0)
    find_shape_model (SearchImage, ModelID, rad(0), rad(360), 0.5, 0, 0.5, 'least_squares', [0,3], 0.9, Row, Column, Angle, Score)
    if (|Row| < 1)
        disp_message (WindowHandle, 'No objects found', 'window', 12, 12, 'black', 'true')
        continue
    endif
    * 
    * 选择一个特定的实例(这里:最左边)
    LeftmostIdx := sort_index(Column)[0]
    GraspingPointRow := Row[LeftmostIdx]
    GraspingPointColumn := Column[LeftmostIdx]
    GraspingPointAngle := Angle[LeftmostIdx]
    * 
    * 显示匹配结果,指示待抓取对象
    dev_display_shape_matching_results (ModelID, 'blue', Row, Column, Angle, 1, 1, 0)
    dev_display_shape_matching_results (ModelID, 'green', GraspingPointRow, GraspingPointColumn, GraspingPointAngle, 1, 1, 0)
    disp_message (WindowHandle, |Row| + ' objects found (Green: Object to be grasped)', 'window', 12, 12, 'black', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
    * 
    * 计算带固定摄像机的SCARA机器人要接近的点(ObjInBasePose:待抓取物体在机器人基底坐标系中的位姿)
    calculate_point_to_approach_scara_stationary (GraspingPointRow, GraspingPointColumn, GraspingPointAngle + rad(GraspingPointModelAngle), RectifyImages, MapUpperLeftX, MapUpperLeftY, MappingScale, MPInCamHomMat3DMapping, CameraParam, MPInCamPose, CamInBasePose, ObjInBasePose)
    * 
    * 被抓取物体连同抓取点一起显示
    dev_clear_window ()
    dev_display (SearchImage)
    dev_display_shape_matching_results (ModelID, 'green', GraspingPointRow, GraspingPointColumn, GraspingPointAngle, 1, 1, 0)
    * 
    dev_set_colored (12)
    if (RectifyImages)
        * 获取图像的宽高
        get_image_size (SearchImage, Width, Height)
        CamParamRect := [0,0,MappingScale,MappingScale,-MapUpperLeftX / MappingScale,-MapUpperLeftY / MappingScale,Width,Height]
        GraspingPointXMP := MapUpperLeftX + GraspingPointColumn * MappingScale
        GraspingPointYMP := MapUpperLeftY + GraspingPointRow * MappingScale
        PoseCoordSystemVis := [GraspingPointXMP,GraspingPointYMP,0,0,0,-deg(GraspingPointAngle) + GraspingPointModelAngle,0]
        * 显示坐标系的轴
        disp_3d_coord_system (WindowHandle, CamParamRect, PoseCoordSystemVis, 0.02)
    else
        pose_invert (CamInBasePose, BaseInCamPose)
        pose_compose (BaseInCamPose, ObjInBasePose, PoseCoordSystemVis)
        disp_3d_coord_system (WindowHandle, CameraParam, PoseCoordSystemVis, 0.02)
    endif
    * 
    disp_message (WindowHandle, '按F5抓取并放置指定的对象', 'window', 12, 12, 'black', 'true')
    disp_message (WindowHandle, ['ObjInBasePose:','Tx:    ','Ty:    ','Tz:    ','Alpha: ','Beta:  ','Gamma: '] + ['',ObjInBasePose[0:5]$'.3f' + [' m',' m',' m',' deg',' deg',' deg']], 'window', 305, 12, 'black', 'true')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
    * 如有必要,将姿态的平移部分转换为mm
    ToolInBasePoseMM := [ObjInBasePose[0:2] * 1000,ObjInBasePose[3:6]]
    * 
    * 抓取并放置对象
    * 
    * 在这里,应该将机器人移动到上述确定的对象(ToolInBasePoseMM)的位姿,
    * 在该位姿下,抓取对象,然后将其放置在某个预定义的位置(类似于PlacePositionInBasePoseMM)。
    * t最后,机器人应再次移动到备用姿态,以便拍摄测量平面的无遮挡图像。
    *
endfor
* 
* 在这里,与机器人的连接应该关闭。
* 
* 释放形状模型的内存
clear_shape_model (ModelID)
set_system ('border_shape_models', 'false')
dev_clear_window ()

猜你喜欢

转载自blog.csdn.net/Kevin_Sun777/article/details/108753352