机器人手眼标定快速精度验证方法

这篇具有很好参考价值的文章主要介绍了机器人手眼标定快速精度验证方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、原理及流程

        机器人的手眼标定原理在本文中不再过多描述,基本流程都是先标定相机的内外参数,然后标定两台相机之间的位置关系,如果相机是可以转动的话,还要标定转台与机械臂之间的关系。

        在手眼标定完成后,怎么确定标定结果是否准确呢?传统方法是利用指点验证的办法去进行测试,就是在手眼标定完成后,将棋盘格摆在相机视野范围内,然后双目相机计算出棋盘格角点坐标X、Y、Z,然后把计算的坐标结果,利用坐标系转换至机器人坐标系下X1、Y1、Z1,控制机械臂移动至刚才的X1、Y1、Z1坐标处,看看棋盘格角点与机械臂指点工具末端相差多少,如下图所示。这样本质上没有问题,只是速度会比较慢,而且经验不足的话,末端会撞到标定板。

aruco标定板,机器人手眼标定及精度验证,机器人,python,scipy,numpy,conda

         本文是借助了aruco标定板,这个标定板本身就是可以用于机械臂手眼标定的,在Python里面是有现成的程序的,在Linux里面配置好ROS直接调用就可以

aruco制作的链接:Online ArUco markers generator (chev.me)

aruco手眼标定方法的链接:手眼标定——使用 easy_handeye 和 aruco_马天乐233的博客-CSDN博客_easyhandeye

基于ROS的机械臂手眼标定-Aruco使用与相机标定_鱼香ROS的博客-CSDN博客_aruco标定

Kinect v2 在ros上利用easy_handeye进行手眼标定 - 古月居 (guyuehome.com)

        假如说每次相机工作都要转到不同的角度去识别不同的东西,可以在每个相机工作的角度都标定一次手眼关系,到达那个位置就调用哪个位置的标定文件。本文此次介绍的是其中一个位置,就拿初始位置,记作00位,来介绍精度验证原理及流程:

1、手眼标定的的本质就是在进行坐标系变换,存在两种情况(眼在手外、眼在手上),两者的区别是,眼在手外标定结果是相机与机器人基坐标系之间的关系,眼在手上标定结果是相机与机械臂末端之间的关系。

2、了解了基本情况后,如何实现坐标系转换呢,本文所建立的快速精度验证的方法,是建立在机械臂精度满足要求且没有故障的情况下。借助aruco板,通过相机识别aruco板,能够得出aruco板中心在相机坐标系下的坐标(这一步是ROS里面那个标定方法自带的,只要是相机能够看到板子,就会计算出中心坐标,并标记出坐标轴),如图所示,将坐标利用手眼标定关系转换到机器人基坐标系下,即为aruco坐标的测量值

aruco标定板,机器人手眼标定及精度验证,机器人,python,scipy,numpy,conda

 3.怎么得出机器人基坐标系下,aruco中心点的真实坐标呢,这个需要借用机器人软件了,因为机器人软件一般都会有一个功能,就是实时显示机械臂末端点在基坐标系下的坐标,这个坐标也是可以自己写程序获取到的。借助标定工装,利用标定工装三维图里的数据,得到标定工装的实际长度,在机器人软件里面把末端工具的长度加进去就可以了,工装如图所示,根据实际情况自己设计加工。这样就得到了aruco标定板中心的坐标在机器人基座标系下的真实值。

aruco标定板,机器人手眼标定及精度验证,机器人,python,scipy,numpy,conda

 4、需要注意的是,本次方法的前提是:①机器人精度满足要求且没有故障,这个一般都没有问题,应该都是各单位自己正在使用的产品;②双目标定的结果是准确的,目前还是根据重投影误差来初步判断,标定的时候注意光线,焦距等问题。标定板尽量买精度高一点的,这样的话还可以用来测试双目标定是否准确,比如说棋盘格角点间距是30cm,以此为真实值,利用双目识别两个角点,计算出来的间距为测量值,也可以判断双目结果是否准确。

