函数库

import %装载
ETS2.* %二维空间
ETS3.* %三维空间
Rz() %绕z轴旋转
Tx() %沿着x轴平移
.fkine() %正运动学
.teach %示教
.structure %关节的数量和类型
Revolute() %创建转动连杆对象
.A() %计算参数为()时的变换
.type %连杆类别
.offset %设置初始偏移值
models %工具箱自带模型
mdl_ %装载
.edit %编辑模型参数
.n %关节数目
.tool %工具
.base %基座
syms ··· real %定义一些实值符号变量
ikine6s()%求逆运动学封闭解
ikine() %求逆运动学数值解
ikunc() %求逆运动学解
mask 遮盖向量
mtraj() %两点间多轴轨迹
jtraj() %计算关节空间轨迹(具有tpoly插值的mtraj)
ctraj() %两个姿态之间的笛卡尔轨迹
mstraj() %多轴多段轨迹
sim_ %运行simlink
qplot() %绘制关节坐标图
maniplty() %路径的可操作性
DHFactor() %转换为DH因子
dh.command()%生成一个机器人
eval() %计算matlab表达式
RevoluteMDH() %创建连杆对象(改进DH参数)

学习记录

正运动学

"关节j带动连杆j"

  • fkine 正运动学

二维机械臂

>> import ETS2.* %载入SE2
>> a1 = 1;
>> E = Rz('q1') * Tx(a1) %绕z轴旋转q1然后沿着x轴平移a1
>> E.fkine( 30, 'deg') %q1= 30°时的正运动学
>> E.teach %示教
>> a1 = 1; a2 = 1;
>> E = Rz('q1') * Tx(a1) * Rz('q2') * Tx(a2) %两轴RR机械臂
>> E.fkine( [30, 40], 'deg')
>> E.plot( [30, 40], 'deg')
>> E.structure %关节的数量和类型
ans ='RR'
>> clear import %卸掉SE(2),装载SE(3)
>> import ETS3.*
>> a1 = 1;
>> E = Rz('q1') * Tx(a1) * Tz('q2') %RP机械臂
>> E.structure

三维机械臂

>> import ETS3.*
>> L1 = 0; L2 = -0.2337; L3 = 0.4318; L4 = 0.0203; L5 = 0.0837; L6 = 0.4318;
>> E3 = Tz(L1) * Rz('q1') * Ry('q2') * Ty(L2) * Tz(L3) * Ry('q3')* Tx(L4) * Ty(L5) * Tz(L6) * Rz('q4') * Ry('q5') * Rz('q6');
>> E3.fkine([0 0 0 0 0 0])

D-H参数法

>> L = Revolute('a', 1) %创建一个a为1的转动关节 Revolute是Link下的子类
L =
Revolute(std): theta=q, d=0, a=1, alpha=0, offset=0
>> L.A(0.5) %q=0.5时的变换
>> L.type %连杆类别
ans ='R'
>> L.a %连杆参数 a=1
ans =1
>> L.offset = 0.5; %设置初始偏移值
>> L.A(0)
%用SerialLink类将Link类对象串联起来
>> robot = SerialLink( [ Revolute('a', 1) Revolute('a', 1) ],'name', 'my robot')
>> robot.fkine([30 40], 'deg') %计算正向运动学
>> models %工具箱自带模型
>> mdl_irb140 %装载
>> robot.edit %编辑模型参数
>> robot.n %关节数目

指数

>> a1 = 1; a2 = 1; %定义连杆长度
>> TE0 = SE2(a1+a2, 0, 0); %计算TE0
>> S1 = Twist( 'R', [0 0] ); %定义两个Twist
>> S2 = Twist( 'R', [a1 0] );
>> TE = S1.T(30, 'deg') * S2.T(40, 'deg') * TE0 %将它们应用于TE0
错误使用  *  (第 395 行)
operands to * cannot be composed   ???????????????

坐标变换微分方程为

,解可表示为

,那么,对于2连杆机械臂可表示为

,对于多连杆

六轴工业机器人

