当前位置:   article > 正文

机械臂手眼标定realsense d435相机——眼在手上python、matlab_进行机械臂手眼标定前,需要标定realsense相机吗

进行机械臂手眼标定前,需要标定realsense相机吗

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

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

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

目录

手眼标定原理

获得手眼矩阵X

验证准确性


手眼标定原理

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

 由图可知,

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

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

end to camera 是代求的X

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

Tbaseboard=TcameraboardTendcameraTbaseend

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

T1cameraboardT1endcameraT1baseend=T2cameraboardT2endcameraT2baseend

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

接下来的目的就是求得X

获得手眼矩阵X

eyeinhandcalibrate.py

  1. def get_matrix_eular_radu(x, y, z, rx, ry, rz):
  2. rmat = tfs.euler.euler2mat(math.radians(rx), math.radians(ry), math.radians(rz))
  3. rmat = tfs.affines.compose(np.squeeze(np.asarray((x, y, z))), rmat, [1, 1, 1])
  4. return rmat
  5. def skew(v):
  6. return np.array([[0, -v[2], v[1]],
  7. [v[2], 0, -v[0]],
  8. [-v[1], v[0], 0]])
  9. def rot2quat_minimal(m):
  10. quat = tfs.quaternions.mat2quat(m[0:3, 0:3])
  11. return quat[1:]
  12. def quatMinimal2rot(q):
  13. p = np.dot(q.T, q)
  14. w = np.sqrt(np.subtract(1, p[0][0]))
  15. return tfs.quaternions.quat2mat([w, q[0], q[1], q[2]])
  16. # hand = [1.1988093940033604, -0.42405585264804424, 0.18828251788562061, 151.3390418721659, -18.612399542280507,
  17. # 153.05074895025035,
  18. # 1.1684831621733476, -0.183273375514656, 0.12744868246620855, -161.57083804238462, 9.07159838346732,
  19. # 89.1641128844487,
  20. # 1.1508343174145468, -0.22694301453461405, 0.26625166858469146, 177.8815855486261, 0.8991159570568988,
  21. # 77.67286224959672]
  22. hand = [
  23. # -0.05448,-0.15018,0.06552,89.61059916,-2.119943842,-1.031324031,
  24. # -0.10149,-0.23025,0.04023,96.7725716,6.187944187,5.328507495,
  25. # -0.10114,-0.2207,0.04853,97.00175472,5.729577951,1.375098708 毫米单位
  26. -54.48, -150.18, 65.52, 89.61059916, -2.119943842, -1.031324031,
  27. -101.49,-230.25, 40.23, 96.7725716, 6.187944187, 5.328507495,
  28. -101.14,-220.7 , 48.53, 97.00175472, 5.729577951, 1.375098708
  29. ]
  30. # camera = [-0.16249272227287292, -0.047310635447502136, 0.4077761471271515, -56.98037030812389, -6.16739631361851,
  31. # -115.84333735802369,
  32. # 0.03955405578017235, -0.013497642241418362, 0.33975949883461, -100.87129330834215, -17.192685528625265,
  33. # -173.07354634882094,
  34. # -0.08517949283123016, 0.00957852229475975, 0.46546608209609985, -90.85270962096058, 0.9315977976503153,
  35. # 175.2059707654342]
  36. camera = [
  37. # -0.0794887,-0.0812433,0.0246,0.0008,0.0033,0.0182,
  38. # -0.078034,-0.0879632,0.4881494,-0.1085,0.0925,-0.1569,
  39. # -0.1086702,-0.0881681,0.4240367,-0.1052,0.1251,-0.1124,
  40. -79.4887, -81.2433, 24.6, 0.0008, 0.0033, 0.0182,
  41. -78.034, -87.9632, 488.1494, -0.1085, 0.0925, -0.1569,
  42. -108.6702, -88.1681, 424.0367, -0.1052, 0.1251, -0.1124,
  43. ]
  44. Hgs, Hcs = [], []
  45. for i in range(0, len(hand), 6):
  46. Hgs.append(get_matrix_eular_radu(hand[i], hand[i + 1], hand[i + 2], hand[i + 3], hand[i + 4], hand[i + 5],))
  47. Hcs.append(
  48. get_matrix_eular_radu(camera[i], camera[i + 1], camera[i + 2], camera[i + 3], camera[i + 4], camera[i + 5]))
  49. Hgijs = []
  50. Hcijs = []
  51. A = []
  52. B = []
  53. size = 0
  54. for i in range(len(Hgs)):
  55. for j in range(i + 1, len(Hgs)):
  56. size += 1
  57. Hgij = np.dot(np.linalg.inv(Hgs[j]), Hgs[i])
  58. Hgijs.append(Hgij)
  59. Pgij = np.dot(2, rot2quat_minimal(Hgij))
  60. Hcij = np.dot(Hcs[j], np.linalg.inv(Hcs[i]))
  61. Hcijs.append(Hcij)
  62. Pcij = np.dot(2, rot2quat_minimal(Hcij))
  63. A.append(skew(np.add(Pgij, Pcij)))
  64. B.append(np.subtract(Pcij, Pgij))
  65. MA = np.asarray(A).reshape(size * 3, 3)
  66. MB = np.asarray(B).reshape(size * 3, 1)
  67. Pcg_ = np.dot(np.linalg.pinv(MA), MB)
  68. pcg_norm = np.dot(np.conjugate(Pcg_).T, Pcg_)
  69. Pcg = np.sqrt(np.add(1, np.dot(Pcg_.T, Pcg_)))
  70. Pcg = np.dot(np.dot(2, Pcg_), np.linalg.inv(Pcg))
  71. Rcg = quatMinimal2rot(np.divide(Pcg, 2)).reshape(3, 3)
  72. A = []
  73. B = []
  74. id = 0
  75. for i in range(len(Hgs)):
  76. for j in range(i + 1, len(Hgs)):
  77. Hgij = Hgijs[id]
  78. Hcij = Hcijs[id]
  79. A.append(np.subtract(Hgij[0:3, 0:3], np.eye(3, 3)))
  80. B.append(np.subtract(np.dot(Rcg, Hcij[0:3, 3:4]), Hgij[0:3, 3:4]))
  81. id += 1
  82. MA = np.asarray(A).reshape(size * 3, 3)
  83. MB = np.asarray(B).reshape(size * 3, 1)
  84. Tcg = np.dot(np.linalg.pinv(MA), MB).reshape(3, )
  85. print(tfs.affines.compose(Tcg, np.squeeze(Rcg), [1, 1, 1]))

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

 

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

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

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

 

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

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

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

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

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