5、怎么实现坐标系转化的过程呢,这一步需要理解下坐标系转换的过程

姿态矩阵表达:

  • Rij:表示从i坐标系到j坐标系的旋转矩阵,注意是从第一个小写字母表达的坐标系到第二个小写字母表达的坐标系;
  • Rik=Rjk*Rij:表示坐标系i到坐标系k的姿态矩阵传递链,中间通过坐标系j过度,注意矩阵相乘顺序;

        目前已知的是,相机坐标系下的aruco中心坐标为p_c_a,由标定结果可得机器人基坐标系到相机坐标系的旋转、平移矩阵为 Rjc,Tjc ,那么根据坐标系转换关系,可得aruco中心坐标在机器人基坐标系下的坐标为p_j_a = Rjc * p_c_a + Tjc 

二、精度检测程序运行流程

        1、打开节点,调用相机实时显示aruco坐标

                rostopic echo /aruco_tracking/pose

        2、想办法获取到坐标数据,我用的方法比较粗暴,直接录制一段数据,然后把rosbag数据再转成txt,程序去读取txt

                rosbag record -O aruco --duration=5 /aruco_tracking/pose

                rostopic echo -b aruco.bag /aruco_tracking/pose > aruco.txt

        3、精度检测代码,眼在手外,代码如下:

#文件名称auto_verify.py
#功能:快速精度验证
#作者:laoli
#类型: 眼在手外

import pandas
import os
from scipy.spatial.transform import Rotation as R
import numpy as np
import time
import datetime
import socket
import struct

#读取TXT文件,
def read_tablemethod(filename):
    data2 = pandas.read_table(filename, header=None, delim_whitespace=True)
    return data2

#此处暂时没有用到
def readFile(filepath):
    f1 = open(filepath, "r")
    nowDir = os.path.split(filepath)[0]
    fileName = os.path.split(filepath)[1]
    newFileDir = os.path.join(nowDir, "python" + fileName)
    # print("nowDir",nowDir)
    # print("fileName",fileName)
    print("newFileDir",newFileDir)
    fnew = open(newFileDir, "w")

    content = f1.read()
    # s = [i for i in content if (str.isdigit(i) or i == '.' or i == '\n')] 等价于
    s = []  # s是个字符list
    for i in content:
        # 保留数字,小数点、空格与换行符
        if (str.isdigit(i) or i == '.' or i == '\n' or i == ''):
            s.append(i)
        # 将冒号换空格
        elif i == ':':
            s.append(' ')
    s2 = ''.join(s)
    fnew.write(s2)

    f1.close()
    fnew.close()

#此处暂时没有用到
def eachFile(filepath):
    pathDir = os.listdir(filepath)
    for s in pathDir:
        newDir = os.path.join(filepath, s)
        if os.path.isfile(newDir):
            if os.path.splitext(newDir)[1] == ".txt":
                readFile(newDir)
                pass
        else:
            eachFile(newDir)

#读取R、T矩阵数据
def zhuanhuan_rt():
    result = []
    folder = '/opt/ros/calibration'#手眼标定结果的路径
    for f in os.listdir(folder):
        if f.endswith('00_rs_left.txt'):
            with open(os.path.join(folder, f), 'r') as r:
                data4 = r.read().split('\n')


                # print("data4", data4)
            for i in data4:
                result.append(i.split(':')[-1])
            # result = map(float, result)
            # print("result", result)
            # print("list",list(result))
    with open('00_rs_left_result.txt','w') as r1:
        r1.write('\n'.join([i for i in result]))
    lines = open('00_rs_left_result.txt', 'r').readlines()
    fp = open('00_rs_left_result.txt', 'w')
    for s in lines:
        fp.write(s.replace(' ', ''))
    fp.close()

    return result
