☰
参数不确定二阶系统的自适应滑模控制:Matlab仿真全流程
2026/10/9 4:09:36 网站建设 项目流程

最近在一个带不确定参数的二阶非线性系统上做控制仿真,把自适应滑模控制方案用 Matlab 完整跑了一遍。这个题目看起来像是教材里的经典命题,但真正落地的坑不少:自适应增益选多少、滑模切换项怎么处理、参数估计为什么不收敛,这些代码里都能体现出来。这篇文章就围绕项目本身,把方案设计、稳定性思路、完整仿真代码和实测过程中踩过的坑一次性讲清楚。

1. 项目简介:什么时候会用到自适应滑模控制

1.1 参数不确定性从哪来

实际工程里的被控对象,参数几乎不可能被精确测量。机械臂的惯量会随着负载变化,电机驱动器的摩擦系数会随着温度漂移,飞行器的气动系数更是随着姿态和速度变化。所谓“参数不确定”,就是指数学模型的结构已知,但里面的系数不知道精确值。例如一个二阶系统写成

[ \ddot{x} = \theta_1 x^2 + \theta_2 \sin(x) + \theta_3 x + g u + d(t) ]

这里 (\theta_1, \theta_2, \theta_3) 是未知常数,(g) 是已知控制增益,(d(t)) 是集总干扰。这种模型在倒立摆、单关节机械臂、部分机电系统中非常常见。

传统控制方法遇到这种问题会有点尴尬。如果直接把所有参数当作标称值,模型失配会让闭环性能下降,严重时直接发散。如果采用滑模控制,设计者通常需要知道不确定项的界,而这个界往往要靠经验和反复试验去凑。

1.2 自适应控制和滑模控制各自的短板

自适应控制擅长在线调整未知参数,核心思想是根据跟踪误差实时更新参数估计值,让控制器逐渐“适应”被控对象。但纯自适应控制对外部干扰和未建模动态比较敏感,如果扰动的幅值突然变大,参数更新律可能会把估计值带偏。

滑模控制擅长处理系统的不确定性和外部扰动,通过让状态进入并保持在滑模面上,实现对外界干扰的不敏感。但传统滑模控制需要知道不确定项的上界,上界取得太小,鲁棒性不够;上界取得太大,控制量抖动严重,执行器容易疲劳受损。

自适应滑模控制就是把两者组合起来:用自适应律在线估计未知参数,降低对参数上界的依赖;用滑模项补偿残差扰动,保证系统的鲁棒性。

1.3 这个项目适合谁参考

如果你是正在学现代控制理论的学生,或是在做欠驱动系统、机械臂轨迹跟踪、电机位置控制的工程师,这个项目可以直接当作入手模板。它不涉及过深的数学推导,但把自适应滑模从设计到仿真的完整链路走了一遍。代码结构也保留了扩展空间,后续无论你要改成高阶系统、加执行器饱和还是换其他趋近律,都能在这个骨架上改。

2. 控制方案设计:滑模面、趋近律和自适应律如何配合

2.1 被控对象与前提假设

仿真采用的被控对象为:

[ \dot{x}_1 = x_2 ]

[ \dot{x}_2 = \theta_1 x_2^2 + \theta_2 \sin(x_1) + \theta_3 x_1 + g u + d(t) ]

其中 (d(t) = 0.2\sin(3t)),幅值有界;真实参数取

[ \theta_1 = 0.5, \quad \theta_2 = -1.2, \quad \theta_3 = 0.8, \quad g = 2 ]

控制器只知道系统结构,不知道具体的 (\theta)。这里的前提假设有三条:参数是慢时变或常值;控制增益 (g) 已知且符号已知;外部扰动有界。这三条做工程仿真基本够用,真要做实物实验还需要再加执行器动态和测量噪声。

2.2 滑模面的设计思路

定义跟踪误差:

[ e = x_1 - y_d ]

其中 (y_d) 是期望轨迹。取滑模面:

[ s = \dot{e} + \lambda e ]

(\lambda) 是一个正数,它的作用是把跟踪误差和误差变化率融合成一个标量。当 (s) 收敛到 0,误差动态就变成一阶线性系统 (\dot{e} = -\lambda e),误差以指数速度收敛。因此 (\lambda) 决定了跟踪误差的“带宽”,选得越大收敛越快,但也会放大噪声。

滑模面的初始值和期望轨迹密切相关,如果初始误差很大,刚开始 (s) 会很大,控制器输出容易饱和,所以仿真初始状态我取得不大。

2.3 趋近律与控制器推导

