☰
自抗扰控制(ADRC)仿真实例全解析:从原理到参数整定避坑指南
2026/10/22 7:56:28 网站建设 项目流程

简介:面向自动控制与电机驱动方向学习者的自抗扰控制(ADRC)Simulink仿真实例合集,既能帮助刚接触ADRC的学生建立直观认识,也为需要调试观测器和控制律的工程师提供了可直接运行的模型与对比素材。压缩包共62个文件、约67.32MB,以15篇PDF文献、7个SLX仿真模型、12个MAT数据文件为主体,另含CAJ论文、M脚本、DOCX技术文档、AVI演示录像及P文件等,目录按LESO/NESO对比、PMSM双闭环、单轴云台、磁悬浮等主题划分,便于按需查找。典型实例覆盖永磁同步电机速度与电流控制、单轴云台指向、上拉式磁悬浮等工程对象,并通过线性扩展状态观测器与非线性扩展状态观测器、fhan与fsun两种非线性控制函数的对比,展示不同扰动观测方式和非线性调节策略对控制性能的影响;配套的调参脚本、技术笔记与PMSM专题文献,可帮助读者理解ESO带宽、跟踪微分器以及抗扰性能之间的内在关系。该资源已有1715人学习,适合需要快速搭建ADRC仿真环境并系统掌握其设计方法的自动化、电气工程相关专业学生及工程师。

1. 自抗扰控制仿真实例到底“全”在哪里:一个能直接复现的参数库

自抗扰控制(ADRC)的仿真实例,网上其实不少,但真正称得上“很全”的很少:要么藏在论文里只给波形不给参数,要么给了一组参数但换一个被控对象就发散。这篇笔记把我这几年在设备控制仿真里反复验证过的 ADRC 实例按对象难度汇总起来,一阶、二阶、纯时滞、非线性对象全都有可抄的模型和参数。适合正在做控制系统仿真、打算把 PID 换成 ADRC 试水的工程师,也适合被导师丢给“自抗扰控制”课题但不知道从哪下手的初学者。看完你应该能回答三个问题:这东西到底解决什么问题,参数从哪来,仿真里最常见的翻车点怎么避开。

2. 自抗扰控制的核心逻辑:为什么模型给不准也能压住扰动

2.1 总扰动的概念:把“模型不准”变成可观测的状态

ADRC 最反直觉的一点是:它不追求精确的模型,反而故意把模型偏差当成扰动的一部分。常规 PID 是看见误差再消除误差,而 ADRC 是把“外扰 + 模型偏差 + 内部耦合”打包成一个总扰动 f,然后用扩张状态观测器把这个 f 实时估出来,在控制量里直接补偿掉。这意味着你不需要知道对象的精确微分方程,只需要知道一个大致的控制增益 b0 就行,剩下的差值全部算进总扰动里。

比如一个一阶对象实际是 dot y = 6.25 u + d,但你在控制器里写的增益是 b0 = 5,那么 1.25 u 这个偏差就会被 ESO 当成扰动的一部分估计出来。只要 ESO 收敛够快,这个偏差就不会破坏闭环稳定性。这一点和自适应控制、鲁棒控制的思路都不一样:ADRC 不调整模型参数,而是绕开模型直接估计影响。

从实用角度看,这个特性非常值钱。工业现场里你拿到的对象模型往往是辨识得到的,低频增益能对个七八成就不错了,加上执行机构老化、负载变化,模型失配是常态。ADRC 允许 b0 有偏差还能稳定工作,这比 PID 整定对工况变化的容忍度高得多。

2.2 ESO 到底在观测什么:二阶对象的扩张状态方程

扩张状态观测器的“扩张”二字,指的就是把总扰动 f 当成一个新的状态变量加进原始状态方程。以二阶对象 dot x1 = x2,dot x2 = a x1 + b x2 + b0 u + f 为例,ESO 的方程写作:

dot z1 = z2 - beta1 (z1 - y) dot z2 = z3 + b0 u - beta2 (z1 - y) dot z3 = -beta3 (z1 - y)

其中 z1 跟踪输出 y,z2 跟踪速度 x2,z3 跟踪总扰动 f。三个增益 beta1、beta2、beta3 决定观测器收敛速度和噪声放大程度。这里没有玄学,它就是 Luenberger 观测器套在扩张系统上,只不过把“标称模型”换成“标称增益 b0 + 未知扰动 f”。