#读取aruco中心坐标
def zhuanhuan_xyz():
    result = []
    folder = '/opt/ros/calibration'#aruco存储结果的路径
    for f in os.listdir(folder):
        if f.endswith('aruco.txt'):
            with open(os.path.join(folder, f), 'r') as r:
                data4 = r.read().split('\n')
            for i in data4:
                result.append(i.split(':')[-1])
            # result = map(float, result)
            # print("result", result)
            # print("list", list(result))
    with open('aruco_result.txt','w') as r1:
        r1.write('\n'.join([i for i in result]))
    lines = open('aruco_result.txt', 'r').readlines()
    fp = open('aruco_result.txt', 'w')
    for s in lines:
        fp.write(s.replace(' ', ''))
    fp.close()

    return result

#读取机械臂数据,在这里我需要得到的是末端工具的坐标,也就是aruco在机器人基坐标系下的X,Y,Z
def jixiebi_xyz():

    PORT = 30003  # The same port as used by the server
    HOST = '192.168.x.xx'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    dic = {'MessageSize': 'i', 'Time': 'd', 'q target': '6d', 'qd target': '6d', 'qdd target': '6d',
           'I target': '6d',
           'M target': '6d', 'q actual': '6d', 'qd actual': '6d', 'I actual': '6d', 'I control': '6d',
           'Tool vector actual': '6d', 'TCP speed actual': '6d', 'TCP force': '6d', 'Tool vector target': '6d',
           'TCP speed target': '6d', 'Digital input bits': 'd', 'Motor temperatures': '6d', 'Controller Timer': 'd',
           'Test value': 'd', 'Robot Mode': 'd', 'Joint Modes': '6d', 'Safety Mode': 'd', 'empty1': '6d',
           'Tool Accelerometer values': '3d',
           'empty2': '6d', 'Speed scaling': 'd', 'Linear momentum norm': 'd', 'SoftwareOnly': 'd',
           'softwareOnly2': 'd', 'V main': 'd',
           'V robot': 'd', 'I robot': 'd', 'V actual': '6d', 'Digital outputs': 'd', 'Program state': 'd',
           'Elbow position': '3d', 'Elbow velocity': '3d'}

    data = s.recv(1108)
    # print (data)
    names = []
    ii = range(len(dic))
    for key, i in zip(dic, ii):
        fmtsize = struct.calcsize(dic[key])
        data1, data = data[0:fmtsize], data[fmtsize:]
        fmt = "!" + dic[key]
        names.append(struct.unpack(fmt, data1))
        dic[key] = dic[key], struct.unpack(fmt, data1)
    b = dic["Tool vector actual"]
    # print(b)
    # print("x: ", b[1][0])
    # print("y: ", b[1][1])
    # print("z: ", b[1][2])

    return b[1][0]*1000, b[1][1]*1000, b[1][2]*1000



