简介:这份文档资料面向使用MATLAB进行机器人建模与控制的初学者及工程技术人员,围绕Robotics Toolbox在MATLAB 2020a搭配v10.4环境下的常用命令展开,可解决工具箱版本差异导致的命令不兼容、入门无从下手等问题。内容涵盖二维与三维位姿描述(SE2、transl2、rotx/roty/rotz、trplot与tranimate动画)、基于DH参数的Link关节定义与SerialLink机械臂建模、fkine正运动学与ikine/ikine6s逆运动学、jacob0与jacobn雅克比矩阵求解,以及关节空间jtraj、笛卡尔空间ctraj的轨迹规划。动力学部分进一步整理了rne逆动力学、gravload重力载荷、inertia惯性矩阵、coriolis耦合矩阵、payload载荷施加,并以PD控制器力矩函数配合fdyn正向动力学给出示例,公式与调用格式对照清晰。资源共1个PDF文件,压缩包约101KB,篇幅精炼便于随时查阅与打印。目前已有717人学习浏览,适合作为课程实验、课题开发时的速查手册与命令参考。
1. 从一段六轴轨迹说起:MATLAB 机器人工具箱到底替你算了什么
给你六组关节角和一份 DH 参数表,让你回答三个问题:末端现在在哪、从 A 点怎么沿直线走到 B 点、每个关节电机要出多大力。这三件事分别对应正运动学、轨迹规划和逆动力学,手推一遍矩阵乘法足以劝退大多数人。MATLAB 机器人工具箱(Robotics Toolbox)做的事情就是把这套计算封装成几十个函数:喂进去关节角,吐出来齐次变换矩阵、雅可比矩阵和关节力矩向量。
它适合两类人。一类是做课程设计、大作业、论文仿真的人,需要在一两个晚上把机械臂模型跑起来、出几张图;另一类是手上已有真机或者 URDF 模型的人,想在 MATLAB 里离线验证控制逻辑,再决定要不要改控制器参数。它的边界同样清楚:不做实时控制,也不替代专业仿真环境,强项是矩阵运算、图形绘制和实验数据后处理——这也是为什么很多人最后是拿它算数据、拿别的工具跑实时。
所以「MATLAB 机器人工具箱使用教程」这个标题真正要拆开的,是四个动作:建出 SerialLink 对象、算正解和逆解、生成轨迹、算力矩与验证。下面按这个顺序走一遍,每一步都给出能直接粘贴运行的代码。
2. MATLAB 机器人工具箱安装与刚体链建模:DH 参数怎么落到代码里
2.1 先分清 Robotics Toolbox 与 Robotics System Toolbox
新手最容易踩的第一个坑不是语法,是装错了东西。MATLAB 生态里有两套名字极像的工具:
| 名称 | 来源 | 建模入口 | 典型用途 |
|---|---|---|---|
| Robotics Toolbox(常被简称 RTB) | 第三方开源工具箱 | SerialLink+Revolute/Link | 运动学、动力学、轨迹、教学仿真 |
| Robotics System Toolbox | MathWorks 官方 | rigidBodyTree、importrobot | 与 Simulink 联合、URDF 导入、代码生成 |
两者的函数名高度相似,比如都有正运动学求解,但对象类型完全不兼容。搜到的教程代码跑不通,八成是照着另一套的文档抄的。判断方法很简单:看代码里出现的是SerialLink还是rigidBodyTree。混用会直接报「未定义函数」或参数类型错误,不要试图去转对象,老老实实按其中一套写完整流程。
常见做法是:做运动学推导、画图、写论文用 RTB;要接 Simulink 做控制器闭环、要往硬件部署,用官方那套。两边都需要时,用 URDF 做中间桥。
2.2 安装与路径自检的三条命令
安装方式通常有两种:在 MATLAB 的附加功能管理器里搜索安装,或者拿到.mltbx安装包后双击,MATLAB 会自动挂载路径。手动解压的目录则用addpath挂上去。装完先自检,别急着写模型:
% 1) 确认关键类能被定位到,返回完整路径才算装好 which SerialLink which Revolute % 2) 列出路径中所有含 Robotics 的目录条目,核对是不是你想要的那一份 p = strsplit(path, pathsep); disp(p(contains(p, 'Robotics'))') % 3) 手动安装时把目录挂上并保存,避免每次重启都要重来 % addpath(genpath('D:\toolbox\RoboticsToolbox')); % savepath;which返回空说明路径没挂上,检查是否解压到了带空格或中文的目录;返回的是官方工具箱里的同名文件,说明你引用的类有冲突,把第三方工具的路径提前(addpath放在最前面)。savepath会把当前路径写进用户配置,只有在你有写权限、且确认这份代码长期使用时才执行,公用机器上不建议。
2.3 用 Revolute/Prismatic 建刚体链:DH 参数的四个数
建模型的本质是把 DH 表翻译成对象数组。较新的接口用Revolute(转动关节)和Prismatic(移动关节)逐个构造,再交给SerialLink串起来:
% 六轴串联臂示例:d/a 单位米,alpha/qlim/offset 单位弧度 L(1) = Revolute('d', 0.400, 'a', 0.025, 'alpha', pi/2, 'qlim', deg2rad([-160 160])); L(2) = Revolute('d', 0, 'a', 0.455, 'alpha', 0, 'qlim', deg2rad([-225 45])); L(3) = Revolute('d', 0, 'a', 0.035, 'alpha', pi/2, 'qlim', deg2rad([-45 225])); L(4) = Revolute('d', 0.420, 'a', 0, 'alpha', -pi/2, 'qlim', deg2rad([-110 110])); L(5) = Revolute('d', 0, 'a', 0, 'alpha', pi/2, 'qlim', deg2rad([-100 100])); L(6) = Revolute('d', 0.080, 'a', 0, 'alpha', 0, 'qlim', deg2rad([-266 266])); robot = SerialLink(L, 'name', 'my6'); robot.display(); % 打印 DH 表,用来跟原始参数逐个核对四个核心参数的物理含义和最常见错误:
| 参数 | 含义 | 单位 | 常见错误 |
|---|---|---|---|
d | 沿前一关节轴线的连杆偏距 | 米 | 图纸是毫米,直接填进去导致模型缩小 1000 倍 |
a | 沿当前关节轴线的连杆长度 | 米 | 与d位置写反 |
alpha | 相邻轴线夹角(扭转角) | 弧度 | 用角度填90,画出来的臂是拧的 |
offset | 关节零位与 DH 零位的差值 | 弧度 | 真机零位不在 DH 定义处时漏填,导致正解整体偏一个常量 |
qlim | 关节限位 | 弧度 | 逆解求出来的角度超出限位却没检查 |
老式写法是Link([theta d a alpha sigma])的向量形式,sigma为 0 表示转动关节、1 表示移动关节。两种写法生成的模型等价,混用时注意第三、四个数不要串位——向量法里第四个位置是alpha,不是关节角。
提示:如果手里没有真实参数,先用自带模型熟悉接口,
p560 = mdl_puma560;会载入一台经典六轴臂,它的连杆质量和惯量参数是齐备的,后面算动力学可以直接用。
2.4 建模后的第一次自检:plot 与 teach
模型建完,先看它长什么样,再看它动起来像不像:
% 原地画一帧,限定显示范围,避免自动缩放导致看不清 robot.plot([0 0 0 0 0 0], 'workspace', [-1 1 -1 1 -0.2 1.4]); % 交互式拖动关节滑块,肉眼核对每个关节的转向和限位 robot.teach(); % 打印各连杆的变换矩阵,核对与手推结果是否一致 T = robot.fkine([0 0 0 0 0 0]); disp(T);workspace参数给的是显示包围盒[xmin xmax ymin ymax zmin zmax],单位米。台架式机械臂一般用一块扁平的盒子就够,值给太小会把连杆裁掉,给太大又看不清细节。teach打开后逐关节拖滑块,重点看两件事:关节转向是否和真机一致(不一致多半是alpha或offset符号错),以及滑块到端点时是否被qlim卡住。这一步花五分钟,能省掉后面调试逆解的两小时。
3. 正解、逆解与雅可比:用 fkine/ikine 把关节角算成位姿再算回来
3.1 fkine 的返回值拆开看
正运动学只有一行,但返回的 4×4 齐次变换矩阵要会拆:
q = [0 pi/4 pi/4 0 pi/4 0]; T = robot.fkine(q); p = transl(T); % 3x1 位置向量,单位米 R = t2r(T); % 3x3 旋转矩阵 eul = tr2eul(T); % ZYZ 欧拉角,单位弧度 rpy = tr2rpy(T); % roll-pitch-yaw,单位弧度 % 反推:用位置和姿态重新拼回变换矩阵,验证拆分是否正确 T2 = transl(p) * trotz(eul(1)) * troty(eul(2)) * trotz(eul(3)); norm(T2 - T) < 1e-12 % 返回 1 说明拼接无误transl(T)在不同大版本里的调用形式有差别:有的版本接受一个 3 元向量,有的版本接受三个标量。写transl(p(1), p(2), p(3))和transl(p)都试一下,报错就换另一种。姿态表示同理,tr2eul给的是 ZYZ 欧拉角,tr2rpy给的是固定轴 RPY,两者数值完全不同,拿去和真机控制器对比时先确认对方用的是哪一种,否则会出现「位置对、姿态全错」的假故障。
3.2 ikine 的四种返回与 mask 的用法
逆运动学是出错最多的地方,关键在于理解它是个数值优化问题,不是解析公式:
T = transl(0.4, -0.2, 0.6) * trotx(pi); % 目标位姿 q0 = [0 pi/4 pi/4 0 pi/4 0]; % 初值,越接近目标越好 % 位置姿态全控,六自由度都参与优化 q_full = robot.ikine(T, q0, 'mask', [1 1 1 1 1 1], 'tol', 1e-6, 'ilimit', 1000); % 只控位置,姿态任其自由,常用于四轴臂或只看落点 q_pos = robot.ikine(T, q0, 'mask', [1 1 1 0 0 0]); % 六轴球腕结构可以走解析解,速度更快也更稳 q_ana = robot.ikine6s(T); % 校验:逆解代回正解,看误差是否可接受 err = norm(transl(robot.fkine(q_full)) - transl(T))关键参数的含义与推荐取值:
| 选项 | 作用 | 建议 |
|---|---|---|
'mask' | 六元 0/1 向量,指定哪些自由度参与优化 | 全控用[1 1 1 1 1 1],只控位置用[1 1 1 0 0 0] |
'q0' | 迭代初值 | 用上一时刻的关节角,比全零收敛快得多 |
'tol' | 收敛容差 | 一般 1e-6,精度要求高再收紧 |
'ilimit' | 最大迭代次数 | 默认偏小,复杂位姿改到 1000 |
'trans'/'rot' | 位置与姿态误差权重 | 位置精度优先时把rot调小 |
ikine6s只对满足球形手腕条件的六轴臂有效,参数不满足会直接报错,此时退回到ikine的数值解。另外要注意:数值逆解返回的是一组解,不是唯一解。同一个末端位姿通常存在 8 组关节角,哪一组取决于初值。真机上要选远离限位、远离奇异点的那一组,所以拿到解之后必须用qlim逐个检查。
3.3 jacob0 判奇异:最小奇异值与可操作度
雅可比矩阵描述关节速度到末端速度的映射,也是判断「这个位姿能不能干活」的工具:
q = [0 pi/4 pi/4 0 pi/4 0]; J0 = robot.jacob0(q); % 基坐标系下的 6xN 雅可比 Jv = J0(1:3, :); % 只取位置部分 w = sqrt(det(J0 * J0')); % 可操作度,越接近 0 越接近奇异 s = svd(J0); s_min = s(end); % 最小奇异值,常用阈值 0.01 量级 Jt = robot.jacob0(q, 'trans'); % 部分版本支持只返回平移部分robot.jacob0返回基坐标系(世界系)下的雅可比,robot.jacob(T, q)返回的是末端工具坐标系下的表达。做力控制、算末端刚度的场景用后者,做速度分配、判奇异用前者。判断方法上,可操作度w和最小奇异值s_min会同时趋近于零,实际用最小奇异值更方便设阈值。工程上不要等到严格为零才处理,s_min掉到 0.01 以下就应该降速或者绕路。
3.4 逆解不收敛时按顺序排查
逆解返回空、返回全零、或者代回正解误差很大,按下面顺序查,基本不会漏:
- 位姿是否在工作空间内。把
transl(T)和目标臂长比一下,超出臂展的位姿任何算法都无解,ikine只会返回一个残差很大的近似值。 - 姿态是否可达。位置对但姿态要求末端翻转 180°,很多构型做不到,先只解位置(
mask屏蔽姿态)确认位置可达。 q0是否离真实解太远。把初值换成上一时刻关节角,或在附近撒几个初值分别求解取误差最小的一组。- 关节限位是否被触发。解出来的角度逐项和
qlim对比,超出就换另一组解。 - 目标位姿是否接近奇异位形。用第 3.3 节的方法算一下
s_min,接近零时数值解本身就不稳定。
4. 轨迹规划与动力学:jtraj、ctraj 和 rne 的组合用法
4.1 jtraj 五次多项式:q/qd/qdd 三个输出怎么用
关节空间轨迹最常用的是jtraj,它给每条关节生成五次多项式插值,位置、速度、加速度连续:
t = 0:0.02:2; % 2 秒,50 Hz 采样 q0 = [0 0 0 0 0 0]; qf = [pi/4 pi/6 -pi/6 0 pi/3 0]; [q, qd, qdd] = jtraj(q0, qf, t); % 位置、速度、加速度 % 动画:fps 控制播放速度,trail 画出末端拖尾 robot.plot(q, 'fps', 50, 'trail', 'r-', ... 'workspace', [-1 1 -1 1 -0.2 1.4]); % 画图核对:三条曲线应该平滑、首尾速度为零 subplot(3,1,1); plot(t, q); ylabel('q (rad)'); grid on subplot(3,1,2); plot(t, qd); ylabel('qd (rad/s)'); grid on subplot(3,1,3); plot(t, qdd); ylabel('qdd (rad/s^2)'); grid on第三个参数t给的是时间向量而不是步数,采样间隔直接决定qd的数值精度:间隔太大,差分出来的速度会有明显台阶;间隔太小,动画播放会拖慢(用fps限制)。qd的输出可以直接喂给速度环做前馈,qdd配合惯量矩阵算力矩。若某条关节曲线出现明显超调,说明起止点跨度太大,中间加一个路径点分段插值,比强行拉长时间更有效。
4.2 ctraj 笛卡尔直线与逆解回代
要求末端走直线、走圆弧的时候,关节空间插值就不够用了,得在笛卡尔空间插值再逐点求逆解:
T0 = robot.fkine(q0); T1 = robot.fkine(qf); Ts = ctraj(T0, T1, length(t)); % 位姿序列,直线插值 % 逐点逆解,用上一时刻结果作初值保证解连续 q_c = zeros(length(t), 6); q_c(1,:) = q0; for k = 2:length(t) q_c(k,:) = robot.ikine(Ts(:,:,k), q_c(k-1,:), ... 'mask', [1 1 1 1 1 1], 'tol', 1e-6); end两种规划的差别直接决定适用场景:
| 对比项 | jtraj | ctraj |
|---|---|---|
| 插值空间 | 关节空间 | 笛卡尔空间 |
| 输入 | 起止关节角 | 起止位姿矩阵 |
| 输出 | q/qd/qdd | 位姿序列Ts |
| 末端路径 | 不可控,通常是曲线 | 直线或按给定路径 |
| 是否需要逆解 | 不需要 | 每点都要 |
| 奇异点风险 | 低 | 高,直线穿过奇异区会失败 |
循环里用上一时刻的解作初值,是为了防止逆解在相邻两点之间跳到另一组解上,出现关节突然大幅摆动。逐点算完之后,建议对q_c做一次差分求速度,检查有没有单点尖峰;有尖峰说明该点接近奇异,把路径整体平移一点或者抬高绕行。
4.3 rne、gravload、inertia:动力学问的三个问题
运动学只管几何,动力学才涉及质量和力。三个函数对应三类问题:
% 前提:连杆必须带质量、质心和惯量参数,否则结果全是零 % 自带模型 p560 参数齐全,自定义模型要用 'm'、'r'、'I' 补齐 q = [0 pi/4 pi/4 0 pi/4 0]; qd = zeros(1,6); qdd = zeros(1,6); tau_g = robot.gravload(q); % 问题一:静止不动要多大静态力矩 M = robot.inertia(q); % 问题二:当前位形的惯量矩阵 tau = robot.rne(q, qd, qdd); % 问题三:给定运动状态的逆动力学力矩 % 只算重力项时,rne 与 gravload 应当一致 norm(tau - tau_g) < 1e-9rne是递归牛顿-欧拉法的逆动力学,输入位置、速度、加速度返回关节力矩;gravload是它的特例,速度加速度都为零时只剩重力项。新手最常见的现象是「rne返回全零」,原因几乎都是建模时只填了 DH 参数、没填'm'(质量)、'r'(质心位置)和'I'(惯量矩阵)这三个动力学参数。这三个量必须来自 CAD 或手册,不能凭感觉凑,否则算出来的力矩只具有数量级参考意义。
注意:
robot.inertia(q)在部分版本里名为robot.inertia,老版本可能通过rne的多返回值获得,报错时用which查一下当前版本提供的方法名。
4.4 用阶跃响应和 pid tuner 校核关节跟踪
算出力矩之后,接下来的问题是控制器跟不跟得上。RTB 不提供控制器设计功能,但可以把算出来的模型参数导出到 Simulink,用pid tuner调参,再看matlab 阶跃响应:
% 把关节等效成二阶模型做快速摸底,K 为关节刚度近似项,J 为惯量矩阵对角元 q_test = [0 pi/4 pi/4 0 pi/4 0]; J = diag(robot.inertia(q_test)); sys = tf(1, [J(2) 0 0]); % 简化模型,仅用于看带宽量级 step(sys); grid on; % 看超调、上升时间、稳态误差这是一种近似:把多关节耦合系统按对角元解耦成独立二阶环节。它不会给出精确的控制器参数,但能快速判断「这套机构大概能跑多快」。真实调参还是在仿真环境里闭合全部耦合项做,pid tuner更适合在这个简化模型上定初值,再拿去精调。
5. 从模型到实物:URDF 交叉校核与三个验证技巧
建模出错最怕的是没人告诉你错了——模型看起来能跑、图也能画,可末端位置就是差几厘米。下面三个技巧用来给模型做交叉验证。
5.1 用 URDF 导入结果对照 DH 建模
如果手上已经有一份 URDF,用官方工具箱导入后,取几个位形对比末端位姿,是性价比最高的校核方式:
rbt = importrobot('myarm.urdf', 'MeshPath', 'meshes'); show(rbt); % 可视化,确认关节轴向和零点方向importrobot建出的是刚性体树对象,与 RTB 的SerialLink不是同一类型,但两者都能算正运动学。挑 5 到 10 组关节角,分别用两套模型算末端位置,逐个比对:
| 校验项 | 期望结果 | 不符时的排查方向 |
|---|---|---|
| 零位末端位置 | 两套模型差在毫米级 | DH 的d/a抄写错误或单位不一致 |
| 单个关节转 90° 后位置 | 变化方向与轴向一致 | alpha符号或关节轴方向定义相反 |
| 整臂旋转一周的位置轨迹 | 是标准圆或圆弧 | offset漏填,导致整体偏常量 |
| 极限位形下的姿态 | RPY 三个角一致 | 姿态表示方式不同(ZYZ 与 RPY 混用) |
差异集中在某个常量上,基本就是offset或关节零位定义的问题;差异随位形变化而不固定,则更可能是alpha或a写错。
5.2 用数值微分验证雅可比
雅可比矩阵错了,速度分配和力分配就全错,而且这种错误往往在跑轨迹时才暴露。用数值微分对一下,几分钟能省掉半天:
q = [0 pi/4 pi/4 0 pi/4 0]; dq = 1e-7; J_ana = robot.jacob0(q); J_num = zeros(6, 6); T0 = robot.fkine(q).T; for k = 1:6 qp = q; qp(k) = qp(k) + dq; Tp = robot.fkine(qp).T; dT = (Tp - T0) / dq; % 从变换矩阵的微分中提取线速度和角速度 J_num(1:3, k) = dT(1:3, 4); J_num(4:6, k) = [dT(3,2); dT(1,3); dT(2,1)]; end max(abs(J_ana - J_num), [], 'all') % 应该是个很小的数数值微分的步长dq不能太大也不能太小:太大会带来截断误差,太小会被浮点精度吃掉,1e-7是常见取值。算出来的最大偏差在 1e-6 量级就说明雅可比没问题,差得离谱就回到第 3.3 节检查是不是取错了坐标系(jacob0与jacob)。
5.3 用关节限位扫描提前发现行程问题
最后一招是给整个工作空间做一遍粗扫,把不可达、超限位和接近奇异的位形先标出来:
q1 = linspace(-pi, pi, 13); q2 = linspace(-pi/2, pi/2, 7); bad = 0; near_sing = 0; for a = q1 for b = q2 q = [a b -pi/4 0 pi/4 0]; if any(abs(q) > robot.qlim(:,2)') % 超出上限 bad = bad + 1; continue end if svd(robot.jacob0(q), 'econ'); end s = svd(robot.jacob0(q)); if s(end) < 0.01 % 接近奇异 near_sing = near_sing + 1; end end end fprintf('超限位位形 %d 个,接近奇异位形 %d 个\n', bad, near_sing);扫描粒度不用太细,先粗后细。把s(end) < 0.01的位形标记出来,在实际规划路径时主动避开这片区域,比在运行时用异常处理去兜底要省事得多。真机上手前跑一遍这个扫描,能拿到一份「哪些区域别去」的清单,这条清单本身就是控制器里限位和降速策略的直接依据。
本文还有配套的精品资源,点击获取