☰
机器人运动学建模与Simscape仿真:从DH参数到轨迹控制
2026/10/21 16:37:19 网站建设 项目流程

最近整理了一套机器人运动学分析与控制仿真的完整流程,对象一个是六轴关节型机器人,一个是SCARA平面关节型机器人。整个过程从DH参数建模开始,到正运动学和逆运动学推导,再到Simulink/Simscape Multibody物理建模,最后做了关节空间和笛卡尔空间的轨迹跟踪控制仿真。这篇文章把每一步的推导依据、参数选型逻辑和实际踩过的坑都写出来,适合刚接触机器人运动学、想在MATLAB里把仿真链路打通,或者在Simscape里调模型调到怀疑人生的开发者参考。

先说结论:MATLAB/Simulink/Simscape这套工具链做机器人的运动学分析和控制仿真,完全够用,而且比某些开源方案更快出结果。但前提是DH参数必须吃透,不然坐标系一错,后面所有仿真结果都是建立在流沙上的。这篇文章不会从零教你机器人学,但会把你做项目时最容易卡住的地方全部过一遍,包括正解怎么验证、逆解多解怎么处理、Simscape模型为什么总是弹、PID调参到底有没有章法。

1. 项目背景与整体思路拆解

1.1 为什么把六轴和SCARA放在一起分析

标题里同时出现六轴和SCARA,不是随手凑数的,这两类机器人在运动学上正好代表了两种典型的构型思路。

SCARA是Selective Compliance Assembly Robot Arm,选择性柔顺装配机械臂,结构上一般是四个自由度:肩部旋转、肘部旋转、垂直升降、末端工具旋转。它的特点是水平方向刚度高、垂直方向柔顺,天生适合电路板插装、小零件装配、高速搬运这种“平面定位+垂直插入”的工况。因为前两个关节轴平行,运动学本质上退化成了一个平面二连杆问题,逆解可以用纯几何关系直接写出来,连矩阵都不用展开。

六轴关节型机器人则是典型的空间6R串联机构,前三个关节确定腕心位置,后三个关节确定末端姿态,工作空间是球形或准球形,覆盖姿态能力强,适合焊接、喷涂、上下料等需要末端多角度作业的场景。它的逆解虽然也有解析解,但推导过程比SCARA复杂得多,存在多解、奇异位形、腕部翻转等问题。

放在一个项目里做,最直接的价值是:同一个DH分析框架、同一套MATLAB脚本、同一个Simscape搭建流程,可以同时验证两类机器人的建模通用性和差异性。先拿SCARA这种简单结构把整个链路跑通,再上六轴,排错成本会低很多。我的建议是不要一上来就死磕六轴的解析逆解,先把SCARA的几何法逆解玩明白,很多概念就通了。

1.2 工具链选型:MATLAB/Simulink/Simscape

我选MATLAB而不是其他开源方案,并不是因为开源工具不好,而是这套组合在“推公式-建模型-搭控制-调参数”这条链路里,衔接成本最低。

第一,符号数学工具箱可以直接做齐次变换矩阵的连乘推导。SCARA的正运动学还能手推,六轴那种四个以上关节的矩阵连乘,手推容易错,用syms变量一跑,表达式直接规整输出,还能自动化简。第二,Robotics System Toolbox提供了rigidBodyTree、trapveltraj、inverseKinematics这些现成函数,省掉了很多底层实现。第三,Simscape Multibody使用多体物理引擎,刚体、关节、坐标系、传感器都是图形化模块,拖拽配置即可,不需要自己写动力学积分器。

当然,这套路也有缺点。Simscape的物理仿真实时性一般,真要部署到控制器上还得转C++,变量步长求解器在复杂模型下可能跑得很慢。但它作为算法验证和参数预调工具,性价比极高。我的经验是:纸面推导用MATLAB脚本,物理模型用Simscape,控制验证用Simulink,三个环境之间用MATLAB变量桥接,整个仿真链路非常顺滑。

1.3 整体建模与控制的五步流程

