机械臂手眼标定realsense d435相机——眼在手上python、matlab

这篇具有很好参考价值的文章主要介绍了机械臂手眼标定realsense d435相机——眼在手上python、matlab。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

两周内看了好多博客,博客上的代码甚至github上的代码都试过了一遍,各种语言matlab、c++、python,了解到了许多做手眼标定的平台——halcon、ros(这俩还需要从头开始学,时间不太够用),最后看到了鱼香ros的博客,参考了一下并总结完整,附链接

此博客仅记录学习过程总结思路,可以借鉴,有问题可以指出并联系我

基于ROS的机械臂手眼标定-基础使用_鱼香ros手眼标定_鱼香ROS的博客-CSDN博客

目录

手眼标定原理

获得手眼矩阵X

验证准确性


手眼标定原理

眼在手上,眼在手上的目的是求出末端到相机的变换矩阵X,也成为了手眼矩阵

matlab 手眼标定,机械臂,matlab,开发语言

 由图可知,

标定板在机械臂坐标系下的位姿=标定板在相机坐标系下的位姿—>相机在末端坐标系下的位姿—>末端在机械臂基坐标系下的位姿

base to end 可以通过机械臂运动学得到

end to camera 是代求的X

camera to object 是通过相机拍下标定板照片得到

只要有两组数据,就可以列恒等式

除了X外,剩下的矩阵都可通过以上手法求得,通过数学方法移项后就是我们常说的AX=XB

接下来的目的就是求得X

获得手眼矩阵X

eyeinhandcalibrate.py

def get_matrix_eular_radu(x, y, z, rx, ry, rz):
    rmat = tfs.euler.euler2mat(math.radians(rx), math.radians(ry), math.radians(rz))
    rmat = tfs.affines.compose(np.squeeze(np.asarray((x, y, z))), rmat, [1, 1, 1])
    return rmat


def skew(v):
    return np.array([[0, -v[2], v[1]],
                     [v[2], 0, -v[0]],
                     [-v[1], v[0], 0]])


def rot2quat_minimal(m):
    quat = tfs.quaternions.mat2quat(m[0:3, 0:3])
    return quat[1:]


def quatMinimal2rot(q):
    p = np.dot(q.T, q)
    w = np.sqrt(np.subtract(1, p[0][0]))
    return tfs.quaternions.quat2mat([w, q[0], q[1], q[2]])


# hand = [1.1988093940033604, -0.42405585264804424, 0.18828251788562061, 151.3390418721659, -18.612399542280507,
#         153.05074895025035,
#         1.1684831621733476, -0.183273375514656, 0.12744868246620855, -161.57083804238462, 9.07159838346732,
#         89.1641128844487,
#         1.1508343174145468, -0.22694301453461405, 0.26625166858469146, 177.8815855486261, 0.8991159570568988,
#         77.67286224959672]
hand = [

    # -0.05448,-0.15018,0.06552,89.61059916,-2.119943842,-1.031324031,
    #     -0.10149,-0.23025,0.04023,96.7725716,6.187944187,5.328507495,
    #     -0.10114,-0.2207,0.04853,97.00175472,5.729577951,1.375098708    毫米单位

-54.48,	-150.18,	65.52,  89.61059916,    -2.119943842,   -1.031324031,
-101.49,-230.25,    40.23,  96.7725716,      6.187944187,    5.328507495,
-101.14,-220.7	,   48.53,  97.00175472,    5.729577951,    1.375098708

        ]

# camera = [-0.16249272227287292, -0.047310635447502136, 0.4077761471271515, -56.98037030812389, -6.16739631361851,
#           -115.84333735802369,
#           0.03955405578017235, -0.013497642241418362, 0.33975949883461, -100.87129330834215, -17.192685528625265,
#           -173.07354634882094,
#           -0.08517949283123016, 0.00957852229475975, 0.46546608209609985, -90.85270962096058, 0.9315977976503153,
#           175.2059707654342]

