这学期机器人学的大作业是做一个七自由度机械臂,
其中六个转动关节,一个伸缩关节
前三个转动关节+一个伸缩关节+末尾三个转动关节
这里记录一下我耗时最久的解析解
首先其实七自由度是有冗余的,我们求解只需要求解六个关节,
我是求解六个旋转关节,然后伸缩关节用于后续规划。
这种解析解的方法是适用于常规机械臂,即前面的关节确定腕部位置,后三个关节确定姿态。
求解θ1 θ2 θ3
将机械臂简化成下图,用于分析解析解。
我们已知机械臂末端的位姿0T7
0T7=0T11T22T33T44T55T66T7=[0R700P71]
首先我们根据末端坐标系将P07转换到P06,记a为0R7.a,则
0P6=0P7−aL
而坐标系5与坐标系6原点重合,所以有
0P5=0P6
现在已知0P5,而0P5仅是关于θ1,θ2,θ3的函数。三个未知数,三个方程,可解。将其不断展开如下
0P5=0T11T22T33T44P5
=0T11T22T33T4⎣⎢⎢⎢⎡00d51⎦⎥⎥⎥⎤
=0T11T22T3⎣⎢⎢⎢⎡00d4+d51⎦⎥⎥⎥⎤
=0T11T2⎣⎢⎢⎢⎡(d4+d5)Sθ3−(d4+d5)Cθ301⎦⎥⎥⎥⎤
=0T1⎣⎢⎢⎢⎡f1Cθ2−f2Sθ2+a2Cθ2f1Sθ2+f2Cθ2+a2Sθ2f31⎦⎥⎥⎥⎤
=⎣⎢⎢⎢⎡g1Cθ1+g3Sθ1g1Sθ1−g3Cθ1g2+d11⎦⎥⎥⎥⎤
其中
f1=(d4+d5)Sθ3g1=f1Cθ2−f2Sθ2+a2Cθ2f2=−(d4+d5)Cθ3g2=f1Sθ2+f2Cθ2+a2Sθ2f3=0g3=f3
所以
⎣⎢⎡px−aLpy−aLpz−aL⎦⎥⎤=⎣⎢⎡g1Cθ1+g3Sθ1g1Sθ1−g3Cθ1g2+d1⎦⎥⎤
通过平方和可以消掉θ1,令
r=(px−aL)2+(py−aL)2+(pz−aL)2=k1(θ2,θ3)
且
pz−aL=g2+d1=k2(θ2,θ3)
则我们获得了两个仅含未知数θ2和θ3的两个方程,可解。化简可得
θ3=asin[2a2(d4+d5)r−(d4+d5)2−a22+d12−2d1z]
观察得g3=0,所以
θ1=atan2(py−aL,px−aL)
求解θ2是求解
ACθ2+BSθ2=C
其中
A=−(d4+d5)Cθ3B=a2+(d4+d5)Sθ3C=z−d1
设
t=tan2θ2
则
cos(θ2)=1+t21−t2sin(θ2)=1+t22t
所以可解得
t=A+CB±B2+A2−C2θ2=2atan(t)
假设θ1,θ2,θ3的取值范围为(0∼2π),
则θ1,θ2,θ3各有两个解,共八组解,但是其中有四组解是错误的。
原因在于求解θ1时使用θ1=atan2(y,x),只关注y和x的比值关系,
有四组错误的解是y和x与正确的解正负号颠倒,
故我们要增加一个关于x或者关于y的条件,
在八组解里筛选出来正确的解。可以使用条件如下
px−aL=g1Cθ1+g3Sθ1py−aL=g1Sθ1−g3Cθ1
最终可解得正确的四组θ1,θ2,θ3。
四组解其实只对应两种姿态,同姿态的两组解θ3相差π
对于三角函数的解的特殊情况,做如下处理
如果不在工作空间的点,θ3求解为复数,则不继续计算。
求解θ2有可能出现单解情况,处理成两个相同的解,保证最后有四组解。
求解θ5 θ6 θ7
已知θ1,θ2,θ3,可得到0T3
0T3=0T11T22T3
又已知0T7,所以可得3T7
3T7=3T00T7
因为
3R7=⎣⎢⎡Sθ5Sθ7+Cθ5Cθ6Cθ7−Cθ5Sθ7+Sθ5Cθ6Cθ7Cθ7Sθ6Cθ7Sθ5−Cθ5Cθ6Sθ7−Cθ7Cθ5−Sθ5Cθ6Sθ7−Sθ6Sθ7Cθ5Sθ6Sθ5Sθ6−Cθ6⎦⎥⎤
所以,当Sθ6=0时,
θ6=atan2(Sθ6,Cθ6)θ5=atan2(R23,R13)θ7=atan2(−R32,R31)
当Sθ6=0时,
θ6=π,θ5=0,θ7=atan2(R12,−R11)θ6=0,θ5=0,θ7=atan2(−R12,R11)
所以最终我们可以解得四组θ1,θ2,θ3,θ5,θ6,θ7。
确定最后的解
因为没有实际躲避碰撞要求,规划最后解就采用关节变化最小的解。
内循环则挑选四组解中与当前关节角度变化最小的一组解
外循环则迭代伸缩关节,计算出不同伸缩关节长度对应的关节变化的最小值的解
然后最后再取所有的最小值,即为最后的解。
Matlab代码
其中全局的Link包含了机械臂的各种当前信息
解析解求解完也只需更新Link
function analytical_inverse_slove(T,dz,dx,alf,telescopic_length)
global Link
theta = zeros(1,7);
for i = 2:8
theta(i-1) = Link(i).th;
end
if dz(4)<0
dz_min = dz(4) - telescopic_length;
dz_max = dz(4);
else
dz_min = dz(4);
dz_max = dz(4) + telescopic_length;
end
ths = [];
dzs = [];
for m = dz_min:2:dz_max
dz(4) = m ;
link_target = T(1:3,4) + T(1:3,3) * abs(dz(7));
r = sum(link_target.*link_target);
x = link_target(1);
y = link_target(2);
z = link_target(3);
th3_1 = asin((r-(dz(4)+dz(5))^2-dx(2)^2+dz(1)^2-2*dz(1)*z)/(2*dx(2)*(dz(4)+dz(5))));
th3_2 = pi-th3_1;
th3 = [th3_1,th3_2];
th1_1 =atan2(y,x);
th1_2 = th1_1 + pi;
th1 = [th1_1,th1_2];
th_123 = zeros(4,3);
index =1;
for j =1:length(th1)
for i=1:length(th3)
A = -(dz(4)+dz(5))*cos(th3(i));
B = dx(2)+(dz(4)+dz(5))*sin(th3(i));
C = z -dz(1);
th2_1_2=solve_cos_plus_sin(A,B,C);
for k=1:length(th2_1_2)
g1 = (dx(2)+(dz(4)+dz(5))*sin(th3(i)))*cos(th2_1_2(k))+...
(dz(4)+dz(5))*cos(th3(i))*sin(th2_1_2(k));
if abs(cos(th1(j))* g1-x)<1e-11 && abs(sin(th1(j))* g1-y)<1e-11
th_123(index,:) = [th1(j),th2_1_2(k),th3(i)];
index = index + 1;
end
end
end
end
if ~isreal(th_123)
continue
end
R06 = T(1:3,1:3);
th_567 = ones(size(th_123,1),3);
for i = 1:size(th_123,1)
T01 = getT(th_123(i,1),dz(1),dx(1),alf(1));
T12 = getT(th_123(i,2),dz(2),dx(2),alf(2));
T23 = getT(th_123(i,3),dz(3),dx(3),alf(3));
T03 = T01 * T12 * T23;
R03 = T03(1:3,1:3);
R36 = R03 \ R06;
[th_567(i,1), th_567(i,2), th_567(i,3)] = solve_R36(R36);
end
th = [th_123, zeros(size(th_123,1),1), th_567];
errs = zeros(1,4);
for i = 1:size(th_123,1)
errs(i) = sum((th(i,:) - theta) .* (th(i,:) - theta));
end
[~,min_index]=min(errs);
ths = [ths;th(min_index,:)];
dzs = [dzs;m];
end
if size(ths,1)~=0
errs = zeros(1,size(ths,1));
for i = 1:size(size(ths,1))
errs(i) = sum((ths(i,:) - theta) .* (ths(i,:) - theta));
end
[~,min_index] = min(errs);
dz(4) = dzs(min_index);
calc_DH(ths(min_index,:),dz,dx,alf);
end
end
参考:https://www.bilibili.com/video/BV1v4411H7ez?p=30