完整项目可以拆成五个阶段,每个阶段都有明确的交付物:

  1. 建立DH参数表:根据机械结构图纸或实际测量数据,确定各关节的连杆长度、偏置距离、扭角。
  2. 符号推导正运动学:编写齐次变换矩阵函数,连乘得到末端位姿表达式,并用数值代入验证。
  3. 求解逆运动学:SCARA用几何法,六轴用解析法或数值迭代法,并处理多解选择。
  4. 搭建Simscape物理模型:从URDF导入或者手工搭建多体模型,配置关节执行器和传感器。
  5. 设计与验证控制器:做关节空间轨迹规划,设计PID控制器,闭环仿真,再扩展到笛卡尔空间跟踪。

这个顺序非常重要。我见过很多初学者跳过第一步直接拖Simscape模块,结果模型跑起来完全不知道对不对。DH参数是整个项目的地基,后续所有推导和仿真都建立在它上面,这一步多花时间绝不亏。

2. 运动学建模:从DH参数到正逆解

2.1 DH参数与坐标系建立

DH参数法有两种主流约定:标准DH和改进DH,区别在于坐标系固连在连杆的前端还是后端、变换顺序是“先旋转再平移”还是“先平移再旋转”。我强烈建议统一用改进DH(也叫Craig约定),因为Robotics System Toolbox默认采用这种约定,而且它在处理树形结构和闭链时更直观。

改进DH的四个参数定义如下:α_{i-1}是从Z_{i-1}轴旋转到Z_i轴的绕X_{i-1}轴转角;a_{i-1}是沿X_{i-1}轴从O_{i-1}移动到O_i的距离;d_i是沿Z_i轴从X_{i-1}轴移动到X_i轴的距离;θ_i是绕Z_i轴从X_{i-1}轴旋转到X_i轴的转角。对于旋转关节,θ_i是变量;对于棱柱关节,d_i是变量。

以我的SCARA示例模型为例,DH参数表如下:

关节iα_{i-1} (°)a_{i-1} (mm)d_i (mm)θ_i
100250q1
203200q2
30300q30
40080q4

注意关节3是棱柱关节,所以表中d3=q3是变量,θ3固定为0。这套示例参数的物理含义是:基座高度250mm,大臂长度320mm,小臂长度300mm,末端工具偏置80mm。实际机器人如果Z轴方向有出入,比如某些SCARA的关节2坐标系Z轴和关节1相反(表现为α_1=π),必须以图纸为准,不能照抄。

六轴机器人的示例DH参数表我给一下:

关节iα_{i-1} (°)a_{i-1} (mm)d_i (mm)θ_i
100400q1
2-901500q2
306000q3
4-900650q4
59000q5
6-900100q6

这个构型和很多通用工业六轴比较接近,适合做算法验证。有一个细节:SCARA所有α都是0,意味着所有关节轴相互平行,所以运动学平面退化。而六轴中α有±90°的跳变,正是这些扭角让机械臂获得了空间运动能力。如果你在搭DH表时发现相邻关节轴明明不在你预期方向上,大概率是扭角符号写反了。

DH表建完之后,把参数存成矩阵放进MATLAB脚本。我的习惯是同时写一个dh_transform函数,直接输入θ,d,a,α四个标量,返回4x4齐次变换矩阵,这样可以复用。

2.2 正运动学推导

正运动学的目标是给定四个关节变量(q1,q2,q3,q4),求出末端相对于基座标系的位姿。对于SCARA来说,由于前两个关节在平面内、第三个关节上下移动、第四个关节旋转,末端位置是可以直接手写的:

x = L1cos(q1) + L2cos(q1+q2) y = L1sin(q1) + L2sin(q1+q2) z = d1 - q3 姿态角φ = q1 + q2 + q4

这就是平面二连杆的位置方程,小学生都能看懂,但它背后对应的是四个齐次变换矩阵相乘。在MATLAB里,可以写一个正解函数,用循环连乘所有DH变换,而不是手工展开矩阵,这样代码更通用,换个DH参数表就能复用到六轴上。核心代码如下:

function T = scara_fk(q, dh_params) % q: [q1 q2 q3 q4],dh_params: 每行为 [alpha a d theta_offset] T = eye(4); n = length(q); for i = 1:n alpha = dh_params(i,1); a = dh_params(i,2); d = dh_params(i,3); theta = q(i) + dh_params(i,4); Ti = [cos(theta), -sin(theta)*cos(alpha), sin(theta)*sin(alpha), a*cos(theta); sin(theta), cos(theta)*cos(alpha), -cos(theta)*sin(alpha), a*sin(theta); 0, sin(alpha), cos(alpha), d; 0, 0, 0, 1]; T = T * Ti; end end