为了让 (s) 快速收敛,并对外部扰动保持鲁棒性,采用指数趋近律加上切换项的经典形式:

[ \dot{s} = -k s - \eta ,\text{sign}(s) ]

(k) 决定滑模趋近段的收敛速度,(\eta) 用于压制扰动的有界幅值。对 (s) 求导得到:

[ \dot{s} = \ddot{x}_1 - \ddot{y}_d + \lambda(\dot{x}_1 - \dot{y}_d) ]

代入系统动态并假设参数估计值为 (\hat{\theta}),控制器设计为:

[ u = \frac{1}{g} \left[ -\hat{\theta}^T \phi(t) + \ddot{y}_d - \lambda \dot{e} - k s - \eta ,\text{sign}(s) \right] ]

其中 (\phi(t) = [x_2^2, \sin(x_1), x_1]^T) 是回归向量。把控制律代回滑模面导数,得到闭环动态:

[ \dot{s} = -\tilde{\theta}^T \phi(t) + d(t) - k s - \eta ,\text{sign}(s) ]

其中 (\tilde{\theta} = \hat{\theta} - \theta) 是参数估计误差。如果参数估计不更新,滑模项只能补偿总不确定性的上界,一旦 (\eta) 不够大,稳态误差就会明显。自适应律的任务就是把 (\tilde{\theta}) 压下去,减轻滑模项的压力。

2.4 自适应律的导出过程

构造 Lyapunov 函数:

[ V = \frac12 s^2 + \frac12 \sum_{i=1}^{3} \frac{1}{\gamma_i} \tilde{\theta}_i^2 ]

其中 (\gamma_i) 是自适应学习率。对时间求导:

[ \dot{V} = s \dot{s} + \sum_{i=1}^{3} \frac{1}{\gamma_i} \tilde{\theta}_i \dot{\hat{\theta}}_i ]

把闭环滑模动态代进去,整理后能看出,如果取自适应律为:

[ \dot{\hat{\theta}} = \gamma \cdot s \cdot \phi ]

那么参数误差项与 (s \tilde{\theta}^T \phi) 互相抵消,Lyapunov 导数变为:

[ \dot{V} = -k s^2 - \eta |s| + s d(t) \le -k s^2 - (\eta - d_{\max}) |s| ]

只要满足 (\eta > d_{\max}),(\dot{V}) 负定或半负定,闭环系统稳定,滑模面收敛,跟踪误差进入可接受的边界层。从这个推导能很直观地看出,自适应项抵消了参数不确定性,切换项只负责剩余的扰动。这样的分工让控制器在参数严重不确定时仍然好用。

3. Matlab 仿真实现:完整代码与参数选择方法

3.1 主程序与系统函数的代码结构

整个仿真只需要一个主脚本和一个系统函数,我用ode45求解,代码结构如下。

主脚本main_asmc.m:

