|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
6 P3 B) E# ]/ H; F' `
四足机器人MATLAB仿真
, x6 m( H7 C0 Z我们的目标是创建一个四足步行机器人。首先,我们创建一个三轴机器臂,将其作为步行机器人的一条腿,并为其规划一个适合步行的轨迹,然后将四条腿组合以完成最后的步行机器人。, u* q+ N7 G, C7 H& D* B" S
# w" v7 O0 W) ?% o, v1 k. u; a& s3 Z1 创建一条机器人腿
+ E$ H! C, @ k* u7 {
0 v. |# R7 u E, W
' w$ J+ G) t! W: N
0 f* X2 O. _7 w$ q }' K u2 j
# A1 b! @4 D% d
2 z. p) k U) z: h5 a+ S
我们用工具箱确定D-H参数:: N+ a) M' C, K
( |5 P/ D' {: p% Y, |, [& I! ~
- s='Rz(q1) Rx(q2) Ty(L1) Rx(q3) Tz(L2)';
- dh=DHFactor(s);
- dh.display+ ^% I' c0 i m
: m U2 k% J8 K7 T
1 X# q$ Z5 j- n7 e$ ]1 ^
6 Z- x v8 [! `! }5 A; t0 a1 i" Y( b" n4 D! H. l; h
工具变换:
- f) j9 B& h; m/ }; [* h8 j3 r# Z9 t. H% M2 j, o: f! G- B0 w# p# s
- dh.tool
$ |1 O. z6 h" y$ E* i / i% z. k$ G; t9 c
' X( o2 y; p: s+ A0 E/ Q* h
C$ Z; v! r, s) V: e1 W" ^$ L! Y2 N& g
它改变了脚部坐标系的方向。然而,在这个问题中脚与地面只是一个简单的点接触,所以我们并不关注它的方向。方法dh .command生成一个工具箱命令字符串,用以创建一个 serialLink对象:4 z1 \( b2 p* ^% k
$ V5 t8 Q' w$ }& y$ Y: u
- dh.command('leg')/ J, Y) g# s7 N& s( t3 Y
. _$ f, u- X1 l. U+ X- J
0 c9 G1 ~' }8 L( ]' {7 K& b. W结果:5 w; c, w5 m9 m9 Y$ |/ j' s7 H
1 H7 n! x4 a! u- R* `0 g- 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 ])) a! q4 T1 G0 B' w0 @1 Y5 N; [
7 N* F9 J+ L* `! Z+ T
3 E9 q) Z* `! j2 q& j
在MATLAB工作区里将腿的各个部分长度都设置为100毫米之后,将SerialLink对象输入MATLAB的eval命令中:
9 p+ X; P" m1 v a) U0 Z+ X5 K$ K9 m! o- ?- I1 u4 ]9 G
- L1=0.1;L2=0.1;
- leg=eval(dh.command('leg'))
7 B) {8 v8 ^! {7 f
, i, s! ]+ g0 v% [" s2 F- t* ?# k1 N/ E3 C6 P# D) ^3 V
0 r9 m6 l u$ L
' W# S% K/ w8 @9 W/ m( }$ B: d在零关节角度时,脚尖处于我们所设计的位置上:
, _+ ]: I# {* r5 k7 r7 v {( E+ ?% ?% D( N
- transl(leg.fkine([0,0,0])); u9 F+ u7 O& C) C" i
* F' m, k+ P0 t( Q0 F" X1 |! ], B0 ]
" @- J) d! g* S2 m% j! z5 l) `% ?2 {我们可以绘制出机器人的零角度位姿:
' U0 C- g" @* h/ X- C8 z7 U
- l/ C4 [ V! L9 g( a! z- transl(leg.fkine([0,0,0]))
- leg.plot([0,0,0],'nobase','noshadow')
- set(gca,'Zdir','reverse');view(137,48);" E5 T1 Q( R% l0 J6 l
3 c- f# e6 D0 i# M4 N" [! e& E3 J7 c6 e) g5 G$ {
; |, W- C* h& m w; A( q0 f) R! W6 ?1 m( w" ?
现在,我们测试各个关节是否能产生期望的运动:
4 o4 N9 b' ?5 u2 W' x, {- j# G$ \1 U: g
- transl(leg.fkine([0.2,0,0]))'
- transl(leg.fkine([0,0.2,0]))'
- transl(leg.fkine([0,0,0.2]))'/ ~% I! A+ I2 {6 W6 F
+ r; @% X' `5 ^
) t7 ~- v# u- ?% ~+ q
; `5 s+ ]: Q: k$ |6 s
至此,我们已经创建并验证了一个简单的机器人腿。
+ l1 E5 r/ }3 D) D7 j
4 q4 s; f5 V5 S& n& Z( ^, X2 单腿运动( w& |) f t1 s4 B
下一步是定义的腿的末端执行器(即它的脚)将运行的路径。首先考虑的是:所有的脚都在地面上以相同的速度向后移动,其作用是在脚实际上没有相对地面滑动的情况下推动机器人身体向前运动。由于每条腿的运动范围有限,因此它不能后退很长的距离。在某个点我们必须复位机器人腿——抬起脚,向前移动,再放在地面上。第二个考虑是静态稳定性—任何时候机器人必须至少有三只脚同时站在地面上,所以每条腿必须按顺序依次复位。这就要求在一个周期内每条腿有3/4的时间与地面接触,而另外1/4的时间在复位。其结果是,腿在复位期间必须加快移动,因为它要用相对少的时间来完成一段更长的路径。
# B: ~. x' u& b4 T( y8 G1 p% o
& k9 o- N% t" H9 x所需的轨迹是由所有途径点所决定:7 o4 w, H8 y# z: g
8 Q# V9 n8 Y L/ \" ^- N- D- xf=50;xb=-xf;y=50;zu=20;zd=50;
- path=[xf,y,zd;xb,y,zd;xb,y,zu;xf,y,zu;xf,y,zd]&1e-3;& U9 k t- d/ R5 B* O
+ I; p: E! H7 ?; `. ~+ k( o9 G( n) f7 T
其中,xf和xb分别是 x x x方向上腿部前进和后退运动的极限(以毫米为单位), y y y是 y y y方向上脚到机体的距离,而zu和zd分别是在 z z z方向上脚抬起和放下时脚的高度。在这个示例中,脚是从髋部前面50毫米运动至后面50毫米。当脚部放下时,它位于髋部下方50毫米,而在复位期间脚提升到髋部下方20毫米处(注意:仿真中z轴设置为向下)。6 C0 h2 [3 U3 m) h
6 s0 |/ |2 w9 `( V0 D& j9 D3 V
2 F8 w( C) h: I% F8 P9 a+ T
( Q% w+ D9 M- _$ M1 T5 Z; p
在path中的点包含一个完整的周期,对应于站立的开始阶段、站立的结束阶段、脚尖抬起阶段、脚尖返回阶段、最后回到站立的开始,如图所示。! ^$ \8 b- a6 ^0 l' h5 s$ }
. @( x$ e; j3 `+ L3 n$ x- % 100HZ的频率对多段路径进行采样
- path=mstraj(path,[],[0,3,0.25,0.5,0.25]',path(1,:),0.01,0);
- plot3(path(:,1),path(:,2),path(:,3),'color','k','LineWidth',2)0 T" F: W# b; Y+ {+ D0 _( s
( D; J: e7 O* ?. y
7 i5 q; f* g" }# z此例中,我们已经指定了一个包含各段运动时间的向量,而不是最大的关节速度。最后3个参数分别是初始位置、采样间隔和加速时间。这个轨迹总的运行时间为4秒,因此它包含了400个点。
/ x4 V- w# A9 e
! [7 W- ]- k; q5 a3 p( w/ G* B
% ]$ R" a: \) A5 W# K0 v2 O$ p; ?, W4 s& P0 ~) Q/ U) W: Z
我们用逆运动学来确定脚尖路径所需的关节角度轨迹。这个机器人是欠驱动的,所以我们使用广义逆运动学ikine,并通过设置掩盖向量以求解末端执行器的平移:4 ?6 P5 ]0 o" p: z
$ ?1 h( ~) M3 _1 R5 E9 z `/ @: {2 B- qcycle=leg.ikine(transl(path),[],[1,1,1,0,0,0]);
- % 动画
- view(-pi,-pi/2)
- leg.plot(qcycle,'loop')/ Z0 _" T0 S" w9 U% p
! W! C# X+ I7 T% K9 Y* ^/ n9 A7 s. \/ V: l/ s% x( l4 ^1 ]% g/ x
9 m1 K( F8 a1 R/ g5 L
1 L; W- P3 A4 w) z5 D* ~ n以验证它是否如我们所愿:先沿着地面缓慢运动,然后快速提升、向前运动和放下脚。' loop '选项将使轨迹的显示一直循环不断,而你需要键人Control-C来停止它。
7 J$ w8 Y, x3 k; ?& ?, t8 K8 [2 L
3 四腿运动% ~# \2 N5 X$ A2 D6 i# R
定义机器人的宽度和长度:% A! K! l* e' D9 Q
! j1 n" x9 B1 t$ c$ R% Z! Z# q- W=0.1;L=0.2;
; |$ I; d, H2 v; ^6 m3 X; I5 O - T% P' o2 m: c! `
0 B; ]+ K9 h- I3 M通过复制先前生成的leg对象,就可以创建多条腿的机器人。但其中我们要提供不同的基座转换,以将腿连接到机体上不同的点:
. N$ h' ^- T; q" h% }
! X9 E) j# G4 m/ q2 O9 o: O2 {- legs(1) = SerialLink(leg, 'name', 'leg1');
- legs(2) = SerialLink(leg, 'name', 'leg2', 'base', transl(-L, 0, 0));
- legs(3) = SerialLink(leg, 'name', 'leg3', 'base', transl(-L, -W, 0)*trotz(pi));
- legs(4) = SerialLink(leg, 'name', 'leg4', 'base', transl(0, -W, 0)*trotz(pi));
8 ^: {; r3 x( p8 N- C9 b 5 _- _( e$ I: q- G: z; z
7 f$ h' y7 \/ x
得到的结果是一个包含多个SerialLink对象的向量。请注意,机体左侧的第3条和第4条腿已经绕着z轴进行了旋转trotz(pi),使得它们都朝向身体外侧。
* I& Q: E" ~$ g' \% |) }$ }7 `" I7 d/ B; {" e U: @0 V+ v$ ]6 o; C
如前所述,每条腿必须按照各自的顺序进行复位。由于腿的轨迹是一个周期运动,我们可以通过使每个腿的运动轨迹有一个相位偏移来实现按顺序复位,该相移时间为总循环周期的1/4。由于总周期有400点,因此每条腿的相移为100个点。然后我们使用模运算来模拟每条腿的循环步态。
) |: Z$ P& P/ d6 K9 f) R' H; [: S# d; R/ U
行走程序的核心是4 a1 Q* K) \5 }
# H3 j4 [ l# Z4 [- k=1;
- for i=1:500
- legs(1).animate( gait(qcycle, k, 0, 0));
- legs(2).animate( gait(qcycle, k, 100, 0));
- legs(3).animate( gait(qcycle, k, 200, 1));
- legs(4).animate( gait(qcycle, k, 300, 1));
- drawnow
- k = k+1;
- end
$ s1 r/ d2 z- ^3 G" K
# E6 P9 J2 [: J7 @) g+ n2 Q8 Q0 J" D6 d- n+ j1 K
其中的函数
6 d& H% n) e( `. ?9 d4 [* m. E- ?$ I8 z3 u' i& j
- gait(q,k, ph,. flip)& f7 k. E' \2 K+ z4 y
9 O4 `: L& {9 W- Y
& g4 t9 h" l' `将通过模运算返回q的第k +ph个元素,而模运算将q看作一个周期。参数flip是将机器人左侧两条腿上关节1运动的符号取反(从动态图可以看到左右第一个关节的转向是相反的)。* M) C3 N. ~, v3 x! m: v, f
d5 Y1 m/ ]0 V8 w) Y5 @
- clc;
- clear
- close all
- s='Rz(q1) Rx(q2) Ty(L1) Rx(q3) Tz(L2)';
- dh=DHFactor(s);
- L1=0.1;L2=0.1;
- leg=eval(dh.command('leg;'));
- % 定义沿着x轴方向走的关键参数
- xf = 5; xb = -xf; % x方向上腿前进和后退运动的极限
- y = 5; % y方向上脚到机体的距离 运动时是固定的
- zu = 2; zd = 5; % z方向上脚抬起和放下时脚的高度。
- % 定义方形轨迹
- segments = [xf y zd; xb y zd; xb y zu; xf y zu] * 0.01;
- segments = [segments; segments]; % 长度为8,两个运动周期分八段
- % build the gait. the points are:
- % 1 start of walking stroke
- % 2 end of walking stroke
- % 3 end of foot raise
- % 4 foot raised and forward
- %
- % The segments times are :
- % 1->2 3s
- % 2->3 0.25s
- % 3->4 0.5s
- % 4->1 0.25s
- tseg = [3 0.25 0.5 0.25]';
- tseg = [1; tseg; tseg]; % 在开头增加一个1是为预加速
- x = mstraj(segments, [], tseg, segments(1,:), 0.01, 0.1); % 采样间隔为0.01,总的有400step
- % 总的为1, 2, 3, 4, 1, 2, 3, 4,去掉加速部分(舍弃一些值),
- % 其中的 2->3->4->1 is smooth cyclic motion so we "cut it out" and use it.
- xcycle = x(100:500,:);
- %=========================================================
- % 运行以下程序即可知道"cut it out"的目的。
- % figure(1)
- % plot3(x(:,1),x(:,2),x(:,3))
- % rotate3d on
- % figure(2)
- % plot3(xcycle(:,1),xcycle(:,2),xcycle(:,3),'color','r')
- % rotate3d on
- %=========================================================
- qcycle = leg.ikine( transl(xcycle), [], [1 1 1 0 0 0], 'pinv' );
- % 机器人长方形身体的宽和长
- W = 0.1; L = 0.2;
- % 创建4条腿的机器人。每条腿都是我们上面造的腿机器人的克隆,
- % 通过'base'基变换将四条腿安装在身体的四个角
- legs(1) = SerialLink(leg, 'name', 'leg1');
- legs(2) = SerialLink(leg, 'name', 'leg2', 'base', transl(-L, 0, 0));
- legs(3) = SerialLink(leg, 'name', 'leg3', 'base', transl(-L, -W, 0)*trotz(pi));
- legs(4) = SerialLink(leg, 'name', 'leg4', 'base', transl(0, -W, 0)*trotz(pi));
- % create a fixed size axis for the robot, and set z positive downward
- clf; axis([-0.3 0.1 -0.2 0.2 -0.15 0.05]); set(gca,'Zdir', 'reverse')
- hold on
- % draw the robot's body
- patch([0 -L -L 0], [0 0 -W -W], [0 0 0 0], ...
- 'FaceColor', 'r', 'FaceAlpha', 0.5);
- % 初始化机器人
- % 一点优化。我们使用了很多打印选项来快速制作动画:
- % 关闭注释,如手腕轴、地面阴影、关节轴、无平滑着色。
- % 我们不是在每个循环中解析开关,而是在这里预先将它们分解成plotopt结构。
- plotopt = {'noraise', 'nobase', 'noshadow', 'nowrist', 'nojaxes', 'delay', 0};
- for i=1:4
- legs(i).plot(qcycle(1,:), plotopt{:});
- end
- hold off
- k = 1;
- while 1
- legs(1).animate( gait(qcycle, k, 0, 0))
- legs(2).animate( gait(qcycle, k, 100, 0))
- legs(3).animate( gait(qcycle, k, 200, 1))
- legs(4).animate( gait(qcycle, k, 300, 1))
- drawnow
- k = k+1;
- end
: o7 z. @0 v7 h3 S$ u
/ f# w/ C5 l: C
8 c# {( j/ k! i! A: C- o
( O: O1 T8 Z, n6 c) Q2 l
|
|