写完正解后必须验证。最有效的办法是“单关节验证法”:把其他关节锁定为0,只让第i个关节转动,观察末端位置变化轨迹。比如只动q1时,末端应该画出以基座为圆心的圆弧;只动q2时,末端应该画出以大臂末端为圆心的圆弧。如果轨迹方向反了,说明坐标系绕向定义有问题;如果半径不对,说明a参数或相邻坐标系原点位置有问题。这个验证步骤我每次都会做,哪怕是同型号机器人换了一台的DH参数,也必须重新跑一遍。

2.3 逆运动学求解

SCARA的位置逆解可以直接用余弦定理解出,这是所有机器人教材里都会讲的内容。记末端平面位置为(px, py),则:

r² = px² + py² cos(q2) = (r² - L1² - L2²) / (2L1L2) sin(q2) = ±sqrt(1 - cos²(q2)) q2 = atan2(sin(q2), cos(q2))

注意q2有两个符号相反的候选解,对应“肘部朝左”和“肘部朝右”两种构型。然后求q1:

q1 = atan2(py, px) - atan2(L2sin(q2), L1 + L2cos(q2))

第三关节的位移直接由高度差给出:q3 = d1 - pz。第四关节的姿态角需要从末端期望姿态φ反推:q4 = φ - q1 - q2。

在MATLAB里可以这样实现:

function q = scara_ik(px, py, pz, phi, L1, L2, d1, elbow) r = sqrt(px^2 + py^2); cos_q2 = (r^2 - L1^2 - L2^2) / (2*L1*L2); cos_q2 = max(min(cos_q2, 1), -1); % 防止浮点超界 sin_q2 = elbow * sqrt(1 - cos_q2^2); q2 = atan2(sin_q2, cos_q2); q1 = atan2(py, px) - atan2(L2*sin_q2, L1 + L2*cos_q2); q3 = d1 - pz; q4 = phi - q1 - q2; q = [q1 q2 q3 q4]; end

这里elbow参数取±1,用来选择肘部构型。我建议把构型选择显式暴露出来,而不是写死,因为实际项目中同一个末端位置可能需要根据避障需求切换构型。

六轴逆解就要麻烦很多。通用做法是:如果满足Pieper准则(后三个关节轴交于一点),就可以先求腕心位置,分离出位置逆解和姿态逆解,得到八组解析解。如果不满足这个条件,只能走数值迭代。Robotics System Toolbox里的inverseKinematics函数用的是数值法,对初始猜测比较敏感。示例代码如下:

ik = inverseKinematics('RigidBodyTree', robot); weights = [1 1 1 1 1 1]; initialGuess = robot.homeConfiguration; [q_sol, solInfo] = ik(eeName, targetTform, weights, initialGuess);

如果solInfo里显示迭代不收敛,先别急着改代码,检查两件事:一是初始猜测离目标位形太远,二是目标位形本身不在工作空间内。解决办法是把上一时刻的关节角作为初始猜测传给下一次求解,这样连续轨迹跟踪时基本不会跳解。

3. Simulink/Simscape Multibody物理建模实操

3.1 从URDF导入和手工搭建两条路

Simscape Multibody搭建机构模型有两条路:自动导入和手工搭建。如果机器人模型是用SolidWorks之类的CAD软件画的,可以导出URDF,然后用smimport函数一键生成Simscape模型,模块命名和层次结构都会被自动整理好。这条路的优点是省事、几何外观完整、惯性参数可以自动从CAD材质属性计算出来。缺点是URDF文件质量会直接决定模型质量,很多URDF导出插件在关节轴方向、坐标系原点上处理不规范,导入后经常需要手工修正。

另一条路是手工搭建:在Simscape Multibody里一个一个添加刚体模块、关节模块、坐标系变换模块。虽然繁琐,但每一步都可控。我的习惯是:小范围验证用SCARA这种简单构型就手工搭,快速又清晰;复杂六轴如果有CAD模型就导出URDF再导入,节省时间但必须做好验证。

SCARA的手工搭建逻辑可以这样描述:依次放置一个基座刚体、一个旋转关节、一个大臂刚体、一个旋转关节、一个小臂刚体、一个棱柱关节、一个末端升降刚体、一个旋转关节,最后接工具刚体。每个刚体模块都要配置质量属性和惯性张量,关节模块要选择类型并设置运动范围。