if __name__=="__main__":

    #将录制转换后的aruco.txt,进一步剔除无用数据,得到aruco_result.txt
    result_xyz = zhuanhuan_xyz()
    #读取aruco_result.txt中aruco的xyz坐标
    data = read_tablemethod('aruco_result.txt')
    p_c_a = np.mat([[float(data[0][4])], [float(data[0][5])], [float(data[0][6])]])
    print("p_c_a",p_c_a)
    #读取标定结果中的旋转向量,注意此处是旋转向量,下面还需要转换成旋转矩阵
    result_rt = zhuanhuan_rt()
    Rq_a = [result_rt[5], result_rt[6], result_rt[7], result_rt[8]]
    print("Rq_a", Rq_a)
    #读取平移矩阵
    data_t = read_tablemethod('00_rs_left_result.txt')
    T = np.mat([[data_t[0][0]], [data_t[0][1]], [data_t[0][2]]])
    print("T", T)
    #旋转向量转化成旋转矩阵
    Rm = R.from_quat(Rq_a)
    # print("R", R)
    rotation_matrix = Rm.as_matrix()
    print('rotation:\n', rotation_matrix)
    #查看逆矩阵
    R = np.linalg.inv(rotation_matrix)
    print('linalg_rotation:\n', R)
    #计算机器人基坐标系下,aruco的坐标
    pa = rotation_matrix * p_c_a + T
    #精度检测,实际就是真实值与测量值求差
    print("********************position verify******************************")
    print("pa x,y,z ", -pa[0]*1000, -pa[1]*1000, pa[2]*1000)
    # print("pa", type(pa[0]))
    #在这里,xy坐标取负数的原因是在项目的实际应用时,把机器人的轴系正好旋转了180度
    #需要自己手动给补回来,这块当时也是困扰了好久,最后才发现是机器人坐标系定义的问题
    a = str(-pa[0]*1000)
    b = str(-pa[1]*1000)
    c = str(pa[2]*1000)
    d = a+b+c
    tim1 = datetime.datetime.now()
    #转换成字符串
    a1 = float(-pa[0] * 1000)
    b1 = float(-pa[1] * 1000)
    c1 = float(pa[2] * 1000)
    #读取机械臂上末端的数据,也就aruco坐标真实值
    jx, jy, jz = jixiebi_xyz()
    print(" jx, jy ,jz", jx, jy , jz)
    jx1 = str(jx)
    jy1 = str(jy)
    jz1 = str(jz)
    dj = jx1 + ',' + jy1 + ',' + jz1

    #计算误差
    pa1 = (a1 - jx, b1 - jy, c1 - jz)
    print("diff value", pa1)
    a3 = str(pa1[0])
    b3 = str(pa1[1])
    c3 = str(pa1[2])
    d3 = a3 + ',' + b3 + ',' + c3
    e3 = a3 + ' ' + b3 + ' ' + c3
    #保存结果
    with open ( '/opt/ros/00_verify_result.txt','a+') as f:
        [f.write(str(tim1) + d + '[' + dj + ']' + '[' + d3 + ']' + '\n') for item in pa[0]]
        f.close()
    #保存结果另外一个文件中,如果满足精度要求,数值置1,否则置零
    #此处的目的是为了连续精度验证,在a位置精度验证完成后,检测是或合格,合格则转入b位置
    with open ( '/opt/ros/00_rs_left_verify_result_single.txt','w') as f:
        if ((a1 - jx) < 1000 and (b1 - jy)< 1000 and (c1 - jz)< 1000):
            [f.write(e3 + ' ' + '1') for item in pa[0]]
            f.close()
            print("calib 00 position  is ok ")
        else:
            print("calib position 00 again")
            [f.write(e3 + ' ' + '0') for item in pa[0]]
            f.close()

        4 、运行脚本如下:

#!/bin/bash

#source /opt/ros/melodic/setup.bash
echo "work start !"


#录制节点信息
gnome-terminal -t "rostopic" -x bash -c "cd /opt/ros && rostopic echo /aruco_tracking/pose;exec bash"
gnome-terminal -t "rosbag" -x bash -c "cd /opt/ros && rosbag record -O aruco --duration=5 /aruco_tracking/pose ;exec bash"

sleep 8

gnome-terminal -t "txt" -x bash -c "rostopic echo -b aruco.bag /aruco_tracking/pose > aruco.txt ;exec bash"

sleep 3 

gnome-terminal -t "verify_hand2eye_auto" -x bash -c "export PATH=/home/ros/anaconda3/bin:$PATH && source activate && conda activate net  && python auto_verify.py;exec bash"






5、精度检测代码,眼在手上,代码如下: 文章来源地址https://www.toymoban.com/news/detail-786598.html

#眼在手上,快速精度验证程序
#与眼在手外不同的是,眼在手上需要读取两个机械臂数据,一个是aruco坐标,一个将手眼标定结果,转换至基坐标系

import pandas
import os
from scipy.spatial.transform import Rotation as R
import numpy as np
import  time
import datetime
import socket
import struct
import cv2



def read_tablemethod(filename):
    data2 = pandas.read_table(filename, header=None, delim_whitespace=True)
    return data2


