UR3机械臂正逆运动学详解及c++完整代码

博主也是刚开始学习机械臂,不断搜索网上的教程,找论文,费尽千辛万苦终于计算正确,学习之路太过坎坷

D-H参数表

i i i α i − 1 \alpha_{i-1} αi1 d i d_{i} di a i − 1 a_{i-1} ai1 θ i \theta_{i} θi
1 1 1 0 0 0 d 1 d_{1} d1 0 0 0 θ 1 \theta_{1} θ1
2 2 2 90 90 90 0 0 0 0 0 0 θ 2 \theta_{2} θ2
3 3 3 0 0 0 0 0 0 a 2 a_{2} a2 θ 3 \theta_{3} θ3
4 4 4 0 0 0 d 4 d_{4} d4 a 3 a_{3} a3 θ 4 \theta_{4} θ4
5 5 5 90 90 90 d 5 d_{5} d5 0 0 0 θ 5 \theta_{5} θ5
6 6 6 − 90 -90 90 d 6 d_{6} d6 0 0 0 θ 6 \theta_{6} θ6

正运动学

公式推导

这里的 s i s_{i} si代表 sin ⁡ ( θ i ) \sin(\theta_i) sin(θi) c i c_{i} ci代表 cos ⁡ ( θ i ) \cos(\theta_i) cos(θi),以及下文逆运动学中出现的 s i j s_{ij} sij代表 sin ⁡ ( θ i + θ j ) \sin(\theta_i+\theta_j) sin(θi+θj)

由于
i i − 1 T = [ c i − s i 0 a i − 1 s i c α i − 1 c i c α i − 1 − s α i − 1 − s α i − 1 d i s i s α i − 1 c i s α i − 1 c α i − 1 c α i − 1 d i 0 0 0 1 ] (*) {}^{i-1}_{i}T= \begin{bmatrix} c_{i} & -s_{i} & 0 & a_{i-1} \\ s_{i}c_{\alpha_{i-1}} & c_{i}c_{\alpha_{i-1}} & -s_{\alpha_{i-1}} & -s_{\alpha_{i-1}}d_{i} \\ s_{i}s_{\alpha_{i-1}} & c_{i}s_{\alpha_{i-1}} & c_{\alpha_{i-1}} & c_{\alpha_{i-1}}d_{i} \\ 0 & 0& 0&1 \end{bmatrix}\tag{*} ii1T=cisicαi1sisαi10sicicαi1cisαi100sαi1cαi10ai1sαi1dicαi1di1(*)
所以我们可以得到六个变换矩阵(这是代入 α \alpha α d d d a a a中的零值后的结果)
1 0 T ( θ 1 ) = [ c 1 − s 1 0 0 s 1 c 1 0 0 0 0 1 d 1 0 0 0 1 ] (1) {}^{0}_{1}T(\theta_{1})= \begin{bmatrix} c_{1} & -s_{1} & 0 & 0 \\ s_{1} & c_{1} & 0&0 \\ 0& 0 & 1& d_{1} \\ 0 & 0& 0&1\tag{1} \end{bmatrix} 10T(θ1)=c1s100s1c100001000d11(1)
2 1 T ( θ 2 ) = [ c 2 − s 2 0 0 0 0 − 1 0 s 2 c 2 0 0 0 0 0 1 ] (2) {}^{1}_{2}T(\theta_{2})= \begin{bmatrix} c_{2} & -s_{2} & 0 & 0 \\ 0 & 0 & -1&0 \\ s_{2} & c_{2} & 0&0 \\ 0 & 0& 0&1\tag{2} \end{bmatrix} 21T(θ2)=c20s20s20c2001000001(2)
3 2 T ( θ 3 ) = [ c 3 − s 3 0 a 2 s 3 c 3 0 0 0 0 1 0 0 0 0 1 ] (3) {}^{2}_{3}T(\theta_{3})= \begin{bmatrix} c_{3} & -s_{3} & 0 & a_{2} \\ s_{3} & c_{3} & 0&0 \\ 0& 0 & 1& 0 \\ 0 & 0& 0&1\tag{3} \end{bmatrix} 32T(θ3)=c3s300s3c3000010a2001(3)
4 3 T ( θ 4 ) = [ c 4 − s 4 0 a 3 s 4 c 4 0 0 0 0 1 d 4 0 0 0 1 ] (4) {}^{3}_{4}T(\theta_{4})= \begin{bmatrix} c_{4} & -s_{4} & 0 & a_{3} \\ s_{4} & c_{4} & 0&0 \\ 0& 0 & 1& d_{4} \\ 0 & 0& 0&1\tag{4} \end{bmatrix} 43T(θ4)=c4s400s4c4000010a30d41(4)
5 4 T ( θ 5 ) = [ c 5 − s 5 0 0 0 0 − 1 − d 5 s 5 c 5 0 0 0 0 0 1 ] (5) {}^{4}_{5}T(\theta_{5})= \begin{bmatrix} c_{5} & -s_{5} & 0 & 0 \\ 0& 0 & -1&-d_{5} \\ s_{5} & c_{5} & 0&0 \\ 0 & 0& 0&1\tag{5} \end{bmatrix} 54T(θ5)=c50s50s50c5001000d501(5)
6 5 T ( θ 6 ) = [ c 6 − s 6 0 0 0 0 1 d 6 − s 6 − c 6 0 0 0 0 0 1 ] (6) {}^{5}_{6}T(\theta_{6})= \begin{bmatrix} c_{6} & -s_{6} & 0 & 0 \\ 0& 0 & 1&d_{6} \\ -s_{6} & -c_{6} & 0&0 \\ 0 & 0& 0&1\tag{6} \end{bmatrix} 65T(θ6)=c60s60s60c6001000d601(6)
于是
6 0 T = 1 0 T 2 1 T 3 2 T 4 3 T 5 4 T 6 5 T (7) {}^{0}_{6}T= {}^{0}_{1}T{}^{1}_{2}T{}^{2}_{3}T{}^{3}_{4}T{}^{4}_{5}T{}^{5}_{6}T\tag{7} 60T=10T21T32T43T54T65T(7)
6 0 T {}^{0}_{6}T 60T中第四列的前三行数据就是机器人末端连杆在笛卡儿坐标系里的位置

