Udacity机器人软件工程师课程笔记(十七)-机械臂仿真控制实例(其二)-KR210机械臂正向运动学

机械臂仿真控制实例(其二)-KR210正向运动学

我们使用kuka-kr210系列机械手作为例子,同时KR210也是用于拾取和放置项目的机械臂。

如果我们需要描述机械臂的零位置,则我们需要urdf文件。urdf文件时定义所有关节变量都为零时的机械臂姿态。

目录
  1. 构建DH参数
  2. a i a_i ai d i d_i di的值
  3. python代码与其解释
  4. 回顾正向运动学
  5. 调试Kuka arm的正向运动学

1.构建DH参数

打开关于KR210的rviz模拟器。如果在rviz中添加axis主题,我们可以发现机械臂基本上都位于x和z平面上。如果我们要计算机械臂的位置,则需要构建关于机械臂的DH参数表,在笔记(十五)中已经介绍过DH参数的定义过程。
定义过程如下:

  1. 标记{1,2,…,n }中的所有关节。

  2. 将{0,1,…,n}中的所有链接标记为固定的基本链接为0。

  3. 在所有关节上画线,定义关节轴。

  4. 分配每个框架的Z轴指向其关节轴。

  5. Z ^ i − 1 \hat{Z}_{i-1} Z^i1 Z ^ i \hat{Z}_{i} Z^i之间识别每个坐标系的共同法线 。

  6. “中间链接”(即,不是基础链接或末端执行器。)的端点与两个关节轴 i {i} i i + 1 {i + 1} i+1相关联。对于从1到n-1的 i i i,将 X ^ i \hat{X} _{i} X^i赋值为:

    • 对于倾斜轴,沿法线之间 Z ^ i \hat{Z}_{i} Z^i Z ^ i + 1 \hat{Z} _{i + 1} Z^i+1,并从 i {i} i指向 i + 1 {i + 1} i+1

    • 对于相交轴,垂直于包含 Z ^ i \hat{Z}_{i} Z^i Z ^ i + 1 \hat{Z}_{i + 1} Z^i+1

    • 对于平行轴或重合轴,分配是任意的;寻找使其他DH参数等于零的方法。

  7. 对于基本链接,当第一个关节变量( θ 1 \theta_1 θ1或者 d 1 d_1 d1)为0时,总是选择坐标系 0 {0} 0与坐标系 1 {1} 1重合。这将保证 α 0 {\alpha}_{0} α0 = 0。注意,如果关节1是转动的,则 连接偏移 d 1 {d}_{1} d1 =0。如果关节1是棱柱形的,则 转动角度 θ 1 = 0 {\theta}_{1} = 0 θ1=0

  8. 对于末端执行器坐标系,如果关节n是转动关节。 当 θ n {\theta}_{n} θn = 0和坐标系n的原点即 d n {d}_{n} dn = 0,选择 X n {X}_{n} Xn朝向 X n − 1 {X}_{n-1} Xn1

在这里插入图片描述

其中:
夹持器坐标系(框架):gripper_link
x i x_i xi z i z_i zi是关节轴。
a i a_i ai d i d_i di是非零连接的长度。

值得注意的是,我们在夹持器中心添加了一个额外的夹持器坐标,其严格的连接到链接6。夹持器的位置和方向已经在图中标出。它与链接6的参考系的区别仅在于沿Z轴平移了。

扭转角 α i {\alpha_i} αi
在这里插入图片描述

2. a i a_i ai d i d_i di的值

(1)urdf文件

a i a_i ai d i d_i di的值是由urdf文件来定义的。urdf的文件名是kr210.urdf.xacro ,它位于urdf文件夹中。我们需要关注joints标题下的内容,其中定义了所有活动的关节。
在这里插入图片描述看一个例子:
在这里插入图片描述

这段代码将joint_1标识为revolute,并且围绕z轴旋转,并将base_link连接到link_one。“origin”字段定义了关节相对于父链接的位置和方向
在这里插入图片描述
这段代码是固定在link_6上的夹持器框架,其起点为相对于link_6在x轴方向上0.0375m的位置上。夹持器是一固定的,这意味着它和link_6之间没有相对运动。

在大多数情况下,URDF文件中的关节原点与根据DH参数约定创建的框架原点不一致,它们也没有相同的方向。且不能在RVIZ中直接显示关节参考系

如果我们关掉模型显示,那么能够看到的参考框架实际上是链接参考框架。

在这里插入图片描述关于urdf文件,每个关键都是相对于其父关节定义的。

(2)DH参数

在这里插入图片描述
如上图所示,joint_1到joint_2,x要增加0.35m,z要增加0.42m。DH参数的每一行都表示,各个坐标系(框架)之间转换

在这里插入图片描述
KUKA KR210具有6个旋转关节。关节2是唯一棘手的对象。

