news 2026/10/22 10:02:41

ADRC二阶仿真实践:LESO脚本、Simulink模型与Bode图调试指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ADRC二阶仿真实践:LESO脚本、Simulink模型与Bode图调试指南

简介:面向自动控制学习者与研究人员的ADRC二阶系统仿真资料,围绕自抗扰控制理论,重点演示扩展状态观测器(ESO)与Bode图分析在二阶系统中的应用。压缩包共5个文件,涵盖MATLAB脚本与Simulink模型(mdl、slx):m脚本覆盖ADRC/ESO算法实现及Bode图绘制程序,mdl/slx文件用于搭建二阶系统仿真模型,整体仅41KB,轻量易用。目前已有809人学习浏览。通过学习该案例,读者可从二阶系统建模、ESO参数整定到控制器设计形成完整认知,掌握利用ADRC抑制内外扰动、提升响应速度的仿真方法,并为后续机械、电气或航空航天等领域的工程实践提供可复用的分析工具。

1. 一套能跑的ADRC二阶仿真:LESO脚本、Bode图与两个Simulink模型

ADRC二阶仿真,最怕的不是看不懂理论,而是拿到模型后第一步就报错。这套压缩包恰好给出了一组完整可复现的组合件:两个Simulink模型(Motion_acc03.mdl、acc_2003.slx)配合三个MATLAB脚本(acc2003.m、LESO_step.m、LESO_bode.m),把扩张状态观测器的阶跃响应和Bode图都补齐了。它适合正在做ADRC课程设计、想快速跑通二阶对象闭环的学生,也适合那些想用Bode图验证观测器带宽、不把参数整定当玄学的从业者。整包不依赖额外工具箱,基础MATLAB/Simulink环境就能跑,重点是把二阶对象、LESO和控制律三块串成一条能对照理论公式的链路。

2. 拆开压缩包:五个文件的角色、入口顺序与Simulink模型驱动逻辑

拿到压缩包后先别急着双击.slx。这套文件里有模型、有脚本,谁先谁后直接决定你能不能跑出结果。以我拆老项目压缩包的习惯,第一步永远是列一张文件清单,标清楚每个文件的职责和入口,避免在某个旧模型上浪费时间。

2.1 五个文件分别负责什么:从.mdl到.m的分工表

文件类型在整套资源里的角色
Motion_acc03.mdlSimulink模型(旧版文本格式)二阶对象与ADRC闭环回路,适合查看模块连接关系
acc_2003.slxSimulink模型(新版压缩格式)与.mdl功能对应的可运行模型,通常优先打开它
acc2003.mMATLAB初始化脚本预置对象参数、控制器带宽、LESO增益到工作区
LESO_step.mMATLAB脚本用连续时间状态方程单独跑LESO,看扩张状态对扰动的估计
LESO_bode.mMATLAB脚本绘制LESO或闭环回路的Bode图,校验带宽与裕度

模型文件负责搭回路,脚本负责给参数和出图。Motion_acc03.mdl和acc_2003.slx大概率是同一套仿真在不同Simulink版本下的两种存档格式,前者是旧版文本格式,后者是新版打包格式。如果你的环境是R2012a之后的版本,直接跑.slx即可;若打开.mdl报版本不支持,也不用慌,另存为.slx或按模型文本重建都行。

2.2 入口顺序:哪些文件先跑,哪些文件自动加载

我一般会按“初始化脚本→Simulink模型→独立验证脚本”的顺序来复现。核心原因是.mdl和.slx里的参数通常不是写死的,而是通过工作区变量引用。比如模型里的增益块可能写的是b0、kp、beta1这样的名字,变量必须由acc2003.m一次性写入工作区。

%% 拆包后的执行顺序(常见做法) acc2003; % 一次性执行初始化,灌入对象与ADRC参数 open_system('acc_2003'); % 打开模型,或直接双击 .slx

这段代码逻辑很简单,但很多人会栽在第一句上。直接在MATLAB当前目录打开模型,而不先执行acc2003.m,模型里的变量全是空的,点了仿真直接报未定义变量。我自己的习惯是尽量不靠手动执行脚本,而是在模型属性里写一个PreLoadFcn回调,把初始化脚本接到模型加载事件上,后面每次打开都不会忘。

