我想控制我的7自由度机械臂沿世界框架中的笛卡尔轨迹运动。对于翻译,我可以做到这一点,但是我在为轮换实现类似的方法上苦苦挣扎。到目前为止,我的所有尝试似乎都不稳定。

轨迹描述为平移和旋转速度,以及距离和/或超时停止标准。基本上,我希望末端执行器相对于其当前位置移动一小段距离。由于数字错误,控制器错误,合规性等原因,机械臂不会完全位于您上一次迭代所需的位置。所以我不只是做$ J ^ {-1} v_e $。取而代之的是,我在开始时存储末端执行器的姿势,然后在每次迭代中计算末端执行器在当前时间应位于的位置,取当前位置与当前位置之间的差,然后将其输入到Jacobian中。

我将首先描述我的翻译实现。以下是一些伪OpenRave Python:

# velocity_transform specified in m/s as relative motion
def move(velocity_transform):
  t_start = time.time()
  pose_start = effector.GetTransform()
  while True:
    t_now = time.time()
    t_elapsed = t_now - t_start
    pose_current = effector.GetTransform()
    translation_target = pose_start[:3,3] + velocity_transform[:3,3] * t_elapsed
    v_trans = translation_target - pose_current[:3,3]
    vels = J_plus.dot(v_trans) # some math simplified here


旋转有点棘手。为了确定当前所需的旋转角度,我使用了球面线性插值(SLERP)。 OpenRave提供了我使用的quatSlerp()函数。 (它需要转换为四元数,但似乎可以使用)。然后,我计算当前姿势和目标旋转之间的相对旋转。最后,我转换为欧拉角,这是我必须传递给AngularVelocityJacobian的角度。这是它的伪代码。这些行在while循环中:

rot_t1 = np.dot(pose_start[:3,:3], velocity_transform[:3,:3]) # desired rotation of end-effector 1 second from start
quat_start = quatFromRotationMatrix(pose_start) # start pose as quaternion
quat_t1 = quatFromRotationMatrix(rot_t1) # rot_t1 as quaternion

# use SLERP to compute proper rotation at this time
quat_target = quatSlerp(quat_start, quat_t1, t_elapsed) # world_to_target
rot_target = rotationMatrixFromQuat(quat_target) # world_to_target
v_rot = np.dot(np.linalg.inv(pose_current[:3,:3]), rot_target) # current_to_target
v_euler = eulerFromRotationMatrix(v_rot) # get rotation about world axes


然后将v_euler与v_trans一起馈入Jacobian。我很确定我的Jacobian代码很好。因为我已经给它恒定的旋转速度了。

注意,我不是要您调试我的代码。我之所以只发布代码,是因为我认为它比将其全部转换为数学代码更加清晰。我对为什么这可能变得不稳定感兴趣。具体来说,数学有误吗?如果这完全没有根据,请告诉我。我确定人们必须以某种方式解决这个问题。

到目前为止,我一直给它提供缓慢的线速度(0.01 m / s)和零目标转速。手臂位于工作空间中的一个好位置,可以轻松实现所需的运动。代码以200Hz运行,应该足够快。

我可以用硬编码方式输入到雅可比行列式中的角速度,而不用使用计算出的v_euler,并且没有不稳定。所以我的数学有问题。这适用于零和非零目标角速度。有趣的是,当我以0.01 rad / sec的角速度进给时,末端执行器以90度/秒的速度旋转。

更新:如果我将末端执行器放在其他位置在工作区中使其轴与世界轴对齐,那么一切似乎都正常。如果末端执行器与世界坐标轴成45度角,则某些动作似乎起作用,而其他动作则未按照应有的方式精确移动,尽管我认为我没有看到它会变得不稳定。与世界相距90度以上时,它会变得不稳定。

评论

如果简单命令旋转,手臂会变得不稳定吗?

时间步长足够短吗?

好问题,我通过回答扩大了我的问题。

非常感谢您的帖子和答案。我能够计算期望值与当前值之间3x3的旋转矩阵中的误差。我不知道如何得出轴角(r * sin(theta))。如果我做错了,请纠正我,我认为通过转换为四元数形式可以使轴和角度变大。你能解释一下吗?在此先感谢

欢迎使用机器人技术Vikram Sridhar。在堆栈交换中,答案需要回答问题。如果您有一个相关的问题,则应将其作为一个新问题(最好是参考此问题)提出。请注意,我们倾向于根据您所遇到的实际问题提出实用,可回答的问题。请查看“如何询问和浏览”以获取有关堆栈交换如何工作的更多信息。

