Proeasy机器人:建立动态用户坐标系取料

首先视觉固定在机器人的Z轴丝杆中心搭配取料,在这过程中我们遇到了以下几个问题:

1.视觉与机械手标定后,发现视觉Y轴方向与机器人Y轴方向相反

2.建立用户坐标系后,物料进行旋转10度左右,进行拍照抓取发现角度没有问题,X和Y的方向不对

3.建立用户坐标系后,用相机中心和丝杆中心在用户坐标系的1号用户坐标,进行(0,0)原点移动,发现都不在视觉的mark中心,以镜像对称的方式移到了另外一边

4.在机械手标定,物料模板标定,机械手取料点标定的正确下,发现Y轴偏移值不对

针对上面的问题情况,分析出现的原因和采取对应的措施如下:

原因:前三个问题都出现在视觉与机械手标定,当视觉固定在Z轴上时,走九点标点方向就会相反

解决办法:在标定过程中,机械手往相反的方向跑就可以

原因:最后一个问题出现在视觉做mark点模板的时候,识别的特征点不对就会导致机械手取料位置不对

解决办法:重新做mark模板标定

-----------------------------------------------以下是封装的函数--------------------------------------------------------

--- <summary>*用三点示教定义和显示用户坐标系(本地坐标系)\n </summary>
--- <argument name="UF_Idx">用户坐标系编号,范围(1,9)。(type:number)\n </argument>
--- <argument name="select_plane">选择示教平面,0为XY平面,1为XZ平面(type:number)\n</argument>
--- <argument name="Base_point">原点。(type:table)\n</argument>
--- <argument name="X_point">X方向点。(type:table) \n</argument>
--- <argument name="Y_or_Z_point">Y方向或Z方向点。(type:table)\n</argument>
--- <argument name="ActiveTilt">启用倾斜,为1时启用,0或nil则不启用,可省略(type:number)\n</argument>
--- <argument name="ActiveOrthogonality">启用非正交,为1时启用,0或nil则不启用,可省略(type:number)\n</argument>
--- <argument name="XScale">X轴比例尺,单位:μm。可省略(type:number)\n</argument>
--- <argument name="YScale">Y轴或Z轴比例尺,单位:μm。可省略(type:number)\n</argument>
function Local(UF_Idx, select_plane, Base_point, X_point, Y_or_Z_point, ActiveTilt, ActiveOrthogonality, XScale, YScale)  --用户坐标系三点示教法
    --select_plane:0是XY平面,1是XZ平面。
    local tValid = _LUA_NONE_ERR
    local TmpValid = {}
    local tmpIdx = 1
    local TmpUserFrameP = {}
    local Pn = {}

    --传入参数错误判断
    if type(UF_Idx) ~= "number" or type(Base_point) ~= "table" or type(X_point) ~= "table" or type(Y_or_Z_point) ~= "table" or type(select_plane) ~= "number" then
        motion.ProgramStop(string.format("Function Local(): Argument input type is error!"))
        --print("Function Local(): Argument input type is error!", "\n")
        --tValid = _LUA_IP_TYPE_ERR
        --return tValid
    end

    if UF_Idx < 1 or UF_Idx > 9 then
        motion.ProgramStop(string.format("Function Local():Value of UF_Idx is out of range!"))
        --print("Function Local():Value of UF_Idx is out of range!", "\n")
        --tValid = _LUA_IP_OUT_RANGE_ERR
        --return tValid
    end

    if type(ActiveTilt) ~= "nil" then
        if type(ActiveTilt) ~= "number" then
            motion.ProgramStop(string.format("Function Local(): Type of ActiveTilt is error!"))
            --print("Function Local(): Type of ActiveTilt is error!", "\n")
            --tValid = _LUA_IP_OUT_RANGE_ERR
            --return tValid
        else
            if ActiveTilt < 0 or ActiveTilt > 1 then
                 motion.ProgramStop(string.format("Function Local():Value of ActiveTilt is out of range!"))
                --print("Function Local():Value of ActiveTilt is out of range!", "\n")
                --tValid = _LUA_IP_OUT_RANGE_ERR
                --return tValid
            end
        end
    end

    if type(ActiveOrthogonality) ~= "nil" then
        if type(ActiveOrthogonality) ~= "number" then
            motion.ProgramStop(string.format("Function Local(): Type of ActiveOrthogonality is error!"))
            --print("Function Local(): Type of ActiveOrthogonality is error!", "\n")
            --tValid = _LUA_IP_OUT_RANGE_ERR
            --return tValid
        else
            if ActiveOrthogonality < 0 or ActiveOrthogonality > 1 then
                   motion.ProgramStop(string.format("Function Local():Value of ActiveOrthogonality is out of range!"))
                --print("Function Local():Value of ActiveOrthogonality is out of range!", "\n")
                --tValid = _LUA_IP_OUT_RANGE_ERR
                --return tValid
            end
        end
    end

    --索引值
    local function_code_write_teach_buffer_1 = 0x00010013
    local function_code_write_teach_buffer_2 = 0x01010013
    local function_code_write_teach_buffer_3 = 0x02010013

    --功能码
    local function_code_write_uf_volatile_teach_Point_1 = 0x00011142 + (UF_Idx*0x01000000) ----------原点
    local function_code_write_uf_volatile_teach_Point_2 = 0x00012142 + (UF_Idx*0x01000000) -------X方向点
    local function_code_write_uf_volatile_teach_Point_3 = 0x00013142 + (UF_Idx*0x01000000) --Y or Z方向点
    local function_code_write_uf_XY_Cal = 0x00000141 + (UF_Idx*0x01000000) ----------------计算XY平面教导点
    local function_code_write_uf_XZ_Cal = 0x00001141 + (UF_Idx*0x01000000) ----------------计算XZ平面教导点
    local function_code_write_uf_Active_Tile_Or = 0x00012F42 + (UF_Idx * 0x01000000) ---------倾斜与非正交
    local function_code_write_uf_Active_Scale = 0x00014142 + (UF_Idx * 0x01000000) -----------X,Y轴比例尺
    local function_code_save_uf_to_non_volatile_data = 0x00010D41 + (UF_Idx*0x01000000) ---保存使用者坐标系

    --写入原点
    for k,v in pairs(Base_point) do
        Pn[k] = v
    end
    setmetatable(Pn, P.mt)
    TmpUserFrameP = Pn
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.x)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_2)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.y)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_3)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.z)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_volatile_teach_Point_1)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)

    --写入X方向点
    for k,v in pairs(X_point) do
        Pn[k] = v
    end
    setmetatable(Pn, P.mt)
    TmpUserFrameP = Pn
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.x)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_2)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.y)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_3)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.z)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_volatile_teach_Point_2)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)

    --写入Y方向点
    for k,v in pairs(Y_or_Z_point) do
        Pn[k] = v
    end
    setmetatable(Pn, P.mt)
    TmpUserFrameP = Pn
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.x)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_2)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.y)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_3)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, TmpUserFrameP.z)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_volatile_teach_Point_3)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)

    --倾斜与非正交
    --TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
    --tmpIdx = tmpIdx + 1
    --DELAY(0.004)
    local tmpActiveTile = 0
    local tmpValue = 0

    if ActiveTilt == 1 then
        tmpActiveTile = 1
    else
        tmpActiveTile = 0  ---------------ActiveTilt(倾斜)为nil或0
    end

    local tmpOrthogonality = 0
    if ActiveOrthogonality == 1 then
        tmpOrthogonality = 2
    else
        tmpOrthogonality = 0  --ActiveOrthogonality(非正交)为nil或0
    end

    tmpValue = tmpActiveTile + tmpOrthogonality;
    TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 08, tmpValue)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)
    TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_Active_Tile_Or)
    tmpIdx = tmpIdx + 1
    DELAY(0.004)

    --X,Y轴比例尺
    if (type(XScale) ~= "nil" and type(YScale) ~= "nil") then
        TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_1)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        TmpValid[tmpIdx] = para.Write(0, 2, 08, XScale)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        TmpValid[tmpIdx] = para.Write(0, 2, 07, function_code_write_teach_buffer_2)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        TmpValid[tmpIdx] = para.Write(0, 2, 08, YScale)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_Active_Scale)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)

    elseif (type(XScale) == "nil" and type(YScale) ~= "nil") then
        motion.ProgramStop(string.format("Function Local():Value of XScale is nil!"))
        --print("Function Local():Value of YScale is nil!")
        --tValid = _LUA_IP_NIL
        --return tValid

      elseif (type(XScale) ~= "nil" and type(YScale) == "nil") then
        motion.ProgramStop(string.format("Function Local():Value of YScale is nil!"))
        --print("Function Local():Value of XScale is nil!")
        --tValid = _LUA_IP_NIL
        --return tValid
    end

    --计算XY或XZ平面教导点
    if select_plane == 0 then  ------XY平面
        TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_XY_Cal)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        --TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_save_uf_to_non_volatile_data)
        --DELAY(0.004)
    elseif select_plane == 1 then  --XZ平面
        TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_write_uf_XZ_Cal)
        tmpIdx = tmpIdx + 1
        DELAY(0.004)
        --TmpValid[tmpIdx] = para.Write(0, 2, 06, function_code_save_uf_to_non_volatile_data)
        --DELAY(0.004)
    else
        motion.ProgramStop(string.format("Function Local():Select a plane error!"))
        --print("Function Local():Select a plane error!")
        --tValid = _LUA_IP_NIL
        --return tValid
    end

    --for i = 1, tmpIdx do
        --if (TmpValid[i] > 0x00) then
            --print("Function Local(): Parameters written fail!")
            --tValid = _LUA_PARA_W_ERR
            --return tValid
        --end
    --end

    return tValid