2.3 .mdl与.slx新旧格式:什么时候用哪一个

判断依据很简单:你的MATLAB版本能不能直接打开、有没有兼容提示。旧版.mdl是纯文本格式,遇到高版本Simulink有时会有兼容警告,但好处是diff非常方便,改动一个增益可以直接在文本里看到;.slx是二进制压缩格式,体积小、加载快,但没法肉眼读diff。若你只是复现仿真结果,用.slx;若你想看清模块如何连接、或需要给模型做版本迁移,先用.mdl打开文本内容会更直观。

Simulink模型里的代数环是另一个隐藏入口问题。ADRC控制器里LESO的输出z3会反馈到控制律,控制律又去驱动对象,如果模型的连续块之间没有积分环节隔开,求解器容易形成代数环。遇到这类情况,常见做法是在反馈通路里加一个极小时间常数的一阶惯性环节,或者让LESO的离散版本使用单位延迟。

2.4 连续域与离散域的选择:先分清再复现

这包文件里的.mdl名称带Motion_acc03,看起来是连续域对象模型。连续域的好处是理论推导直接对得上LESO方程,但实际部署时控制器几乎都是离散实现的。复现时如果发现仿真步长必须设到1e-4以下才能稳定,说明模型里可能存在高频动态,这时候要么把LESO也离散化,要么改用ode15s,不要死磕ode45。两者换一下求解器,结果往往就稳定了。

3. 二阶对象接入ADRC:模型结构、LESO方程与参数初始化脚本

ADRC的核心不是把PID换一组新增益,而是把对象看成“二阶积分串联加总扰动”。这一步决定了你在Simulink里看到的对象模型到底该怎么画,也决定了LESO为什么要做成三维状态。

3.1 二阶系统的数学模型与“总扰动”的观测器视角

二阶对象最常见的形式是\ddot{y}=f+b0*u,其中f包含模型不确定性和外部扰动。若被控对象是质量-弹簧-阻尼,它可以写成J*\ddot{θ}=u-c*\dot{θ}-k*θ+d,归一化后就变成\ddot{y}=f+b*u。ADRC不追究f的具体表达式,而是把它当成第三个状态,用LESO在线估出来,最后在控制律里减掉。

这一视角的工程意义在于:不需要精确建模,也不需要扰动模型,只要b0的符号和大致量级对,LESO就能把剩余误差和扰动一起补偿掉。Simulink里搭模型时,对象部分用传递函数块或者积分器搭积分链都可以。我推荐用积分器搭,因为观察中间状态更方便,也方便给LESO引出y_dot的参考信号。

3.2 acc2003.m参数初始化:带宽比和b0怎么设

初始化脚本是整套资源的“总闸”。参数整定的顺序我习惯固定为:先定对象工况、再定控制器带宽ωc、再定观测器带宽ωo、最后微调b0。这里的顺序不能反过来,因为观测器带宽依赖控制器带宽,而b0的误差容忍度由观测器带宽兜底。

%% acc2003.m 参数初始化(对照常见ADRC二阶设置) % 二阶对象: G(s) = k / (s^2 + a*s),k为增益,a为阻尼项系数 k = 2.0; % 对象稳态增益 a = 1.5; % 对象阻尼项系数 b0 = 2.0; % 控制增益估计值,允许与实际增益有偏差 wc = 5; % 控制器带宽,单位 rad/s,决定跟踪速度 wo = 25; % 观测器带宽,通常取 wc 的 5~10 倍 kp = wc^2; % 控制律比例增益 kd = 2*wc; % 控制律微分增益 beta1 = 3*wo; % LESO 增益 β1 beta2 = 3*wo^2; % β2 beta3 = wo^3; % β3

这里最关键的是b0。它的含义是你对“控制输入到二阶加速度”的增益估计。ADRC对b0的误差有一定容忍度,b0偏大容易引起振荡甚至发散,b0偏小则补偿不足、扰动抑制变慢。符号必须和实际对象一致,这一点没有商量余地。ωo和ωc的比例也不是越大越好,观测器带宽大了,高频测量噪声会被放大,Bode图上会看到明显的高频抬升。

3.3 Simulink里控制器与观测器的连接关系