注意 ESO 的输入是控制量 u 和输出 y,不依赖对象微分方程的精确参数,所以它天然适合模型不准的场合。代价是 ESO 本身有带宽限制,离散化步长太大或者物理量测噪声太强,z3 会抖得很厉害。这部分我在第 5 章避坑清单里会专门展开。

2.3 三块结构如何配合:安排过渡过程、估计扰动、误差反馈

完整 ADRC 通常由三块组成:跟踪微分器 TD、扩张状态观测器 ESO、非线性状态误差反馈 NLSEF。TD 的作用是把突变的阶跃给定变成平滑的过渡信号,避免一开始就把控制量打满;ESO 负责估计总扰动;误差反馈则对输出误差做比例和微分组合。

工程上我很少用真正的“非线性”反馈,因为非线性反馈的增益难调、离散化后容易振铃。大多数场景用线性形式就够,也就是常说的 LADRC:反馈增益只留两个系数 k1 = wc^2,k2 = 2 wc,观测器增益用 beta1 = 3 wo,beta2 = 3 wo^2,beta3 = wo^3。这里的 wc 是控制器带宽,wo 是观测器带宽。

我一般会给团队定一个默认选型标准:对象模型失配在 50% 以内、扰动变化不太剧烈、没有明显的量测噪声,全部先用 LADRC;只有要求大范围跟踪或者被控对象是明显非线性(比如带摩擦、带间隙)时才考虑加 TD 和非线性反馈。因为 LADRC 只有 wo、wc、b0 三个参数,仿真阶段一周就能摸熟,而完整 ADRC 牵扯到 TD 的速度因子和非线性参数的幂次,调参时间成倍增加。

3. 从零搭一个最小 ADRC 仿真:MATLAB 和 Python 两套可跑代码

3.1 用 MATLAB 脚本跑通一阶对象的最小 LADRC

先上一段可以直接复制进 MATLAB 的脚本,对象是一阶惯性加一个阶跃扰动。这段代码我习惯作为所有仿真的起点,换对象只改三行参数。

% adrc_minimal.m —— 一阶惯性对象的最小 LADRC 仿真 h = 0.001; % 固定步长 1ms t = 0:h:6; % 仿真 6 秒 N = length(t); K = 5.0; T = 0.8; % 被控对象 G(s) = 5/(0.8s+1) B_ACT = K / T; % 对象实际增益 6.25 b0 = B_ACT * 1.2; % 控制器故意留 20% 失配 wc = 8.0; wo = 30.0; % 控制器/观测器带宽 beta1 = 2 * wo; beta2 = wo * wo; % 一阶 ESO 两个增益 kp = wc; % 一阶反馈比例增益 x1 = 0; x2 = 0; % 对象状态:x1 是输出,x2 是扰动 z1 = 0; z2 = 0; % ESO 估计状态 u = 0; r = 1; % 控制量和阶跃给定 y_hist = zeros(1, N-1); for k = 1:N-1 d = 0.5 * (t(k) >= 2.0); % 第 2 秒加入阶跃扰动 x1 = x1 + h * (B_ACT * u + d); % 欧拉法更新对象 y = x1; e = z1 - y; z1 = z1 + h * (z2 + b0 * u - beta1 * e); z2 = z2 + h * (-beta2 * e); u = (kp * (r - z1) - z2) / b0; % LADRC 控制律 y_hist(k) = y; end plot(t(1:end-1), y_hist); grid on;

这段代码里最容易被抄错的是控制律。u = (kp * (r - z1) - z2) / b0,注意 kp 这一项也要除以 b0,这样闭环回路增益才等于 kp 本身。如果写成 u = kp * (r - z1) - z2 / b0,系统的实际闭环带宽会变成 b0 * kp,当你 b0 和真实增益偏差较大时,阶跃响应快慢会和你预期的 wc 完全对不上。这个坑出现在很多入门笔记里,调试时第一眼看响应速度不对,先回来检查这一条。