def readFile(filepath):
    f1 = open(filepath, "r")
    nowDir = os.path.split(filepath)[0]
    fileName = os.path.split(filepath)[1]
    newFileDir = os.path.join(nowDir, "python" + fileName)
    # print("nowDir",nowDir)
    # print("fileName",fileName)
    print("newFileDir",newFileDir)
    fnew = open(newFileDir, "w")

    content = f1.read()
    # s = [i for i in content if (str.isdigit(i) or i == '.' or i == '\n')] 等价于
    s = []  # s是个字符list
    for i in content:
        # 保留数字,小数点、空格与换行符
        if (str.isdigit(i) or i == '.' or i == '\n' or i == ''):
            s.append(i)
        # 将冒号换空格
        elif i == ':':
            s.append(' ')
    s2 = ''.join(s)
    fnew.write(s2)
    f1.close()
    fnew.close()


def eachFile(filepath):
    pathDir = os.listdir(filepath)
    for s in pathDir:
        newDir = os.path.join(filepath, s)
        if os.path.isfile(newDir):
            if os.path.splitext(newDir)[1] == ".txt":
                readFile(newDir)
                pass
        else:
            eachFile(newDir)


def zhuanhuan_rt():
    result = []
    folder = '/opt/ros/calibration'
    for f in os.listdir(folder):
        if f.endswith('eyeinhand_right.txt'):
            with open(os.path.join(folder, f), 'r') as r:
                data4 = r.read().split('\n')
            for i in data4:
                result.append(i.split(':')[-1])

    with open('right_arm_result.txt','w') as r1:
        r1.write('\n'.join([i for i in result]))
    lines = open('right_arm_result.txt', 'r').readlines()
    fp = open('right_arm_result.txt', 'w')
    for s in lines:
        fp.write(s.replace(' ', ''))
    fp.close()

    return result

def zhuanhuan_xyz():
    result = []
    folder = '/opt/ros/calibration'
    for f in os.listdir(folder):
        if f.endswith('aruco.txt'):
            with open(os.path.join(folder, f), 'r') as r:
                data4 = r.read().split('\n')
            for i in data4:
                result.append(i.split(':')[-1])
            # result = map(float, result)
            # print("result", result)
            # print("list", list(result))
    with open('aruco_result.txt','w') as r1:
        r1.write('\n'.join([i for i in result]))
    lines = open('aruco_result.txt', 'r').readlines()
    fp = open('aruco_result.txt', 'w')
    for s in lines:
        fp.write(s.replace(' ', ''))
    fp.close()

    return result


def jixiebi_rightarm_xyz():

    PORT = 30003  # The same port as used by the server
    HOST = '192.168.x.xx'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    dic = {'MessageSize': 'i', 'Time': 'd', 'q target': '6d', 'qd target': '6d', 'qdd target': '6d',
           'I target': '6d',
           'M target': '6d', 'q actual': '6d', 'qd actual': '6d', 'I actual': '6d', 'I control': '6d',
           'Tool vector actual': '6d', 'TCP speed actual': '6d', 'TCP force': '6d', 'Tool vector target': '6d',
           'TCP speed target': '6d', 'Digital input bits': 'd', 'Motor temperatures': '6d', 'Controller Timer': 'd',
           'Test value': 'd', 'Robot Mode': 'd', 'Joint Modes': '6d', 'Safety Mode': 'd', 'empty1': '6d',
           'Tool Accelerometer values': '3d',
           'empty2': '6d', 'Speed scaling': 'd', 'Linear momentum norm': 'd', 'SoftwareOnly': 'd',
           'softwareOnly2': 'd', 'V main': 'd',
           'V robot': 'd', 'I robot': 'd', 'V actual': '6d', 'Digital outputs': 'd', 'Program state': 'd',
           'Elbow position': '3d', 'Elbow velocity': '3d'}

    data = s.recv(1108)
    # print (data)
    names = []
    ii = range(len(dic))
    for key, i in zip(dic, ii):
        fmtsize = struct.calcsize(dic[key])
        data1, data = data[0:fmtsize], data[fmtsize:]
        fmt = "!" + dic[key]
        names.append(struct.unpack(fmt, data1))
        dic[key] = dic[key], struct.unpack(fmt, data1)
    b = dic["Tool vector actual"]
    print("b",b)
    # print("x: ", b[1][0])
    # print("y: ", b[1][1])
    # print("z: ", b[1][2])

    return b[1][0]*1000, b[1][1]*1000, b[1][2]*1000, b[1][3], b[1][4], b[1][5]