end

function UF_Model(UF_Idx,X,Y,C)   --接收视觉发的值建立用户坐标系(注意:视觉发送过来的角度,单位°)
    
    tcmd, Here = motion.GetFeedbackPosition(1)
    
    P_1 = P.new(X, Y, 0, 0, 0, 0, Here.Elbow, Here.Shoulder, Here.Flip, Here.PS, Here.UF, Here.TF, Here.Coord)        --Mark点
    
    P_2_x = 100000 * math.cos(math.rad(C))            --X方向点
    P_2_y = 100000 * math.sin(math.rad(C))
    P_2 = CopyPoint(P_1)
    P_2.x = X + P_2_x
    P_2.y = Y + P_2_y
    
    P_3_x = 100000 * math.cos(math.rad(C + 90))        --Y方向点
    P_3_y = 100000 * math.sin(math.rad(C + 90))
    P_3 = CopyPoint(P_1)
    P_3.x = X + P_3_x
    P_3.y = Y + P_3_y
    
    --print(P_2_x, ",", P_2_y, ", ", P_3_x, ", ", P_3_y, "\n")
    Local(UF_Idx, 0, P_1, P_2, P_3)                        --生成用户坐标系
    
end


-------------------------------------------以下是动作流程-----------------------------------------------------------------

-
    FreePort.ECM_Close(1)    --打开以太网作为客户端
    repeat
        FreePort.ECM_OpenAsClient(1,"192.168.1.10",60000,nil,CR_LF)
        local aa = FreePort.ECM_ChkConnect(1)
        DELAY(0.1)
    until aa == 0
    
    print('相机连接成功',"\n")
   
    FreePort.ECM_Clear(1)
    FreePort.ECM_Tx(1,"M1".."\r")
    
    repeat
    tcmd,CCDdata=FreePort.ECM_Rx(1)
    until tcmd==0
    
    data=string.split(CCDdata,",")
    
   
    print(data[1],"\n")
    print(data[2],"\n")
    print(data[3],"\n")


    -------------------------------------有两种方法去建立动态用户坐标系--------------------------------------

-----------第一种:使用自己封装的函数去实现


    UF_Model(1,data[1]*1000,data[2]*1000,data[3]*1)     --建立用户坐标系


    --算出视觉mark模板和机械手取料点之间的XY偏差(还用一种方法,生成用户坐标系后,直接用户           坐标系教导点位直接跑)
    X_pianyi = 376761  - 501153                   
    Y_pianyi = -320074 + 249979                
    Quliao = P.new(X_pianyi,Y_pianyi,-201618,0,0,-92729,1,0,0,0,1,0,1)

    MovL(Quliao .. P.Z(-50000))
    MovL(Quliao)

------------第二种:使用台达提供的功能指令


    UF.Clear(2)       --先清除上一个用户坐标系
    UF.Update.dXYZABC(2,0,data[1]*1000,data[2]*1000,0,0,0,data[3]*1000)     --建立用户坐标系
    UF.Retain.dXYZABC(2)         --写入用户坐标系
    ModbusWrite16(0x1B00,1)    ---拍照完成
    
    --生成用户坐标系后,用 用户坐标系教导点位3号点
    MovL(Quliao .. P.Z(-50000))
    MovL(3)
  

猜你喜欢

转载自blog.csdn.net/weixin_52300845/article/details/124310292