本代码是我的毕设里面的一部分,首先是将SCARA机器人简化成为简单的平面双机械臂模型,对其进行动力学建模,由于SCARA机器人的特性,动力学方程中的重力项可以忽略,最后将动力学方程化简成为AX=B的形式,用递推最小二乘的方法,对其中的惯性参数进行辨识,将模型的惯性参数分为六个未知量,在已知位置,速度,加速度和力矩的情况下,进行递推就可以最终得到辨识的六个参数。
有关递推最小二乘的原理,可以参考刘金琨老师的《系统辨识理论及MATLAB仿真》一书的第三章内容,书中详尽的描述了最小二乘,加权最小二乘,递推最小二乘等一系列基础辨识方法的知识,并附有详尽的代码和注释,很有参考价值。
递推最小二乘的核心公式如下:
关键就是通过之前时刻的估计值,以及下一时刻的估计值,更新增益矩阵K和P阵,一步一步实现递推。在调试的过程中,值得注意的一点是P和theta初值的选取,一共有两种方法,如下所示:
在我的调试中发现,书中提供的代码采用的是第二种方式,即任意假设的方式,尽管随着递推的进行,该初值对于辨识结果的影响会越来越小,但是我实际对比中发现,其效果在迭代了3000次以后还是不尽人意,因此如果不是对计算量又要求的 话,选用第一种方法能都得到更好的结果。
通过调用Robotic Toolbox中的rne函数,可以得到每一个关节的力矩输出,通过jtraj函数可以得到运动轨迹。不过在进行系统辨识的时候,观测矩阵的条件数越接近于1,得到的辨识效果就会越好,所以机械臂的运动轨迹选取又是一个很重要的问题,通常选用傅里叶级数的轨迹,轨迹中参数的选取是很重要的,因此在优化激励轨迹参数的时候又延伸出了很多的优化方法,比较常用的就是用条件数的方法,即寻求最小的条件数,在我参阅的论文里面,大多使用遗传算法对激励轨迹进行优化。这一部分的内容留待以后细说。
废话少说,直接贴代码了。欢迎看到我这篇博客的朋友在下面留言一起交流一下学习心得。毕竟我也只是一个菜鸟,还需要多多学习。
clc, clear, close all; deg = pi/180; L1 = Revolute('d', 0.265, 'a', 0.300, 'alpha', 0, ... 'I', [0.003342, 0.050903, 0.052965, 0, 0, 0], ... 'r', [0.1490, 0, 0.0150], ... 'm', 3.0659, ... 'Jm', 200e-6, ... 'G', 1.0063, ... 'B', 1.38e-3, ... 'Tc', [0.132, -0.105], ... 'qlim', [-180 180]*deg ); L2 = Revolute('d', 0.34, 'a',0.300, 'alpha', 0, ... 'I', [0.027638, 0.083822, 0.066801, 0, 0, 0], ... 'r', [0.0824, 0.0, 0.1007], ... 'm', 7.1715, ... 'Jm', 33e-6, ... 'G', 1.0364, ... 'B', 71.2e-6, ... 'Tc', [11.2e-3, -16.9e-3], ... 'qlim', [-180 180]*deg); bot = SerialLink([L1 L2], 'name', 'SCARA'); syms a1 a2 a3 b1 b2 b3 q0 t a21 a22 a23 b21 b22 b23 q20; a1 = 0.999023; a2 = 0.000489; a3 = -0.10124; b1 = -0.998046; b2 = -0.040547; b3 = 0.106009; q0 = 0.681851; a21 = -0.749267; a22 = 0.002565; a23 = -0.111016; b21 = 0.741939; b22 = 0.022350; b23 = -0.106619; q20 = 0.330890; N = 300; t = [0:3/N:3-3/N]; wf = 2*pi/3; q1 = q0 + a1*sin(wf*t)/wf + a2*sin(2*wf*t)/(2*wf) + a3*sin(3*wf*t)/(3*wf) - ... b1*cos(wf*t)/wf - b2*cos(2*wf*t)/(2*wf) - b3*cos(3*wf*t)/(3*wf); q1d = a1*cos(wf*t) + a2*cos(2*wf*t) + a3*cos(3*wf*t) + b1*sin(wf*t) + ... b2*sin(2*wf*t) + b3*sin(3*wf*t); q1dd = b1*wf*cos(wf*t) + b2*wf*2*cos(2*wf*t) + b3*wf*3*cos(3*wf*t) -... a1*wf*sin(wf*t) -a2*2*wf*sin(2*wf*t) -a3*wf*3*sin(3*wf*t); q21 = q20 + a21*sin(wf*t)/wf + a22*sin(2*wf*t)/(2*wf) + a23*sin(3*wf*t)/(3*wf)... - b21*cos(wf*t)/wf - b22*cos(2*wf*t)/(2*wf) - b23*cos(3*wf*t)/(3*wf); q21d = a21*cos(wf*t) + a22*cos(2*wf*t) + a23*cos(3*wf*t) + b21*sin(wf*t)... + b22*sin(2*wf*t) + b23*sin(3*wf*t); q21dd = b21*wf*cos(wf*t) + b22*wf*2*cos(2*wf*t) + b23*wf*3*cos(3*wf*t) -... a21*wf*sin(wf*t) -a22*2*wf*sin(2*wf*t) -a23*wf*3*sin(3*wf*t); lj=[q1',q21']; ljd=[q1d',q21d']; ljdd=[q1dd',q21dd']; tau=bot.rne(lj,ljd,ljdd,[0 0 0]'); k=2; % [q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) ,... % (2*q1dd(1,k-1)+q21dd(1,k-1))*cos(q21(1,k-1))-2*q1d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1))-q21d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1))]';... h1= [0, q1dd(1,k-1)+q21dd(1,k-1) , 0, q1dd(1,k-1)+q21dd(1,k-1) , 0 , q1dd(1,k-1)*cos(q21(1,k-1))+q1d(1,k-1)*q1d(1,k-1)*sin(q21(1,k-1))]'; H(k-1,:)=h1; c0=((H*H')H*tau(k-1,2)')'; p0=inv(H*H'); E=0.000000005; %相对误差 c=[c0,zeros(6,N-1)]; %被辨识参数矩阵的初始值及大小 e=zeros(6,N); %相对误差的初始值及大小 lamt=1; for k=3:N; %[q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) ,... %(2*q1dd(1,k-1)+q21dd(1,k-1))*cos(q21(1,k-1))-2*q1d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1))-q21d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1))]';... h1=[0, q1dd(1,k-1)+q21dd(1,k-1) ,0, q1dd(1,k-1)+q21dd(1,k-1) , 0 , q1dd(1,k-1)*cos(q21(1,k-1))+q1d(1,k-1)*q1d(1,k-1)*sin(q21(1,k-1))]'; k1=(p0*h1)/(h1'*p0*h1+1*lamt); %求出K的值 new=tau(k-1,2)'-h1'*c0; c1=c0+k1*new; %求被辨识参数c p1=p0-p0*h1*inv(1+h1'*p0*h1)*h1'*p0; e1=(c1-c0)./c0; %求参数当前值与上一次的值的差值 e(:,k)=e1; %把当前相对变化的列向量加入误差矩阵的最后一列 c(:,k)=c1; %把辨识参数c列向量加入辨识参数矩阵的最后一列 c0=c1; %新获得的参数作为下一次递推的旧参数 p0=p1; if norm(e1)<=E break; %若参数收敛满足要求,终止计算 end end a1=c(1,:); a2=c(2,:); a3=c(3,:); a4=c(4,:); a5=c(5,:); a6=c(6,:); ea1=e(1,:); ea2=e(2,:); ea3=e(3,:); ea4=e(4,:); ea5=e(5,:); ea6=e(6,:); for k = 3:N; phi=[q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) , q1dd(1,k-1)+q21dd(1,k-1) , q1dd(1,k-1) ,... (2*q1dd(1,k-1)+q21dd(1,k-1))*cos(q21(1,k-1))-2*q1d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1))-q21d(1,k-1)*q21d(1,k-1)*sin(q21(1,k-1));... 0, q1dd(1,k-1)+q21dd(1,k-1) ,0, q1dd(1,k-1)+q21dd(1,k-1) , 0 , q1dd(1,k-1)*cos(q21(1,k-1))+q1d(1,k-1)*q1d(1,k-1)*sin(q21(1,k-1))]'; ntau(k,:) = phi'*c1; end figure(1); i=1:N; plot(i,a1,'k',i,a2,'b',i,a3,'r',i,a4,'g',i,a5,'y',i,a6,'m') %画出辨识结果 legend('a1','a2','a3','a4','a5','a6'); title('递推最小二乘参数辨识') figure(2); i=1:N; plot(i,ea1,'k',i,ea2,'b',i,ea3,'r',i,ea4,'g',i,ea5,'y',i,ea6,'m') %画出辨识结果的收敛情况 legend('a1','a2','a3','a4','a5','a6'); title('辨识精度'); figure(3); plot(tau(:,1));hold on;plot(ntau(:,1)); legend('实际模型','辨识模型'); title('第一关节力矩'); figure(4); plot(tau(:,2));hold on;plot(ntau(:,2)); legend('实际模型','辨识模型'); title('第二关节力矩');
参考的几篇硕士论文:
SCARA机器人动力学分析及鲁棒性控制研究_闫昊
SCARA机器人参数自适应与补偿控制研究_于昊
SCARA机械手运动特性与控制策略研究_赵威
工业机器人动力学参数辨识方法研究_耿令波