关节坐标向量,典型机器人位型

  • qz (0,0, 0, 0,0, 0) 零角度

  • qr (0,pi/2,-pi/2,0,0, 0) 就绪状态,机械臂伸直且垂直

  • qs (0,0, -pi/2,0,0, 0) 伸展状态,机械臂伸直且水平

  • qn (0,pi/4,-pi, 0,pi/4,0) 标准姿态,机械臂处于一个灵巧工作姿态

>> mdl_puma560 %加载工具箱自带的puma560
>> p560
>> p560.plot(qz) %绘制位形图
>> TE = p560.fkine(qz) %计算正运动学
>> p560.tool = SE3(0, 0, 0.2); %定义一个工具变换
>> p560.fkine(qz)
>> p560.base = SE3(0, 0, 30*0.0254); %基座变换
>> p560.fkine(qz)
>> p560.base = SE3(0,0,3) * SE3.Rx(pi);
>> p560.fkine(qz)

逆运动学

  • ikine6s:逆运动学封闭解

  • ikine:数值解

2D封闭解

>> import ETS2.*
>> a1 = 1; a2 = 1;
>> E = Rz('q1') * Tx(a1) * Rz('q2') * Tx(a2)
>> syms q1 q2 real %定义一些实值符号变量来表示关节角度
>> TE = E.fkine( [q1, q2] ) %求正运动学
>> syms x y real %定义另外两个符号变量来表示期望的末端执行器位置(x, y)
>> e1 = x == TE.t(1) %将它们与正运动学的结果等同起来
>> e2 = y == TE.t(2)
>> [s1,s2] = solve( [e1 e2], [q1 q2] ) %它给出了两个可以同时解的标量方程
>> length(s2) %q2有两个解
ans =2
>> s2(1)
ans =
-2*atan((-(x^2 + y^2)*(x^2 + y^2 - 4))^(1/2)/(x^2 + y^2))

3D封闭解

  • 'l','r' 左手或右手

  • 'u','d' 肘部在上或在下

  • 'f','n' 手腕翻转或不翻转

>> mdl_puma560
>> qn
qn =0    0.7854    3.1416         0    0.7854         0
>> T = p560.fkine(qn)
>> qi = p560.ikine6s(T) %计算逆运动学封闭解
qi =2.6486   -3.9270    0.0940    2.5326    0.9743    0.3734
>> p560.fkine(qi)
>> qi = p560.ikine6s(T, 'ru') %计算逆运动学右手位形解
qi =-0.0000    0.7854    3.1416   -0.0000    0.7854    0.0000
>> p560.ikine6s( SE3(3, 0, 0) ) %存在无法到达的点
警告: point not reachable
>> q = [0 pi/4 pi 0.1 0 0.2];
>> p560.ikine6s(p560.fkine(q), 'ru') %奇异位型
ans =-0.0000    0.7854    3.1416   -3.0409    0.0000   -2.9423
>> q(4)+q(6) %q4与q6的值与原来完全不同,但和始终等于0.3
ans =0.3000

3D数值解

>> T = p560.fkine(qn)
>> qi = p560.ikine(T) %求数值解
qi =-0.0000   -0.8335    0.0940    0.0000   -0.8312   -0.0000
>> p560.fkine(qi) %qi与qn不同,但计算出的位姿相同
>> p560.plot(qi) %ikine获得了手肘向下的解
>> qi = p560.ikine(T, 'q0', [0 0 3 0 0 0]) %如果我们指定初始关节坐标,则可找到手肘向上的杰
qi = -0.0000    0.7854   -3.1416   -0.0000    0.7854    0.0000

ikine的一般数值方法比ikine6s的解析方法慢得多。但是它有一个很大的优势就是能够处理奇点处的机械手以及小于或大于6个关节的机械手。

欠驱动机械臂

>> mdl_cobra600
>> c600
>> T = SE3(0.4, -0.3, 0.2) * SE3.rpy(30, 40, 160, 'deg') %定义一个理想的末端执行器位姿
>> q = c600.ikine(T, 'mask', [1 1 1 0 0 1]) %遮盖向量(关于x轴和y轴的旋转将被忽略)求数值解
>> Ta = c600.fkine(q);
>> Ta.print('xyz')
t = (0.4, -0.3, 0.2), RPY/xyz = (92.7, 0, 180) deg
%它有理想的平移和偏航角,但俯仰和横摇角是不正确的,正如我们所允许的那样。
>> trplot(T, 'color', 'b')
>> hold on
>> trplot(Ta, 'color', 'r')