其实在编程中无需把每一个变换矩阵的表达式计算出,只要按照式子 ( ∗ ) (*) () 把对应的值代入计算即可,每计算一个变换矩阵,都做一次矩阵相乘。(可以看最后的代码来理解)但在下文的逆运动学中我会具体写出每一步的计算结果,上面的式子算作一个铺垫

代码

因为逆运动学要涉及反代入检验,所以看后面逆运动学求解的代码就行了

测试

红色框为仿真环境给出的数据,下面六个角度就是我输入的六个 θ \theta θ的值
橙色框为程序计算出的位置,这里由于单位问题,两组值相差了 1 0 3 10^{3} 103
ur3正运动学求解范例

逆运动学

准备工作

首先推得
1 0 T − 1 ( θ 1 ) = [ c 1 s 1 0 0 − s 1 c 1 0 0 0 0 1 − d 1 0 0 0 1 ] (8) {}^{0}_{1}T^{-1}(\theta_{1})= \begin{bmatrix} c_{1} & s_{1} & 0 & 0 \\ -s_{1} & c_{1} & 0&0 \\ 0& 0 & 1& -d_{1} \\ 0 & 0& 0&1\tag{8} \end{bmatrix} 10T1(θ1)=c1s100s1c100001000d11(8)
然后逐步计算
3 1 T = 2 1 T 3 2 T = [ c 23 − s 23 0 c 2 a 2 0 0 − 1 0 s 23 c 23 0 s 2 a 2 0 0 0 1 ] (9) {}^{1}_{3}T= {}^{1}_{2}T {}^{2}_{3}T= \begin{bmatrix} c_{23} & -s_{23} & 0 & c_2a_2 \\ 0 &0 & -1&0 \\ s_{23} & c_{23} & 0 & s_2a_2 \\ 0 & 0& 0&1\tag{9} \end{bmatrix} 31T=21T32T=c230s230s230c2300100c2a20s2a21(9)
4 1 T = 3 1 T 4 3 T = [ c 234 − s 234 0 c 23 a 3 + c 2 a 2 0 0 − 1 − d 4 s 234 c 234 0 s 23 a 3 + s 2 a 2 0 0 0 1 ] (10) {}^{1}_{4}T= {}^{1}_{3}T {}^{3}_{4}T= \begin{bmatrix} c_{234} & -s_{234} & 0 & c_{23}a_3+c_2a_2 \\ 0 &0 & -1&-d_4 \\ s_{234} & c_{234} & 0 & s_{23}a_3+s_2a_2 \\ 0 & 0& 0&1\tag{10} \end{bmatrix} 41T=31T43T=c2340s2340s2340c23400100c23a3+c2a2d4s23a3+s2a21(10)
5 1 T = 4 1 T 5 4 T = [ c 234 c 5 − c 234 s 5 s 234 s 234 d 5 + c 23 a 3 + c 2 a 2 − s 5 − c 5 0 − d 4 s 234 c 5 − s 234 s 5 − c 234 − c 234 d 5 + s 23 a 3 + s 2 a 2 0 0 0 1 ] (11) {}^{1}_{5}T= {}^{1}_{4}T {}^{4}_{5}T= \begin{bmatrix} c_{234}c_5 & -c_{234}s_5 & s_{234} & s_{234}d_5+c_{23}a_3+c_2a_2 \\ -s_5 &-c_5 & 0&-d_4 \\ s_{234}c_5 & -s_{234}s_5 & -c_{234} & -c_{234}d_5+s_{23}a_3+s_2a_2 \\ 0 & 0& 0&1\tag{11} \end{bmatrix} 51T=41T54T=c234c5s5s234c50c234s5c5s234s50s2340c2340s234d5+c23a3+c2a2d4c234d5+s23a3+s2a21(11)
6 1 T = 5 1 T 6 5 T = [ c 234 c 5 c 6 − s 234 s 6 − c 234 c 5 s 6 − s 234 c 6 − c 234 s 5 − c 234 s 5 d 6 + s 234 d 5 + c 23 a 3 + c 2 a 2 − s 5 c 6 s 5 s 6 − c 5 − c 5 d 6 − d 4 s 234 c 5 c 6 + c 234 s 6 − s 234 c 5 s 6 + c 234 c 6 − s 234 s 5 − s 234 s 5 d 6 − c 234 d 5 + s 23 a 3 + s 2 a 2 0 0 0 1 ] (12) {}^{1}_{6}T= {}^{1}_{5}T {}^{5}_{6}T= \begin{bmatrix} c_{234}c_5c_6-s_{234}s_6 & -c_{234}c_5s_6-s_{234}c_6 & -c_{234}s_5 & -c_{234}s_5d_6+s_{234}d_5+c_{23}a_3+c_2a_2 \\ -s_5c_6 &s_5s_6 & -c_5&-c_5d_6-d_4 \\ s_{234}c_5c_6+c_{234}s_6 & -s_{234}c_5s_6+c_{234}c_6 & -s_{234}s_5 & -s_{234}s_5d_6-c_{234}d_5+s_{23}a_3+s_2a_2 \\ 0 & 0& 0&1 \end{bmatrix}\tag{12} 61T=51T65T=c234c5c6s234s6s5c6s234c5c6+c234s60c234c5s6s234c6s5s6s234c5s6+c234c60c234s5c5s234s50c234s5d6+s234d5+c23a3+c2a2c5d6d4s234s5d6c234d5+s23a3+s2a21(12)
由于