def jixiebi_leftarm_xyz():

    PORT = 30003  # The same port as used by the server
    HOST = '192.168.xx.xx'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    dic = {'MessageSize': 'i', 'Time': 'd', 'q target': '6d', 'qd target': '6d', 'qdd target': '6d',
           'I target': '6d',
           'M target': '6d', 'q actual': '6d', 'qd actual': '6d', 'I actual': '6d', 'I control': '6d',
           'Tool vector actual': '6d', 'TCP speed actual': '6d', 'TCP force': '6d', 'Tool vector target': '6d',
           'TCP speed target': '6d', 'Digital input bits': 'd', 'Motor temperatures': '6d', 'Controller Timer': 'd',
           'Test value': 'd', 'Robot Mode': 'd', 'Joint Modes': '6d', 'Safety Mode': 'd', 'empty1': '6d',
           'Tool Accelerometer values': '3d',
           'empty2': '6d', 'Speed scaling': 'd', 'Linear momentum norm': 'd', 'SoftwareOnly': 'd',
           'softwareOnly2': 'd', 'V main': 'd',
           'V robot': 'd', 'I robot': 'd', 'V actual': '6d', 'Digital outputs': 'd', 'Program state': 'd',
           'Elbow position': '3d', 'Elbow velocity': '3d'}

    data = s.recv(1108)
    # print (data)
    names = []
    ii = range(len(dic))
    for key, i in zip(dic, ii):
        fmtsize = struct.calcsize(dic[key])
        data1, data = data[0:fmtsize], data[fmtsize:]
        fmt = "!" + dic[key]
        names.append(struct.unpack(fmt, data1))
        dic[key] = dic[key], struct.unpack(fmt, data1)
    b = dic["Tool vector actual"]
    print("b",b)
    # print("x: ", b[1][0])
    # print("y: ", b[1][1])
    # print("z: ", b[1][2])

    return b[1][0]*1000, b[1][1]*1000, b[1][2]*1000, b[1][3], b[1][4], b[1][5]

