1. 项目概述:从零开始理解机器人DH建模
如果你正在学习机器人学,或者需要为一个串联机械臂编写控制程序,那么“DH建模”这个词你一定不陌生。它就像是机器人的“身份证”和“说明书”,用一套简洁的数学语言,清晰地描述了机器人每个关节和连杆之间的位置与姿态关系。没有它,你就无法告诉计算机你的机器人长什么样,更别提让它精准地运动了。而MATLAB,作为工程计算领域的瑞士军刀,为我们实现这套理论、进行仿真验证提供了极其便利的环境。今天,我就结合自己多年在机器人项目中的实操经验,来详细拆解如何在MATLAB中,从理论到代码,一步步完成串联机器人的DH建模。这个过程不仅是公式的堆砌,更涉及到对机器人运动学本质的理解,以及如何将严谨的数学转化为可靠、高效的代码。
很多人一开始会觉得DH参数很抽象,四个参数(杆长、扭角、偏距、关节角)绕来绕去。其实,你可以把它想象成给机器人“量体裁衣”和“记录动作”。每个连杆的尺寸是固定的(杆长a和扭角α),就像人的臂长和关节的朝向;而关节的运动(偏距d和关节角θ)则是可变的,就像人的肘关节可以弯曲、肩关节可以旋转。DH建模的核心,就是用一个4x4的齐次变换矩阵,把这两个固定信息和两个可变信息完美地融合在一起,从而可以从机器人的基座一步步推算到末端执行器的精确位置。在MATLAB里做这件事,目标不仅仅是得到一堆矩阵,更是为了后续的轨迹规划、运动仿真乃至实时控制打下坚实的基础。无论你是学生做课程设计,还是工程师进行原型验证,掌握这套流程都至关重要。
2. DH参数法原理深度解析与坐标系建立
2.1 DH参数法的核心思想与四种约定
DH(Denavit-Hartenberg)参数法之所以成为机器人运动学建模的“标准答案”,在于它用最少的参数(每对连杆关节仅需4个)就能完整描述其空间关系。其核心思想是:在两个相邻连杆之间,通过四次有顺序的变换(两次平移,两次旋转),就可以将后一个连杆的坐标系,从前一个连杆的坐标系中“变”出来。
这里必须首先厘清一个关键点:DH参数有标准型(Standard DH)和改进型(Modified DH)两种主流约定,它们坐标系附着的方式和变换顺序不同,极易混淆。我强烈建议在开始任何项目前,先明确你参考的教材、论文或机器人模型使用的是哪一种,并始终坚持同一种约定,否则会导致灾难性的错误。
- 标准DH(SDH):坐标系附着在连杆的末端(即靠近下一个关节的一端)。其变换顺序为:绕Z轴旋转θ(关节角)→ 沿Z轴平移d(偏距)→ 沿X轴平移a(杆长)→ 绕X轴旋转α(扭角)。这种约定在经典教材中更常见。
- 改进DH(MDH):坐标系附着在连杆的前端(即靠近上一个关节的一端)。其变换顺序为:沿X轴平移a(杆长)→ 绕X轴旋转α(扭角)→ 沿Z轴平移d(偏距)→ 绕Z轴旋转θ(关节角)。这种约定在诸如PUMA、斯坦福臂等经典机器人模型以及Robotics Toolbox for MATLAB(10.x版本后)中广泛使用。
注意:本文后续的讲解和示例将基于改进DH(MDH)约定,因为它在现代机器人学软件和库中应用更为广泛,逻辑上也更直观(坐标系从基座向末端依次建立)。
这四个参数的具体物理意义如下:
- 连杆长度 (a_i):从坐标系
{i-1}的Z轴,沿其X轴方向,到坐标系{i}的Z轴的公垂线距离。它总是一个非负值,代表了连杆的“长度”维度。 - 连杆扭角 (α_i):从坐标系
{i-1}的Z轴,绕其X轴旋转,到与坐标系{i}的Z轴平行时所需的角度。它描述了连杆的“扭曲”程度。 - 连杆偏距 (d_i):从坐标系
{i-1}的X轴,沿其Z轴方向,到与坐标系{i}的X轴相交的距离。对于移动关节,这是一个变量。 - 关节转角 (θ_i):从坐标系
{i-1}的X轴,绕其Z轴旋转,到与坐标系{i}的X轴平行时所需的角度。对于旋转关节,这是一个变量。
对于旋转关节,θ是变量,d是常量;对于移动关节,d是变量,θ是常量。a和α永远是描述连杆几何形状的常量。
2.2 为你的机器人建立DH坐标系
理论懂了,第一步不是写代码,而是拿起笔和纸(或绘图软件),为你的机器人模型正确地建立坐标系。这一步是后续所有工作的基石,错了就全错了。我总结了一个“五步法”:
- 确定关节轴:找出所有关节的旋转轴或移动方向线,并标记为Z轴。Z0是基座坐标系的Z轴,通常与第一个关节轴重合。
- 建立基座坐标系
{0}:将{0}的原点放在第一个关节轴上任意方便的位置。通常,X0和Y0的选择使得坐标系满足右手定则,并尽可能简化后续参数。 - 建立末端坐标系
{n}:对于n个关节的机器人,将{n}的原点放在末端执行器的中心或工具点。Zn的方向通常与末端接近方向一致,Yn与末端开口方向一致(遵循工具坐标系惯例,如TCP)。 - 建立中间坐标系
{i}(i=1 to n-1):这是最关键的一步。对于改进DH法:- 原点:位于关节轴i和关节轴i+1的公垂线与关节轴i的交点处。如果两轴相交,原点就在交点;如果平行,原点可任选在轴i上(通常选与前一原点公垂线最短处)。
- Z_i轴:与关节轴i重合,方向按需指定(通常与运动正方向一致)。
- X_i轴:沿关节轴i和关节轴i+1的公垂线方向,从轴i指向轴i+1。如果两轴相交,X_i轴垂直于由Z_i和Z_{i+1}构成的平面,方向由右手定则从Z_i转向Z_{i+1}确定(即叉乘方向)。
- Y_i轴:由右手定则(X_i × Z_i = Y_i)确定。
- 填写DH参数表:根据建立好的所有坐标系,逐一测量或计算每对相邻坐标系之间的四个DH参数(a_i, α_i, d_i, θ_i),并形成表格。这个表格就是你模型的“宪法”。
实操心得:在纸上画图时,用不同颜色区分Z轴(关节轴)和X轴(公垂线方向)。对于复杂的多轴平行或相交情况,耐心推导。一个快速检查方法是:从坐标系{i-1}出发,经过a_i(沿X_{i-1}平移)、α_i(绕X_{i-1}旋转)、d_i(沿新的Z轴平移)、θ_i(绕新的Z轴旋转)后,应该正好与坐标系{i}重合。可以用这个逻辑反向验证你建立的坐标系和参数是否正确。
3. MATLAB环境准备与Robotics Toolbox的应用
3.1 核心工具选择:为什么是Robotics Toolbox?
在MATLAB中实现DH建模和运动学计算,你有几种选择:从头编写所有矩阵运算函数;利用Symbolic Math Toolbox进行符号推导;或者使用现成的专业工具箱。对于绝大多数应用场景,我强烈推荐使用Peter Corke教授开发的Robotics Toolbox for MATLAB。它的优势非常明显:
- 成熟可靠:经过学术界和工业界数十年的检验,代码稳定,功能全面。
- API优雅:面向对象的设计,用起来非常直观。例如,用
SerialLink类代表一个机器人,用Link类代表一个关节,思维模型和物理模型高度对应。 - 功能集成:不仅支持正/逆运动学,还集成了动力学、轨迹规划、可视化仿真等高级功能,为你后续的扩展铺平道路。
- 社区丰富:遇到问题容易找到资料和解答。
当然,如果你的项目有极其特殊的定制化需求,或者是为了深入理解底层数学,自己实现一遍变换矩阵乘法也是极好的学习过程。但就工程效率和可靠性而言,Robotics Toolbox是首选。
3.2 工具箱安装与基础验证
安装Robotics Toolbox非常简单。你可以从其GitHub仓库或Peter Corke的网站下载最新版本。通常,解压后将文件夹添加到MATLAB路径即可。为了验证安装成功并熟悉基础操作,我们可以在命令行快速测试一下:
% 创建一个简单的旋转关节连杆,使用改进DH参数 % Link 构造函数:Link([theta, d, a, alpha, sigma], 'modified') % sigma: 0为旋转关节,1为移动关节 L1 = Link([0, 0, 1, 0, 0], 'modified'); % 一个长度为1,无扭转的旋转关节 L2 = Link([0, 0, 0.8, -pi/2, 0], 'modified'); % 一个长度为0.8,绕X轴扭转-90度的旋转关节 % 将连杆串联成机器人 robot = SerialLink([L1 L2], 'name', 'myTwoLinkArm'); % 显示机器人的DH参数表 robot.display() % 在零位(所有关节角为0)下,计算正运动学,得到末端位姿(4x4齐次变换矩阵) T = robot.fkine([0, 0]); disp('末端位姿矩阵T:'); disp(T); % 快速进行可视化,看看机器人长什么样 robot.plot([0, 0]);运行这段代码,你应该能看到一个简单的两连杆机械臂模型,并能在命令行看到它的DH参数和末端位姿矩阵。这个矩阵的左上角3x3部分是旋转矩阵,右上角3x1部分是位置向量。这就完成了最基础的建模-计算-可视化闭环,确认了你的环境是正常的。
注意事项:创建Link对象时,'modified'这个参数标志至关重要,它指明我们使用改进DH约定。如果你漏掉了,工具箱会默认使用标准DH约定,导致基于改进DH参数计算的结果完全错误。这是一个高频踩坑点,务必在创建每个机器人的第一行代码就明确指定。
4. 完整建模流程:以六轴工业机器人为例
现在,我们以一个典型的六轴旋转关节工业机器人为例,走完从参数确定到模型可用的全流程。假设我们已经通过图纸或测量,得到了它的改进DH参数表如下:
| 关节 i | θ_i (变量) | d_i (米) | a_i (米) | α_i (弧度) | 关节类型 |
|---|---|---|---|---|---|
| 1 | q1 | 0.4 | 0 | -π/2 | 旋转 |
| 2 | q2 | 0 | 0.6 | 0 | 旋转 |
| 3 | q3 | 0 | 0.5 | -π/2 | 旋转 |
| 4 | q4 | 0.5 | 0 | π/2 | 旋转 |
| 5 | q5 | 0 | 0 | -π/2 | 旋转 |
| 6 | q6 | 0.1 | 0 | 0 | 旋转 |
4.1 在MATLAB中构建机器人模型
根据上表,我们在MATLAB中构建机器人模型。注意,θ值在创建Link对象时通常传入0(作为初始值或默认值),真正的关节变量在计算时通过q1, q2...传入。
%% 六轴机器人建模示例 clear; clc; close all; % 使用改进DH参数创建六个连杆(Link)对象 % Link([theta, d, a, alpha, sigma], 'modified') L(1) = Link([0, 0.4, 0, -pi/2, 0], 'modified'); % 关节1 L(2) = Link([0, 0, 0.6, 0, 0], 'modified'); % 关节2 L(3) = Link([0, 0, 0.5, -pi/2, 0], 'modified'); % 关节3 L(4) = Link([0, 0.5, 0, pi/2, 0], 'modified'); % 关节4 L(5) = Link([0, 0, 0, -pi/2, 0], 'modified'); % 关节5 L(6) = Link([0, 0.1, 0, 0, 0], 'modified'); % 关节6 % 将连杆串联起来,创建机器人对象 six_axis_robot = SerialLink(L, 'name', 'Six-Axis Industrial Robot'); % 显示详细的DH参数和机器人属性 disp('=== 机器人DH参数表 ==='); six_axis_robot.display() % 设置更友好的显示格式 format compact;运行后,six_axis_robot.display()会打印出机器人的所有参数,包括每个关节的运动学参数、惯性参数(默认为0)等。你可以核对一下,是否与你输入的参数一致。
4.2 正运动学计算与末端位姿验证
正运动学就是“给定所有关节角度,求末端在哪里”。我们使用fkine方法。
%% 正运动学计算示例 % 定义一组关节角度(单位:弧度),例如“零位”或某个特定姿态 q = [0, pi/6, -pi/4, 0, pi/3, 0]; % 六个关节的角度 % 计算正运动学,得到末端坐标系相对于基座坐标系的齐次变换矩阵 T_end = six_axis_robot.fkine(q); disp('末端执行器齐次变换矩阵 T_end:'); disp(T_end); % 从变换矩阵中提取位置和欧拉角(或RPY角)以便于理解 position = transl(T_end); % 提取位置向量 [x; y; z] orientation = tr2rpy(T_end); % 提取RPY角(绕固定轴ZYX旋转),单位弧度 % 或者使用 tr2eul 提取ZYZ欧拉角,根据你的习惯选择 disp(['末端位置 (x, y, z): ', num2str(position')]); disp(['末端姿态 (RPY - roll, pitch, yaw in rad): ', num2str(orientation)]);transl和tr2rpy是Robotics Toolbox提供的非常方便的工具函数,用于从4x4齐次变换矩阵中解析出直观的位置和姿态表示。你可以尝试多换几组q值,观察末端位置和姿态的变化,直观感受正运动学的映射关系。
4.3 模型可视化与交互式探索
“一图胜千言”,可视化是验证模型正确性最直观的方式。Robotics Toolbox的plot函数非常强大。
%% 机器人可视化 figure('Name', '六轴机器人模型', 'NumberTitle', 'off'); six_axis_robot.plot(q, 'workspace', [-2 2 -2 2 -0.5 2], 'scale', 0.5); % 'workspace' 设置图形显示范围 [xmin xmax ymin ymax zmin zmax] % 'scale' 设置关节和连杆显示的缩放因子 light; % 添加光照 lighting gouraud; % 设置光照模式,使模型更立体 material dull; % 设置材质 hold on; grid on; xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)'); title('六轴工业机器人模型 (改进DH)'); view(135, 30); % 设置视角 % 可以在图形界面中手动拖拽关节滑块(如果生成的话),或者通过代码驱动 % 例如,让机器人完成一个简单的运动 q_traj = jtraj([0 0 0 0 0 0], [pi/2 pi/6 -pi/3 pi/4 0 pi/2], 50); % 生成50个点的轨迹 for i = 1:size(q_traj, 1) six_axis_robot.plot(q_traj(i, :)); pause(0.05); % 控制动画速度 endjtraj函数用于生成关节空间内两点之间的五次多项式插值轨迹,运动平滑。通过这个动画,你可以清晰地看到机器人各连杆和关节是如何协调运动的,这是检验你DH坐标系建立是否合理的终极手段。如果机器人的姿态看起来“别扭”或“反了”,很可能就是某个α参数的符号错了,或者关节旋转方向定义反了。
5. 进阶应用:逆运动学与轨迹规划初步
5.1 逆运动学的求解与陷阱
正运动学是唯一的,但逆运动学(给定末端位姿,求关节角度)往往有多解、无解的情况,是机器人学中的难点。Robotics Toolbox提供了数值解法(ikine)和(对某些特定构型)解析解法(ikine6s,适用于球形腕机器人)。
%% 逆运动学求解示例 % 首先,定义一个期望的末端位姿。我们可以从上面正运动学的结果反推,确保有解。 desired_position = [0.8; 0.2; 1.0]; % 期望位置 [x; y; z] desired_orientation = rpy2tr(0.1, 0.2, 0.3); % 用RPY角创建旋转矩阵,再转为齐次变换 T_desired = transl(desired_position) * desired_orientation; % 使用数值逆解(迭代法),需要提供一个初始关节角度猜测q0 q0 = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1]; % 初始猜测值,很重要! % 设置求解选项:关闭详细输出,设置误差容忍度 ik_options = {'tol', 1e-6, 'ilimit', 1000, 'mask', [1 1 1 1 1 1]}; % 'mask' 可以指定求解哪些自由度,[1 1 1 1 1 1]表示全解 [q_ik, ~, exit_flag] = six_axis_robot.ikine(T_desired, 'q0', q0, ik_options{:}); if exit_flag > 0 disp('逆运动学求解成功!'); disp('求解得到的关节角度 (rad):'); disp(q_ik'); % 验证:将求得的关节角代入正运动学,看是否接近期望位姿 T_verify = six_axis_robot.fkine(q_ik); error_position = norm(transl(T_desired) - transl(T_verify)); error_orientation = norm(rotm2eul(t2r(T_desired)) - rotm2eul(t2r(T_verify))); disp(['位置误差 (m): ', num2str(error_position)]); disp(['姿态误差 (rad): ', num2str(error_orientation)]); else disp('逆运动学求解失败!可能无解,或初始猜测值离解太远。'); end实操心得与避坑指南:
- 初始猜测值
q0至关重要:数值迭代法严重依赖初始值。q0应尽可能接近真实解。如果求解失败或得到奇怪的角度,首先尝试不同的q0。 - 多解问题:对于六轴机器人,同一末端位姿通常对应最多8组不同的关节角解(取决于构型)。
ikine默认返回它找到的第一个解(通常接近q0)。如果需要特定构型(如肘部向上/向下,手腕是否翻转),可能需要使用解析逆解ikine6s(如果机器人是球形腕结构)并指定标志位,或者用不同的q0去“引导”数值解。 - 奇异位形:当机器人完全伸直或某些关节轴对齐时,会失去一个或多个方向的自由度,进入奇异点。此时逆运动学可能无解或数值不稳定。在轨迹规划时需要避开这些区域。
- 无解情况:期望的末端位姿可能超出机器人的工作空间。求解前,最好对期望位姿进行可达性判断。
5.2 简单的关节空间轨迹规划
让机器人平滑地从一个点运动到另一个点,需要轨迹规划。关节空间规划是最简单直接的方式。
%% 关节空间轨迹规划示例 % 定义起点和终点的关节角度 q_start = [0, 0, 0, 0, 0, 0]; q_end = [pi/2, pi/4, -pi/6, pi/3, -pi/4, 0]; % 规划时间:总时间3秒,采样周期0.01秒 t_total = 3; t_sample = 0.01; t = 0:t_sample:t_total; steps = length(t); % 使用jtraj进行五次多项式插值(默认) [q_traj, qd_traj, qdd_traj] = jtraj(q_start, q_end, steps); % q_traj: 位置轨迹 % qd_traj: 速度轨迹 % qdd_traj: 加速度轨迹 % 可视化轨迹 figure('Name', '关节空间轨迹', 'NumberTitle', 'off'); subplot(3,1,1); plot(t, q_traj); ylabel('关节位置 (rad)'); legend('q1','q2','q3','q4','q5','q6'); title('关节位置轨迹'); grid on; subplot(3,1,2); plot(t, qd_traj); ylabel('关节速度 (rad/s)'); title('关节速度轨迹'); grid on; subplot(3,1,3); plot(t, qdd_traj); xlabel('时间 (s)'); ylabel('关节加速度 (rad/s^2)'); title('关节加速度轨迹'); grid on; % 播放机器人沿轨迹运动的动画 figure('Name', '轨迹动画', 'NumberTitle', 'off'); six_axis_robot.plot(q_traj, 'trail', 'r-', 'fps', 30); % 'trail' 显示末端轨迹jtraj生成的轨迹保证了起点和终点的位置、速度均为零(可指定),加速度连续,非常适合点到点的运动。从绘制的曲线可以看到,位置、速度、加速度都是光滑的,这对于减少机械冲击、保护电机和减速器非常重要。
6. 常见问题排查与模型调试技巧实录
在实际建模和仿真中,你几乎一定会遇到各种问题。下面是我总结的一些典型问题及其排查思路。
6.1 模型姿态异常或运动方向相反
- 症状:机器人可视化后,姿态很奇怪,比如本该向上的连杆朝下了,或者关节旋转方向与预期相反。
- 排查步骤:
- 检查DH参数符号:重点检查
α(连杆扭角)和θ的初始零位符号。α绕X轴旋转,遵循右手定则(拇指指向X轴正方向,四指弯曲方向为正)。一个常见的错误是把-π/2写成π/2。 - 检查坐标系建立:回顾“五步法”,确认每个坐标系的X轴方向是否正确。X轴应沿公垂线方向,从本关节轴指向下一个关节轴。方向画反会导致
a为负(虽然a通常定义为正,但方向由X轴定义隐含)。 - 检查关节变量符号:在
Link对象中,关节变量(theta或d)的正方向与对应Z轴的正方向满足右手定则。如果你发现运动方向反了,可以在定义Link时,通过offset参数添加一个固定的偏移,或者在控制代码中对关节指令取反。
- 检查DH参数符号:重点检查
6.2 逆运动学求解失败或不准确
- 症状:
ikine返回错误标志,或求解出的关节角代入正运动学后与目标位姿误差很大。 - 排查步骤:
- 验证目标位姿是否可达:先用正运动学,让机器人运动到一个你知道的、合理的关节空间位置
q_known,用fkine计算出对应的末端位姿T_known。然后用这个T_known作为ikine的输入,并以q_known附近的值作为初始猜测q0。如果这样都求解失败或不准,那问题出在模型或求解器配置上。 - 调整
ikine选项:降低'tol'(误差容忍度),增加'ilimit'(迭代次数)。检查'mask'参数是否正确,如果你不关心末端绕某个轴的旋转,可以将对应位置设为0,降低求解难度。 - 尝试不同的初始猜测
q0:这是解决数值逆解局部最优问题的关键。可以随机生成多组q0,分别求解,选取误差最小的解。 - 检查是否处于奇异点附近:计算机器人雅可比矩阵的行列式,如果接近0,说明接近奇异位形。此时逆运动学问题本身是不适定的,需要从任务层面避开这个姿态。
- 验证目标位姿是否可达:先用正运动学,让机器人运动到一个你知道的、合理的关节空间位置
6.3 可视化或动画卡顿、出错
- 症状:
plot命令很慢,或者动画时图形闪烁、崩溃。 - 排查步骤:
- 限制
workspace范围:将plot的'workspace'参数设置在一个合理的、刚好能容纳机器人运动的空间,避免绘制巨大的空白区域。 - 降低绘制精度或关闭额外功能:在
plot选项中,可以尝试'noarrow'关闭坐标轴箭头,'nobase'不绘制基座,'noshadow'关闭阴影,'ortho'使用正交投影,这些都能提升性能。 - 减少轨迹点数:在播放动画时,如果
q_traj的点数太多(比如上万点),可以适当降采样后再用于plot。 - 更新图形驱动/使用更简单的图形渲染:确保MATLAB的OpenGL渲染正常。有时在虚拟机中运行MATLAB的3D图形会有问题。
- 限制
6.4 DH参数表与实物/图纸对不上
- 症状:按照图纸参数建模后,机器人工作范围或姿态与实物不符。
- 排查步骤:
- 确认DH约定:这是最大的坑!务必、务必、务必确认图纸或手册使用的是标准DH还是改进DH。一个关键鉴别点是看坐标系是附着在连杆的前端还是末端。如果手册给出了齐次变换矩阵
A_i的公式,可以对照一下变换顺序。 - 检查参数单位:确认
a、d的单位是米还是毫米?α、θ的单位是度还是弧度?在MATLAB中,所有长度单位应统一(通常为米),角度单位必须为弧度。 - 检查零位定义:机器人的“零位”姿态(所有关节变量为0时的姿态)是如何定义的?你的DH参数表中的
θ或d的零点是否与之对应?有时需要在Link的offset参数中补偿一个固定的偏移量,才能使模型的零位与实物对齐。 - 使用“三点法”标定:如果条件允许,可以手动驱动机器人到三个以上不同且差异较大的姿态,记录每个姿态下的关节角读数(
q_measured)和末端在基坐标系下的实际位置(通过测量获得T_actual)。然后,用你的模型计算这些关节角下的末端位姿(T_model)。通过优化算法(如最小二乘法)微调你的DH参数(尤其是a、d、α的初始值以及offset),使T_model尽可能接近T_actual。这是将理论模型与物理机器人对齐的高阶技能。
- 确认DH约定:这是最大的坑!务必、务必、务必确认图纸或手册使用的是标准DH还是改进DH。一个关键鉴别点是看坐标系是附着在连杆的前端还是末端。如果手册给出了齐次变换矩阵
建模从来都不是一次成功的事情,它是一个“建立-验证-调试-再验证”的循环。利用好MATLAB强大的计算和可视化能力,结合上述排查方法,你就能高效地构建出准确、可靠的串联机器人运动学模型,为后续的控制、规划和仿真打下坚实的基础。记住,清晰的坐标系图示和一份准确的DH参数表,是你最宝贵的资产。