#1 楼

在Sciavicco-Siciliano的书中很好地描述了处理定向误差(就所需位置和所需速度而言的误差而言)所需的数学运算。请参阅从第137页开始的第3.7.3节。

我个人使用轴角标记,因此我对第139页给出的公式(3.89)进行了编码,结果正确。

简而言之,给定在位置和速度上都跟踪笛卡尔空间中6D轨迹的目标,输入是平移部分的$ \ left(p_d,\ dot {p} _d \ right)$和$ \向左(\ theta_d,\ omega_d \ right)$表示方向部分(轴角度)。输入是随时间变化的(即$ p_d \ equiv p_d \ left(t \ right)$)。然后,分析误差的动态(例如参见第3.7.1节),得出一个收敛规则,其$ \ mathbin {K} _P $和$ \ mathbin {K} _O $是作用于正定矩阵的增益错误本身。这些矩阵仅设置收敛速度。

我没有进入您的代码,但是此公式作为其不同版本,利用Jacobian的伪逆来产生阶跃。逐步以大约指定的笛卡尔速度将机械手朝末端执行器的目标位置和方向驱动所需的关节速度。

更新

请在下面的注释中,为您提供一个非常基本的起点,请看一下这些行。它们是计算笛卡尔误差的方法的一部分,而笛卡尔误差又是我们与iCub一起使用的操作空间控制器的重要组成部分。