在模型里,ADRC通常会体现为三个相互连接的子结构:对象、LESO、控制律。对象输出y接到LESO的输入,LESO三个输出z1、z2、z3分别代表估计的y、估计的导数、估计的扰动。控制律用的是u=(kp*(r-z1)-kd*z2-z3)/b0。注意,控制律减的z3是LESO对总扰动的估计,不是真实扰动。许多人在模型里把z3直接加到对象内部去抵消扰动,这种画法在Simulink里也能仿真,但会掩盖观测器收敛过程,不利于分析。建议保持“对象不含补偿、补偿只在控制律”的经典结构。

我还会特意在模型里加两个To Workspace块,把y和控制量u导出来,方便和LESO_step.m的结果做交叉对比。若模型里已经带了Scope,也可以不改,但To Workspace的数据更便于做数值指标计算。

另一个常见细节是LESO阶数和对象阶数的关系。二阶对象需要估计的状态是位置、速度和总扰动,所以LESO是三维的,极点配置在同一个实极点-ωo上。如果对象是二阶而你把LESO也写成二阶,那就只能估计两个状态,扰动完全没有观测通道,控制律里的z3也就不存在,整个ADRC退化成状态反馈加积分。判断LESO结构是否正确,最简单的方法是看LESO_step.m里状态变量是不是三个。

4. 运行LESO_step.m:看扩张状态观测器怎样估计总扰动

LESO_step.m是我觉得整个压缩包里最值得先跑的文件。它不依赖Simulink,把LESO方程直接放在MATLAB脚本里用求解器跑,能很清楚地看到“扰动是怎么被估计出来的”。对新手来说,这个文件比模型更容易读懂。

4.1 脚本的仿真逻辑与代码骨架

LESO_step.m的核心逻辑是构造一个包含被控对象和观测器的连续时间状态方程,然后用ode45数值积分。常见做法是把对象真实模型写成一个函数,把LESO写成另一组微分方程,最终合成一个状态向量。

%% LESO_step.m 核心骨架(数值验证用) % 状态定义: [y, dy, f, z1, z2, z3] function dx = leso_demo(t, x, b0, beta) y = x(1); dy = x(2); ft = 0.5*sin(2*pi*0.3*t) + (t>=2); % 扰动: 正弦+阶跃 u = 0; % 开环观测模式 dx(1) = dy; dx(2) = b0*u + ft; % 对象真实模型 dx(3) = 0; % 真实扰动变化率 e = x(1) - x(4); % LESO输出误差 dx(4) = x(5) + beta(1)*e; dx(5) = x(6) + beta(2)*e + b0*u; dx(6) = beta(3)*e; end

脚本里把对象和观测器写在同一个函数里,直接比较z3和真实f的时间序列。这个写法有个好处:对象和观测器可以共用一个输入u,完全模拟闭环里“LESO只拿到y和u”的信息流。参数beta通常由wo按乘积关系生成。看到z3曲线逼近ft曲线时,就说明LESO的扩张通道设计对了。

4.2 怎么看收敛:稳态误差、恢复时间、峰值毛刺

判断LESO调得好不好,不要只看最后稳态。三个指标我每次都会导出来:扰动发生后的恢复时间、稳态误差、扰动瞬间的峰值偏差。观测器带宽wo从10调到30,恢复时间会明显缩短;但如果你把噪声加进测量输出,会发现wo越高,y毛刺越大。这就是观测器设计和噪声抑制的天然矛盾,也是后面LESO_bode.m要解决的核心问题。

4.3 wo=10/30/50三组对比:参数改多少能看到差异

wo (rad/s)扰动后恢复时间稳态误差量级对测量噪声的放大
10约1.2s10^-2较小
30约0.4s10^-3中等
50约0.15s10^-4明显

这张表不是固定结论,但它反映的规律是通用的。我一般会跑三组数据,再把输出曲线叠加到一张图上,看z3是否在可接受时间内跟上真实扰动。看到恢复时间和噪声放大一对比,你对wo该取多少会比我直接给建议更清楚。

4.4 从开环观测改成闭环补偿的快速验证