参数说明:wc = 8 意味着期望闭环时间常数约 1/8 秒,阶跃响应大概 0.5 秒进稳态;wo = 30 让 ESO 比控制器快 3 到 5 倍,才能把扰动在影响输出之前就补偿掉。b0 故意设成真实增益的 1.2 倍,用来模拟模型失配,仿真结果依然能回到给定值,说明 ESO 把差值当扰动处理了。

3.2 用 Python 对照实现:无 Simulink 环境下跑通同一套逻辑

很多团队没有 MATLAB 授权,或者只想快速验证算法,用 Python 加 numpy 就够了。代码逻辑和 MATLAB 版本完全一致,只是改成了 numpy 数组循环。

import numpy as np import matplotlib.pyplot as plt h = 0.001 t = np.arange(0, 6 + h, h) N = t.size K, T = 5.0, 0.8 B_ACT = K / T b0 = B_ACT * 1.2 wc, wo = 8.0, 30.0 beta1 = 2 * wo beta2 = wo * wo kp = wc x1, x2 = 0.0, 0.0 z1, z2 = 0.0, 0.0 u = 0.0 r = 1.0 y_hist = [] for k in range(N - 1): d = 0.5 if t[k] >= 2.0 else 0.0 x1 = x1 + h * (B_ACT * u + d) y = x1 e = z1 - y z1 = z1 + h * (z2 + b0 * u - beta1 * e) z2 = z2 + h * (-beta2 * e) u = (kp * (r - z1) - z2) / b0 y_hist.append(y) plt.plot(t[:-1], y_hist) plt.grid(True) plt.show()

跑出来的曲线应该是:0 到 2 秒输出平滑接近 1,2 秒时受扰动出现一个小低谷或小峰,然后在 0.5 秒以内回到 1。如果看不到这个特征,先检查 beta1、beta2 是不是按 wo 计算的,再看采样步长 h 和 wo 的乘积是否小于 0.2。

对比两个版本,除了语言差异外几乎没有区别。我建议仿真验证阶段先用 Python 做批量调参,因为方便写循环自动搜索 wo 和 wc;定稿后再把最终参数搬进 MATLAB 做 Simulink 联调。这样只维护一份算法逻辑,不会两边调出两套结论来。

4. 仿真实例汇总:一阶、二阶、时滞到非线性对象的关键参数

4.1 一阶惯性对象实例:参数表与波形验证点

一阶惯性对象是最简单的验证对象,适合入门,也适合快速验证 ESO 的补偿效果。典型模型是 G(s) = K / (T s + 1),状态方程 dot y = (K/T) u + f,对应一阶 LADRC:beta1 = 2 wo,beta2 = wo^2,控制律只保留比例项加扰动补偿。

对象参数KTb0 取值wcwo采样步长 h
快速小惯性50.8K/T 上下浮动 20%8300.001
慢大惯性25.0K/T 上下浮动 20%2100.001
带积分环节3036250.001

第三个例子是 G(s)=3/s,也就是对象本身带积分,这在电机转速控制里很常见。ESO 的 z2 会估计掉残余扰动,控制律同样能压住静差。验证时看两个点:第一,2 秒加阶跃扰动后输出能否在约 4 倍观测器带宽时间内恢复;第二,b0 改为真实值的 60% 和 150% 分别仿真,曲线不应该发散。

4.2 二阶位置控制实例:让系统按期望动力学走

二阶对象是机械位置控制的常见模型,比如 dot x1 = x2,dot x2 = a x1 + b x2 + b0 u + f。典型参数 a = -25,b = -2,b0 = 10,仿真里给定的阶跃目标从 0 到 1,2 秒时加一个幅值 1 的推力扰动。

这组实例必须用三阶 ESO:beta1 = 3 wo,beta2 = 3 wo^2,beta3 = wo^3。控制器用两组反馈系数:k1 = wc^2,k2 = 2 wc。控制律写成:

u = (k1 (r - z1) + k2 (0 - z2) - z3) / b0

其中 z2 是速度估计,给定速度通常是 0,所以直接写成 k2 * (0 - z2)。如果直接忽略掉速度反馈,系统会变成欠阻尼,阶跃爬升慢而且容易超调。验证时加一个尖峰扰动,观察 z3 的估计波形,应该能在输出还没明显变化时就出现一个反向补偿脉冲,这就是 ESO 的前馈效果。

