ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

3R机械臂动力学仿真与Simulink实现:从拉格朗日方程到S-Function

3R机械臂动力学仿真与Simulink实现:从拉格朗日方程到S-Function 简介面向机器人控制与仿真的Matlab工程包针对三自由度机械臂动力学建模与PD控制器设计需求基于Matlab 2018b开发适用于高校课程设计、毕业设计及科研预研。压缩包内共5个文件包括SLX仿真模型、M脚本、使用说明TXT、PDF安装教程以及Robot Toolbox安装包ZIP总大小约20.26MB结构紧凑从模型搭建到控制实现均有对应文件支撑。目前已有2545人学习下载。工程使用Simscape Multibody多体工具箱建立三连杆机械臂模型通过PD反馈控制实现轨迹无余差跟踪建模思路与控制系统结构清晰完整。资源内附完整仿真工程并额外提供Robot Toolbox安装包与图文安装教程可帮助读者复现平面三自由度机器人动力学仿真、理解PD控制作用机理及掌握Multibody建模流程适合机器人方向初学者、相关课程学生及需要快速搭建机械臂仿真环境的开发者。 前阵子一个师弟拿着课设题目来问我3R机械臂动力学仿真Simulink怎么下手标题里把Simulink拼成了Sinulink一看就是输入法顺手干的但问题本身很典型。3R机械臂是三自由度旋转关节机械臂的简称动力学仿真则是把运动方程算出来这件事从纸面搬到电脑上。很多人卡住不是因为公式难而是不知道Simulink里那一堆积分器、S-Function、控制器模块应该怎么组织起来。这篇文章就把整条路走一遍从模型推导到S-Function实现再到调试踩坑适合做课设、准备毕设或者刚开始接触机器人仿真的朋友参考。我一直觉得做动力学仿真最忌讳一上来就拖模块。你得先清楚自己在仿什么、方程从哪来、模块怎么对应方程。搞清楚这三件事Simulink反而是最简单的一环。下文我会尽量把每一步为什么这么做也讲明白不是只给一张能跑的图就完事。1. 为什么用Simulink做3R机械臂动力学仿真1.1 3R机械臂到底在仿什么3R机械臂就是由三个转动关节串联组成的机械臂常见于平面三连杆臂和空间小型串联臂。动力学仿真要回答的核心问题是给定每个关节的驱动力矩机械臂会怎么动反过来给定期望轨迹每个关节需要输出多少力矩。前者叫正动力学后者叫逆动力学两者在仿真里都会被用到。我见过不少人把仿真当成动画看觉得模型动起来就算成功。实际上动力学仿真最有价值的产出是关节力矩曲线、速度/加速度响应、轨迹跟踪误差这些数据直接用于电机选型、控制器设计和结构校核。你做课设时可能只要求角度曲线收敛但到了实际工程里力矩算不准电机买小了机械臂抬都抬不起来所以仿真环节的动力学精度很关键。Simulink做这件事的优势在于它是图形化建模环境积木式搭建很直观而且自带强大求解器连续/离散、刚性问题都能处理。你不需要自己写龙格库塔积分器也不需要处理矩阵运算的数值稳定性细节把这些精力留给模型本身。1.2 建模路线选择拉格朗日还是牛顿-欧拉机械臂动力学建模有两条主流路线。拉格朗日法从能量出发写出系统动能和势能再对广义坐标求偏导得到标准的动力学方程形式。牛顿-欧拉法从力和力矩的递推出发正向计算速度与加速度反向递推关节力/力矩计算效率很高适合做实时控制。我做仿真时倾向于拉格朗日法原因很实在它天然给出形如 M(q)q̈ C(q,q̇)q̇ G(q) τ 的结构化方程。M是惯性矩阵C是科氏力/离心力矩阵G是重力项这个结构对控制器设计极其友好计算力矩法、反步法、自适应控制全是在这个框架上做文章的。牛顿-欧拉法效率高但用力矩形式给出结果调试时你很难直观看出哪部分力矩是惯性贡献的哪部分是重力贡献的。所以对3R这种自由度不太高的机械臂我建议走拉格朗日法把M、C、G三个矩阵明确求出来后面加什么控制律都方便。2. 动力学模型的核心推导与关键参数2.1 正运动学是动力学的地基在求动力学之前先把正运动学搞定。对平面3R机械臂设三连杆长度分别为 l1、l2、l3关节角为 q1、q2、q3末端的坐标可以写成x l1·cos(q1) l2·cos(q1q2) l3·cos(q1q2q3)y l1·sin(q1) l2·sin(q1q2) l3·sin(q1q2q3)这套公式是后面求雅可比矩阵、算质心速度的基础。有个很容易忽略的点求动力学时每根连杆的等效质量集中在哪、转动惯量是多少都需要通过质心坐标来计算而不是直接用末端坐标。所以建议把每根杆的质心位置也写成 q1、q2、q3 的函数单独写一个motion函数返回每根杆质心位置和速度。这一步写清楚了后面拉格朗日方程就好推了。我记得第一次自己写3R动力学直接从教材上抄M矩阵公式结果符号对不上仿真结果直接发散。后来老老实实从质心坐标重新推导一遍发现是某个连杆质心位置漏了一项。所以别嫌运动学基础它是动力学里最容易出错也最关键的一层。2.2 拉格朗日方程与M、C、G矩阵的形成拉格朗日函数 L K - PK是系统总动能P是总势能。对3R平面臂总动能是三个连杆动能之和每根杆的动能包含平动部分和转动部分总势能则是三个质心高度乘以质量和重力加速度之和。把L代入拉格朗日方程τ d/dt(∂L/∂q̇) - ∂L/∂q整理后一定会得到 M(q)q̈ C(q,q̇)q̇ G(q) τ 的形式。这里M是3x3对称矩阵C是3x3矩阵G是3x1向量。用手推导3R臂的M矩阵还能接受但C矩阵里面的科氏项非常容易漏。我习惯用MATLAB的Symbolic Toolbox做符号推导把M、C、G直接以符号表达式导出再转成MATLAB函数省去大量手算错误。如果你不想用符号工具箱也有一个很工程化的替代方案用数值扰动法计算M矩阵。给某个关节一个单位角加速度同时把其他关节加速度设为零通过牛顿-欧拉正向递推求所需力矩这个力矩就是M矩阵对应的一列。这个方法不需要手动求导适合验证你的符号推导是否正确。我经常用它当参考答案来检查自己的M矩阵有没有写错。2.3 参数设定与统一单位动力学仿真里单位不一致的坑太常见了。长度用厘米质量用克转动惯量却用了kg·m²结果惯性矩阵数量级差了几个量级仿真直接飞掉。我的建议是统一采用SI单位制长度用米质量用千克惯量用kg·m²力矩用N·m。角度用弧度角速度/角加速度分别是rad/s和rad/s²。参数示例一个典型的小型桌面级3R机械臂l1 0.3 ml2 0.25 ml3 0.15 m三杆质量 m1 2.0 kgm2 1.5 kgm3 0.8 kg各杆绕质心转动惯量 I1 0.05 kg·m²I2 0.03 kg·m²I3 0.01 kg·m²为什么三杆惯量越来越小因为越靠近末端连杆越短越轻这是实际机械臂设计的普遍规律。仿真参数设置得合理结果才有参考价值不能随便拍脑袋填数字。质心位置一般取在连杆几何中心附近但真实机械臂因为电机、减速器集中在关节处质心会偏向大关节一侧这一点在精度要求高的时候要考虑进去。3. Simulink仿真模型搭建与S-Function实现3.1 顶层架构状态积分是核心Simulink做动力学仿真有一个核心套路把动力学方程从 q̈ M⁻¹(τ - Cq̇ - G) 转化成积分链的形式。也就是说用两个积分器串联第二个积分器对q̈积分得到q̇第一个积分器对q̇积分得到q。整个模型的核心就是这一个积分环外部再叠加控制器和轨迹生成模块。控制器输出的力矩τ进入动力学方程模块动力学模块计算出q̈并送入积分器积分出来的q和q̇再反馈回动力学模块形成闭环。整个顶层模型非常简洁。很多人上来就把M、C、G手动搭成一大片增益矩阵和乘法器模型搞得像一团蜘蛛网调试时根本分不清哪根线连哪根线。我更建议把动力学方程封装成S-Function让代码去处理矩阵运算Simulink层面保持清爽。3.2 写一个能跑的S-FunctionS-Function本质是告诉Simulink你的状态是什么、状态的导数怎么算、输出是什么。对3R动力学状态x选择为 [q1; q2; q3; q̇1; q̇2; q̇3]一共6个连续状态。输入u选为三关节驱动力矩 [τ1; τ2; τ3]输出可以选当前状态。下面这个例子是我常用的动力学S-Function骨架function [sys,x0,str,ts] robot3r_dyn(t,x,u,flag) switch flag case 0 [sys,x0,str,ts] mdlInitializeSizes; case 1 sys mdlDerivatives(t,x,u); case 3 sys mdlOutputs(t,x,u); case {2,4,9} sys []; otherwise error([Unhandled flag , num2str(flag)]); end function [sys,x0,str,ts] mdlInitializeSizes sizes simsizes; sizes.NumContStates 6; sizes.NumDiscStates 0; sizes.NumOutputs 6; sizes.NumInputs 3; sizes.DirFeedthrough 0; sizes.NumSampleTimes 1; sys simsizes(sizes); x0 [0; 0; 0; 0; 0; 0]; str []; ts [0 0]; function sys mdlDerivatives(t,x,u) q x(1:3); qd x(4:6); tau u(1:3); [M,C,G] lagrange3r(q, qd); qdd M \ (tau - C*qd - G); sys [qd; qdd]; function sys mdlOutputs(t,x,u) sys x;这里唯一需要你补全的就是lagrange3r函数它根据当前q和q̇返回3x3的M矩阵、3x3的C矩阵和3x1的G向量。这个函数可以由符号工具箱自动导出也可以手写。矩阵求逆我用的是左除M \ b不建议用inv(M)*b数值稳定性差得多这是N维矩阵运算的基本素养。注意到mdlInitializeSizes里DirFeedthrough设为0因为当前输出不直接依赖当前输入u而是依赖连续状态x。这一点如果设错了Simulink会报警告甚至引入虚假的代数环。3.3 控制器封装让机械臂真正跟轨迹有了动力学模型你还需要一个控制器去驱动它跟踪期望轨迹。最简单也最常用的方案是计算力矩控制也称逆动力学控制τ M(q)·(q̈_des Kd·(q̇_des - q̇) Kp·(q_des - q)) C(q,q̇)q̇ G(q)这个控制律的思路是把非线性项C和G前馈补偿掉把系统变成解耦的线性二阶系统再通过PD反馈调误差。Kp和Kd分别取对角矩阵比如Kp diag([100, 100, 100])Kd diag([20, 20, 20])系统就会有类似弹簧阻尼的跟踪表现。在Simulink里实现时期望轨迹用Clock模块配合MATLAB Function生成比如每个关节规划一条从初始位置到目标位置的平滑轨迹用五次多项式插值保证位置、速度、加速度连续。控制器输出τ送入S-Function就形成了完整的闭环仿真。我强烈建议你在这个阶段把三个关节的期望角度、实际角度、跟踪误差、控制力矩都接上Scope或Record模块这几个波形就是论文/报告里最有说服力的结果。4. 仿真调试常见问题与排查技巧4.1 仿真发散数值直接飞掉怎么办仿真发散的常见原因有四个初始条件不合理、Kp/Kd过大、步长太大、M矩阵求逆不稳定。我的排查顺序是先看步长固定步长求解器从1e-3改为1e-4如果用变步长就限制最大步长。再看初始条件确保q0和q̇0在物理上合理。然后减小Kp/Kd观察发散是否和增益有关。最后检查M矩阵是不是正定的如果某个关节角组合下M接近奇异说明机械臂接近奇异位形此时动力学天然敏感仿真容易爆。我遇到过一次特别隐蔽的发散原因lagrange3r函数里某个角度用了角度制的sin/cos其他地方用了弧度制结果混着算导致周期性跳变。这提醒我写完代码先做一个零输入零速度的静力验证看重力项输出是否等于 m·g·h 的解析值这一步能筛掉大半低级错误。4.2 代数环警告怎么处理使用S-Function并且设了正确的DirFeedthrough之后代数环问题少很多。但如果你在Simulink里用纯模块搭动力学方程力矩反馈回q̈计算时很容易出现代数环。代数环意味着信号在同一个仿真步内形成隐式依赖求解器需要迭代容易拖慢仿真甚至报错。最简单的处理办法是把动力学方程放进S-Function并正确设置直接馈通标志。如果还想用纯模块搭建可以在反馈回路里加一个很小的Transport Delay或者Memory模块打破代数环但这样会引入人为延迟精度受影响。我更推荐S-Function方案既干净又高效。S-Function里也别在输出函数里计算q̈把q̈放在导数函数里算输出只给状态本身。4.3 那些文档里查不到的坑第一个坑是MATLAB Function模块的变量名。第一次用某个变量前如果没通过信号端口或者初始化赋值MATLAB Function会报未定义或者自动推断成错误尺寸。建议在模块内部第一行加q zeros(3,1); qd zeros(3,1);这类预分配把变量尺寸钉死。第二个坑是Scope波形看着乱。三根杆的角度初始值都是0期望轨迹又是从0开始三条线完全重叠根本无法分辨。我习惯把三条曲线用不同颜色并设置Y轴偏移或者分别用三个Scope显示生成报告时一目了然。第三个坑是S-Function名字不要和MATLAB内部函数重名。比如你把S-Function命名为dyn.mMATLAB可能优先调用你的脚本第一次能跑但换个路径就行为不一致。命名建议加前缀比如rob3r_dyn_sfun避免各种奇奇怪怪的冲突。再分享一个实战技巧想让仿真更接近真实系统可以在关节处增加库仑摩擦和粘滞摩擦项 τ_friction Fv·q̇ Fc·sign(q̇)。虽然这会让模型多两个参数但很多课程设计和工程预研里加摩擦后的力矩曲线明显更真实展示的时候也更有说服力。在S-Function里只需要在力矩方程中减去这个摩擦项即可。关于这套仿真的迁移能力说一点我个人的体会。你把3R臂的S-Function写明白之后换到六轴机械臂只是状态变量多几个、lagrange3r换成一个更通用的牛顿-欧拉递推函数整体架构完全不用动。我后来做移动机械臂和双机械臂协同仿真沿用的一直是这个动力学方程封装成S-Function 外部PD/计算力矩控制器的模式。所以说3R臂不是一个孤立的课设它是理解整个机器人仿真体系最好的一把钥匙。最后再提醒一句调试时保存好每次修改前后的仿真曲线我习惯用simout把数据导出到工作区和上次结果比较差异。很多时候你觉得改完变好了是错觉数据对比才是真实依据。本文还有配套的精品资源点击获取
返回列表