冗余机械臂

>> mdl_baxter
>> left %7轴
>> TE = SE3(0.8, 0.2, -0.2) * SE3.Ry(pi);
>> q = left.ikine(TE)
>> left.fkine(q).print('xyz')
t = (0.8, 0.2, -0.2), RPY/xyz = (180, -4.2e-10, 180) deg
>> left.plot(q)

轨迹

  • tpoly:生成标量多项式轨迹

  • lspb:线性段与抛物线混合

  • mtraj:两点间多轴轨迹

  • jtraj:计算关节空间轨迹(具有tpoly插值的mtraj)

  • ctraj:两个姿态之间的笛卡尔轨迹

  • mstraj:多段多轴轨迹

关节空间运动

>> startup_rvc
>> mdl_puma560
>> T1 = SE3(0.4, 0.2, 0) * SE3.Rx(pi);
>> T2 = SE3(0.4, -0.2, 0) * SE3.Rx(pi/2);
>> q1 = p560.ikine6s(T1);
>> q2 = p560.ikine6s(T2);
>> t = [0:0.05:2]';
>> q = jtraj(q1, q2, t);
>> [q,qd,qdd] = jtraj(q1,q2,t);
>> q = p560.jtraj(T1, T2 ,t);
>> p560.plot(q)
>> plot(t, q(:,2))
>> qplot(t, q); %绘制所有随时间变化的关节角
>> T = p560.fkine(q);
>> p = transl(T);//>> p = T.transl;
>> about(p)
>> plot(p(:,1),p(:,2)) %绘制末端执行器在xy平面的轨迹
>> plot(t,tr2rpy(T)) // >> plot(t, T.torpy('xyz')) %绘制末端执行器的姿态随时间变化的图形(横滚-俯仰-偏航角形式)
>> sl_jspace
>> sim('sl_jspace',10);

笛卡尔运动

>> Ts = ctraj(T1,T2,length(t)); %笛卡尔轨迹
>> plot(t, Ts.transl); %提取并绘制位置分量
>> plot(t,Ts.torpy('xyz')); %提取并绘制姿态分量

通过奇异位型的运动

>> T1 = SE3(0.5,  0.3, 0.44) * SE3.Ry(pi/2);
>> T2 = SE3(0.5, -0.3, 0.44) * SE3.Ry(pi/2);
>> Ts = ctraj(T1, T2, length(t)); %得到笛卡尔路径
>> qc =  p560.ikine6s(Ts); %将其转换到关节坐标(封闭解)
>> qplot(t, qc) %绘制关节坐标图a
>> qik2 =  p560.ikunc(Ts);
>> qplot(t,qik2) %绘制关节坐标图b
>> q = p560.jtraj(T1,T2,t); %求关节空间运动的轨迹
>> qplot(t, q)%绘制关节空间运动计算的关节坐标图c
>> m = p560.maniplty(qc); %路径的可操作性
%画出各情况路径的可操作性,如图d
>> mc = p560.maniplty(qc);
>> mk = p560.maniplty(qik2);
>> m = p560.maniplty(q);
>> plot(mc);
>> hold on
>> plot(mk)
>> hold on
>> plot(m)

图a ikine6s得出的关节轨迹图

图b ikunc得出的关节轨迹图

ikine6s:在t≈0.7s时,q4,q6变化率高,奇异点(失去一个自由度,运动学上仅可以求出q4+q6的值)

图c 关节空间运动的关节坐标

图d 可操作性图

ikunc()可以较好地处理奇异性问题

位形转换

>> T = SE3(0.4, 0.2, 0) * SE3.Rx(pi);
>> qr = p560.ikine6s(T, 'ru');
>> ql = p560.ikine6s(T, 'lu');
>> q = jtraj(qr, ql, t); %在这两个关节坐标向量之间创建一个关节空间轨迹
>> p560.plot(q)
>> qplot(q)