另外,脚本里的扰动形式也值得动手改一改。默认如果有阶跃,改为斜坡ft=0.5*t可以检验LESO对斜坡扰动的跟踪能力,因为扩张状态观测器的第三维能估计常值扰动,但对快速时变扰动会有相位滞后。想看补偿效果时,把u从0改为(kp*(r-z1)-kd*z2-z3)/b0,LESO_step.m就从一个开环观测器变成了完整闭环仿真,这也是验证“先观测、后补偿”最快的方式。

5. LESO_bode.m 与避坑手册:Bode图验证和五个常见仿真事故

Bode图在这个资源里的作用是给LESO带宽一个“可测量的定义”,而不是凭感觉取wo。LESO_bode.m我拿到后通常会做两件事:画LESO从y到z3的传函,再看闭环回路有没有异常峰值。两步做完,参数整定就有了客观依据。

5.1 Bode图上看什么:观测器带宽、峰值与抗噪边界

LESO从y到z3的传递函数可以按观测器增益写出来,常见形式是Z3(s)/Y(s)=β3/(s^3+β1*s^2+β2*s+β3)。用bode绘制后,低频段增益趋于0dB,代表z3能准确估计常值扰动;频率接近ωo时开始衰减,这就是观测器的有效带宽。

%% LESO_bode.m 核心绘图段(基于观测器增益) wo = 25; beta1 = 3*wo; beta2 = 3*wo^2; beta3 = wo^3; num = [beta3]; den = [1 beta1 beta2 beta3]; sys = tf(num, den); bode(sys, {0.1, 100}); grid on;

这段代码不长,但能直观看出带宽选择是否合理。如果幅频曲线在远低于wo的地方出现鼓包,说明观测器增益矩阵配置有问题;如果在高频段曲线下降斜率过缓,说明噪声会被传入控制律。看到这两个现象,就该回头查β1、β2、β3,不是继续盲调。重点提醒一句:Bode图是线性频域分析工具,只反映频段特性,最终还是要和LESO_step.m的时域曲线对照。

5.2 避坑记录:五个常见ADRC仿真事故

  1. 现象:打开.slx后直接点仿真,报错Undefined function or variable 'b0'。原因:初始化脚本没在模型加载前写入工作区,Simulink里变量全是空的。解决:先运行acc2003.m,或在模型属性Callbacks的PreLoadFcn里写一行acc2003;。

  2. 现象:LESO_step.m跑完后,z3始终不等于真实扰动,差一个固定比例。原因:b0与实际对象增益差异过大,补偿幅度系统性偏差。解决:先确认b0符号与实际对象一致,再把b0调到接近真实值的1.5~2倍以内观察误差变化。

  3. 现象:Bode图幅频曲线高频段出现抬升,仿真里闭环噪声大。原因:观测器带宽wo取太高,把测量噪声直接放大。解决:降低wo,或给LESO输入加一阶低通滤波,但要注意低通滤波会引入相位滞后,需要重新看Bode图。

  4. 现象:Simulink用ode45变步长仿真跑到某一步就发散。原因:对象和LESO之间的时间常数差异太大,或者存在代数环。解决:换ode15s试跑,若立刻稳定,优先考虑是不是带宽比过大;若仍然发散,检查反馈路径是否有代数环。

  5. 现象:.mdl文件在高版本Simulink打不开,提示版本过旧或格式不支持。原因:.mdl是老格式,版本迁移有兼容限制。解决:用低版本MATLAB另存为.slx,或基于acc_2003.slx重建;不要直接改后缀。

5.3 Bode图和STEP结果对不上时怎么排查

如果LESO_step.m显示z3收敛很好,但Bode图显示的带宽明显偏低,多半是你看的Bode图不是同一个传函。z3到y的传函反映观测能力,而从r到y的闭环传函才反映整体跟踪性能。先确认当前图中画的是哪条传递函数,再看仿真激励幅值是否足够大。小信号仿真时非线性摩擦等因素占主导,Bode预测的线性行为会偏离,这种情况把工作点移到线性区间再验证。

6. 从二阶固定对象到扰动自适应:给ADRC加时变扰动并验证补偿效果

二阶对象模型跑通之后,我就已经不想只做固定扰动的测试了。我一般会做的第一件事,就是把扰动从“常值阶跃”改成时变扰动,例如幅值和频率都在变化的信号,再看ADRC的补偿能力。这样做能快速判断你调出来的观测器带宽到底够不够用。