参数锚点我通常给 wc = 6,wo = 3 * wc,也就是 wo 取 18。如果对象本身阻尼很弱,比如 b = 0,wc 要降到 4 左右;如果阻尼强,wc 可以放到 10。位置控制里最忌讳一上来把 wc 拉到 10 以上,二质量系统在 10 赫兹以上会出现结构谐振,ESO 会把谐振也当成扰动硬补,效果反而更抖。

4.3 带纯时滞的对象实例:能控但有边界

时滞是 ADRC 最容易让人误判的场景。模型写成 G(s) = e^{-tau s} * K / (T s + 1),比如 tau = 0.5,K = 5,T = 0.8。用同一组一阶 LADRC 参数仿真的话,wc = 8 会直接振荡。原因不是 ESO 失效,而是 ESO 根据当前输出估计扰动,但扰动经过时滞才反映到输出上,ESO 看到的“当前扰动”其实是 0.5 秒之前的,补偿时机晚了。

时滞 tauwc 上限参考wo 参考现象
0.1830接近无时滞效果
0.52.515有小超调,能稳定
1.01.28响应慢,但优于同带宽 PID

我的处理习惯是:tau 不超过对象时间常数的 20% 时,ADRC 直接用;tau 大到和 T 同量级时,必须降低 wc,并把仿真中的阶跃给定改成斜坡,否则控制量一开始就会大幅摆动。更激进的做法是搭配 Smith 预估器,但那是另一个方案,不是 ADRC 默认配置。仿真实例里我一般先对比“低带宽 ADRC”和“低带宽 PID”,结论通常是 ADRC 恢复扰动更快,但在大时滞下优势明显缩水。

4.4 非线性与模型失配实例:ESO 的补偿上限在哪里

非线性实例最能体现 ADRC 的价值。常见的是二阶系统加上库仑摩擦:dot x2 = a x1 + b x2 + b0 u - 2 * sign(x2) + d。其中 sign(x2) 产生的摩擦力矩是状态相关的非线性,传统线性 PID 在低速跟踪时会出现极限环振荡。

用同一个三阶 LADRC,参数维持 wc = 4,wo = 16,不需要针对摩擦专门建模。观察 z3 的波形,它会稳定在一个接近负 2 的均值附近,这就是 ESO 把摩擦辨识成常值扰动并完成补偿。输出曲线的表现是:最终没有静差,低速时不再爬行。这里可以明显看到“模型给不准也能控”的实际意义。

另一个更苛刻的边界是 b0 本身变化。比如真实增益在 8 和 12 之间跳变,而控制器固定 b0 = 10,这种情况 ESO 能补偿缓慢变化,但如果增益每 0.1 秒跳变一次,ESO 带宽跟不上,输出就会明显波动。遇到这场景我没有捷径,要么提高 wo 到极限,要么改成在线辨识 b0,单纯靠 ESO 硬扛是不行的。仿真里可以这样设计:把 b0 的跳变周期设成 0.5 秒,观察 z3 和输出的变化幅度,你就摸到 ADRC 的补偿上限了。

5. 仿真实战避坑清单:5 条让结果变形的隐藏问题

5.1 现象:一上仿真就发散,波形直接炸到 1e6 量级

原因基本是采样步长 h 与 ESO 带宽 wo 的乘积超过了数值稳定性边界。欧拉法离散 ESO 时,稳定性要求 wo * h 小于大约 0.3。wo 取 30 时 h 必须小于 0.01,很多人图省事直接把 Simulink 默认步长记在 0.01 以上,配上 wo = 50,一跑就发散。解决办法是先定 h,再反推 wo 上限,我一般要求 wo * h <= 0.1,留三倍裕量,这样 z3 也不会因为离散误差抖动。

5.2 现象:ESO 估计的 z3 明显滞后实际扰动,补偿总慢半拍

滞后通常来自 wo 太低,或者量测输出经过了一阶滤波。如果你在反馈通道加了低通滤波,滤波时间常数为 0.02 秒,而 wo 是 20,滤波器的相位延迟已经超过 ESO 的响应速度,z3 自然跟不上。解决方法是把滤波器的截止频率设到 5 倍 wo 以上,或者把滤波器模型也引入 ESO 的参考对象,让它知道自己观测的是滤波后的输出。真实工程里没有“无滞后测量”,做仿真时加滤波器再调参比直接不加滤波更接近实际。