右手位形变换到左手位形的关节空间运动

机器人仍然执行了一种十分显著的关节空间运动

高级问题

关节角偏移

>> L = Link([0 0 1 0]);
>> L.offset = pi/4
%或
>> p560.links(2).offset = pi/2;

确定D-H参数

>> s = 'Tz(L1) Rz(q1) Ry(q2) Ty(L2) Tz(L3) Ry(q3) Tx(L4) Ty(L5) Tz(L6) Rz(q4) Ry(q5) Rz(q6)' %写入一个字符串>> dh = DHFactor(s); %将字符串输入一个符号代数函数,返回一个DHFactor对象
>> dh %显示一种机器人运动学结构的可读形式,各关节参数顺序分别为θ,d,a,α
>> cmd = dh.command('puma') %创建一个名为“puma”的机器人
>> L1 = 8; L2 = 3; L3 = 8; L4 = 1; L5 = 8; L6 = 1; L7 = 2;
>> robot = eval(cmd); %创建一个名为robot的工作空间变量(SerialLink对象)

改进DH参数

>> L1 = RevoluteMDH('d', 1)
%或
>> L1 = Link([0 1 0 0 0], 'modified')
%与标准形式区分
>> L1 = Revolute('d', 1)
%或
>> L1 = Link([0 1 0 0 0])

应用:绘图

startup_rvc                                                                 %导入工具箱
mdl_puma560                                                                 %导入机器人模型puma 560
load hershey                                                                %导入字符库
B = hershey{'B'}                                                            %定义B,B为一个结构体,描述了字符的尺寸,垂直从0到0.84,水平从0到0.84(由返回值知)
B.stroke                                                                    %B的路径 且为2行23列的矩阵(由返回值知)
path = [ 0.5*B.stroke; zeros(1,numcols(B.stroke))];                         %缩放路径到原来的0.5倍,添加一零行
k = find(isnan(path(1,:)));                                                 %找到含NaNs的纵列
path(:,k) = path(:,k-1); path(3,k) = 0.2;                                   %将含NaNs的纵列替换为前一列,将z坐标设置为0.2以使笔脱离表面
traj = mstraj(path(:,2:end)', [0.5 0.5 0.5], [], path(:,1)', 0.02, 0.2);    %多轴多段轨迹traj,最大速度0.5,初始坐标为第一列,采样间隔0.02,加速时间0.2
about(traj)
numrows(traj) * 0.02                                                        %计算轨迹所需时间
plot3(traj(:,1), traj(:,2), traj(:,3))                                      %绘制轨迹
Tp = SE3(0.4, 0, 0) * SE3(traj) * SE3.oa( [0 1 0], [0 0 -1]);               %接近向量a向下,夹持器o在y方向上,字符放置在工作区中的(0.4,0,0)处
p = Tp.transl;
plot3(p(:,1), p(:,2), p(:,3))                                               %绘制实际轨迹
q = p560.ikine6s(Tp);
p560.plot(q)

应用:一个简单的步行机器人