camera = [

    # -0.0794887,-0.0812433,0.0246,0.0008,0.0033,0.0182,
    #       -0.078034,-0.0879632,0.4881494,-0.1085,0.0925,-0.1569,
    #       -0.1086702,-0.0881681,0.4240367,-0.1052,0.1251,-0.1124,
-79.4887,	-81.2433,	24.6,        0.0008,     0.0033,     0.0182,
-78.034,	-87.9632,	488.1494,    -0.1085,    0.0925,     -0.1569,
-108.6702,	-88.1681,	424.0367,    -0.1052,    0.1251,     -0.1124,


          ]

Hgs, Hcs = [], []
for i in range(0, len(hand), 6):
    Hgs.append(get_matrix_eular_radu(hand[i], hand[i + 1], hand[i + 2], hand[i + 3], hand[i + 4], hand[i + 5],))
    Hcs.append(
        get_matrix_eular_radu(camera[i], camera[i + 1], camera[i + 2], camera[i + 3], camera[i + 4], camera[i + 5]))

Hgijs = []
Hcijs = []
A = []
B = []
size = 0
for i in range(len(Hgs)):
    for j in range(i + 1, len(Hgs)):
        size += 1
        Hgij = np.dot(np.linalg.inv(Hgs[j]), Hgs[i])
        Hgijs.append(Hgij)
        Pgij = np.dot(2, rot2quat_minimal(Hgij))

        Hcij = np.dot(Hcs[j], np.linalg.inv(Hcs[i]))
        Hcijs.append(Hcij)
        Pcij = np.dot(2, rot2quat_minimal(Hcij))

        A.append(skew(np.add(Pgij, Pcij)))
        B.append(np.subtract(Pcij, Pgij))
MA = np.asarray(A).reshape(size * 3, 3)
MB = np.asarray(B).reshape(size * 3, 1)
Pcg_ = np.dot(np.linalg.pinv(MA), MB)
pcg_norm = np.dot(np.conjugate(Pcg_).T, Pcg_)
Pcg = np.sqrt(np.add(1, np.dot(Pcg_.T, Pcg_)))
Pcg = np.dot(np.dot(2, Pcg_), np.linalg.inv(Pcg))
Rcg = quatMinimal2rot(np.divide(Pcg, 2)).reshape(3, 3)

A = []
B = []
id = 0
for i in range(len(Hgs)):
    for j in range(i + 1, len(Hgs)):
        Hgij = Hgijs[id]
        Hcij = Hcijs[id]
        A.append(np.subtract(Hgij[0:3, 0:3], np.eye(3, 3)))
        B.append(np.subtract(np.dot(Rcg, Hcij[0:3, 3:4]), Hgij[0:3, 3:4]))
        id += 1

MA = np.asarray(A).reshape(size * 3, 3)
MB = np.asarray(B).reshape(size * 3, 1)
Tcg = np.dot(np.linalg.pinv(MA), MB).reshape(3, )
print(tfs.affines.compose(Tcg, np.squeeze(Rcg), [1, 1, 1]))

其中,hand为基坐标系下夹爪的位姿,一般从示教器上获取,我用的是ur5机械臂,注意单位mm和rad

matlab 手眼标定,机械臂,matlab,开发语言

 

三行为三组数据,hand=(x,y,z,rx,ry,rz),同时应将弧度制转为角度制

matlab 手眼标定,机械臂,matlab,开发语言

 camera后输入的为相机的外参(平移向量和旋转矩阵),相机中标定板的位姿

三行为三组数据,camera=(x,y,z,rx,ry,rz),同时应将弧度制转为角度制

matlab 手眼标定,机械臂,matlab,开发语言

 

我是使用matlab工具包对相机外参进行标定的

注:得到的旋转向量应转为旋转矩阵,再转为欧拉角,Python、matlab代码见如下链接