if __name__=="__main__":



    result_xyz = zhuanhuan_xyz()
    data = read_tablemethod('aruco_result.txt')
   
   
    p_c_a = np.mat([[float(data[0][4])], [float(data[0][5])], [float(data[0][6])]])
    print("p_c_a",p_c_a)
   
    result_rt = zhuanhuan_rt()
    Rq_a = [result_rt[5], result_rt[6], result_rt[7], result_rt[8]]
    print("Rq_a", Rq_a)

    data_t = read_tablemethod('right_arm_result.txt')
    T = np.mat([[data_t[0][0]], [data_t[0][1]], [data_t[0][2]]])
    print("T", T)

    Rm = R.from_quat(Rq_a)
    rotation_matrix = Rm.as_matrix()
    print('rotation:\n', rotation_matrix)

    R = np.linalg.inv(rotation_matrix)
    print('linalg_rotation:\n', R)
    
    pa = rotation_matrix * p_c_a + T
    pa1 = (-pa[0]*1000, -pa[1]*1000, pa[2]*1000)
    print("********************check arm camera ******************************")
    print("pa x,y,z ", -pa[0]*1000, -pa[1]*1000, pa[2]*1000)
    # print("pa", type(pa[0]))
    a = str(-pa[0]*1000)
    b = str(-pa[1]*1000)
    c = str(pa[2]*1000)
    d= a+b+c
    tim1 = datetime.datetime.now()

    a1 = float(-pa[0] * 1000)
    b1 = float(-pa[1] * 1000)
    c1 = float(pa[2] * 1000)

    jrx, jry, jrz, RX, RY, RZ = jixiebi_rightarm_xyz()

    print(" jrx, jry ,jrz", jrx, jry, jrz)
    jx1 = str(jrx)
    jy1 = str(jry)
    jz1 = str(jrz)
    dj = jx1 + ',' + jy1 + ',' + jz1


    pa1 = (a1 - jrx, b1 - jry, c1 - jrz)
    print("diff value", pa1)
    a3 = str(pa1[0])
    b3 = str(pa1[1])
    c3 = str(pa1[2])
    d3 = a3 + ',' + b3 + ',' + c3
    e3 = a3 + ' ' + b3 + ' ' + c3

    A = (RX, RY, RZ)
    Rr, j = cv2.Rodrigues(A)
    print("A", A)
    print("Rr", Rr)
    TtcpB = np.mat([[jrx/1000],[jry/1000],[jrz/1000]])
    print("TtcpB", TtcpB)
    #先转移到基坐标系下
    parB = Rr * pa + TtcpB

    #左右臂之间的关系
    Rrf = np.mat([[1, 0, 0],
                 [0, 1, 0],
                 [0, 0, 1]])
    Trf = np.mat([[-0.522], [0], [0]])
    
    #再转移到左臂
    palB = Rrf * parB + Trf
    print("pa2", palB)
    palBx = str(palB[0]* 1000)
    palBy = str(palB[1]* 1000)
    palBz = str(palB[2]* 1000)
    PalB = palBx + ',' + palBy + ',' + palBz

    #读取左臂真实数据
    jlx, jly, jlz, RlX, RlY, RlZ = jixiebi_leftarm_xyz()

    print(" jlx, jly ,jlz", jlx, jly, jlz)
    jlx1 = str(jlx)
    jly1 = str(jly)
    jlz1 = str(jlz)
    dlj = jlx1 + ',' + jly1 + ',' + jlz1

    al = float(palB[0] * 1000)
    bl = float(palB[1] * 1000)
    cl = float(palB[2] * 1000)

    #计算误差
    value = (al - jlx, bl - jly, cl - jlz)
    print("diff value", value)
    vx = str(value[0])
    vy = str(value[1])
    vz = str(value[2])
    V = vx + ' ' + vy + ' ' + vz

    #保存结果
    with open(
            '/opt/ros/arm_right_verify_result.txt',
            'a+') as f:
        [f.write(str(tim1) + '['+ PalB + ']'+ '[' + dlj + ']' + '[' + V + ']' + '\n') for item in pa[0]]
        f.close()
    with open(
            '/opt/ros/arm_right_verify_result_single.txt',
            'w') as f:
        if ((al - jlx) < 1000 and (bl - jly) < 1000 and (cl - jlz) < 1000):
            [f.write(V + ' ' + '1') for item in pa[0]]
            f.close()
            print("calib arm tool is ok ")
        else:
            print("calib arm tool again")
            [f.write(e3 + ' ' + '0') for item in pa[0]]
            f.close()