clear; clc; close all; % 被控对象真实参数(仅仿真用,控制器未知) g = 2; theta_true = [0.5; -1.2; 0.8]; % 控制器设计参数 lambda = 5; % 滑模面系数 k = 8; % 趋近律线性增益 eta = 2; % 切换项增益,需大于干扰幅值 gamma = [2; 2; 2]; % 自适应学习率,逐分量设置 % 初始状态: x1, x2, theta_hat1, theta_hat2, theta_hat3 x0 = [0.3; -0.2; 0; 0; 0]; % 仿真时间 Tsim = 15; % 求解闭环系统 options = odeset('MaxStep', 0.01); [t, X] = ode45(@(t, x) asmcSystem(t, x, g, theta_true, lambda, k, eta, gamma), ... [0 Tsim], x0, options); % 提取状态 x1 = X(:,1); x2 = X(:,2); theta_hat1 = X(:,3); theta_hat2 = X(:,4); theta_hat3 = X(:,5); % 期望轨迹及其导数 yd = 0.5 * sin(t); ydot = 0.5 * cos(t); yddot = -0.5 * sin(t); % 跟踪误差与滑模面 e = x1 - yd; edot = x2 - ydot; s = edot + lambda * e; % 根据控制律反算控制量,便于画图 u = zeros(size(t)); for i = 1:length(t) theta_hat = [theta_hat1(i); theta_hat2(i); theta_hat3(i)]; phi = [x2(i)^2; sin(x1(i)); x1(i)]; u(i) = (1/g) * (-theta_hat' * phi + yddot(i) ... - lambda * edot(i) - k * s(i) - eta * tanh(s(i)/0.05)); end % 绘图 figure(1); subplot(2,1,1); plot(t, yd, 'k--', t, x1, 'b-', 'LineWidth', 1.5); legend('期望轨迹', '实际轨迹'); title('轨迹跟踪效果'); grid on; subplot(2,1,2); plot(t, e, 'r-', 'LineWidth', 1.5); title('跟踪误差 e'); xlabel('t/s'); grid on; figure(2); subplot(3,1,1); plot(t, theta_hat1, 'b-', 'LineWidth', 1.2); hold on; plot(t, theta_true(1) * ones(size(t)), 'r--', 'LineWidth', 1.2); ylabel('\theta_1 估计值'); legend('估计值', '真实值'); grid on; subplot(3,1,2); plot(t, theta_hat2, 'b-', 'LineWidth', 1.2); hold on; plot(t, theta_true(2) * ones(size(t)), 'r--', 'LineWidth', 1.2); ylabel('\theta_2 估计值'); legend('估计值', '真实值'); grid on; subplot(3,1,3); plot(t, theta_hat3, 'b-', 'LineWidth', 1.2); hold on; plot(t, theta_true(3) * ones(size(t)), 'r--', 'LineWidth', 1.2); ylabel('\theta_3 估计值'); xlabel('t/s'); legend('估计值', '真实值'); grid on; figure(3); plot(t, u, 'b-', 'LineWidth', 1.2); title('控制输入 u'); xlabel('t/s'); grid on;

系统函数asmcSystem.m:

function dx = asmcSystem(t, state, g, theta_true, lambda, k, eta, gamma) x1 = state(1); x2 = state(2); theta_hat = state(3:5); % 期望轨迹及其导数 yd = 0.5 * sin(t); ydot = 0.5 * cos(t); yddot = -0.5 * sin(t); % 误差与滑模面 e = x1 - yd; edot = x2 - ydot; s = edot + lambda * e; % 回归向量 phi = [x2^2; sin(x1); x1]; % 自适应滑模控制律 u = (1/g) * (-theta_hat' * phi + yddot - lambda * edot ... - k * s - eta * tanh(s/0.05)); % 外部扰动 d = 0.2 * sin(3 * t); % 系统动态 x1dot = x2; x2dot = theta_true' * phi + g * u + d; % 自适应律 theta_hat_dot = gamma .* (s .* phi); dx = [x1dot; x2dot; theta_hat_dot]; end

把两个文件放到同一个目录下,直接运行main_asmc.m就能得到全部曲线。代码里我用了tanh(s/0.05)代替sign(s),目的是减少滑模切换带来的数值抖动,这个细节后面还会单独讲。

3.2 控制器参数怎么选

参数选取是这类控制仿真里最容易被忽略的部分。我的经验是,每个参数都有明确物理作用,不要盲目乱试。

lambda决定闭环误差动态的收敛速度。你可以把它理解为“期望误差的虚拟极点”,如果跟踪误差收敛过慢,就增大lambda;但取得太大,控制量初始幅值会很高,容易激活执行器饱和。常规范围是 2~20,仿真中取 5。

k是趋近律中的线性项增益,它控制滑模面从初始位置向原点收敛的速度。k越大,系统进入滑模面越快,但控制输入也越大。取 8 是因为在仿真对象中,这个值已经能让滑模面在大约 1 秒内收敛。

eta是最关键也最容易选错的参数。它必须大于外部扰动的上界,否则无法保证滑模面收敛。但eta过大会导致控制量高频大幅切换,系统输出会出现明显的抖振。实测中我比较推荐“先用小扰动测试最小eta,再留 30% 裕量”的方式。

gamma是自适应律的学习率。学习率太小,参数估计收敛慢,初期跟踪误差大;学习率太大,参数估计会震荡,控制系统可能失稳。我遇到最稳妥的方法是先用较小的gamma(0.5~1)跑一次,看估计曲线是否单调上升,再逐步加大。

3.3 仿真结果如何解读

运行代码后可以看到三张图的典型结果。

跟踪效果图中,实际轨迹在大约 1 秒内贴合期望轨迹,之后几乎重合。稳态跟踪误差维持在 (10^{-3}) 量级,这个误差主要来自切换项的连续化近似和自适应参数的有界残差。

参数估计图最能说明问题:三个参数从初始零值开始,经过一段过渡过程后进入稳定状态。注意,它们并不一定收敛到真实值,尤其是theta_hat2和theta_hat3,主要是因为正弦期望轨迹提供的激励不够充分,回归向量之间不满足持续激励条件。这是自适应控制中的固有现象,跟踪性能仍然很好,因为控制器需要的是“组合起来的补偿效果”,而非估计值本身准确。

控制输入曲线在刚开始比较大,进入滑模阶段后呈现出带状波动,这是滑模控制的典型特征。把tanh(s/0.05)改成sign(s)后,这个带会变得非常密集,仿真时间也会成倍增加,实际应用时这个折中很有必要。

4. 实操中遇到的常见问题与排查技巧

4.1 符号函数引起的抖动问题

第一次跑仿真时,我直接用sign(s)做切换项,结果ode45在滑模面附近反复调整步长,仿真跑了很久,控制输入像密集的锯齿波。

原因很直接:理想的滑模控制要求以无限频率切换,数值求解器面对这种不连续动态时会在每个切换点附近切碎步长。解决办法就是连续化近似。工程上用饱和函数或者双曲正切函数替换符号函数,我在代码里用的是:

u_switch = eta * tanh(s / 0.05);

这里的 0.05 是边界层厚度。边界层越厚,控制越平滑,但跟踪稳态误差会变大。如果你对稳态误差要求很高,可以把这个值再调小,比如 0.01;如果执行器动作太频繁,就适当调大。

如果必须在实物上跑,强烈建议用基于边界层的准滑模或者高阶滑模,单纯靠连续化近似只能缓解,无法彻底消除系统对高频切换的依赖。

4.2 参数估计为什么不朝真实值收敛

很多初学者跑完仿真会疑惑:参数估计曲线明明稳定了,为什么跟真实值还有偏差?我在前面说过,这是缺乏持续激励导致的。

自适应律 (\dot{\hat{\theta}} = \gamma s \phi) 本质上是在做在线梯度下降,只有当回归向量 (\phi) 的所有分量都随时间充分变化,才能保证参数收敛到唯一值。如果期望轨迹是单一频率的正弦信号,(\sin(x_1)) 和 (x_1) 之间容易近似相关,激励不充分,估计值就会停留在某些组合方向。

实际工程里,如果参数估计值本身有物理含义,比如需要在线识别惯量或摩擦系数,那就要给参考轨迹增加频率成分,或者额外注入激励信号。如果只是为了保证跟踪性能,那么“估计值不完全准确但闭环性能好”是可以接受的结果,没必要为了偏差焦虑。

4.3 自适应律发散与参数漂移问题

仿真时间拉长到 30 秒以上时,我遇到过参数估计缓慢漂移的情况。原因是回归向量和误差之间出现了微弱的相关性,再加上数值积分误差,参数估计像“温水煮青蛙”一样慢慢偏离。

解决这个问题有两种常见手段。第一种是泄漏项法,把自适应律改成:

[ \dot{\hat{\theta}} = \gamma s \phi - \sigma \hat{\theta} ]

其中 (\sigma) 是一个很小的正数,作用是当参数估计太大时强制拉回来,代价是跟踪误差会稍微变大。第二种是投影算子法,给参数估计值设定上下界,当估计值越界时停止更新或修正方向。第二种方法更适合参数物理意义明确的场景。

我做仿真时没有加泄漏项,因为 15 秒内漂移不明显,但如果你要验证长时间运行的稳定性,建议老老实实加上。

4.4 从二阶系统扩展到更复杂的对象

这个代码骨架上还可以做很多扩展。如果你要控制机械臂,把回归向量换成 Lagrange 模型对应的动力学项即可。如果控制增益 (g) 也是未知的,自适应律里就需要增加对 (g) 的估计,同时注意保证估计值不穿越零点。如果系统自带执行器饱和,控制律里还要加抗饱和补偿项,否则滑模面收敛性能会明显下降。

我自己实测的时候,最常用的扩展是把ode45换成离散时间格式,用固定步长欧拉法或四阶定步长方法。滑模控制在离散实现中会有固有抖振,工程上通常结合边界层和干扰观测器去处理。

5. 一些实测体会

整个项目做下来,我对自适应滑模控制最深的体会是,数学推导和仿真实现之间的距离往往比想象中要远。Lyapunov 分析只解决了稳定性问题,真正落地时要处理数值抖动、参数激励不足、控制器饱和这些工程问题。尤其是eta和gamma两个参数,理论上有界条件是“大于扰动的上界”“足够小的学习率”,但具体数值只能靠仿真迭代去摸。

如果你刚开始接触这个方向,建议先把我给的代码原样跑通,再按自己的需求修改期望轨迹和真实参数,观察参数估计的变化。等你理解了每个参数对曲线的直观影响,再去做倒立摆或机械臂的严格建模。这个学习路径我实测下来比较有效,比一上来就啃高维系统的推导要顺畅得多。

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

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

立即咨询