zoukankan      html  css  js  c++  java
  • 机器人学——2.3-姿态插值和笛卡尔运动

    之前我们提到mstraj函数并不是不是对坐标系旋转进行插值的理想方式。

    在机器人学中,我们经常需要对姿态进行插值。例如,我们需要机器人的末端执行器平滑地从姿态 ξ0xi_0 和改变到 ξ1xi_1。假设某个函数 ξ(s)=σ(ξ0,ξ1,s)xi(s)=sigma(xi_0, xi_1, s),其中 s[0,1]sin[0,1],可以看做是一条归一化了的路径,函数的边界条件为 σ(ξ0,ξ1,0)=ξ0sigma(xi_0, xi_1, 0)=xi_0σ(ξ0,ξ1,1)=ξ1sigma(xi_0, xi_1, 1)=xi_1,而且 σ(ξ0,ξ1,s)sigma(xi_0, xi_1, s) 要能平滑地经过 ss 内定义的一系列中间位姿。我们之间已经了解了多种位姿的描述方式,我们不妨分别讨论。

    如果位姿由正交旋转矩阵表示,ξRSO(3)xisim Rin SO(3),如果用简单的线性插值 σ(R0,R1,s)=(1s)R0+sR1sigma(R_0,R_1,s)=(1-s)R_0+sR_1。但这是不可行的,这样插值后得到的通常不再是有效的正交矩阵,因为正交矩阵必须满足的列向量范数为1以及列向量之间正交的条件。

    一般是选择三角度表示法,如欧拉角或横滚-俯仰-偏航角,ξΓS3xisimGammainmathbb{S}^3,这样就可以使用线性插值法:
    σ(Γ0,Γ1,s)=(1s)Γ0+sΓ1 sigma(Gamma_0, Gamma_1, s)=(1-s)Gamma_0+sGamma_1 例如,我们定义了两个姿态:

    >> R0 = rotz(-1) * roty(-1);
    >> R1 = rotz(1) * roty(1);
    

    得到等价横滚-俯仰-偏航角:

    >> rpy0 = tr2rpy(R0);
    >> rpy1 = tr2rpy(R1);
    

    然后分50个时间步在它们之间生成一条轨迹:

    >> rpy = mtraj(@tpoly, rpy0, rpy1, 50);
    

    通过动画演示,很容易观察轨迹变化过程(rpy是一个 50×350×3 矩阵,而rpy2tr的结果是 4×4×504×4×50 矩阵。):

    >> tranimate(rpy2tr(rpy));
    

    由于姿态变化较大,可以看出坐标系的旋转轴线沿轨迹的变化。这个动作虽然平滑,但有时看起来也不太协调。另外,如果在所采用的三角度系统中有 ξ0xi_0ξ1xi_1 与之一接近奇异点,也会出现问题。

    采用单位四元数的插值法只比三角度向量法复杂一点点,它在空间中产生一个绕固定轴旋转的姿态变化。首先,我们利用机器人工具箱函数找到与这两个位姿等价的四元数:

    >> q0 = Quaternion(R0);
    >> q1 = Quaternion(R1);
    

    然后对它们进行插值并进行动画演示:

    >> q = interp(q0, q1, [0:49]'/49);
    >> about(q)
    q [Quaternion] : 1x50 (1.6 kB)
    >> tranimate(q)
    

    四元数插值法是通过使用球形线性插值(slerp)来实现的,其中单位四元数要在一个四维超球面上沿一个大圆路径运动。而在三维空间中的结果就是绕定轴的转动。

    笛卡尔运动

    另一个常见的需求是在 SE(3)SE(3) 中生成两位姿之间的光滑路径,它同时涉及位置及姿态的变化。在机器人学中这通常被称作笛卡儿运动。我们将初始和最终位姿都表示成齐次变换矩阵:

    >> T0 = transl(0.4, 0.2, 0) * trotx(pi);
    >> T1 = transl(-0.4, -0.2, 0.3) * troty(pi/2) * trotz(-pi/2);
    

    工具箱函数trinterp提供了沿路径单位化距离 s[0,1]sin[0,1] 中的位姿插值。例如,其中间的位姿是

    >> trinterp(T0, T1, 0.5)
    ans =
        0.6667   -0.3333    0.6667         0
       -0.6667   -0.6667    0.3333         0
        0.3333   -0.6667   -0.6667    0.1500
             0         0         0    1.0000
    

    其中平移部分是用线性插值,旋转部分是用四元数插值法interp进行球形插值。
    两个位姿之间 5050 个分步的轨迹可用以下方法生成:

    >> Ts = trinterp(T0, T1, [0:49]'/49);
    

    参数分别对应的是起点和终点的位姿,以及从 0011 线性变化的路径长度。由此产生的轨迹Ts是一个三维矩阵:

    >> about(Ts)
    Ts [double] : 4x4x50 (6.4 kB)
    

    代表的是每个时间分步(第三个指数 5050 )对应的齐次变换矩阵(前两个指数 4×44×4 )。其中,路径上第一点的齐次变换是:

    >> Ts(:,:,1)
    ans =
        1.0000         0         0    0.4000
             0   -1.0000         0    0.2000
             0         0   -1.0000         0
             0         0         0    1.0000
    

    最简单直观的表现方法仍然是通过动画:

    >> tranimate(Ts)
    

    它将展现出坐标系从位姿T1平移、旋转到位姿T2的变化过程。
    该轨迹的平移部分由以下方式获得:

    >> P = transl(Ts);
    

    它将以矩阵形式返回轨迹的笛卡儿位置坐标:

    >> about(P)
    P [double] : 50x3 (1.2 kB)
    

    可以看出,P505033 列,每一行对应每个时间分步上的位置向量。
    位置向量的变化可以用plot 函数画出:

    >> plot(P)
    

    以横滚-俯仰-偏摆角格式画的姿态变化曲线:

    >> rpy = tr2rpy(Ts);
    >> plot(rpy);
    

    在这里插入图片描述
    从图中看到,位置坐标随时间的变化既平滑又呈线性,而姿态随时间的变化也平滑,但不是线性的。横滚-俯仰-偏航角之所以不呈现时间线性,因为它们是对线性变化的四元数进行非线性变换的结果。最后两个点之间的不连续性,是因为对于横滚-俯仰一偏航角,其最终姿态是一个奇异点。

    然而,平移运动在第一个和最后一个点上的速度和加速度是不连续的。问题在于虽然轨迹在空间中是平滑的,但沿轨迹的步距 ss 在时间上并不平滑。路径起点上的速度值从零跳跃到有限值,然后在终点又突降至零——没有相应的起始加速和结束减速。我们可以用前面讨论过的标量函数tpolylspb来创建一个时间上平滑的 ss,这样沿路径的运动也平滑了。我们只需将传递给trinterp的第三个参数更改为一个沿路径的单位化距离向量即可:

    >> Ts = trinterp(T0, T1, lspb(0, 1, 50))
    

    这样做对于轨迹是不变的,但这时坐标系会沿路径逐渐加速到一个恒定速度,然后结束时再减速,这一点可以从下图中轨迹姿态部分较光滑的曲线反映出来。
    在这里插入图片描述
    工具箱中还提供了一个方便的速记函数ctraj来进行轨迹插值,其中的参数是初始和最终的位姿,以及分步数量。:

    >> Ts = ctraj(T0, T1, 50);
    
  • 相关阅读:
    快逸报表调用存储过程(SqlServer)
    一个睡五分钟等于六个钟头的方法 (转)
    Windows Live Writer For Windows Server 2003
    设计模式装饰者模式
    SqlServerCUBE
    Android 70道面试题汇总不再愁面试
    说服力:让你的PPT会说话
    亮剑Java项目开发案例导航
    初入社会必知的88个潜规则
    android UI进阶之仿iphone的tab效果2
  • 原文地址:https://www.cnblogs.com/thewaytotheway/p/12847242.html
Copyright © 2011-2022 走看看