ARTICLE DETAIL

资讯详情

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

机器人运动学滑模变结构控制:Simulink仿真设计与抖振抑制实践

机器人运动学滑模变结构控制:Simulink仿真设计与抖振抑制实践 滑模变结构控制这名字听着唬人但在机器人运动学仿真里它其实是个特别“直接”的控制思路——说白了就是设计一条误差收敛的“滑模面”然后用不连续的切换控制把系统状态“按”到这条面上再沿着面滑到零点。我当年第一次在Simulink里把二连杆机械臂的运动学模型和滑模控制器接起来时看到示波器里那条误差曲线稳稳收敛才真正理解课本上那句“对参数摄动和外部扰动具有鲁棒性”是什么意思。这篇就围绕“机器人运动学控制 Simulink仿真模型 滑模变结构控制”三件事展开把建模、控制器设计、仿真实操和踩坑经验一次讲透。适合刚接触滑模控制的研究生、做毕业设计的本科生以及想快速验证控制算法的工程师。1. 先搞清楚机器人运动学模型1.1 为什么从运动学入手很多人一上来就怼动力学方程结果被惯性矩阵、科氏力、重力项搞得焦头烂额。滑模控制虽然是鲁棒控制里的常客但学习路径上完全可以先从运动学层面切入。运动学只研究关节角度与末端位置之间的映射关系不涉及力/力矩与加速度的因果模型形式简单控制目标也直观——就是让末端或关节角度精确跟踪期望轨迹。在这个层面上把滑模设计的逻辑跑通再去碰动力学会轻松得多。从工程角度看机器人运动学控制场景也很常见视觉引导的末端定位、关节空间轨迹跟踪、冗余机械臂的运动规划等本质上都需要先解决“让关节角度按期望曲线走”的问题。所以用二连杆机械臂作为仿真对象既保留了多轴耦合的特征又不会像六轴机械臂那样把雅可比矩阵推导变成灾难。等你把二连杆的运动学滑模控制吃透换成其他构型只是换一套正解公式而已。1.2 二连杆机械臂的运动学方程我采用最常见的平面二连杆模型两个连杆长度分别为 (L_1)、(L_2)关节角度为 (\theta_1)、(\theta_2)。末端位置 ((x, y)) 由正运动学给出[ x L_1 \cos(\theta_1) L_2 \cos(\theta_1 \theta_2) ] [ y L_1 \sin(\theta_1) L_2 \sin(\theta_1 \theta_2) ]对时间求导得到末端速度与关节角速度的关系[ \dot{x} -L_1 \sin(\theta_1)\dot{\theta}_1 - L_2 \sin(\theta_1 \theta_2)(\dot{\theta}_1 \dot{\theta}_2) ] [ \dot{y} L_1 \cos(\theta_1)\dot{\theta}_1 L_2 \cos(\theta_1 \theta_2)(\dot{\theta}_1 \dot{\theta}_2) ]写成矩阵形式就是 (\dot{\mathbf{p}} \mathbf{J}(\boldsymbol{\theta}) \dot{\boldsymbol{\theta}})其中 (\mathbf{J}) 是雅可比矩阵。运动学控制的目标通常是给定期望末端轨迹 (\mathbf{p}_d(t))求关节角速度指令 (\dot{\boldsymbol{\theta}})。如果只用逆雅可比 (\dot{\boldsymbol{\theta}} \mathbf{J}^{-1}(\dot{\mathbf{p}}_d \mathbf{K}\mathbf{e}))那是经典的“运动学PID”但面对模型误差和扰动时跟踪性能会打折。滑模控制在这里的用法就是针对跟踪误差设计鲁棒控制器不依赖精确的逆雅可比。在Simulink里搭模型时不少教程喜欢直接用积分模块把 (\dot{\boldsymbol{\theta}}) 变成 (\boldsymbol{\theta})再用角度计算末端位置。我建议把这些运算封装进一个“正运动学子系统”输入关节角度输出末端位置和雅可比矩阵这样后期换三连杆、换球坐标都很方便。模块层面用Fcn模块或MATLAB Function都可以但MATLAB Function写雅可比更清晰还能顺便输出条件数以观察奇异性。2. 滑模变结构控制的核心思路2.1 滑模面的设计滑模控制的设计分两步选滑模面定控制律。先说滑模面。对于关节角度跟踪问题定义误差 (e \theta_d - \theta)常见的线性滑模面为[ s \dot{e} \lambda e ]其中 (\lambda 0)。这个面的物理意义很直观如果系统状态能保持在 (s 0) 上那么 (\dot{e} -\lambda e)误差指数收敛到零收敛速度由 (\lambda) 决定。你可以把 (s) 理解成“误差空间的综合指标”它同时包含位置误差和速度误差。当 (s) 不为零时控制器要驱动系统让 (s) 趋向零这个过程叫“到达阶段”一旦 (s 0)就进入“滑模阶段”。之所以说滑模控制“对匹配扰动不敏感”是因为在滑模面上系统运动由滑模面方程决定原有的动力学参数被“替换”了。当然前提是控制增益能克服扰动上界否则系统会被扰动推出滑模面。这个“上界”的概念在设计符号函数增益时特别关键后面细说。2.2 趋近律与抖振抑制光让 (s 0) 还不够得规定 (s) 怎么走向零。最粗暴的做法是用符号函数[ \dot{s} -\eta ,\text{sgn}(s) ]对应控制律里会出现 (\eta ,\text{sgn}(s)) 这样的切换项。这种“指数趋近律”简单但会导致一个经典问题——抖振。因为符号函数在零附近高速切换理想状态下是无限频率实际离散仿真里就会表现为高频振荡反映在关节角度曲线上就是毛刺或极限环。很多初学者第一次跑仿真看见角度曲线抖得像心电图第一反应是模型错了其实只是符号函数增益太大。抑制抖振的常规方法有几种用饱和函数 (\text{sat}(s/\phi)) 代替 (\text{sgn}(s))在边界层内做线性过渡代价是牺牲一点收敛精度。用超螺旋算法等高阶滑模本质是让切换项作用在 (s) 的高阶导数上抖振大幅减弱但参数调节复杂些。适当调小切换增益 (\eta)只要能覆盖模型误差和扰动的上界就行没必要给得过大。我个人在做运动学仿真时先用饱和函数把逻辑跑通再换成符号函数对比抖振差异这个对比过程本身就是学习滑模控制最好的教材。你可以把饱和函数边界层厚度 (\phi) 设成 0.01~0.05增益 (\eta) 先设个保守值比如 0.5然后在仿真里一点点加。2.3 为什么要用“趋近律”而不是直接设计控制输入运动学模型的输入是关节角速度 (\dot{\boldsymbol{\theta}})不是力矩。所以控制律的形式不能照搬动力学里的 (u \tau)。这里需要用“运动学级”的虚拟控制量 (v \dot{\boldsymbol{\theta}}_c)把它当作关节角速度指令。我们设计[ \dot{\boldsymbol{\theta}}_c \mathbf{J}^{-1}\left(\dot{\mathbf{p}}_d \lambda \mathbf{e} \eta ,\text{sgn}(s)\right) ]其中 (\mathbf{e} \mathbf{p}_d - \mathbf{p}) 是末端位置误差(s \dot{\mathbf{e}} \lambda \mathbf{e})。这块设计逻辑是如果用 (\dot{\boldsymbol{\theta}}_c) 驱动真实机械臂那么末端速度会趋近期望速度误差沿滑模面收敛。在Simulink里这个 (\dot{\boldsymbol{\theta}}_c) 通常不能直接作为物理关节速度输入需要再串一个底层速度环或者直接把 (\dot{\boldsymbol{\theta}}_c) 当作指令给理想速度源。做运动学级仿真时我用的是“积分器理想速度驱动”把 (\dot{\boldsymbol{\theta}}_c) 积分得到实际角度再反馈给正运动学模块这样简单且能看清控制器核心性能不掺动力学干扰。当然这种理想化模型忽略了很多执行器特性但它作为学习载体非常合适——你可以单独评估滑模控制的鲁棒性比如给雅可比矩阵加5%的参数偏差看误差是否还能收敛这就比纯粹的PID更能体现滑模优势。3. Simulink仿真模型搭建全流程3.1 模型架构与模块选型整个Simulink模型分四块轨迹生成、滑模控制器、被控对象正运动学雅可比、信号观测。我从一个大框架说起你按这个结构搭不容易乱。轨迹生成模块我用MATLAB Function生成圆形轨迹圆心 ((0.6, 0.4))半径 0.1角频率 0.5 rad/s仿真时长 10 秒。输出期望末端位置 (\mathbf{p}_d) 和期望速度 (\dot{\mathbf{p}}_d)。也可以在Constant模块里用Clock和表达式实现但MATLAB Function最好改参数。滑模控制器模块输入期望位置、期望速度、实际位置、实际角度输出 (\dot{\boldsymbol{\theta}}_c)。这个模块内部用MATLAB Function实现雅可比计算、误差计算、趋近律和控制律。注意雅可比矩阵可能奇异二连杆在某些位形下 (\det(\mathbf{J}) 0)需要在函数里加个判断如果行列式绝对值小于阈值就用伪逆或阻尼最小二乘。常见做法是加个参数 (\epsilon)[ \mathbf{J}^ \mathbf{J}^T(\mathbf{J}\mathbf{J}^T \epsilon \mathbf{I})^{-1} ]这个 (\epsilon) 设成 0.01 左右能避免仿真中途因奇异而报NAN。被控对象模块理想速度源就是两个积分器输入 (\dot{\boldsymbol{\theta}}_c)输出实际关节角度 (\boldsymbol{\theta})反馈给控制器和正运动学。如果想更贴近真实可以在这个积分器前加一阶惯性环节模拟执行器延迟但学习阶段别加先看纯运动学下的控制效果。信号观测模块用Scope观察末端位置跟踪、关节角度曲线、误差和滑模面 (s)。建议把误差和 (s) 单独放一个Scope方便看收敛速度。3.2 机器人运动学子系统实现我习惯把正运动学封装成一个子系统内部用MATLAB Function写function [pos, J] fk_2link(theta, L1, L2) % 正运动学 q1 theta(1); q2 theta(2); x L1*cos(q1) L2*cos(q1q2); y L1*sin(q1) L2*sin(q1q2); pos [x; y]; % 雅可比矩阵 J [-L1*sin(q1)-L2*sin(q1q2), -L2*sin(q1q2); L1*cos(q1)L2*cos(q1q2), L2*cos(q1q2)]; end输入是 (\theta_1)、(\theta_2) 合成的一个向量信号用Vector Concatenate模块或直接两路输入到MATLAB Function都行。输出pos和J。注意MATLAB Function里不要用全局变量参数通过对话框传递。运行时长度参数 (L_1 0.5)(L_2 0.4)单位米。这里有个容易踩的坑MATLAB Function默认输出类型会被推断如果初始化时没有给输出变量赋值Simulink可能报“输出未定义”。所以在函数开头最好先写一行 (\text{pos} zeros(2,1); J zeros(2,2);)或者用coder.extrinsic调用不了就直接在代码里给默认值。3.3 滑模控制器子系统实现控制器的MATLAB Function写法大概是这样function [theta_dot_cmd] smc_controller(pd, pd_dot, p_current, theta, L1, L2, lambda, eta, phi) % pd: 期望位置2x1, pd_dot: 期望速度2x1, p_current: 实际位置2x1 % theta: 关节角2x1 [~, J] fk_2link(theta, L1, L2); e pd - p_current; edot pd_dot - J * theta_dot_current; % 注意这里需要当前关节角速度 s edot lambda * e; % 滑模面 % 饱和函数替代符号函数 sat_s min(1, max(-1, s / phi)); % 阻尼最小二乘逆 Jt J; JtJ J * Jt 0.01 * eye(2); Jinv Jt * (JtJ \ eye(2)); % 控制律 theta_dot_cmd Jinv * (pd_dot lambda * e eta * sat_s); end这里隐含一个依赖需要当前关节角速度 (\dot{\boldsymbol{\theta}})。我们的被控对象是理想积分器所以 (\dot{\boldsymbol{\theta}}) 正好等于 (\dot{\boldsymbol{\theta}}_c)也就是控制器的输出。这就形成一个代数环控制器输出决定实际速度实际速度又反馈到控制器计算。Simulink会报警告“代数环”虽然在小步长下能跑但最好显式消除。消除代数环的办法是把积分器输出的状态 (\boldsymbol{\theta}) 反馈给控制器但在控制器里用差分近似关节速度比如 (\dot{\theta}[k] (\theta[k] - \theta[k-1]) / h)通过Memory模块或Unit Delay实现。这样可以打破代数环代价是速度估计有一点延迟和噪声。运动学仿真中这个噪声可接受。更优雅的方案是在被控对象里加一个一阶惯性滤波但学习阶段我建议用Unit Delay近似简单实用。另一个更直接的办法既然被控对象是积分器控制器输出就是速度那就别把“当前速度”当反馈直接用期望速度的误差做滑模面。末端位置误差 (e) 是位置量其导数可以从期望速度减去“当前速度”但我们可以把滑模面定义为[ s \dot{\mathbf{p}}_d - \dot{\mathbf{p}} \lambda e ]其中 (\dot{\mathbf{p}} \mathbf{J} \dot{\boldsymbol{\theta}})。如果控制器输出 (\dot{\boldsymbol{\theta}}_c) 直接等于被控对象速度那么 (\dot{\mathbf{p}} \mathbf{J}\dot{\boldsymbol{\theta}}_c)。代入控制律会得到关于 (\dot{\boldsymbol{\theta}}_c) 的隐式方程。所以还是得打破代数环。我在实践中用如上Unit Delay估计速度方案效果稳定。3.4 参数设置与仿真配置仿真步长选择很关键。滑模控制带符号函数切换时如果步长太大控制器输出在几个步长之间反复跳变误差曲线会呈现锯齿状。我推荐用变步长ode45最大步长设 (0.001) 秒相对误差 (1e-4)。如果用的是饱和函数可以放宽到 (0.005) 秒。控制器参数我试用过一组不错的初始值(\lambda 3)(\eta 0.8)(\phi 0.05)。仿真10秒期望轨迹是半径0.1米的圆。初始关节角度可以从末端位置反解也可以直接设 (\theta_1 0.5)(\theta_2 0.8) 开始让控制器自己收。注意期望轨迹的起始点最好和机械臂实际末端位置一致否则初始误差很大符号函数增益可能让速度指令瞬间饱和出现超调。我一般用MATLAB脚本先算初始关节角对应末端位置把期望轨迹的起点移到那里比如自定义轨迹函数[ x_d 0.6 0.1\cos(0.5t - \phi_0) ] [ y_d 0.4 0.1\sin(0.5t - \phi_0) ]其中 (\phi_0) 由初始末端位置的极角决定这样初始误差接近零。仿真配置里还要注意解法器是否支持信号代数环。用Unit Delay后应该没有代数环警告如果有可以再插入一个Memory模块在反馈路径上。模型里还建议把所有Scope数据记录到工作区用logsout方便后续分析。4. 仿真结果分析与调试4.1 跟踪效果怎么看仿真跑完先看末端位置跟踪曲线。把期望圆和实际轨迹画在一张图里如果轨迹重叠得比较好说明跟踪精度高。然后看关节角度曲线理想情况下是平滑曲线不应有高频分量。最后看误差曲线 (e_x)、(e_y)稳态误差应该在 (10^{-3}) 量级。还有一个关键指标是滑模面 (s) 的收敛过程。如果设计正确且增益合适(s) 会在很短时间比如0.1秒内从初始值衰减到零随后一直在零附近小幅波动。这个波动幅度取决于饱和函数边界层 (\phi) 和扰动如果波动太大说明增益设置不合理或者速度估计噪声大。4.2 抖振问题与参数调节经验最典型的问题是用符号函数时关节速度指令呈高频切换角度曲线有毛刺。这时候不要急着加大 (\lambda)先检查 (\eta) 是否过大。(\eta) 的物理意义是“对抗扰动的强度”如果模型精确、无扰动(\eta) 只需要大于系统名义部分的误差上界。在运动学级仿真里唯一的扰动是数值误差和速度估计误差(\eta) 设成 0.2~0.5 通常足够。把 (\eta) 调到 2 以上抖振会非常明显除非你故意要观察抖振。第二个常见问题是初始误差大导致速度指令饱和。我在控制器中加过饱和模块限制 (\dot{\theta}_c) 幅值在 3 rad/s 以内否则仿真早期速度会飙到几十数值发散。这个限幅不影响稳态性能但能显著提高仿真稳定性。第三个问题是速度估计用Unit Delay引入的相位滞后。滞后会导致滑模面计算不准确误差稳态值可能达不到理论精度。解决方法是在控制器里对估计的角速度做一阶低通滤波或者用Kalman滤波的简化版。不过对于学习项目Unit Delay足够让你理解问题所在。5. 常见问题速查与避坑清单5.1 高频报错与解决代数环警告反馈路径插入Unit Delay或Memory模块注意采样时间要与信号一致。MATL AB Function输出未定义函数开头给输出赋零值。仿真速度极慢积分步长太小或控制器里有高频切换可改用饱和函数并适当增大最大步长。末端轨迹发散多半是雅可比逆接近奇异或初始误差太大改用阻尼最小二乘逆并做速度限幅。Scope显示没有信号检查信号线是否连错以及MATLAB Function是否设置成了“每步更新”而不是“每帧更新”如果是变步长仿真最好把Scope采样时间设为“继承”。5.2 独家实战心得我做完这个项目后最大的体会是学习滑模控制不能只背趋近律公式一定要亲手在Simulink里改变 (\lambda)、(\eta)、(\phi)观察误差和滑模面的变化。建议你做一个对比实验其他参数不变把 (\eta) 从 0.1 调到 2看误差收敛速度变快但抖振变强然后把符号函数换成饱和函数再看抖振被抑制但稳态误差略增大。这个过程10分钟就能完成但比读十遍论文都有用。另一个心得是运动学级滑模控制只是入门真正的工业应用中滑模控制更多用在动力学层或电机电流环。但是你把运动学模型下的滑模设计逻辑理清后再去看“滑模变结构控制”的经典文献很多符号就不会那么吓人了。比如文献里的 (u u_{eq} u_{sw})等效控制项在运动学级就对应把 (s) 的导数置零求出的控制量切换项对应 (\eta \text{sgn}(s))。这套对应关系搞明白滑模控制就算真正入门了。最后再分享一个小技巧仿真结束后用MATLAB命令窗口运行plot(logsout)可以快速查看所有记录信号。如果你准备写报告或论文建议把误差均方根值也计算一下用rms(e_x)就能得到这个指标比肉眼观察更有说服力。按照上面的步骤搭好模型参数可以先按我给的初始值跑一遍然后再改动各项参数观察效果。相信我亲手调过 (s) 曲线之后“滑模”这两个字就再也不会让你犯怵了。
返回列表