startup_rvc
%运动学
%旋转方式所建DH参数与书中例子会略有不同,所以直接复制了书中的SerialLink对象
L1 = 0.1; L2 = 0.1;
leg = SerialLink([0, 0, 0, pi/2, 0; 0, 0, L1, 0, 0; 0, 0, -L2, 0, 0; ],'name', 'leg', 'base', eye(4,4),'tool', trotz(pi/2)*trotx(-pi/2)*trotz(-pi/2),'offset', [pi/2 0 -pi/2 ])
transl( leg.fkine([0,0,0]) )                                                %测试
leg.plot([0,0,0], 'nobase', 'noshadow', 'notiles')                          %绘制一条腿
set(gca, 'Zdir', 'reverse'); view(137,48);                                  %Z轴倒置,设置视角
%以下三条均为测试
transl( leg.fkine([0.2,0,0]) )
transl( leg.fkine([0,0.2,0]) )
transl( leg.fkine([0,0,0.2]) )
%单腿运动
xf = 50; xb = -xf; y = 50; zu = 20; zd = 50;                                %xf,xb:x方向上腿部前进和后退运动的极限 y:y方向上脚到机体的距离 zu,zd:z方向上脚抬起和放下时脚的高度
path = [xf y zd; xb y zd; xb y zu; xf y zu; xf y zd] * 1e-3;                %路径
p = mstraj(path, [], [0, 3, 0.25, 0.5, 0.25]', path(1,:), 0.01, 0);         %多段路径轨迹:路径、各段运动时间、初始位置、采样间隔和加速时间
qcycle = leg.ikine( SE3(p), 'mask', [1 1 1 0 0 0] );                        %逆运动学,欠驱动使用ikine,遮盖向量只求位置不求姿态
%leg.plot(qcycle, 'loop')                                                    %动画,loop:轨迹显示一直循环不断,键入Control-C来停止它
leg.plot(qcycle)
W = 0.1; L = 0.2;
legs(1) = SerialLink(leg, 'name', 'leg1');
legs(2) = SerialLink(leg, 'name', 'leg2', 'base', SE3(-L, 0, 0));
legs(3) = SerialLink(leg, 'name', 'leg3', 'base', SE3(-L, -W, 0)*SE3.Rz(pi));
legs(4) = SerialLink(leg, 'name', 'leg4', 'base', SE3(0, -W, 0)*SE3.Rz(pi));
clf
k = 1;
%for k = 1:600
set(gca, 'Zdir', 'reverse'); view(137,48);                                  %Z轴倒置,设置视角
while 1legs(1).plot( gait(qcycle, k, 0, false), 'workspace', [-0.3 0.3 -0.3 0.3 -0.3 0.3],'nobase', 'noshadow', 'notiles');if k == 1, hold on; endlegs(2).plot( gait(qcycle, k, 100, false),'nobase', 'noshadow', 'notiles' );legs(3).plot( gait(qcycle, k, 200, true),'nobase', 'noshadow', 'notiles' );legs(4).plot( gait(qcycle, k, 300, true),'nobase', 'noshadow', 'notiles' );drawnowk = k+1;
end

总结

6DOF且手腕为球关节:可计算解析解ikine6s(结果不唯一)

其他机器人(包括欠驱动机器人,冗余机器人):数值解ikine

关节空间路径jtraj:非直线路径

笛卡尔路径ctraj:奇异位形可能会导致高关节速度

plot方法

plot算法:

  1. 如果具有指定名称的机器人存在于当前图形中,则以指定的关节角度重绘。这时在其他图形中同一名称的机器人也会更新。

  1. 如果当前图形中没有这个名称的机器人存在,这时如果hold方法已启动,机器人将被添加到当前图形中,否则将在当前窗口中创建一个指定名称的新机器人。

  1. 如果没有图形,则创建一个新的图形。

>> mdl_puma560
% 在不同基座位置创建一个标准Puma机器人的副本
>> p560_2 = SerialLink(p560, 'name', 'puma %2', 'base', transl(0.5, -0.5,0));
>> p560.plot(qr) %绘制第一个机器人
>> hold on %在原视图上叠加
>> p560_2.plot(qr) %绘制第二个机器人
>> p560.plot(qz) %让第一个机器人产生运动
>> figure %新建视图
>> p560.plot(qz) %添加第一个机器人的另外一个视图
>> p560.plot(qr) %两图里的机器人同时转动
>> p560.teach %示教

【机器人工具箱学习笔记】第七章 机械臂运动学相关推荐

  1. 【Matlab 机器人工具箱 学习笔记】双旋转台5轴数控机床 运动学模型02

    参考: [1]何永红, 齐乐华, 赵宝林. 双转台五轴数控机床后置处理算法研究[J]. 制造技术与机床, 2006(1). [2]李永桥, 陈强, 谌永祥. 双转台五轴数控机床运动变换及求解方法的研究 ...

  2. Effective C++ 学习笔记 第七章:模板与泛型编程

    第一章见 Effective C++ 学习笔记 第一章:让自己习惯 C++ 第二章见 Effective C++ 学习笔记 第二章:构造.析构.赋值运算 第三章见 Effective C++ 学习笔记 ...

  3. matlab机器人工具箱学习笔记——ikine函数

    matlab机器人工具箱学习笔记--ikine函数 ikine函数用法 使用实例 链接: https://blog.csdn.net/weixin_42596724/article/details/8 ...

  4. 《Go语言圣经》学习笔记 第七章 接口

    <Go语言圣经>学习笔记 第七章 接口 目录 接口是合约 接口类型 实现接口的条件 flag.Value接口 接口值 sort.Interface接口 http.Handle接口 erro ...

  5. 吴恩达机器学习学习笔记第七章:逻辑回归

    分类Classification分为正类和负类 (规定谁是正谁是负无所谓) 吴恩达老师举例几个例子:判断邮箱是否是垃圾邮箱 一个在线交易是否是诈骗 一个肿瘤是良性的还是恶性 如果我们用之前学习的lin ...

  6. matlab做机器人运动轨迹,matlab机器人工具箱学习笔记——机器人的运动轨迹

    运动轨迹问题 机械臂在三维空间中的每个关节的位置.速度和加速度都是关于时间的函数,他们构成了机械臂的运动轨迹,这里主要有3个问题: 1)根据具体的操作任务给机械臂指定一条空间中的轨迹 2)描述一条规划 ...

  7. 【机器学习-周志华】学习笔记-第七章

    记录第一遍没看懂的 记录觉得有用的 其他章节:         第一章         第三章         第五章         第六章         第七章         第八章      ...

  8. DSP原理学习笔记--第七章--增强直接存储器访问(EDMA)

    第七章 增强直接存储器访问(EDMA) 第七章 增强直接存储器访问(EDMA) DMA 数据传输 EDMA的特点 EDMA控制器的结构 EDMA传输中的术语 EDMA传输方式 同步事件 EDMA通道与 ...

  9. java学习笔记-第七章:面向对象编程(基础部分)

    第七章:面向对象编程(基础部分) 总体内容 类与对象 引出类与对象 类与对象概述 类与对象的关系示意图 属性概念及其细节 类与对象快速入门案例 对象内存布局 类与对象内存分配机制 引申:java内存的 ...

