仅供个人学习交流之用。
我们的目的是产生一个能使机器人画出一个字母‘E’的轨迹。首先我们定义了一些需要通过的点,这些点定义了字母的笔画。
>>path=[1 0 1;1 0 0;0 0 0;0 2 0;1 2 0;1 2 1;0 1 1;0 1 0;1 1 0;1 1 1];以任意单位在xy平面中定义。当z=0时画笔向下,当z>0时笔向上。可以画出这些路径片段:
>> plot3(path(:, 1), path(:, 2), path(:, 3), 'color', 'k', 'LineWidth', 2)如图7.16所示。转换成连续路径为:
>>p=mstraj(path, [0.5 0.5 0.3], [], [2 2 2], 0.02, 0.2);第二个参数是x-,y-和z-方向的最大速度,第四个参数表示初始坐标,紧跟着的是采样间隔和加速时间。插值路径中的步数是:
>>about(p) p [double] : 1563x3 (37.5 kB)在20ms的采样间隔下的执行时间为(s):
>>numrows(p)*0.02 ans = 31.2600图7.16 通过10个点的轨迹画出字母‘E’。 标记表示的是经过的点,实线表示运动段。
p是一系列x-y-z坐标,我们需要将其转换成一系列笛卡尔位姿。我们定义的路径画出了长两个单位宽一个单位的字母,所以为了使字母长200mm宽100mm需要将坐标用因子0.1缩放:
>> Tp=transl(0.1*p);Tp表示一系列的齐次变换,这些变换描述了路径上每个点的位姿。在工作空间中,将字母的原点放在坐标(0.4, 0, 0):
>> Tp=homtrans(transl(0.4, 0, 0), Tp);将Tp中的每个位姿乘以第一个参数。 最后我们需要考虑方向。在Tp中定义的每一个坐标都假设z轴垂直向上。然而,Puma机器人的“手肘”向上,像人在桌上写字一样,工作于水平表面。因此它工具的方向,也就是它的z轴,必须向下。解决这个矛盾的一种方法是通过设置机器人的工具变换使工具轴朝上:
>> p560.tool=trotx(pi);现在可以使用逆运动学:
>>q=p560.ikine6s(Tp);来确定关节坐标,然后让它动起来:
>>p560.plot(q)Puma机器人正在画字母’E’,在笔画之间会抬起笔。这个方法非常通用,我们能轻松改变字母的大小、画在一个任意平面上或者使用拥有其他运动学的机器人。 图译者注1 Puma机器人运动过程截图
我们的目的是创建一个四足行走机器人。首先创建一个3轴机械臂作为“足”,然后为其规划一个适于行走的轨迹,最后实例化各个“足”的实例从而创建一个可以行走的机器人。
从运动学上来说,机器人的足与机械手臂类似,在这个应用当中,三关节的串联操作臂已经足够了。尽管对于这样一个简单的机器人而言,确定其DH参数也是一个涉及多个方面的过程,在这个过程中需要用单独的步骤确定零角度偏移。因此我们需要用到7.5.2节中介绍的步骤。 首先从定义坐标系开始,如图7.17所示定义了机械足的坐标系及其在零角度时的位姿。按照航空坐标惯例,选择x轴向前,z轴向下,y轴指向右手方向。第一个关节是髋关节前后运动,绕z轴运动写成Rz(q1)。第二个关节是髋关节上下运动,绕x轴运动写成Rx(q2)。这两个关节形成了一个球形的髋关节,因为两个旋转轴相交。膝关节在髋关节沿y轴平移L1的地方,写成Ty(L1)。第三个关节是膝关节,作朝向或远离躯体的运动,写成Rx(q3)。机器人的脚在膝关节沿z轴平移L2的地方,写成Tz(L2)。从髋关节到脚的变换矩阵为:Rz(q1)Rx(q2)Ty(L1)Rx(q3)Tz(L2)。 图7.17 简单机械腿的坐标系和旋转轴 图中的机械腿处于零角度位姿 使用7.5.2节的方法,将这一变换序列用字符串表示:
>> s = 'Rz(q1).Rx(q2).Ty(L1).Rx(q3).Tz(L2)';需要注意的是,长度常数要以L开头。字符串自动被处理成DH因子:
>> dh = DHFactor(s) DH(q1+90, 0, 0, +90).DH(q2, L1, 0, 0). DH(q3-90, L2, 0, 0).Rz(+90).Rx(-90).Rz(-90)该因式分解的最后三项是工具变换:
>> dh.tool ans = trotz(pi/2)*trotx(-pi/2)*trotz(-pi/2)这会改变足部坐标的方向。然而在这个问题中,足部就是一个接触地面的点,所以我们不用关心它的方向。方法dh.command产生一个字符串,这个字符串表示的命令是产生一个SerialLink对象的命令。
>> dh.command('leg') ans = SerialLink([0, 0, 0, pi/2; 0, 0, L1, 0; 0, 0, -L1, 0; ], 'name', 'leg', 'base', eye(4,4), 'tool', trotz(pi/2)*trotx(-pi/2)*trotz(-pi/2), 'offset', [pi/2 0 -pi/2 ])这是输入到MATLAB@eval的命令:
>> L1 = 0.1; L2 = 0.1; >> leg = eval( dh.command('leg') ) >> leg leg = leg (3 axis, RRR, stdDH) +---+-----------+-----------+-----------+-----------+ | j | theta | d | a | alpha | +---+-----------+-----------+-----------+-----------+ | 1| q1| 0| 0| 1.571| | 2| q2| 0| 0.1| 0| | 3| q3| 0| -0.1| 0| +---+-----------+-----------+-----------+-----------+ grav = 0 base = 1 0 0 0 tool = 0 0 -1 0 0 0 1 0 0 0 1 0 0 9.81 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 1首先要在matlab工作空间将每段腿的长度设置成100mm。 像往常一样,我们对我们的机器人进行快速健全性检查。当关节处于零角度时机器人处于如下位姿:
>> transl( leg.fkine([0,0,0]) )' ans = 0 0.1000 0.1000正如我们设计的一样。我们可以将零角度时的位姿画出来:
>> leg.plot([0,0,0], 'nobase', 'noshadow') >> set(gca, 'Zdir', 'reverse'); view(137,48);图7.18 在零角度位姿时的机械腿 如图7.18所示。注意我们告诉MATLAB我们的z轴向下。现在我们应该测试其他关节导致的预期运动。增加q1:
>> transl( leg.fkine([0.2,0,0]) )' ans = -0.0199 0.0980 0.1000结果在xy平面运动,增加q2:
>> transl( leg.fkine([0,0.2,0]) )' ans = -0.0000 0.0781 0.1179结果在yz平面运动,增加q3:
>> transl( leg.fkine([0,0,0.2]) )' ans = -0.0000 0.0801 0.0980现在我们创建并验证了一个简单的机械腿。
下一个步骤是定义机器腿的末端执行器的轨迹,也就是机器人脚的轨迹。第一个需要考虑的是所有脚的末端执行器以一个相同速度在地面上向后运动——如果脚没打滑,会推动机器人身体向前运动。每条腿都有一个极限的运动范围,所以它不能向后移动非常长的距离。在有些点处需要重置(reset)机械腿——举脚、向前运动、将脚放到地面。第二个需要考虑的问题是静态时的平衡问题——任何时刻机器人必须要有至少三条腿在地面,所以每条腿必须轮流重置。这就要求任何一条腿与地面接触的时间为3/4个周期,重置的时间为1/4个周期。这就导致这样一个结果:机械腿必须在重置的时候运动得更快,因为它需要在更短的时间内运动更远的距离。 所需的轨迹由下列点定义:
>> 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;其中,xf和xb分别表示机械腿在x轴方向上向前和向后的运动极限(单位是mm);y表示在y轴方向上脚距离身体的距离;zu和zd分别表示z轴方向上抬起脚和放下脚时的高度。在这个例子中,机械脚从髋关节前50mm的地方运动到髋关节后50mm的地方。当脚向下运动到离髋关节50mm处时,它会在重置的过程中抬起到20mm处。path中的点包含一个完整的运动周期,相当于:开始站立阶段、站立阶段结束、抬腿到最高点、最高点处的腿返回和开始站立阶段。如图7.19a所示。
图7.19 a、一条单腿的运动轨迹,与图7.17相同z轴向下 红色的线段表示机械腿的重置。 b、为显示步态画出了每条腿在x轴方向上的运动轨迹, x轴方向上的高速段是机械腿的重置阶段。
接下来用100Hz频率对以上多段轨迹进行采样: >> p = mstraj(path, [], [0, 3, 0.25, 0.5, 0.25]', path(1,:), 0.01, 0);在这个例子中我们指定了各段所需时间的向量,而不是最大关节速度。最后三个参数分别表示:初始位置、采样间隔和加速时间。这个轨迹总共耗时4s,因此有400个点。 使用逆运动学来确定机械腿跟踪上述路径所需的关节角运动轨迹。这个机器人是欠激活的(underactuated),所以使用通用的逆运动学函数ikine,设置标志以便只对末端执行器的变换进行求解:
>> qcycle = leg.ikine( transl(p), [], [1 1 1 0 0 0] );我们能预览运动动画:
>> leg.plot(qcycle, 'loop')以便检查它是否按照我们希望的方式运动:沿着地面缓慢运动,然后迅速提脚、向前和放脚。选项’loop’将使其显示为一个无限循环,需要键入control-C停止。
机器人的长和宽为:
>> W = 0.1; L = 0.2;将之前创建的leg对象克隆几个实例,从而创建多条腿。提供不同的基变换,以便将四条腿安装到机器人本体的不同地方。
>> 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));这样得到的结果是SerialLink对象的向量。注意leg3和leg4,在机器人本体的左边,为了使它们指向远离本体的方向,需要将它们绕z轴旋转。 上文中说过,每条腿需要轮流重置。因为轨迹是个循环,通过将每条腿运行轨迹的相移等于总循环时间的1/4来实现这一点。因为总循环有共400个点,每条腿的轨迹有100个点,我们使用模算术来索引进入循环步态每条腿。结果如图7.19b所示的步态模式。 核心行走代码为:
k = 1; while 1 q = qleg(p,:); legs(1).plot( gait(qcycle, k, 0, 0) ); legs(2).plot( gait(qcycle, k, 100, 0) ); legs(3).plot( gait(qcycle, k, 200, 1) ); legs(4).plot( gait(qcycle, k, 300, 1) ); drawnow k = k+1; end函数:
gait(q, k, ph, flip)以q为循环的模运算返回q的第k + ph个元素。参数flip反转机器人左边腿的关节1的运动标志。图7.20为仿真的一个快照。带有一些额外细化的整个操作在文件examples/walking.m中,详细的解释由注释给出。 图7.20 行走的机器人