θ i \theta_i θi测量 X i − 1 X_{i-1} Xi1 X i X_i Xi之间关于 Z i Z_i Zi的角度。机器人以其“零配置”绘制,即所有关节角度都假定为0。对于 i = 2 i = 2 i=2 X 1 X_1 X1 X 2 X_2 X2之间存在-90度的恒定偏移量。

(3)夹持器坐标系的方向差异

最后,为了比较base_link和gripper_link之间的全齐次变换,我们需要考虑夹持器坐标系的方向差异
在这里插入图片描述最简单的方法是将固有旋应用于python代码中的夹持器坐标系。
在这里插入图片描述
为了使两个坐标系对齐,可以先绕Z轴旋转180度,然后绕Y轴旋转-90度。

3.python代码与其解释

(1)代码部分

import numpy as np
from numpy import array
from sympy import symbols, cos, sin, pi, simplify, sqrt, atan2
from sympy.matrices import Matrix

# 在sympy中定义符号变量,在DH参数中调用
q1, q2, q3, q4, q5, q6, q7 = symbols('q1:8')  # theta_1
d1, d2, d3, d4, d5, d6, d7 = symbols('d1:8')
a0, a1, a2, a3, a4, a5, a6 = symbols('a0:7')
alpha0, alpha1, alpha2, alpha3, alpha4, alpha5, alpha6 = symbols('alpha0:7')

# 建立一个关于DH参数的列表
s = {alpha0:      0, a0:     0, d1:  0.75,
     alpha1:  -pi/2, a1:  0.35, d2:     0, q2:q2-pi/2,
     alpha2:      0, a2:  1.25, d3:     0,
     alpha3: - pi/2, a3:-0.054, d3:     0,
     alpha4:   pi/2, a4:     0, d4:  1.50,
     alpha5:  -pi/2, a5:     0, d5:     0,
     alpha6:      0, a6:     0, d6: 0.303, q7:0}

# 建立齐次变换
T0_1= Matrix([[            cos(q1),           -sin(q1),            0,              a0],
              [sin(q1)*cos(alpha0), cos(q1)*cos(alpha0), -sin(alpha0), -sin(alpha0)*d1],
              [sin(q1)*sin(alpha0), cos(q1)*sin(alpha0),  cos(alpha0),  cos(alpha0)*d1],
              [                  0,                  0,            0,               1]])
T0_1 = T0_1.subs(s)

T1_2= Matrix([[            cos(q2),            -sin(q2),            0,              a1],
              [sin(q2)*cos(alpha1), cos(q2)*cos(alpha1), -sin(alpha1), -sin(alpha1)*d1],
              [sin(q2)*sin(alpha1), cos(q2)*sin(alpha1),  cos(alpha1),  cos(alpha1)*d1],
              [                0,                 0,           0,              1]])
T1_2 = T1_2.subs(s)

T2_3= Matrix([[            cos(q3),            -sin(q3),            0,              a2],
              [sin(q3)*cos(alpha2), cos(q3)*cos(alpha2), -sin(alpha2), -sin(alpha2)*d1],
              [sin(q3)*sin(alpha2), cos(q3)*sin(alpha2),  cos(alpha2),  cos(alpha2)*d1],
              [                  0,                   0,            0,               1]])
T2_3 = T2_3.subs(s)

T3_4= Matrix([[            cos(q4),            -sin(q4),            0,              a3],
              [sin(q4)*cos(alpha3), cos(q4)*cos(alpha3), -sin(alpha3), -sin(alpha3)*d1],
              [sin(q4)*sin(alpha3), cos(q4)*sin(alpha3),  cos(alpha3),  cos(alpha3)*d1],
              [                  0,                   0,            0,               1]])
T3_4 = T3_4.subs(s)

T4_5= Matrix([[            cos(q5),            -sin(q5),            0,              a4],
              [sin(q5)*cos(alpha4), cos(q5)*cos(alpha4), -sin(alpha4), -sin(alpha4)*d1],
              [sin(q5)*sin(alpha4), cos(q5)*sin(alpha4),  cos(alpha4),  cos(alpha4)*d1],
              [                  0,                   0,            0,               1]])
T4_5 = T4_5.subs(s)

T5_6= Matrix([[            cos(q6),            -sin(q6),            0,              a5],
              [sin(q6)*cos(alpha5), cos(q6)*cos(alpha5), -sin(alpha5), -sin(alpha5)*d1],
              [sin(q6)*sin(alpha5), cos(q6)*sin(alpha5),  cos(alpha5),  cos(alpha5)*d1],
              [                  0,                   0,            0,               1]])
T5_6 = T5_6.subs(s)

T6_G= Matrix([[            cos(q7),            -sin(q7),            0,              a6],
              [sin(q7)*cos(alpha6), cos(q7)*cos(alpha6), -sin(alpha6), -sin(alpha6)*d1],
              [sin(q7)*sin(alpha6), cos(q7)*sin(alpha6),  cos(alpha6),  cos(alpha6)*d1],
              [                  0,                   0,            0,               1]])
