标准DH(SDH)和改进DH(MDH)

一、浅谈标准DH(SDH)和改进DH(MDH)

1.机器人连杆与关节的标号

先标号,再建系。

连杆编号:基座为杆0,从基座往后依次定义为杆1,杆2,…,杆i_;_

关节编号:杆_i_离基座近的一端(近端)的关节为关节_i_,远的一端(远端)为关节i+1。

为便于理解,这里我把连杆的近端用绿色表示,远端用橙色表示,且远端驱动近端转动。大家只要记住一句话,连杆近端关节的标号和连杆标号是一致的

图1连杆和关节标号

2.两种建系方法的区别

区别一: 连杆坐标系建立的位置不同。SDH方法将连杆_i_的坐标系固定在连杆的远端,MDH方法把连杆_i_的坐标系固定在连杆的近端。

(a)SDH (b)MDH

图2 建系方法的不同

区别二: 执行变换的的顺序不同。按照SDH方法变换时四个参数相乘的顺序依次为_d_—>θ—>a—>α,而MDH方法则按照_α_—>a—>θ—>d(正好与SDH相反)。

3.影响

对于树形结构或者闭链机构的机器人来说,按照SDH方法建立的连杆坐标系会产生歧义,因为SDH的建系原则是把连杆i的坐标系建立在连杆的远端,如图3(a)所示,这就导致连杆0上同时出现了两个坐标系。而MDH把连杆坐标系建立在每个连杆的近端,则不会坐标系重合的情况,如图3(b)所示,这就克服了SDH方法建系的缺点。

(a)SDH (b)MDH

图3 坐标系分配的不同

4.总结

1.SDH适合应用于开链结构的机器人**;**

2.当使用SDH表示树状或闭链结构的机器人时,会产生歧义;

3.MDH法对开链、树状、闭链结构的机器人都适用,推荐使用。

参考文献

[1] https://en.wikipedia.org/wiki/Denavit%E2%80%93Hartenberg_parameters.

[2] 霍伟.机器人动力学与控制[M].北京:高等教育出版社,2005:16-22.

二、标准DH建模与改进DH建模

standard_DH

根据DH表示法确定一个一般步骤为每个关节指定参考坐标系,然后确定如何实现任意两个相邻坐标系之间的变换,最后写出机器人的总变换矩阵。如图所示表示了三个顺序关节和两个连杆,每个关节都是可以转动和平移的。第一个关节指定为关节i-1,第二个关节指定为关节i,第三个关节指定为关节i+1。在这些关节前后可能还有其他关节,连杆也是如此表示,连杆i位于关节i与关节i+1之间。
1、standard_DH建立每个关节参考坐标系步骤
(1)所有关节,无一例外用z轴表示。如果是关节是旋转的,z轴位于按右手定则选装的方向,如果关节是滑动的,z轴为沿实现运动的方向。在每一种情况下,关节i处的z轴(以及该关节的本地参考坐标系)的下标为i-1。
(2) 通常关节不一定平行或相交。因此,通常z轴是斜线,但是总有一条距离最短的公垂线,它正交于任意两条斜线。通常在公垂线方向上定义x轴。所以如果 ai 表示 zi−1 与 zi 之间的公垂线,则 xi的方向沿 ai。
(3)如果两个关节的z轴平行,选取与前一关节的公垂线共线的一条公垂线,可简化模型;如果两个相邻关节的z轴是相交的,那么它们之间没有公垂线,可选取两条z轴的叉积2方向作为x轴,可简化模型。
  θ 角表示绕z轴旋转角,d 表示在z轴上两条相邻的公垂线之间的距离,a 表示每一条公垂线的长度,角 α 表示两个相邻的z轴之间的角度。

2、standard_DH建模步骤
(1)绕 zi−1轴旋转θi,它使得 xi−1和 xi互相平行;
(2)沿 zi−1轴平移di距离,使得 xi−1和 xi共线;
(3)沿 xi轴平移 ai距离,使得 xi−1和 xi的原点重合;
(4)将 zi−1轴绕 xi旋转ai,使得 zi−1轴与 zi轴对准。
  通过右乘四个运动的四个矩阵就可以得到变换矩阵 i − 1 T i ^{i-1}T_i i−1Ti:
i − 1 T i = R o t ( z i − 1 , θ i ) × T r a n s ( ( z i − 1 , d i ) × T r a n s ( ( x i , a i ) × R o t ( x i , α i ) \begin{aligned}^{i-1}T_i=Rot(z_{i-1},\theta_i)\times Trans((z_{i-1},d_i)\times Trans((x_{i},a_i)\times Rot(x_{i},\alpha_i)\end{aligned} i1Ti=Rot(zi1,θi)×Trans((zi1,di)×Trans((xi,ai)×Rot(xi,αi)

modified_DH

1、modified_DH建立每个关节参考坐标系步骤
(1)找出关节轴i和i+1之间的公垂线或关节轴i和i+1的交点,以关节轴i和i+1的交点或公垂线与关节轴i的交点作为连杆坐标系{i}的原点;
(2)规定 zi轴沿关节轴i的指向;
(3)规定 xi轴沿公垂线的指向,如果关节轴i和i+1相交,则规定 xi垂直于关节轴i和i+1所在平面。
(4)按照右手定则确定 yi轴

2、modified_DH建模步骤
(1) ai = 沿 xi轴,从 zi移动到 zi+1的距离;
(2) αi = 绕 xi轴,从 zi旋转到 zi+1的角度;
(3) di = 沿 zi轴,从 xi−1移动到 xi的距离;
(4) θi = 沿 zi轴,从 xi−1旋转到 xi的角度;
  变换矩阵可以写成:
i − 1 T i = R X ( α i − 1 ) × D X ( a i − 1 ) × R Z ( θ i ) × D Z ( d i ) \begin{aligned}^{i-1}T_i=R_X(\alpha_{i-1})\times D_X(a_{i-1})\times R_Z(\theta_{i})\times D_Z(d_{i})\end{aligned} i1Ti=RX(αi1)×DX(ai1)×RZ(θi)×DZ(di)

SDH与MDH比较

(1)固连坐标系不同
SDH方法关节i上固连的是i-1坐标系,即坐标系建在连杆的输出端;MDH关节i上固连的是i坐标系,即坐标系建在连杆的输入端。
(2)坐标系变换顺序不同
SDH方法是ZX类变换:先绕着i-1坐标系的的Zi-1轴旋转和平移,再绕着坐标系i的Xi轴进行旋转和平移;MDH方法是XZ类变换:先绕着i坐标系的的Xi轴旋转和平移,再绕着坐标系i的Zi轴进行旋转和平移;

三、MATLAB-Robot(2):标准DH和改进DH的区别

1. 区别

2. WIKI百科对比图

3.0 MATLAB仿真对比

1. 标准DH

%标准DH
%Link(DH,option):
%DH = [THETA D A ALPHA SIGMA]//我的代码中此处定义theta的初始值无效
L1 = Link([0 0.2 1 pi/4 0],'standard');
L2 = Link([0 0.2 1 pi/4 0],'standard');
L3 = Link([0 0 0.5 pi/4 0],'standard');
robot = SerialLink([L1 L2 L3]); %建立连杆机器人
robot.plot([0 0 0]) %显示并赋三个关节变量theta值都为0//此处才可以初始theta

对比代码中的DH参数和图中画的坐标系,再次确定标准DH四个参数含义:

theta:绕Zi轴,从Xi旋转到Xi+1的角度

D:沿Zi轴,从Xi移动到Xi+1的距离

A:沿Xi轴,从Zi移动到Zi+1的距离

alpha:绕Xi+1轴,从Zi旋转到Zi+1的角度

2. 改进DH

%改进DH
%Link(DH,option):DH = [THETAi Di Ai-1 ALPHAi-1 SIGMA]
L1 = Link([0 0.2 1 pi/4 0],'modified');
L2 = Link([0 0.2 1 pi/4 0],'modified');
L3 = Link([0 0 0.5 pi/4 0],'modified');
robot = SerialLink([L1 L2 L3]); %建立连杆机器人
robot.plot([0 0 0]) %显示并赋三个关节变量theta的初始值都为0

MATLAB中定义改进DH连杆时一定要注意DH[theta d a alpha]中前两个参数下表为i,

即当前关节的DH值,后两个参数下表为i-1,及前一个关节的DH值参数值!

此时对比代码中的DH参数和图中画的坐标系,得到DH定义为:

theta:绕Zi轴,从Xi-1旋转到Xi的角度

D:沿Zi轴,从Xi-1移动到Xi的距离

A:沿Xi轴,从Zi移动到Zi+1的距离

alpha:绕Xi轴,从Zi旋转到Zi+1的角度

4.0 总结

标准型和改进型中A和alpha定义相同,都是相对于下一关节而言,不同的是theta和D在标准型中都是相对于下一关节,在改进型中是相对于上一关节。

定义DH表格时:

标准型的列标题为: θ i   d i   a i   α i \theta_i \, d_i \, a_i \, \alpha_i θidiaiαi
在这里插入图片描述

改进型的列标题为: θ i   d i   a i − 1   α i − 1 \theta_i \, d_i \, a_{i-1} \, \alpha_{i-1} θidiai1αi1
在这里插入图片描述

所以一定要注意MATLAB机器人工具箱中连杆定义中DH的对应。
在这里插入图片描述

四、三自由度双足机器人腿建模

%% 改进DH
clear ; clc; close all;
% 机器人各连杆DH参数
d1 = 0.35;
d2 = 0;
d3 = 0;
d4 = 0;

a1 = 0.25;
a2 = 0;
a3 = 0.35;
a4 = 0.30;

alpha1 = pi/2;
alpha2 = -pi/2;
alpha3 = 0;
alpha4 = 0 ;

% 定义各个连杆,默认为转动关节
%           theta      d        a        alpha 
L(1)=Link([  0         d1      a1      alpha1] ,'modified'); L(1).qlim=[-pi,pi]; L(1).offset=-pi/2;
L(2)=Link([  0         d2      a2      alpha2] ,'modified'); L(2).qlim=[-pi,pi]; L(2).offset= pi/6;
L(3)=Link([  0         d3      a3      alpha3] ,'modified'); L(3).qlim=[-pi,pi]; L(3).offset=-pi/2;

% 把上述连杆整合
OLRob=SerialLink(L,'name','改进');
view(3);
% 定义机器人基坐标和工具坐标的变换
%OLRob.base = transl(0 ,-0.7 ,0);
OLRob.tool = transl(0.3 ,0 ,0);
view(77,22);
title('改进-有工具坐标');
OLRob.plot([0 0 0]);
OLRob.teach();   %机器人示教界面

%% 标准DH方法
figure(2)
view(3);
% 定义各个连杆,默认为转动关节
%       theta      d        a        alpha 
f(1)=Link([  0      0       0          pi/2] ); f(1).qlim=[-pi,pi]; f(1).offset=pi/2;
f(2)=Link([  0      0      0.35           0] ); f(2).qlim=[-pi,pi]; f(2).offset=-5*pi/6;
f(3)=Link([  0      0      0.3            0] ); f(3).qlim=[-pi,pi]; f(3).offset= -pi/2;
sta=SerialLink(f,'name','标准');
sta.tool = transl(0 ,0 ,0);
sta.plot([0 0 0]);
sta.teach();   %机器人示教界面

五、Matlab人形机器人建模与仿真

github

%% ------------------------------------------------------------------------
%                      Kinematic Model of Humanoid Robot
%
%                                     Mike
%
%                               Date: 15/7/2022
%
%% ------------------------------- Init Env -------------------------------
clear;
close all;
clc;
pi = 3.14;
%% Link [THETA D A ALPHA SIGMA OFFSET]
%%  OFFSET is a constant displacement between the user joint angle vector 
%   and the true kinematic solution.
%% SIGMA SIGMA=0 for a revolute and 1 for a prismatic joint.
%% ------------------------------ platform  -------------------------------
platform=SerialLink([0 0 0 0],'name','platform','modified');
platform.base=[1 0 0 0;
               0 1 0 0;
               0 0 1 0;
               0 0 0 1;];  
platform.qlim = [0,0]; %Platform
%% ------------------------------ Right Arm -------------------------------           
RA(1)=Link([0        0.49077   0         0         0     0],'modified');  
RA(2)=Link([0        0.283     0         pi/2     0     -pi/2],'modified');
RA(3)=Link([0        0         0         pi/2      0     0],'modified');
RA(4)=Link([0        0         0.287     pi/2      0     0],'modified');
RA(5)=Link([0        0         0.287     pi/2         0     0],'modified');
Humanoid_Robot_RA=SerialLink(RA,'name','RIGHTARM');
RA(1).qlim = [0,0]; % Base for Upper body
RA(2).qlim = [deg2rad(-50),deg2rad(50)]; % Shoulder Pitch
RA(3).qlim = [0,deg2rad(60)]; % Shoulder Roll
RA(4).qlim = [0,deg2rad(140)]; % Elbow Pitch
RA(5).qlim = [0,0];%end-effector
%% -------------------------- Assembly Right Arm --------------------------
pRA=SerialLink([platform,Humanoid_Robot_RA],'name','RA'); 
view(3)
hold on
grid on
len_RA = length(RA);
init_RA = [];
for i=1:len_RA+1
    init_RA(i) = 0;
end
pRA.plot([init_RA],'scale',.5)
% pRA.teach
hold on  
%% ------------------------------ Left Arm --------------------------------           
LA(1)=Link([0        0.49077   0         0         0     0],'modified');  
LA(2)=Link([0        -0.283     0         pi/2     0     -pi/2],'modified');
LA(3)=Link([0        0         0         pi/2      0     0],'modified');
LA(4)=Link([0        0         0.287     pi/2      0     0],'modified');
LA(5)=Link([0        0         0.287     pi/2         0     0],'modified');
Humanoid_Robot_LA=SerialLink(LA,'name','LEFTARM');
LA(1).qlim = [0,0]; % Base for Upper body
LA(2).qlim = [deg2rad(-50),deg2rad(50)]; % Shoulder Pitch
LA(3).qlim = [0,deg2rad(60)]; % Shoulder Roll
LA(4).qlim = [0,deg2rad(140)]; % Elbow Pitch
LA(5).qlim = [0,0]; %end-effector
%% -------------------------- Assembly Left Arm ---------------------------
pLA=SerialLink([platform,Humanoid_Robot_LA],'name','LA'); 
view(3)
hold on
grid on
axis([-1, 1, -1, 1, -1, 1]*0.9)
len_LA = length(LA);
init_LA = [];
for i=1:len_LA+1
    init_LA(i) = 0;
end
pLA.plot([init_LA],'scale',.5)
% pLA.teach
hold on
%% ------------------------------ Left Leg --------------------------------           
LL(1)=Link([0       -0.120       0            pi/2        0     0  ],'modified'); 
LL(2)=Link([0       0              0            pi/2        0    -pi/2  ],'modified');
LL(3)=Link([0       0              0            -pi/2        0    -pi/2 ],'modified');
LL(4)=Link([0       0              0.42       pi/2         0    0 ],'modified');
LL(5)=Link([0       0        0.42            0        0     0],'modified');
LL(6)=Link([0       0.0772              0           -pi/2            0   0],'modified');
LL(7)=Link([0       0              0          0            0   0],'modified');
Humanoid_Robot_LL=SerialLink(LL,'name','LEFTLEG');
LL(1).qlim = [deg2rad(-50),deg2rad(50)]; %Hip Pitch -50 to 50
LL(2).qlim = [deg2rad(-50.15923567),deg2rad(50.15923567)]; %Hip yaw -50.15923567 to 50.15923567
LL(3).qlim = [deg2rad(-5),deg2rad(5)]; %Hip roll -5 to 5
LL(4).qlim = [0,deg2rad(90)]; %knee 0 to 90
LL(5).qlim = [deg2rad(-45),deg2rad(45)]; %Ankle Pitch -45 to 45
LL(6).qlim = [deg2rad(-20),deg2rad(20)]; %Ankle Roll -20 to 20
LL(7).qlim = [0,0]; %end-effector
%% -------------------------- Assembly Left Arm ---------------------------
pLL=SerialLink([platform,Humanoid_Robot_LL],'name','LL'); 
view(3)
hold on
grid on
axis([-1, 1, -1, 1, -1, 1]*0.9)
len_LL = length(LL);
init_LL = [];
for i=1:len_LL+1
    init_LL(i) = 0;
end
pLL.plot([init_LL],'scale',.5)
pLL.teach
hold on
%% ------------------------------ Right Leg --------------------------------           
RL(1)=Link([0       0.120       0            pi/2        0     0  ],'modified'); 
RL(2)=Link([0       0              0            pi/2        0    -pi/2  ],'modified');
RL(3)=Link([0       0              0            -pi/2        0    -pi/2 ],'modified');
RL(4)=Link([0       0              0.42       pi/2         0    0 ],'modified');
RL(5)=Link([0       0        0.42            0        0     0],'modified');
RL(6)=Link([0       0.0772              0           -pi/2            0   0],'modified');
RL(7)=Link([0       0              0           0            0   0],'modified');
Humanoid_Robot_RL=SerialLink(RL,'name','RightLEG');
RL(1).qlim = [deg2rad(-50),deg2rad(50)]; %Hip Pitch -50 to 50
RL(2).qlim = [deg2rad(-50.15923567),deg2rad(50.15923567)]; %Hip yaw -50.15923567 to 50.15923567
RL(3).qlim = [deg2rad(-5),deg2rad(5)]; %Hip roll -5 to 5
RL(4).qlim = [0,deg2rad(90)]; %knee 0 to 90
RL(5).qlim = [deg2rad(-45),deg2rad(45)]; %Ankle Pitch -45 to 45
RL(6).qlim = [deg2rad(-20),deg2rad(20)]; %Ankle Roll -20 to 20
RL(7).qlim = [0,0]; %end-effector
%% -------------------------- Assembly Right Arm --------------------------
pRL=SerialLink([platform,Humanoid_Robot_RL],'name','RL'); 
view(3)
hold on
grid on
axis([-1, 1, -1, 1, -1, 1]*0.9)
len_RL = length(RL);
init_RL = [];
for i=1:len_RL+1
    init_RL(i) = 0;
end
pRL.plot([init_RL],'scale',.5)
pRL.teach
hold on
%% -------------------------------- Jacobian ------------------------------
Q = zeros(7,len_LL);
Jacob_LL = pLL.jacobe(Q);
Q = zeros(7,len_RL);
Jacob_RL = pRL.jacobe(Q);
Q = zeros(7,len_LA);
Jacob_LA = pLA.jacobe(Q);
Q = zeros(7,len_RA);
Jacob_RA = pRA.jacobe(Q);
%% -------------------------------------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lx-summer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值