3.2 Simscape坐标变换与接口配置

手工搭建时最容易出错的就是坐标变换模块Rigid Transform。这个模块负责在刚体内部的子坐标系和父坐标系之间建立固定变换。搭建时一定要搞清楚:前一个坐标系的原点在这个刚体的什么位置,方向是怎样的。我建议在每一个刚体模块内部用一个Rigid Transform把原点从父关节点平移到子关节连接点,方向保持和世界坐标一致,这样关节轴的朝向才准确。

关节执行器和传感器的配置也在这里完成。给旋转关节添加Joint Actuator,输入端接Simulink侧的扭矩或位置指令;再添加Joint Sensor,输出端接实际关节位置、速度信号。要用Simulink-PS Converter和PS-Simulink Converter做两个域之间的信号转换,单位默认是国际单位制。这里有个常见的错误:Simulink里给的是角度制数值,但Simscape内部期望弧度制,如果不做rad转换,角度直接放大57倍,模型立刻飞掉。

3.3 仿真设置与模型验证

模型搭好后,第一件事不是上控制器,而是做开环验证。给每个关节依次给一个匀速斜坡位置指令,让关节从0运动到某个目标角度,用Scope观察末端位置变化。把Simscape输出的末端位置和MATLAB正运动学函数计算的结果画在同一张图里对比。如果曲线重合,说明模型建模正确;如果有恒定偏差,优先检查坐标系变换;如果偏差随时间增大,劣迹检查关节指令换算。

求解器设置在Simscape里很重要。纯Simulink控制环我用定步长ode4,步长1ms;但带上Simscape多体物理后,定步长可能会出现数值不稳定,尤其是关节存在硬限位或接触时。我的实践经验是:先用变步长ode15s或ode23t把模型验证跑通,确认物理模型没问题后,再切换回定步长做实时控制仿真。这样可以避免一开始就被数值问题绕昏头。

4. 运动控制:轨迹规划与伺服跟随

4.1 轨迹规划:关节空间与笛卡尔空间

轨迹规划在控制之前完成。关节空间轨迹是最常用的,给定起点和终点关节角,用梯形速度或S曲线在关节空间内插值。关键是最大速度和最大加速度要设置成实际电机的出力范围。SCARA第一关节大臂是重负载,加速度不能设置太大,否则仿真里扭矩会爆表。

Robotics System Toolbox里trapveltraj可以直接生成梯形速度轨迹,代码只需要三行:

waypoints = [q_start; q_end]'; [q_traj, qd_traj, qdd_traj, t] = trapveltraj(waypoints, 500, 'EndTime', 2);

这个函数会返回按时间离散的关节位置、速度、加速度序列。注意输入矩阵的维度永远是“关节数×路径点数”,我开始时就把维度搞反了好几次。

笛卡尔空间轨迹比关节空间麻烦得多,因为末端要沿直线或圆弧运动时,必须把直线路径上的离散点逐个用逆运动学映射回关节空间。这里有个坑:如果路径点穿越了奇异位形,逆解会突变,导致末端速度瞬间拉高。我处理的办法是在插值前检查工作空间边界,把超出范围的路径点裁剪掉,或者在接近奇异的位置切换成关节空间过渡轨迹。

4.2 单关节PID与力矩前馈

机器人关节控制的最低配置是独立PID。SCARA水平关节的模型近似为一个质量和阻尼系统,PID参数可以用经典整定方法起步:先设Kp让系统稳定,再慢慢加Kd抑制振荡,Ki只用来消除稳态误差,不能加太大。

我记录的SCARA第一关节典型参数起步值大概是这样:Kp=80,Ki=0.5,Kd=5。这个值在仿真模型上能跑,但换到实物上肯定要重新整定。纯粹PID的问题是抗扰动能力弱,而且低速时摩擦补偿不足会导致“爬行”现象。所以在我的控制结构里,PID之后会加一个力矩前馈项,用轨迹规划出来的关节加速度乘以连杆惯量估算出前馈力矩。这个前馈可以显著降低跟踪误差,而且它不依赖反馈,不会引入稳定性问题。

前馈的实现方式是:轨迹规划的qdd_traj经过一个增益模块,增益设置为该关节的转动惯量估算值,然后直接与PID输出相加,得到最终力矩指令。在Simulink里就是一个加法器的事,但效果非常明显。