手眼标定必备——旋转向量转换为旋转矩阵python——罗德里格斯公式Rodrigues_邸笠佘司的博客-CSDN博客

输出的即为手眼标定矩阵X

[[ 9.97623261e-01 -4.70586261e-02  5.03320417e-02  9.72987830e+02]
 [ 4.65612713e-02  9.98854765e-01  1.10094003e-02 -1.27118401e+03]
 [-5.07924869e-02 -8.63971002e-03  9.98671857e-01 -4.29111524e+02]
 [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  1.00000000e+00]]

验证准确性

根据手眼标定原理可知,

使用理论验证法,使用两组数据用等式将其联立,求得X

clc;
%T1*X*T2 = T3*X*T4 = T5*X*T6
%T1为相机到标定板,T2为基坐标到末端
T1 = [  0.9998   -0.0182    0.0033  -79.4887			
         0.0182    0.9998   -0.0008  -81.2433			
        -0.0033    0.0009    1.0000   24.6000			
            0         0         0      1.0000   ];

T2 = [  	 -0.2681   -0.4478   -0.8530  -54.4800				
         -0.3725   -0.7684    0.5205  -150.1800				
         -0.8885    0.4572    0.0392   65.5200				
            0         0         0       1.0000];

T3 = [ 0.9835    0.1556    0.0924  -78.0340			
   -0.1652    0.9803    0.1078  -87.9632			
   -0.0738   -0.1213    0.9899  488.1494			
         0         0         0    1.0000 ];

T4 = [  0.5753    0.8124   -0.0951 -101.4900				
    0.6340   -0.5163   -0.5758 -230.2500				
   -0.5169    0.2709   -0.8120   40.2300				
         0         0         0    1.0000  	]  ;

T5 =   [ 0.9859    0.1113    0.1248 -108.6702			
   -0.1246    0.9867    0.1042  -88.1681			
   -0.1115   -0.1183    0.9867  424.0367			
 0         0         0    1.0000	] 	;

T6 = [  0.1654   -0.8344   -0.5258 -101.1400			
   -0.9468    0.0149   -0.3215 -220.7000			
    0.2761    0.5510   -0.7875   48.5300			
         0         0         0    1.0000 		
];

%X = [[ 0.997623261 -0.0470586261  0.0503320417  972.987830]						
%     [ 0.0465612713  0.998854765  0.0110094003 -1271.18401]						
 %    [-0.0507924869 -0.00863971002  0.998671857 -429.111524]						
  %   [ 0  0  0  1]]						

%ans1 = T1*X*T2
%ans2 = T3*X*T4
%ans3 = T5*X*T6

T1*X*T2==T3*X*T4
X

结果如下文章来源地址https://www.toymoban.com/news/detail-609491.html

X =
   1.0e+03 *
    0.0010   -0.0000    0.0001    0.9730
    0.0000    0.0010    0.0000   -1.2712
   -0.0001   -0.0000    0.0010   -0.4291
         0         0         0    0.0010