验证准确性

根据手眼标定原理可知,

Tbaseboard=TcameraboardTendcameraTbaseend

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

  1. clc;
  2. %T1*X*T2 = T3*X*T4 = T5*X*T6
  3. %T1为相机到标定板,T2为基坐标到末端
  4. T1 = [ 0.9998 -0.0182 0.0033 -79.4887
  5. 0.0182 0.9998 -0.0008 -81.2433
  6. -0.0033 0.0009 1.0000 24.6000
  7. 0 0 0 1.0000 ];
  8. T2 = [ -0.2681 -0.4478 -0.8530 -54.4800
  9. -0.3725 -0.7684 0.5205 -150.1800
  10. -0.8885 0.4572 0.0392 65.5200
  11. 0 0 0 1.0000];
  12. T3 = [ 0.9835 0.1556 0.0924 -78.0340
  13. -0.1652 0.9803 0.1078 -87.9632
  14. -0.0738 -0.1213 0.9899 488.1494
  15. 0 0 0 1.0000 ];
  16. T4 = [ 0.5753 0.8124 -0.0951 -101.4900
  17. 0.6340 -0.5163 -0.5758 -230.2500
  18. -0.5169 0.2709 -0.8120 40.2300
  19. 0 0 0 1.0000 ] ;
  20. T5 = [ 0.9859 0.1113 0.1248 -108.6702
  21. -0.1246 0.9867 0.1042 -88.1681
  22. -0.1115 -0.1183 0.9867 424.0367
  23. 0 0 0 1.0000 ] ;
  24. T6 = [ 0.1654 -0.8344 -0.5258 -101.1400
  25. -0.9468 0.0149 -0.3215 -220.7000
  26. 0.2761 0.5510 -0.7875 48.5300
  27. 0 0 0 1.0000
  28. ];
  29. %X = [[ 0.997623261 -0.0470586261 0.0503320417 972.987830]
  30. % [ 0.0465612713 0.998854765 0.0110094003 -1271.18401]
  31. % [-0.0507924869 -0.00863971002 0.998671857 -429.111524]
  32. % [ 0 0 0 1]]
  33. %ans1 = T1*X*T2
  34. %ans2 = T3*X*T4
  35. %ans3 = T5*X*T6
  36. T1*X*T2==T3*X*T4
  37. X

结果如下

  1. X =
  2. 1.0e+03 *
  3. 0.0010 -0.0000 0.0001 0.9730
  4. 0.0000 0.0010 0.0000 -1.2712
  5. -0.0001 -0.0000 0.0010 -0.4291
  6. 0 0 0 0.0010

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/508676
推荐阅读
相关标签
  

闽ICP备14008679号