6 0 T = 1 0 T 2 1 T 3 2 T 4 3 T 5 4 T 6 5 T = 1 0 T 6 1 T (13) {}^{0}_{6}T= {}^{0}_{1}T{}^{1}_{2}T{}^{2}_{3}T{}^{3}_{4}T{}^{4}_{5}T{}^{5}_{6}T= {}^{0}_{1}T{}^{1}_{6}T\tag{13} 60T=10T21T32T43T54T65T=10T61T(13)
所以有

1 0 T − 1 6 0 T = 6 1 T (14) {}^{0}_{1}T^{-1} {}^{0}_{6}T={}^{1}_{6}T\tag{14} 10T160T=61T(14)
其中, 6 0 T {}^{0}_{6}T 60T是我们可以根据末端位姿获得的,我们设
6 0 T = [ r 11 r 12 r 13 x r 21 r 22 r 23 y r 31 r 32 r 33 z 0 0 0 1 ] (15) {}^{0}_{6}T= \begin{bmatrix} r_{11} & r_{12} & r_{13} & x \\ r_{21} & r_{22} & r_{23}&y \\ r_{31}& r_{32} & r_{33}& z \\ 0 & 0& 0&1\tag{15} \end{bmatrix} 60T=r11r21r310r12r22r320r13r23r330xyz1(15)
因此式 ( 14 ) (14) (14)左边矩阵相乘的结果为
1 0 T − 1 6 0 T = [ c 1 r 11 + s 1 r 21 c 1 r 12 + s 1 r 22 c 1 r 13 + s 1 r 23 c 1 x + s 1 y − s 1 r 11 + c 1 r 21 − s 1 r 12 + c 1 r 22 − s 1 r 13 + c 1 r 23 − s 1 x + c 1 y r 31 r 32 r 33 z − d 1 0 0 0 1 ] (16) {}^{0}_{1}T^{-1} {}^{0}_{6}T= \begin{bmatrix} c_1r_{11}+s_1r_{21} & c_1r_{12}+s_1r_{22} & c_1r_{13}+s_1r_{23} & c_1x+s_1y \\ -s_1r_{11}+c_1r_{21} & -s_1r_{12}+c_1r_{22} & -s_1r_{13}+c_1r_{23}&-s_1x+c_1y \\ r_{31}& r_{32} & r_{33}& z-d_1 \\ 0 & 0& 0&1\tag{16} \end{bmatrix} 10T160T=c1r11+s1r21s1r11+c1r21r310c1r12+s1r22s1r12+c1r22r320c1r13+s1r23s1r13+c1r23r330c1x+s1ys1x+c1yzd11(16)
至此,求逆解的所有准备工作完成了,下面开始逐个计算 θ \theta θ的值