到了这里,关于机械臂手眼标定realsense d435相机——眼在手上python、matlab的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • intel realsense d435i相机标定中文文档

    此文档参考了官方的英文文档,原地址面向英特尔®实感™深度摄像头的 IMU 校准工具 (intelrealsense.com) IMU概述:惯性测量单元(imu)通常由加速度计组成,加速度通常以国际系统(SI)的米/秒为单位输出平方(m/s^2)和陀螺仪,陀螺仪通常以SI单位测量角速度弧度/秒(rad/s)。英特尔Real

    2024年02月09日
    浏览(34)
  • Ubuntu 20.04 Intel RealSense D435i 相机标定教程

    报错:sumpixel_test.cpp:2:10: fatal error: backward.hpp: 没有那个文件或目录,将sumpixel_test.cpp中# include \\\"backward.hpp\\\"改为:#include “code_utils/backward.hpp”。 报错 创建rs_imu_calibration.launch 找到realsense-ros包,进入/catkin_ws/src/realsense2_camera/launch(路径仅供参考),复制其中的rs_camera.launch,并重

    2024年01月16日
    浏览(34)
  • 手眼标定—眼在手上(eye-in-hand)基本原理

    基本概念 相机固定在机械臂末端,机械臂移动相机也随之移动。主要标定求解相机坐标系和机械臂末端坐标系之间的转换矩阵。 涉及坐标系 机械臂基坐标系(base)、机械臂末端坐标系(gripper)、相机坐标系(camera)以及标定板坐标系(target)。eye-in-hand即为求解相机坐标系

    2024年02月05日
    浏览(26)
  • Realsense D455/435内参标定以及手眼标定

    内参数 与相机自身特性有关的参数,焦距,像素大小 外参数, 相机的位置,旋转方向 理想情况下,镜头会将一个三维空间中的直线也映射成直线(即射影变换),但实际上,镜头无法这么完美,通过镜头映射之后,直线会变弯,所以需要相机的畸变参数来描述这种变形效果

    2024年01月17日
    浏览(30)
  • SLAM算法与工程实践——相机篇:RealSense D435使用(2)

    下面是SLAM算法与工程实践系列文章的总链接,本人发表这个系列的文章链接均收录于此 下面是专栏地址: 这个系列的文章是分享SLAM相关技术算法的学习和工程实践 参考: realsense相机两种获取相机内外参的方式 使用Realsense D435i运行VINS-Fusion kalibr标定realsenseD435i --多相机标定

    2024年02月03日
    浏览(29)
  • C++ api调用realsense d435相机,将坐标转换到相机坐标系

            在使用Intel RealSense相机进行编程时,首先需要创建一个 rs2::pipeline 对象,并使用该对象启动相机的数据流。在启动数据流后,相机将根据配置的参数生成相应的数据流,例如深度、彩色或红外流,并将这些数据传输到计算机中。 RS2_STREAM_DEPTH :指定启用的流类型为

    2024年02月16日
    浏览(30)
  • C++ api调用realsense d435相机,并计算真实世界坐标值

            在使用Intel RealSense相机进行编程时,首先需要创建一个 rs2::pipeline 对象,并使用该对象启动相机的数据流。在启动数据流后,相机将根据配置的参数生成相应的数据流,例如深度、彩色或红外流,并将这些数据传输到计算机中。 RS2_STREAM_DEPTH :指定启用的流类型为

    2024年02月11日
    浏览(32)
  • realsense D435i 实现外部时钟触发硬件同步多相机数据采集

    最近有一个调试D435i相机的工作,需要使得三个相机能够完成硬件触发的同步,具体来说,就是有一个固定频率的外部脉冲信号,使得三个相机能够根据外部脉冲信号的硬件触发完成双目图片、深度图片、彩色图片、IMU数据的实时响应采集,因为外部脉冲信号是通过一个精确

    2024年01月16日
    浏览(34)
  • d435i 相机和imu标定

    使用 imu_utils 功能包标定 IMU,由于imu_utils功能包的编译依赖于code_utils,需要先编译code_utils,主要参考 相机与IMU联合标定_熊猫飞天的博客-CSDN博客 Ubuntu20.04编译并运行imu_utils,并且标定IMU_学无止境的小龟的博客-CSDN博客 1.1 编译 code_utils 创建工作空间 1.1.1 修改 CMakeLists.txt 文件

    2024年02月09日
    浏览(44)
  • 3D相机与机械臂手眼标定流程

    1.采集n组点云数据,将第一组点云命名为(点云target)基准点云    这些数据可以通过3D相机采集得到,然后通过一些处理方法(如去噪、滤波等)进一步优化。 2.采集n组点云的同时记录n组机械臂位姿,同样将第一组位姿设为基准位姿(机械臂target) 3.将获取的n组机械臂位姿由欧

    2024年02月12日
    浏览(30)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包