4.3 笛卡尔空间跟踪控制

如果控制目标直接写为“末端走直线”,关节PID就不够用了,因为末端误差和关节角误差之间隔着雅可比矩阵。最简单的办法是内环位置控制加外环笛卡尔校正:先用期望笛卡尔轨迹代入逆运动学得到关节角期望,再做关节PID跟踪,同时用末端实测位姿和期望位姿的偏差生成一个微小修正量,叠加到关节期望上。这种方案对SCARA这种低速应用已经足够。

更高级的做法是阻抗控制或导纳控制,适用于装配这类需要和环境交互的场景。因为SCARA的关键应用就是插装,末端在Z方向的接触力控制比纯位置控制更有意义。仿真里可以用弹簧阻尼模型模拟环境接触力,验证末端力的响应。

5. 常见问题与排查技巧实录

5.1 DH参数正负号和大臂小臂干涉

我在这个项目里遇到的第一类问题很有代表性:按图纸搭完DH表,正解跑出来末端高度差了整整一半。排查了半天发现是坐标系Z轴方向约定不一致,导致d参数正负号写反。这里提供一个排查技巧:拿到任何DH参数表后,先只验证第一关节到第二关节的变换,手动计算当q1=90°、其他关节为0时末端位置应该在哪个方向,和图纸上的机械零位对比。误差超过1mm就说明DH表有问题,不要急着往下做。

SCARA还经常碰到大臂小臂反向折叠的问题。几何法逆解算出来的q1和q2组合可能导致大小臂夹角大于180°,这在物理上就是干涉。解决办法是在运动控制前先做关节限位检查,把每次逆解得到的关节角逐项和机械限位表比对,超出就选另一组候选解。

5.2 Simscape代数环与数值振荡

Simscape模型最常见的问题是仿真弹出“Algebraic Loop”警告。因为关节位置反馈和力矩输出在同一个仿真步内形成闭环,求解器必须迭代求解代数约束。我的经验是:尽量在反馈通道里加入一个小的传输延迟模块,或者把传感器信号经过一阶低通滤波后再进控制器,代数环基本就能消除。

模型振荡的问题通常不是因为控制器,而是因为关节模型里没有设置任何阻尼。Simscape关节默认摩擦和阻尼为0,实际电机和减速器都有阻尼。在joint模块里加上一个很小的粘性阻尼系数,比如每关节0.1 N·m·s/rad,整条跟踪曲线就平滑了。这个细节不写进任何官方教程,但我实测下来非常管用。

5.3 变步长与定步长的选择策略

带Simscape的模型,用定步长求解器在重负载快速运动时会发散;用变步长求解器能跑通但没法做实时仿真。我的组合策略是:模型验证阶段用变步长ode15s,把物理模型可信度先确认好;控制验证阶段换成定步长ode4,步长1ms,然后把控制器增益比变步长时调低20%左右,基本能稳定运行。如果你的模型必须在定步长下才能实时跑,可以考虑简化Simscape模型,把关节摩擦、柔性等非必要建模元素去掉,或者把多体模型替换成等效传递函数模型。

问题现象排查方向解决方案
末端位置恒差固定比例DH参数中a或d单位、Z轴方向错误单关节验证法逐步定位错误关节
逆解结果跳变初始猜测离目标位形远或目标不可达用上一时刻关节角作为下次求解初始猜测
Simscape警告代数环位置反馈与力矩指令形成瞬时环路反馈通道加入低通滤波或小延迟
模型仿真发散关节无阻尼且步长过大添加粘性阻尼系数并缩短步长
跟踪误差随时间增大控制器无前馈,积分项不足以抑制加入基于模型的前馈力矩

最后说一个我个人的习惯:做运动学分析时,永远把正解脚本和逆解脚本分开写,每个脚本都自带一个数值验证段落,每次改动机械参数后全部重新跑一遍。这个习惯帮我拦住过好几次模型改参数后没同步更新导致的正逆解不一致问题。如果你能把SCARA这套流程完整走通,六轴难度大,但套路完全一样。这个项目后续还可以往动力学辨识、自适应控制、柔顺装配插装仿真方向扩展,Simscape模型打磨好了,后面做算法验证就事半功倍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询