最新文章

  1. Nginx负载均衡实现之四层与七层负载
  2. java流式传输对象_Java性能:面向教学与流式传输
  3. 微机计算机原理姚向华课后答案,微型计算机操作系统
  4. 浅析 Linux 初始化 init 系统,第 3 部分: Systemd
  5. centos6.5下postgresql9.4.3安装与配置
  6. python settings模块_Python settings.VERSION属性代码示例
  7. html中文本框冒号对齐,html5 冒号分隔符对齐的实现,
  8. 使用pyinstaller打包pyqt5出错问题解决
  9. 中如何构造有参和无惨_导数中构造函数的神力你应该借助一下
  10. python字符类型
  11. Mysql高级部分系列(一)
  12. css 纯颜色叠加,CSS颜色叠加
  13. obs无法录制mkv视频文件的解决方法
  14. Linux sed命令详解
  15. 虚拟机ipv4和6都没访问权限_ipv4无访问权限,小编教你ipv4无internet访问权限怎么办...
  16. vue3 实现监听store里state状态变化
  17. elasticsearch服务自动断掉
  18. 第二章:简单古典密码(及其五元组)
  19. 2022-2028年中国商业智能化行业发展现状调查及前景战略分析报告
  20. r语言中将茎叶图旋转90度_R语言(02)绘图

热门文章

  1. IP组播配置与管理——5
  2. contentEditable,window.getSelection详解---可编辑div,容器,设置/获取光标位置,光标处插入内容及光标的操作
  3. vue3获取当前页面组件的路由参数信息
  4. 【Html+JS+CSS】简易轮播图核心代码分享 + 效果展示
  5. BZOJ2277 [Poi2011]Strongbox 【数论】
  6. win10可以上网,但是电脑右下角网络连接上有黄色感叹号
  7. 《汇编语言》王爽(第四版) 课程设计1
  8. 虚拟主机可以运行java_下面哪种类型的文件可以在Java虚拟机中运行( ).
  9. 基于Kinetis 60、HC-SR04超声测距模块的简易水情测量装置
  10. Life Situation Two