求逆解的总思路是:通过比对式 ( 12 ) (12) (12)和式 ( 16 ) (16) (16)两个矩阵获得等式,然后消元,最后用 a t a n 2 ( ) atan2() atan2()求解

求解 θ 1 \theta_{1} θ1

由于式 ( 16 ) (16) (16)中的未知数只有 θ 1 \theta_{1} θ1,因此我们选择先计算出 θ 1 \theta_{1} θ1的值。在式 ( 12 ) (12) (12)中,我们观察到第二行第三列(后文都简写为(2,3)这种形式)和(2,4)只有未知数 θ 5 \theta_5 θ5,因此两个未知数两个方程,可解。
于是有
{ ( 2 , 3 ) :   − s 1 r 13 + c 1 r 23 = − c 5 ( 2 , 4 ) :   − s 1 x + c 1 y = − c 5 d 6 − d 4 (17) \begin{cases} (2,3): \ -s_1r_{13}+c_1r_{23}=-c_5 \\ (2,4): \ -s_1x+c_1y=-c_5d_6-d_4 \tag{17} \end{cases} {(2,3): s1r13+c1r23=c5(2,4): s1x+c1y=c5d6d4(17)
消去 θ 5 \theta_5 θ5
− ( r 13 d 6 − x ) s 1 + ( r 23 d 6 − y ) c 1 = d 4 (18) -(r_{13}d_6-x)s_1+(r_{23}d_6-y)c_1=d_4\tag{18} (r13d6x)s1+(r23d6y)c1=d4(18)
为什么要写成这种形式?
因为求解过程中我们发现,这样的形式可以有一个计算公式,即
若有
− A s 1 + B c 1 = C (19) {-As_1+Bc_1=C}\tag{19} As1+Bc1=C(19)

θ 1 = a t a n 2 ( B , A ) − a t a n 2 ( C , ± A 2 + B 2 − C 2 ) (20) \theta_1=atan2(B,A)-atan2(C,\pm\sqrt{A^2+B^2-C^2})\tag{20} θ1=atan2(B,A)atan2(C,±A2+B2C2 )(20)

根据式 ( 18 ) (18) (18),可以确定这里的
A = r 13 d 6 − x B = r 23 d 6 − y C = d 4 (21) \begin{aligned} &A=r_{13}d_6-x \\ &B=r_{23}d_6-y \\ &C =d_4\tag{21} \end{aligned} A=r13d6xB=r23d6yC=d4(21)
于是我们可以计算出 θ 1 \theta_1 θ1的两个解

求解 θ 5 \theta_{5} θ5

由于前面求解 θ 1 \theta_1 θ1时我们也已经找到了 θ 5 \theta_5 θ5的方程,因此当 θ 1 \theta_1 θ1解出来后, θ 5 \theta_5 θ5也就自然而然地能解了
( 2 , 3 ) :   − s 1 r 13 + c 1 r 23 = − c 5 (22) (2,3): \ -s_1r_{13}+c_1r_{23}=-c_5\tag{22} (2,3): s1r13+c1r23=c5(22)
所以有
c 5 = s 1 r 13 − c 1 r 23 (23) c_5=s_1r_{13}-c_1r_{23}\tag{23} c5=s1r13c1r23(23)
继而有
s 5 = ± 1 − ( s 1 r 13 − c 1 r 23 ) 2 (24) s_5= \pm\sqrt{1-(s_1r_{13}-c_1r_{23})^2}\tag{24} s5=±1(s1r13c1r23)2 (24)
因此
θ 5 = a t a n 2 ( ± 1 − ( s 1 r 13 − c 1 r 23 ) 2 , s 1 r 13 − c 1 r 23 ) (25) \theta_5=atan2(\pm\sqrt{1-(s_1r_{13}-c_1r_{23})^2},s_1r_{13}-c_1r_{23})\tag{25} θ5=atan2(±1(s1r13c1r23)2 ,s1r13c1r23)(25)
因为 θ 1 \theta_1 θ1有两个解,所以 θ 5 \theta_5 θ5 2 × 2 = 4 2\times 2=4 2×2=4个解

求解 θ 6 \theta_{6} θ6

我们已经求解出 θ 1 \theta_1 θ1 θ 5 \theta_5 θ5,观察式 ( 12 ) (12) (12)能发现, θ 2 θ 3 θ 4 \theta_2\theta_3\theta_4 θ2θ3θ4牵扯在一块,与此同时(2,1)和(2,2)就显得十分简洁,因此我们第三步求解 θ 6 \theta_6 θ6
{ ( 2 , 1 ) :   − s 1 r 11 + c 1 r 21 = − s 5 c 6 ( 2 , 2 ) :   − s 1 r 12 + c 1 r 22 = s 5 s 6 (26) \begin{cases} (2,1): \ -s_1r_{11}+c_1r_{21}=-s_5c_6 \\ (2,2): \ -s_1r_{12}+c_1r_{22}=s_5s_6 \tag{26} \end{cases} {(2,1): s1r11+c1r21=s5c6(2,2): s1r12+c1r22=s5s6(26)
整理得
s 6 = − s 1 r 12 + c 1 r 22 s 5 c 6 = s 1 r 11 − c 1 r 21 s 5 (27) \begin{aligned} &s_6=\frac{-s_1r_{12}+c_1r_{22}}{s_5} \\\tag{27} &c_6=\frac{s_1r_{11}-c_1r_{21}}{s_5} \end{aligned} s6=s5s1r12+c1r22c6=s5s1r11c1r21(27)
因此
θ 6 = a t a n 2 ( − s 1 r 12 + c 1 r 22 s 5 , s 1 r 11 − c 1 r 21 s 5 ) (28) \theta_6=atan2(\frac{-s_1r_{12}+c_1r_{22}}{s_5} ,\frac{s_1r_{11}-c_1r_{21}}{s_5})\tag{28} θ6=atan2(s5s1r12+c1r22,s5s1r11c1r21)(28)
计算 θ 6 \theta_6 θ6时只需要代入同一组的 θ 1 \theta_1 θ1 θ 5 \theta_5 θ5就行,这边不会产生额外的解

其实因为我们找到了两个方程,所以可以通过消去 θ 5 \theta_5 θ5的方式化作上面的式 ( 19 ) (19) (19)用公式计算,这说明当 θ 1 \theta_1 θ1解出来后, θ 5 \theta_5 θ5 θ 6 \theta_6 θ6应该是同时可以解出来的,不分先后顺序

求解 θ 2 \theta_2 θ2 θ 3 \theta_3 θ3 θ 4 \theta_4 θ4

先求解 θ 234 \theta_{234} θ234

观察矩阵可以看到, θ 2 \theta_2 θ2 θ 3 \theta_3 θ3 θ 4 \theta_4 θ4基本都在一起,所以这三个要用整体的思想去看待与求解,我们这里先求解 θ 234 \theta_{234} θ234,即 θ 2 + θ 3 + θ 4 \theta_2+\theta_3 +\theta_4 θ2+θ3+θ4

{ ( 1 , 3 ) :   c 1 r 13 + s 1 r 23 = − c 234 s 5 ( 3 , 3 ) :   r 33 = − s 234 s 5 (29) \begin{cases} (1,3): \ c_1r_{13}+s_1r_{23}=-c_{234}s_5 \\ (3,3): \ r_{33}=-s_{234}s_5 \tag{29} \end{cases} {(1,3): c1r13+s1r23=c234s5(3,3): r33=s234s5(29)
可得
s 234 = − r 33 s 5 c 234 = − c 1 r 13 + s 1 r 23 s 5 (30) \begin{aligned} &s_{234}=-\frac{r_{33}}{s_5} \\\tag{30} &c_{234}=-\frac{c_1r_{13}+s_1r_{23}}{s_5} \end{aligned} s234=s5r33c234=s5c1r13+s1r23(30)
因此
θ 2 + θ 3 + θ 4 = a t a n 2 ( − r 33 s 5 , − c 1 r 13 + s 1 r 23 s 5 ) (31) \theta_2+\theta_3 +\theta_4=atan2(-\frac{r_{33}}{s_5},-\frac{c_1r_{13}+s_1r_{23}}{s_5})\tag{31} θ2+θ3+θ4=atan2(s5r33,s5c1r13+s1r23)(31)
这边也只需要代入相同组的解,不会产生额外的解
在编程计算中,这里算出来的结果和实际值相差180°,暂未找出错误

再求解 θ 2 \theta_{2} θ2


{ ( 1 , 4 ) :   − c 234 s 5 d 6 + s 234 d 5 + c 23 a 3 + c 2 a 2 = c 1 x + s 1 y ( 3 , 4 ) :   − s 234 s 5 d 6 − c 234 d 5 + s 23 a 3 + s 2 a 2 = z − d 1 (32) \begin{cases} (1,4): \ -c_{234}s_5d_6+s_{234}d_5+c_{23}a_3+c_2a_2=c_1x+s_1y \\ (3,4): \ -s_{234}s_5d_6-c_{234}d_5+s_{23}a_3+s_2a_2=z-d_1 \tag{32} \end{cases} {(1,4): c234s5d6+s234d5+c23a3+c2a2=c1x+s1y(3,4): s234s5d6c234d5+s23a3+s2a2=zd1(32)
我们已经求解出 θ 1 \theta_{1} θ1 θ 5 \theta_{5} θ5 θ 234 \theta_{234} θ234,所以可以把常量拿字母替代掉,让式子变得整洁一点

A = − c 234 s 5 d 6 + s 234 d 5 B = − s 234 s 5 d 6 − c 234 d 5 C = c 1 x + s 1 y D = z − d 1 (33) \begin{aligned} &A=-c_{234}s_5d_6+s_{234}d_5 \\ &B=-s_{234}s_5d_6-c_{234}d_5 \\ &C=c_1x+s_1y \\ \tag{33} &D =z-d_1 \end{aligned} A=c234s5d6+s234d5B=s234s5d6c234d5C=c1x+s1yD=zd1(33)
则式 ( 32 ) (32) (32)可化简为
{ c 23 a 3 = C − A − c 2 a 2 s 23 a 3 = D − B − s 2 a 2 (34) \begin{cases} c_{23}a_3=C-A-c_2a_2 \\ s_{23}a_3=D-B-s_2a_2 \tag{34} \end{cases} {c23a3=CAc2a2s23a3=DBs2a2(34)
这里再设
M = C − A N = D − B (35) \begin{aligned} &M=C-A \\ &N=D-B \tag{35} \end{aligned} M=CAN=DB(35)
对式 ( 34 ) (34) (34)两个等式平方相加消去 θ 23 \theta_{23} θ23,整理得

− ( − 2 N a 2 ) s 2 + 2 M a 2 c 2 = M 2 + N 2 + a 2 2 − a 3 2 (36) -(-2Na_2)s_2+2Ma_2c_2=M^2+N^2+a_2^2-a_3^2\tag{36} (2Na2)s2+2Ma2c2=M2+N2+a22a32(36)
根据式 ( 19 ) ( 20 ) (19)(20) (19)(20)
E = − 2 N a 2 F = 2 M a 2 G = M 2 + N 2 + a 2 2 − a 3 2 (37) \begin{aligned} &E=-2Na_2 \\ &F=2Ma_2 \tag{37} \\ &G=M^2+N^2+a_2^2-a_3^2 \end{aligned} E=2Na2F=2Ma2G=M2+N2+a22a32(37)

θ 2 = a t a n 2 ( F , E ) − a t a n 2 ( G , ± E 2 + F 2 − G 2 ) (38) \theta_2=atan2(F,E)-atan2(G,\pm\sqrt{E^2+F^2-G^2})\tag{38} θ2=atan2(F,E)atan2(G,±E2+F2G2 )(38)
这里在同一组解的情况下, θ 2 \theta_2 θ2会产生额外的一个解,此时解的组数为 4 × 2 = 8 4\times2=8 4×2=8

然后反解 θ 23 \theta_{23} θ23

由式 ( 34 ) ( 35 ) (34)(35) (34)(35)
s 23 = N − s 2 a 2 a 3 c 23 = M − c 2 a 2 a 3 (39) \begin{aligned} &s_{23}=\frac{N-s_2a_2}{a_3} \\ \tag{39} &c_{23}=\frac{M-c_2a_2}{a_3} \end{aligned} s23=a3Ns2a2c23=a3Mc2a2(39)
因此
θ 23 = a t a n 2 ( N − s 2 a 2 a 3 , M − c 2 a 2 a 3 ) (40) \theta_{23}=atan2(\frac{N-s_2a_2}{a_3} ,\frac{M-c_2a_2}{a_3})\tag{40} θ23=atan2(a3Ns2a2,a3Mc2a2)(40)

最后求解 θ 3 \theta_3 θ3 θ 4 \theta_4 θ4

θ 3 = θ 23 − θ 2 (41) \theta_3=\theta_{23}-\theta_{2}\tag{41} θ3=θ23θ2(41) θ 4 = θ 234 − θ 23 (42) \theta_4=\theta_{234}-\theta_{23}\tag{42} θ4=θ234θ23(42)
因为这里的 θ 3 \theta_3 θ3 θ 4 \theta_4 θ4是直接相减得到的,因此也不会产生额外的解

完整代码

Eigen是一个方便矩阵计算(当然不止这个功能)的库,可以去官网下载:http://eigen.tuxfamily.org/

#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;

//ur3数据,这是学长给我的数据,适用于我的仿真环境,大家可以根据自己的环境进行修改
const double d[6+1] = { 0,0.1519,0,0,0.11235,0.08535,0.0819 };//第0个不用
const double a[6] = { 0,0,-0.24365,-0.21325,0,0 };//a有0,没有6
const double alpha[6] = { 0,90,0,0,90,-90 };//alpha有0,没有6
double theta[8 + 1][6 + 1];//八组解,每组解六个角,第0个都不用

//正运动学,用于检验
void kinematics(double* theta_input)
{
	Eigen::Matrix4d T[6 + 1];//为了和theta对应,0不用
	for (int i = 1; i <= 6; i++)
	{
		T[i](0, 0) = cos(theta_input[i]);
		T[i](0, 1) = -sin(theta_input[i]);
		T[i](0, 2) = 0;
		T[i](0, 3) = a[i - 1];
		T[i](1, 0) = sin(theta_input[i]) * cos(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](1, 1) = cos(theta_input[i]) * cos(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](1, 2) = -sin(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](1, 3) = -sin(alpha[i - 1] / 180 * EIGEN_PI) * d[i];
		T[i](2, 0) = sin(theta_input[i]) * sin(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](2, 1) = cos(theta_input[i]) * sin(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](2, 2) = cos(alpha[i - 1] / 180 * EIGEN_PI);
		T[i](2, 3) = cos(alpha[i - 1] / 180 * EIGEN_PI) * d[i];
		T[i](3, 0) = 0;
		T[i](3, 1) = 0;
		T[i](3, 2) = 0;
		T[i](3, 3) = 1;
	}
	Eigen::Matrix4d T06 = T[1] * T[2] * T[3] * T[4] * T[5] * T[6];
	cout << "检验得:X=" << T06(0, 3) * 1000 << "    Y=" << T06(1, 3) * 1000 << "     Z=" << T06(2, 3) * 1000;
}
int main()
{
	double x, y, z, RX, RY, RZ;
	printf("Please input x,y,z,RX,RY,RZ:\n");
	scanf("%lf%lf%lf%lf%lf%lf", &x, &y, &z, &RX, &RY, &RZ);
	//由于仿真软件的单位不同,这边进行转换
	x = x / 1000;
	y = y / 1000;
	z = z / 1000;

	//1.旋转向量转旋转矩阵,即求T06中的r
	Eigen::Vector3d v(RX, RY, RZ);
	double t_alpha = v.norm();//求模
	v.normalize();//标准化
	Eigen::AngleAxisd rv(t_alpha, v);//旋转向量
	Eigen::Matrix3d rm;
	rm = rv.matrix();
	
	//2.求解
	double A, B, C, D, E, F, G, M, N;//用大写字母替代常数

	//注意,由于数组下标从0开始的问题,矩阵第一行第一列的元素是(0,0)
	//theta1
	A = rm(0, 2) * d[6] - x;
	B = rm(1, 2) * d[6] - y;
	C = d[4];
	//第一个解,赋给一到四组
	theta[1][1] = atan2(B, A) - atan2(C, sqrt(A * A + B * B - C * C));
	theta[2][1] = theta[1][1];
	theta[3][1] = theta[1][1];
	theta[4][1] = theta[1][1];
	//第二个解,赋给五到八组
	theta[5][1] = atan2(B, A) - atan2(C, -sqrt(A * A + B * B - C * C));
	theta[6][1] = theta[5][1];
	theta[7][1] = theta[5][1];
	theta[8][1] = theta[5][1];

	//theta5
	//由theta[1][1]产生的第一个解,赋给一到二组
	A = sin(theta[1][1]) * rm(0, 2) - cos(theta[1][1]) * rm(1, 2);
	theta[1][5] = atan2(sqrt(1 - A * A), A);
	theta[2][5] = theta[1][5];
	//由theta[1][1]产生的第二个解,赋给三到四组
	theta[3][5] = atan2(-sqrt(1 - A * A), A);
	theta[4][5] = theta[3][5];
	//由theta[5][1]产生的第一个解,赋给五到六组
	A = sin(theta[5][1]) * rm(0, 2) - cos(theta[5][1]) * rm(1, 2);
	theta[5][5] = atan2(sqrt(1 - A * A), A);
	theta[6][5] = theta[5][5];
	//由theta[5][1]产生的第二个解,赋给七到八组
	theta[7][5] = atan2(-sqrt(1 - A * A), A);
	theta[8][5] = theta[7][5];

	//theta6
	for (int i = 1; i <= 8; i++)
	{
		A = (-sin(theta[i][1]) * rm(0, 1) + cos(theta[i][1]) * rm(1, 1)) / theta[i][5];
		B = (sin(theta[i][1]) * rm(0, 0) - cos(theta[i][1]) * rm(1, 0)) / theta[i][5];
		theta[i][6] = atan2(A, B);
	}

	//theta2、theta3、theta4
	for (int i = 1; i <= 8; i = i + 2)
	{
		//先算theta2+theta3+theta4
		double theta234[8 + 1];
		A = rm(2, 2) / sin(theta[i][5]);
		B = (cos(theta[i][1]) * rm(0, 2) + sin(theta[i][1]) * rm(1, 2)) / sin(theta[i][5]);
		theta234[i] = atan2(-A, -B) - EIGEN_PI;
		theta234[i + 1] = theta234[i];

		//消去theta2+theta3,计算theta2
		A = -cos(theta234[i]) * sin(theta[i][5]) * d[6] + sin(theta234[i]) * d[5];
		B = -sin(theta234[i]) * sin(theta[i][5]) * d[6] - cos(theta234[i]) * d[5];
		C = cos(theta[i][1]) * x + sin(theta[i][1]) * y;
		D = z - d[1];
		M = C - A;
		N = D - B;
		E = -2 * N * a[2];
		F = 2 * M * a[2];
		G = M * M + N * N + a[2] * a[2] - a[3] * a[3];
		theta[i][2] = atan2(F, E) - atan2(G, sqrt(E * E + F * F - G * G));
		theta[i + 1][2] = atan2(F, E) - atan2(G, -sqrt(E * E + F * F - G * G));

		//用theta2反求theta2+theta3
		double theta23[8 + 1];
		theta23[i] = atan2((N - sin(theta[i][2]) * a[2]) / a[3], (M - cos(theta[i][2]) * a[2]) / a[3]);
		theta23[i + 1] = atan2((N - sin(theta[i + 1][2]) * a[2]) / a[3], (M - cos(theta[i + 1][2]) * a[2]) / a[3]);

		//theta3
		theta[i][3] = theta23[i] - theta[i][2];
		theta[i + 1][3] = theta23[i + 1] - theta[i + 1][2];

		//theta4
		theta[i][4] = theta234[i] - theta23[i];
		theta[i + 1][4] = theta234[i + 1] - theta23[i + 1];
	}

	//输出并检验
	for (int i = 1; i <= 8; i++)
	{
		cout << "第" << i << "组解:" << endl;
		for (int j = 1; j <= 6; j++)
			cout << "theta" << j << "=" << theta[i][j] * 180 / EIGEN_PI << "  ";
		cout << endl;
		kinematics(theta[i]);
		cout << endl << endl;
	}
}

测试结果

(数据皆从仿真环境获得,不同的环境可能有不一样的数据配置)

测试数据1
输入: -118.43 -268.05 157.28 0.001 -3.166 -0.040
一组解为: -91.71 -98.96 -126.22 -46.29 91.39 358.22

在这里插入图片描述
测试数据2
输入: -63.78 -201.25 137.28 0.192 3.109 0.036
一组解为: -76.28 -83.49 -151.01 -36.32 91.85 20.76
在这里插入图片描述

不足之处

  1. 没有考虑角度为0°或90°的特殊情况,这边只是计算出了普遍的结果
  2. 一些角度计算出来和实际值相差360°,虽然不影响计算,但说明程序不够完善

代码仅供学习交流使用,如有错误或者疑问可以在评论区提出。转载请标明出处!

  • 35
    点赞
  • 240
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
要实现UR3机械臂逆运动学求解,可以使用Matlab和机器人工具箱(Robotics Toolbox)。根据引用和引用的信息,可以得到以下步骤来求解UR3机械臂逆运动学: 1. 导入Robotics Toolbox: 使用Matlab命令`addpath`添加Robotics Toolbox的路径,确保能够调用相关函数。 2. 定义机器人模型: 使用机器人工具箱中的`SerialLink`函数定义UR3机械臂的模型。根据UR3的DH参数和关节限制进行设置。 3. 设定目标末端位姿: 在Matlab中指定UR3机械臂末端的目标位置和姿态。 4. 进行逆运动学求解: 使用机器人工具箱中的`ikine`函数对UR3机械臂进行逆运动学求解。将目标末端位姿和初始关节角作为输入参数传入函数中。 5. 获取多组逆解: 根据引用的信息,UR3机械臂逆运动学有多个解。可以使用`ikine`函数的第二个参数来指定需要求解的解的数量。 6. 验证逆解的确性: 可以选择其中三个逆解,将它们设置为机械臂的关节角度,并使用机械臂进行运动学计算。然后将计算得到的末端位姿与目标位姿进行比较,以验证逆解的确性。 请注意,具体的Matlab代码实现需要根据具体情况进行编写,以上步骤仅提供了一个基本的框架。可以参考引用和引用中给出的源代码和工具箱进行进一步的详细研究和实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [UR3机械臂运动学反解之解析解](https://blog.csdn.net/weixin_43220219/article/details/127867646)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [UR5机器人逆运动学(matlab代码)](https://download.csdn.net/download/weixin_42846605/12077687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [MATLAB实现六轴机器人逆运动学求解源码](https://download.csdn.net/download/weixin_45591139/86268830)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值