T6_G = T6_G.subs(s)

# 在基本链接之间建立完整齐次变换
T0_2 = simplify(T0_1*T1_2)
T0_3 = simplify(T0_2*T2_3)
T0_4 = simplify(T0_3*T3_4)
T0_5 = simplify(T0_4*T4_5)
T0_6 = simplify(T0_5*T5_6)
T0_G = simplify(T0_6*T6_G)

# urdf中的Gripper_link定义与DH公约之间的方向差异
R_z = Matrix([[    cos(np.pi), -sin(np.pi),              0,   0],
              [    sin(np.pi),  cos(np.pi),              0,   0],
              [             0,           0,              1,   0],
              [             0,           0,              0,   1]])
R_y = Matrix([[ cos(-np.pi/2),           0, -sin(-np.pi/2),   0],
              [             0,           1,              0,   0],
              [-sin(-np.pi/2),           0,  cos(-np.pi/2),   0],
              [             0,           0,              0,   1]])
R_corr = simplify(R_z*R_y)

# 在Base_link和Gripper_link之间的完整的齐次变换
T_total= simplify(T0_G*R_corr)

(2)代码解释

1)DH参数字典

在这里插入图片描述
这里建立了一个关于DH参数的字典,方便以后的调用。其中 a l p h a alpha alpha表示旋转角, a a a表示链接长度, d d d表示链接偏移, q q q表示联合变量 θ \theta θ。其中各个变量的数值在之前的 2.(2)DH参数 中已经给出。
在这里插入图片描述

2)齐次变换

在这里插入图片描述
我们在各个相邻的连接中中构建齐次变换,从link_1到Gripper_link。

在这里插入图片描述

在base_link 和gripper_link之间建立完整的齐次变换,通过逐步乘单独的齐次变换。

3)base_link与gripper_link之间的方向差异

在这里插入图片描述
之前说过,在urdf和DH公约之间存在gripper_link的方向差异。我们需要解决这个问题。我们借助物体的旋转来解决这个问题。首先旋转z轴然后再旋转y轴即可使两个坐标系重合。所以这个纠正就是两个旋转的集合。

然后我们就可以得出Kuka机械手的正向运动学。然后,我们可以通过评估矩阵在一些任意关节值处的值来评估 b a s e _ l i n k base\_link base_link和校正后的 g r i p p e r _ l i n k gripper\_link gripper_link之间的总变换,并检查其是否与ROS的末端执行器的运动匹配,从而对此进行检查。

4.运动学回顾

正运动学的目标是计算末端执行器的姿态给定所有的关节角度,这里是6个。使用DH参数,可以在各个链接之间创建单独的转换。最好以符号方式创建转换,即使用sympy库,然后将数值替换为非零项作为最后一步。DH参数约定使用四个单独的转换参数,

在这里插入图片描述
以矩阵形式,此变换为

在这里插入图片描述
齐次变换由旋转部分和平移部分组成,如下所示:
在这里插入图片描述
其中, P x , P y , P z P_x, P_y, P_z Px,Py,Pz为末端执行器相对于基础连杆的位置, R T R_T RT为旋转部分。 R T R_T RT可以使用末端执行器的Roll-Pitch-Yaw角(由模拟器提供)来构建。

5.调试Kuka arm的正向运动学

一旦在关节上把单独的变换并完成了完整的齐次变换,就可以通过将结果与模型输出进行比较来验证它们。在终端窗口中,启动正向运动学演示:

$ roslaunch kuka_arm forward_kinematics.launch

执行roslaunch命令应在RViz中生成机械臂以及“joint state publisher window”。如果成功,可以看到:
在这里插入图片描述
ROS使用tf_echo命令非常容易地获得任意两个给定帧之间的转换。该命令的通用语法为:

$ rosrun tf tf_echo [reference frame] [target frame]

打开一个终端窗口,键入:

$ rosrun tf tf_echo base_link link_6

link_6相对于的位置和方向数据base_link在终端窗口中开始流式传输。可以按Ctrl + C停止流。
在这里插入图片描述
平移(链接原点之间的距离)以米为单位,而旋转以四元数和Roll-Pitch-Yaw角给出。

使用该tf_echo命令检查机械手链接和计算之间的变换,以验证每个单独的变换是否正确。

另外,也可以使用 joint_state_publisher窗口。在base_link和之间计算出最终的变换矩阵后gripper_link,可以用自己的值替换关节角度,以获得末端执行器的方向和位置。还可以使用 joint_state_publisher 窗口中的滑块替换这些关节角度值。然后,所得到的位置和方向(四元数)将在TF主题的框架下显示,这可以确认计算:
在这里插入图片描述
以上基本完成了机械臂的正向运动学的验证。在接下来章节就是机械臂反向运动学了。

海外访问CSDN是真的慢,传图片传的我心力憔悴。什么时候CSDN优化下就好了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Stan Fu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值