现在想象一下。然后将执行所有行ctrlPose==IKINCTRL_POSE_FULL。第一块计算平移误差,而第二块实现上面的公式(3.84),该公式处理轴角表示法中的方向误差,其中矩阵Des表示以DCM格式转换的所需方向(Direction-Cosine-Matrix,

一旦正确地填充了$ 6 \ times 1 $误差向量$ e $-是后三个分量,则表示当前姿势。轴-角度约定中的方向错误-然后可以运行控制定律:

$
\ dot {q} = J_G ^ + \ cdot e,
$

其中,$ J_G $是联合速度的$ 6 \ times n $几何雅可比矩阵,而$ \ dot {q} $是$ n \ times $ 1的联合速度矢量。在此基本实现中,我们不处理目标方位速度$ \ omega_d $,它们为零,也不处理目标平移速度$ \ dot {p} _d $。

此外,我们知道$ e = \ left [e_P,e_O \ right] ^ T $,但我们也可以施加$ e = \ left [K_P \ cdot e_P,K_O \ cdot e_O \ right] ^ T $以收敛速度播放。

开始时,甚至可以使$ K_P $和$ K_O $的值大于$ I $,但是请记住,伪逆算法由于例如雅可比矩阵的奇异性和增益矩阵的高值可能会加剧此问题。

要缓解这种不利影响,可以在雅可比矩阵的伪逆矩阵(非常快,但容易产生不稳定)和噪声之间实现协同作用。 Jacobian换位(慢得多,但本质上稳定),最后以经典的阻尼最小二乘(DLS)技术(又称为Levenberg-Marquardt算法)结束。

最后,DLS还会遭受可靠性,准确性和速度问题,尤其是当您要同时控制配备许多自由度的非常冗余的机械手的平移和方向时,尤其如此。这就是为什么我最终想出使用能够即时解决逆运动学问题的非线性优化器的原因。一旦在配置空间中也知道了所需的姿势,就可以极大地简化控制器的设计。

评论


$ \ begingroup $
这看起来像我想要的。我有这本书并且正在研究中,但是您能否详细说明答案?我对为什么方程式3.89中出现$ \ omega_d $感到困惑。因为获得世界框架中的角速度是整个问题。什么是$ K_O $和$ K_P $?而且,这不能解决计算增量目标旋转的问题的前半部分(我正在使用quatSLERP)。这似乎在第4.3.3节(第187页)中有所介绍。但我也不太清楚。
$ \ endgroup $
–Ben♦
15年2月20日在21:48

$ \ begingroup $
我已经扩展了答案。希望这会更好地阐明。
$ \ endgroup $
– Ugo Pattacini
2015年2月21日在8:41

$ \ begingroup $
也许,您可以通过查看方程(3.84)来解决您的疑问,该方程表示当前方向与所需方向之间的旋转矩阵误差。然后,您可以从矩阵中获取相应的轴角。轴部分(3个分量)将随时间保持不变,而角度(1个分量)将变化,例如与时间成线性关系。
$ \ endgroup $
– Ugo Pattacini
2015年2月22日在0:36



$ \ begingroup $
好吧,我认为它变得越来越清楚。不过有两个快速问题。对于您更改符号的方式,我有些困惑。在书中,$ \ vartheta $是角度,$ \ boldsymbol {r} $是轴,而您为角度写了$ \ theta $,为轴写了$ \ omega $。该书将$ \ boldsymbol \ omega $指定为围绕每个轴的角速度。我一直以为是不旋转框架的欧拉角,但也许我错了。您将$ \ boldsymbol \ omega $用作什么?是$ \ vartheta \ boldsymbol {r} $吗?而且,像$ 0.9I $这样的东西对于$ K $矩阵是否足够?
$ \ endgroup $
–Ben♦
2015年2月23日在16:36

$ \ begingroup $
在我的回答中,我某种程度上滥用了表示法:$ \ theta_d $表示轴角$ \ left(a_x,a_y,a_z,\ theta \ right)$与$ \ | a \ | = 1 $对应于目标旋转矩阵$ R_d $,而$ \ omega_d $是第107页所述的框架$ R \ left(t \ right)$的目标角速度,以识别其导数(此处出现著名的偏斜矩阵)。 $ 0.9I $可以。但是,我将进一步直接扩展到答案。
$ \ endgroup $
– Ugo Pattacini
2015年2月23日在19:35

#2 楼

Ugo的答案是“ Sciavicco-Siciliano”,这也是一本好书,我也会引用。

第3.6章介绍了所谓的解析雅可比行列式,它与所谓的几何雅可比行列式不同它显示在:
$
\ omega = J_ {geom} \ cdot \ dot {q},
$
,但是必须从$ J_ {geom} $获得借助转换矩阵$ T_A $:

$
J_ {analytical} = T_A \ cdot J_ {geom}
$

或更翔实的是:

$
\ dot {\ phi} = J_ {analytical} \ cdot \ dot {q}
$

我允许我自己是本章的一句话:


从物理角度看,$ \ omega_e $的含义比$ \ dot {\ phi} _e $的含义更直观
。 。 ωe的三个分量表示相对于基础框架的角速度的
分量。
相反,$ \ dot {\ phi} _e $的三个元素表示角的非正交
分量相对于
框架的轴定义的速度随末端执行器方向的变化而变化。另一方面,虽然$ \ dot {\ phi} _e $随时间的积分为$ \ phi_e $,但
$ \ omega_e $的积分并不容许物理上明确的
解释...


所以好消息是我们可以使用$ \ phi_e $进行工作-以欧拉角表示的末端执行器的方向,坏消息是转换矩阵$ T_A $引入了奇点,这使2的作者放弃了分析雅可比行列式的概念。

OpenRave出现了:

manip=robot.GetManipulators()[0]
# we calculate the rotational Jacobian in quaternion space
quatJ = manip.CalculateRotationJacobian()
quatManip0 = manip.GetTransformPose()[0:4]
# order of multiplication may be wrong in the next line
quatManipTarget = qmult(quatManip0, deltaQuat) # 
wSol=np.linalg.lstsq(quatJ, quatManipTarget)


因此,通过在四元数空间中使用解析雅可比矩阵,可以避免变换矩阵$ T_A $的奇异性。您的Jacobian仍然可以具有数值不稳定性,但这是不同的。

更新:
我再次考虑了四元数空间中$ T_A $的奇异性和解析雅可比行列的可能数值不稳定性。确实,我先前关于$ \ mathbb {R} ^ 3 $中的奇异性与四元数空间中的数字不稳定性不同的主张太“强烈”。

#3 楼

因此,我研究了quatSlerp函数,似乎您传递的t_elapsed错误。看起来该参数应该是插值值,如果t = 0,则返回的旋转是恒等式;如果t = 1,则返回的旋转是所传递的前两个四元数参数之间的完整旋转。

如果此代码在while循环内,并且t_elapsed大于1,则手臂将变得不稳定。

这不能解释为什么不稳定的行为会受到位置的影响。

希望这不是调试代码的意思。

quatSlerp

评论


$ \ begingroup $
我认为quatSlerp可以这种方式使用。您是对的,如果t_elapsed大于1,我将有效地进行插值而不是进行插值。(我进行了一些快速测试,似乎quatSlerp允许这种行为具有正确的行为。)因此,velocity_transform是角速度(以rad / sec为单位),而quat_t1是因此,启动后1秒钟需要旋转一次。收到一些评论后,我意识到如果传递目标姿势和时间来达到目标​​而不是速度会更好。然后,这只会进行插值,但我认为它不会改变太多。
$ \ endgroup $
–Ben♦
15年2月22日在1:22