%% 修改LESO_step.m中的扰动:时变+参数偏差联合验证 ft = 0.5*sin(2*pi*0.3*t) + 0.1*cos(2*pi*1.5*t) + (t>=2); b0 = 1.6; % 故意偏离真实值2.0,检验LESO补偿能力

改这两行之后重新跑,你会发现z3的相位滞后开始显现。低频正弦扰动基本能被补偿,高频分量则明显跟不上。此时就需要把这一路高频扰动的频段与LESO_bode.m里测出的带宽对应起来。扰动频率超过观测器带宽,补偿效果就会下降。知道这个边界后,再遇到“为什么扰动抑制效果差”的反馈,你就知道该查对象的扰动频谱,而不是继续加大wo。

进一步的做法是把LESO离散化,为后续生成嵌入式代码做准备。连续域LESO的极点配置在-ωo,离散化时直接把三阶观测器写成差分方程,采样周期取对象控制周期的1/5到1/10。MATLAB的c2d函数能直接给出离散状态空间对象,再把控制律换成离散形式,整个模型就能在Simulink里用定步长求解器跑,避免连续求解在快速仿真中带来的步长问题。

最后一个技巧是把wo和wc的整定结果记录成一张简单的表格,每改一次参数就把Bode峰值、恢复时间、稳态误差、噪声水平填进去。我最初调ADRC参数时全靠看Scope曲线,后来发现同一个观察误差会被视觉放大,换成数值表格后,参数选择就稳定多了。从那以后,我每次复现这类ADRC源码包,都会强制先跑初始化脚本、再画Bode图、再做时变扰动试验,绕开过不少弯路。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 10:02:30

高速3D-DIC在凝灰岩干湿循环损伤演化试验中的应用

高速3D-DIC这名字听起来有点绕,但对搞岩石力学试验的人来说,它基本算得上近几年最值得上手的观测工具之一。我最初接触这个组合,是因为手里的凝灰岩试件在干湿循环下实在太“不老实”——表面开裂、掉渣、局部鼓起,传统应变片根本…

作者头像 李华
网站建设 2026/10/22 10:00:55

开源大模型+Agent落地实践:选型、微调与降本增效全解析

1. 开源大模型为什么在下半场突然成了“必答题” 说实话,半年前我对开源大模型的判断还是“热闹归热闹,真到生产环境还是得闭源”。但最近几轮行业动向让我彻底改观——尤其当越来越多团队把Agent任务从Demo推向真实业务时,开源模型的角色已经…

作者头像 李华
网站建设 2026/10/22 9:58:55

可灵Kling 4.0深度实测:从抽卡到执导,AI视频生成还差什么

1. 从“抽卡”到“执导”:AI视频生成到底卡在哪第一次用可灵 Kling 4.0 生成视频的时候,我盯着进度条等了大概两分多钟,出来的画面确实让我愣了一下——一个穿风衣的人走在雨夜街头,霓虹灯倒影在积水里晃动,镜头还带了…

作者头像 李华
网站建设 2026/10/22 9:58:14

多智能体协作编程:从单Agent瓶颈到跨平台生态的工程实践

1. 从"一个Agent打天下"到"Agent团队协作"的认知转变 如果你最近在折腾AI编程工具,大概率经历过这样一个阶段:一开始觉得某个AI助手写代码挺惊艳,用着用着发现它在复杂项目里开始"胡言乱语",上下文…

作者头像 李华
网站建设 2026/10/22 9:57:11

LoadRunner性能测试实验二:参数化、关联与并发场景设计实战

简介:这份资源是面向高校软件测试课程学习者与性能测试入门者的实验资料包,对应软件测试质量保证课程中LoadRunner性能测试工具实验二,重点解决并发批量注册用户与并发订票操作两类场景的脚本增强、参数化配置与结果分析问题。包内共356个文件…

作者头像 李华
网站建设 2026/10/22 9:56:28

回归损失函数调参指南:Huber Loss如何优雅对抗异常值

1. 被几个异常样本逼疯之后,我开始重新审视"损失函数" 事情发生在我训练一个某行业预测模型的时候。模型结构不复杂,输入特征几十个,输出一个连续值,本质上就是个回归任务。我图省事,直接用了均方误差&#…

作者头像 李华