5.3 现象:控制量高频振荡,但输出波形看着还行

常见原因是 g 或者是非线性反馈里的指数幂放大了噪声。线性 LADRC 场景下,通常是 wo 取太高,ESO 把量测噪声当成了扰动在补偿。比如 wo = 100 配上 h = 0.001,理论上稳定,但加入白噪声后 z3 的方差会放大到上百,控制量就像锯齿一样。解决办法是先画 z3 波形,如果 z3 抖成随机噪声形状,就降低 wo,直到 z3 只能看到阶跃扰动、看不到噪声为止。记住:观测器不是越快的越好,够用就行。

5.4 现象:阶跃响应超调很大,但改小 wc 又变慢

这是典型的没有配 TD 或者过渡过程没有限制控制量变化率。ADRC 在线性范围内能直接把误差拉回来,但对象有执行机构饱和时,控制量一旦顶到上限,闭环就变成开环,超调随之而来。解决办法是在仿真里加入饱和模块,并且把 ESO 输入 u 取成饱和后的实际控制量,而不是控制器输出的原始控制量。如果加了饱和仍超调,就把给定信号从阶跃换成斜坡或者安排过渡过程,这是 TD 存在的意义,不是 ADRC 的缺陷。

5.5 现象:同一组参数,Simulink 跑的和手写脚本跑的结果对不上

原因基本是求解器差异。手写脚本是固定步长欧拉法,Simulink 默认变步长可能是 ode45,两者的局部误差和离散误差不一样,特别是 ESO 这种强耦合系统,波形形状可能一样但超调量差 2% 到 3%。解决方法是把 Simulink 求解器强制改成固定步长离散求解器,并设置与手写脚本相同的 h,对比前先统一离散化方式和步长。这个坑看起来小,实际上一卡就是半天,我见过有人因此误判参数鲁棒性,白白浪费了一周的时间。

6. 参数整定的进阶技巧:用带宽法快速锚定一组可用参数

1.1 从期望响应时间反推 wc,再用倍数关系套 wo 和 b0

带宽法的核心是三个参数不孤立地调。先确定闭环想要的调节时间 Ts,按经验取 wc = 4 / Ts,比如希望 0.8 秒进稳态,wc 就是 5;然后 wo 直接取 3 到 5 倍的 wc,先别管最优,先用 3 倍跑出第一个曲线。b0 则是被你控对象物理模型给出的名义增益,一般取辨识值或者铭牌值,偏差 50% 以内都允许。注意这里有个反直觉的约束:wo 越大补偿越快,但采样步长、量测噪声、对象未建模动态都会限制它,所以 wo 的上限不是由性能决定,而是由系统里最薄弱的环节决定。实际仿真里我习惯把 wo 逐步翻倍直到控制量出现抖动,然后退回一半作为最终值,这比理论计算更快。参数整定的顺序是:定 b0,标 wc,再拉 wo,最后回头调 b0 的 20% 微调。不要反着来,反着调会陷入毫无边界的搜索循环。

1.2 一套仿真验证套路:阶跃加扰动联合实验,测三个指标

不要只跑一个阶跃响应就宣布参数可用。我的习惯是每调一组参数就跑三个实验:第一是 0 到 1 的阶跃,记录超调量、峰值时间和调节时间;第二是在 2 秒时加入一个已知幅值的阶跃扰动,记录输出最大偏差和恢复到 5% 误差带的时间;第三是把 b0 改成原始值的 0.7 倍和 1.4 倍分别再跑前两个实验,对比曲线差异。三组实验都通过,才敢说这组参数有工程意义。我最后一次在模拟项目X里调位置环,把 wc 从 8 拉到 10 时阶跃曲线很好,但扰动恢复时间翻倍,原因就是 wo 跟不上新的 wc,后来把 wo 从 25 提到了 35 才两难全解。这件事让我养成了习惯:任何参数改动都至少跑一次扰动实验,不要只看阶跃波形。仿真阶段代价为零,这部分花的时间最后都会在联调阶段省回来。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询