到了这里,关于机器人手眼标定快速精度验证方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器人运动学标定:基于DH建模方法

    作者:桂凯 链接:https://www.zhihu.com/question/401957723/answer/1298513878 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 当然,运动学标定这种很基础的问题,理论已非常成熟了,基于激光或拉线编码器的标定系统也已经商业化了。我们在接

    2024年02月12日
    浏览(36)
  • 汇川机器人+五点法标定常规托盘码垛

            个人观点,码垛和拆垛本质上是一样,把流水线上的产品按规律整齐堆叠到托盘里叫码垛,从整齐排列有物料的托盘取料然后放到流水线上叫拆垛。取放料操作一般由机器人完成,我习惯按物料流向将设备分为码盘机(码垛)和上料机(拆垛),以下程序实例中的机器人为

    2024年03月27日
    浏览(42)
  • 手机拍照转机器人末端坐标(九点标定法)

    在图示位置读取九个点的X,Y坐标 测试可以随机拍一张,实用的话需要固定手机的拍照位置,得到的图片如下:  实用如下代码显示这个图片,用鼠标悬停取抄写坐标 效果如下: 鼠标悬停在P1上,在左下角就可以读取这个像素坐标值了。 验证算法如下: 运行后结果分析:

    2024年02月06日
    浏览(37)
  • 发那科机器人:MOTN-049 零点标定结果未更新

    现象如图: 原因:机器人在进行零位标定相关操作后出现 解决方法:MENU---系统---变量---$DMR_GRP--回车---回车 选择有效后查看一下机器人点位 然后重启机器人,开机后查看机器人点位和关机前对比,点位一致则表示成功,上使能机器人就可以手动运动。

    2024年02月01日
    浏览(29)
  • (视觉人机器视觉培训)康耐视3DA5000标定详细流程(相机安装于机器人上)

    (Q有答疑)visionman基本脚本培训-康耐视Visionpro之Visual Studio -调试快速方法 1、打开,运行A5000Viewer 2、修改相应参数,确认图像效果,并在Fifo取像工具自定义属性中添加。 1、本次应用为相机安装在机器人六轴前段,标定块位于相机视野内静止不动,对于相机固定安装稍有差异。

    2023年04月26日
    浏览(50)
  • 文献学习-14-一种用于高精度微创手术的纤维机器人

    Authors: Mohamed E. M. K. Abdelaziz1,2 †, Jinshi Zhao1,3 †, Bruno Gil Rosa1,2 , Hyun-Taek Lee4 , Daniel Simon3,5 , Khushi Vyas1,2 , Bing Li6,7 , Hanifa Koguna3 , Yue Li1 , Ali Anil Demircali3 , Huseyin Uvet8 , Gulsum Gencoglan9,10, Arzu Akcay11,12, Mohamed Elriedy13, James Kinross14, Ranan Dasgupta15, Zoltan Takats3,5 , Eric Yeatman2 , Guang-Zhong Yang16

    2024年03月10日
    浏览(42)
  • (已修正精度 1mm左右)Realsense d435i深度相机+Aruco+棋盘格+OpenCV手眼标定全过程记录

    最近帮别人做了个手眼标定,然后我标定完了大概精度能到1mm左右。所以原文中误差10mm可能是当时那个臂本身的坐标系有问题。然后用的代码改成了基于python的,放在下面。 新来的小伙伴可以只参考前面的代码就可以完成标定了。 有问题的话可以留言,一起交流~ 手眼标定

    2024年02月04日
    浏览(32)
  • 关于机器人状态估计(15)-VIO与VSLAM精度答疑、融合前端、主流深度相机说明与近期工程汇总

    VIOBOT种子用户有了一定的数量,日常大家也会进行交流,整理总结一下近期的交流与答疑。 VIO-SLAM(作为三维SLAM,相对于Lidar-SLAM和LIO-SLAM)在工程上落地的长期障碍,不仅在算法精度本身,还有相对严重的鲁棒性问题,尺度问题,世界观问题和沉重的开销/成本问题。 这些我在

    2024年02月16日
    浏览(26)
  • ros2 机器人imu传感器 加速度计 陀螺仪精度和数据填充单位换算

    起因,imu解算出了加速度 角速度,但原始数据是没有单位的,只是在一个精度范围的值,要使用这些数据,就需要把这些没有单位的数据换算成带单位的数据,下面解说一下换算原理。 imu读取数据代码参考上期的博客: ros2 c++实现JY_95T IMU解算三轴 加速度 角速度 欧拉角 磁力

    2024年02月13日
    浏览(40)
  • Python解决微软Microsoft的登录机器人验证

    前言 本文是该专栏的第8篇, 结合优质项目案例 , 让你精通使用Pyppeteer ,后面会持续分享Pyppeteer的干货知识,记得关注。 在注册微软Microsoft账号或者注册outlook邮箱账号的时候,会遇到如下机器人验证: 是的,你可能第一眼看到这个验证页面,首先会想到是定位它的页面元

    2023年04月21日
    浏览(94)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包