
把LADRC和PID同时放进Simulink里跑一遍仿真对比是我见过学习自抗扰控制最扎实的入门方式。你不必一上来就啃扩张状态观测器那套数学推导只需搭两个闭环、调几组参数、放一个阶跃和一个扰动进去就能直观看到“观测器补偿”和“误差反馈”究竟差在哪里。这篇文章适合三类读者刚学完自动控制理论但没碰过LADRC的学生、想评估LADRC能否替代现有PID回路的工程师以及只在公式层面见过ADRC但想把它真正“跑通”的人。我会从模型准备、控制器搭建、参数整定、结果解读一直写到常见报错把能踩的坑尽量提前替你们摸一遍。1. 为什么要在Simulink里对比LADRC与PID1.1 两种控制器的底层逻辑差异PID控制器的核心逻辑简单说就是“看误差、算误差、消误差”。它把当前误差P、历史误差积分I和误差变化趋势D按比例叠加成一个控制量。这个思路非常朴素工程师上手快调参也有比较成熟的套路。但也正因如此PID对被控对象内部的耦合、外部扰动和参数变化只能通过闭环增益去“被动压制”。LADRC的全称是线性自抗扰控制它做了一件关键的事把系统模型中不确定的部分、外部扰动、内部耦合统一看成“总扰动”,然后用扩张状态观测器ESO去实时估计这个总扰动再把估计值直接补偿掉。放在Simulink里看PID是“用反馈扛扰动”LADRC是“把扰动看见并抵消掉”这个差别在仿真曲线上会非常明显。我经常用一个生活化类比PID像是一个只根据室温偏差调空调的人屋里热了开冷风开过了再调回来LADRC则是这个人额外感知到了阳光暴晒、房间密封性差、隔壁发热设备在散这些“扰动源”然后提前加大制冷补偿而不是等温度偏差变大后才出手。1.2 仿真对比给谁用、能解决什么问题我一直主张第一次接触LADRC的人不要直接上硬件原因很现实真实被控对象通常是非线性的接线有延迟传感器带噪声控制器参数一旦设得离谱轻则系统发散重则损坏设备。而在Simulink里做对比仿真你可以在几秒内改参数、加扰动、换对象模型还能用Scope和MATLAB脚本把响应曲线完整记录下来这是硬件实验做不到的便利。对初学者来说仿真对比真正解决的是“感性认识”问题。LADRC公式里一排增益系数、观测器矩阵看到之后大多数人会懵。但你把它搭进Simulink回路里把目标值阶跃和外部扰动分别加进去再跑一次仿真你就会立刻明白原来LESO是在第三维状态里实时跟踪扰动原来控制器带宽和观测器带宽各自管的是哪一段性能。这种认识一旦建立再回头翻书那些矩阵和特征值配置就不再是抽象符号。2. 搭建模型前的工作确定对象与准备仿真环境2.1 被控对象选择为什么要用二阶传递函数做对比仿真最重要的前提是“公平”。我不会一上来就选择复杂的非线性对象而是用一个典型的二阶线性模型作为被控对象例如一个直流电机速度或位置系统的简化模型[ G(s)\frac{10}{s^22s1} ]这个对象有明确的物理意义s^2项对应转动惯量2s项代表阻尼增益10对应电枢电压到转速的静态放大倍数。选择二阶模型有两个好处一是PID和LADRC的设计都容易起步传递函数结构清晰便于手算二是二阶系统已经能体现出超调、振荡、调节时间等绝大多数控制系统关心的动态特性。如果你手头有实际的被控对象辨识结果比如某个伺服系统的传递函数是G(s)K/(Ts1)(as1)也可以换进去。但要记住对比结论只对“你选的这个对象”成立换一个对象后参数需要重新整定性能优劣也可能反转。做入门学习时先用标准二阶系统把方法论跑通再去换对象才是正路。2.2 Simulink环境配置和公共信号布置在Simulink中新建模型后我建议直接做三件准备工作模型求解器设置、基本模块库准备、公共信号构建。求解器建议用固定步长方式具体步长你可以取0.001秒这一步放在后面第6节会解释原因。模块库里需要准备Step阶跃信号、Sum加减模块、Gain增益模块、Integrator积分器、Scope示波器以及一个关键的PID Controller模块。更重要的准备工作是“把两个控制器放进同一个模型文件还是拆成两个模型文件”。我的习惯是放在同一个模型中用上下两路分别构建PID闭环和LADRC闭环两个闭环共享同一个被控对象模块。这样做的最大好处是方便做对比同一个阶跃信号分别进两路外部扰动模块也可以通过一个多路分配器同时加给两个系统Scope里一框看四根线结果一目了然。2.3 公共参数脚本在Simulink里直接敲参数不够规范尤其在参数数量较多的LADRC里每改一次都要进对话框点一遍非常容易出错。我的做法是先在MATLAB脚本里把公共变量都定义好再在Simulink模块的参数栏填变量名。public_params.m脚本示例% 公共被控对象参数 G_num 10; G_den [1 2 1]; % s^2 2s 1 % 仿真参数 Ts 0.001; % 固定采样周期 T_end 10; % 仿真时长 % 阶跃信号参数 step_start 1; % 阶跃起始时间 step_amp 1; % 阶跃幅值 % 扰动信号参数 dist_time 5; % 扰动加入时间 dist_amp 3; % 扰动幅值脚本执行后所有模块都能直接引用这些变量。之后你想把对象增益改成50只需要改G_num两个回路的公共对象同步变化对比逻辑不会错乱。这个习惯往小了说是省事往大了说是保证对比公平的关键。3. LADRC控制器的Simulink搭建LESO、带宽参数化与离散化3.1 线性自抗扰控制的核心结构LADRC针对二阶对象时的结构非常固定核心由三部分构成线性扩张状态观测器LESO、线性误差反馈控制率LSEF、以及扰动补偿回路。我要先说清楚整个回路里每个信号的走向再落到Simulink模块上。把二阶对象写成一阶状态方程形式[ \dot{x}_1 x_2 ] [ \dot{x}_2 f(x_1,x_2,w,t) b_0 u ] [ \dot{x}_3 \dot{f} ]其中x3就是那个被扩张出来的“总扰动”状态。LESO要做的是用输出y和控制输入u去估计x1、x2、x3[ \dot{z}_1 z_2 l_1 (y - z_1) ] [ \dot{z}_2 z_3 b_0 u l_2 (y - z_1) ] [ \dot{z}_3 l_3 (y - z_1) ]注意这个公式里input用b_0 u即对被控对象输入的估计这个b_0是对象控制增益的估计值它的取值直接影响观测器估计的准确性。控制量则由两部分组成[ u_0 k_p (r - z_1) - k_d z_2 ] [ u \frac{u_0 - z_3}{b_0} ]z3估计出来的总扰动被直接减掉并除以b_0这就是“扰动补偿”的数学含义。你会发现LADRC本质上是一个“状态反馈前馈补偿”的组合与PID的纯误差反馈思路已经不在同一层了。3.2 带宽参数化公式与初始参数LADRC学起来最轻松的一点就是它把多个增益压缩成了两个带宽控制器带宽ωc和观测器带宽ωo。标准配置下控制器增益取[ k_p \omega_c^2, \quad k_d 2\omega_c ]观测器增益取[ l_1 3\omega_o, \quad l_2 3\omega_o^2, \quad l_3 \omega_o^3 ]这个配置的本质是把闭环特征多项式配成典型的多重极点形式。对于入门级参数我通常先取ωc8、ωo40b010。这三个参数的理解方式ωc决定跟踪的速度越大响应越快但超调和噪声问题会冒出来ωo决定观测器估计扰动的速度一般取ωo为ωc的3到10倍太小则扰动估计跟不上太大则噪声被严重放大。3.3 用MATLAB Function模块实现离散LADRC搭建LADRC有纯模块搭法和写代码搭法。纯模块搭法需要三个积分器、多个增益和求和模块连线复杂不适合讲解和复现。所以我会用MATLAB Function模块来写离散化的LADRC控制器这样既贴近实际嵌入式实现代码逻辑也一目了然。在Simulink的User-Defined Functions库中拖一个MATLAB Function模块写入如下代码function u ladrc_controller(y, r, u_past, z1_mem, z2_mem, z3_mem, wc, wo, b0, Ts) % 增益 kp wc^2; kd 2 * wc; l1 3 * wo; l2 3 * wo^2; l3 wo^3; % 观测误差 e y - z1_mem; % 离散LESO一阶欧拉法 z1 z1_mem Ts * (z2_mem l1 * e); z2 z2_mem Ts * (z3_mem b0 * u_past l2 * e); z3 z3_mem Ts * (l3 * e); % 控制率 u0 kp * (r - z1) - kd * z2; u (u0 - z3) / b0; end这里的难点在于状态记忆。Simulink中每次调用这个函数时z1、z2、z3都不应该从零开始而是从上一时刻的结束值继续。上面代码把z1_mem、z2_mem、z3_mem和u_past作为外部记忆输入是为了避免在MATLAB Function内部定义persistent变量时引发的离散状态管理问题。你需要在Simulink模型中用Unit Delay模块或Memory模块来存储这些信号把输出端的z1...等信号返回到输入端形成闭环记忆。模型里每个模块的对应关系是控制器的输入端接目标值r和被控对象输出y控制器的输出u连接被控对象输入。同时把控制器内部更新后的z1、z2、z3、u分别连到几个记忆模块再从记忆模块输出反馈回函数输入。全部连好后LADRC回路就建立起来了。4. PID控制器的搭建与调参从自动整定到手改4.1 在Simulink中放一个可对比的PID ControllerPID那一路直接用Simulink的PID Controller模块是最省事的。拖入模块后双击打开参数页把控制器形式设为PID域设为Continuous Time。这里我建议在参数页里把公式形式选为Parallel或Ideal视模块版本而定增益含义和传递函数中的Kp、Ki、Kd一一对应。PID Controller模块内部会自动帮你做积分限幅、输出饱和等处理但为了和LADRC保持一致的离散对比条件如果你用的是固定步长求解器离散LADRC那么PID这路也建议把域改成Discrete Time并选择同样的采样周期Ts。这算是一个容易忽略的公平性问题一个连续PID配一个离散LADRC响应快慢本身就不可比。4.2 手动初调的顺序和边界条件在拿到一组可用PID参数前我不建议直接把PID Tuner自动整定结果当作终点。先用一组能稳定闭环的参数作为起点再按照“先P、后I、再D”的顺序手动调整你才能理解每个增益在响应曲线上具体影响什么。对于G(s)10/(s^22s1)一组比较稳妥的起始参数是Kp 2; Ki 2; Kd 2;先把Ki和Kd设为0只保留Kp然后逐渐增大Kp直到阶跃响应出现临界等幅振荡记下此时增益Kc和振荡周期Tc再用经验公式推算另外两个增益。这是一种早期的Ziegler-Nichols整定思路。但在Simulink里操作要小心临界振荡时系统已经处于等幅振动的边界继续加增益就会发散一定要小步长地增加Kp。得到稳定响应后我再去处理积分项和微分项。通常的规律是增加Ki会消除静态误差但会带来低频振荡增加Kd能抑制超调但会对高频噪声特别敏感。手动调参时每改一个增益就重跑一次仿真别同时动两个参数否则你根本不知道是哪一个改动让曲线变好了。4.3 自动整定工具的使用时机Simulink的Control Design工具箱里集成了PID Tuner可以用自动整定方式快速生成一组初始参数。打开方法是在PID Controller模块上右键选择“Tune PID”然后在工具界面里选择指定参考阶跃响应性能和鲁棒性水平它会自动算出增益。我的建议是把自动整定当作起点而不是终点。PID Tuner的优点是快几秒钟就能得到一组不发散且基本可用的参数缺点是你不知道它优化的是什么目标而且对于初学者来说会绕过了理解增益含义的环节。所以我习惯在自动整定后仍然看一眼超调量、调节时间和控制量曲线有不满意的指标再手动改。5. 设置公平的仿真场景并解读结果这是最关键的一步5.1 公平的对比场景应该包含什么对比仿真不是“跑起来就行”而是要在一个故意设置了压力场景下看性能。我会在仿真T1秒时给一个幅值为1的阶跃目标信号让两个系统跟踪在T5秒时给被控对象输入端加入一个幅值为3的阶跃扰动信号模拟外部负载突变在T6秒后还可以往测量输出端叠加入一个幅值很小的白噪声观察两种控制器对噪声的敏感度。输入端扰动是LADRC最能发挥优势的场景。因为LESO能把这类外部扰动扩张成总扰动状态并实时估计出来然后通过补偿通道直接抵消掉。PID则只能等扰动导致的输出偏差出现后靠反馈闭环一点点把误差压回去。两者的恢复速度在这种场景下往往拉开明显差距。5.2 从响应曲线上看性能差异跑完仿真Scope里一般能看到两类现象。在阶跃跟踪阶段高带宽LADRC的超调通常明显小于PID尤其当PID为了缩短上升时间而把Kp拉得比较高时超调更容易到15%到30%。LADRC因为用了状态反馈等效于“提前知道”速度误差并修正所以阶跃响应更平缓。在T5秒加入扰动后差异更直观PID输出会先偏出一个明显的鼓包然后经过一段调节周期慢慢回到设定值LADRC输出虽然也会有小幅波动但z3观测器在极短时间内估计出了扰动值补偿量一上去输出很快就被拉回。对比曲线里你能清晰看到LADRC的“抗扰恢复时间”更短这是它相对PID最有说服力的优势。5.3 用stepinfo量化指标而不是凭感觉肉眼看曲线只能定性判断写报告或做方案评估时一定要用量化指标。Simulink里可以直接把系统输出传到MATLAB工作空间然后使用stepinfo函数计算超调量、峰值时间、调节时间等参数。使用步骤是在模型中添加To Workspace模块变量名设为y_pid和y_ladrc仿真结束后在命令行运行info_pid stepinfo(y_pid.Data, y_pid.Time, 1); info_ladrc stepinfo(y_ladrc.Data, y_ladrc.Time, 1);注意这里的第三步参数1表示阶跃最终值为1stepinfo会据此计算2%调节时间。如果目标值不是1就把这个参数改掉。最终你会得到一张类似这样的对照表可以用来做技术选型汇报指标PID示例LADRC示例说明超调量15%~25%0~5%LADRC对超调抑制更明显调节时间2.5 s1.2 sLADRC跟踪更快扰动恢复时间1.8 s0.6 sLADRC抗扰优势最大稳态误差00两者都能消除静差这些数值会随参数变化别把它当作绝对结论重点是看趋势。6. 踩坑记录从仿真发散、代数环到噪声放大6.1 模型发散根源多数在b0和ωo的匹配新手第一次跑LADRC最容易遇到的问题就是模型发散曲线直接飘到几百上千去。我排查过太多的案例九个里面八个出在b0和ωo的不匹配上。b_0是对象控制增益的估计值如果你把被控对象G(s)10/(s^22s1)估计成b01观测器就会认为控制作用被低估z3状态会疯狂增大大概两三秒曲线就飞了。正确的做法是先把b0设成接近对象静态增益的值比如这个对象用b010。如果不知道对象增益宁可先保守一点用b05看看响应趋势再逐步加大。ωo也是一个敏感项我见过有人一上来就把ωo设为1000结果是LESO数值太刚烈固定步长只有0.001秒根本没法跟上一时刻的映射关系直接振荡发散。ωo从40开始是比较稳的起点。6.2 代数环问题离散控制器要避免直通在MATLAB Function里如果直接写成迭代式z1每步都依赖输入y那么y又来自被控对象输出被控对象输入又来自z1的计算结果Simulink就可能检测到Algebraic Loop代数环。它看起来是提示“Algebraic state”错误或者仿真奇慢。解决代数环的办法就是我前面代码里就埋好的u_past方法LESO当前步估计用的控制量是上一时刻的输出u[k-1]而不是当前步的u[k]。这样输入输出之间就永远是天然延迟一拍的状态代数环自然消失。即使使用了Unit Delay也要确保整个控制器回路里至少有一个离散延迟节点而不是把MATLAB Function的输出直接连回自身输入端。6.3 测量噪声与LESO的带宽权衡把Band-Limited White Noise加入测量通道后另一个典型现象会出现LADRC的输出反而比PID抖动得更厉害。原因不难理解LESO把测量噪声误当成状态信息的一部分高频噪声经过高带宽观测器后被放大然后通过控制量u再打回系统里。解决方法是权衡ωo。ωo越高ESO对扰动的响应越快但对噪声越不友好。入门调参时建议先在一个完全没有噪声的模型里把抗扰性能调到满意再逐步加入噪声观察输出抖动的幅度如果抖得太厉害就把ωo向下调直到抖动和抗扰性能之间取得平衡。这是LADRC工程应用中一定会遇到的实际问题仿真阶段不处理真机上会更难收场。7. 一点个人体会什么时候值得用LADRC哪些地方不必强行换这三四年带人做控制方案时我一直提醒大家别把LADRC当成PID的万能替代品。从仿真里看到它的优势之后有人会冲动地把现场所有回路都换成LADRC这并不明智。如果被控对象本身线性度不错、扰动频率低、传感器噪声又大PID完全够用强行上LADRC只会让观测器噪声放大的问题更难缠。LADRC真正发挥价值的地方是被控对象存在明显的模型不确定性和外部扰动比如机械臂在变负载工况下作业、飞行器在风扰条件下姿态控制、电机驱动系统在负荷突变时调速。这些场景下总扰动复杂且难建模LESO的价值就是不需要你知道扰动是什么只要它存在就能估出来并补偿掉。仿真里你可以在输入端任意叠加不同频率的扰动亲眼看LADRC的z3状态实时跟随这个扰动值这种“被看见的扰动”带给人的信心是PID曲线给不了的。最后分享一个实操小技巧把LADRC在Simulink里调通后再用MATLAB Coder把MATLAB Function导成C代码嵌入式部署会顺畅很多。但前提是你在仿真阶段就坚持用离散LADRC千万别搭一个纯连续模块然后指望自动生成代码。仿真里留的扩展空间才是这门技术真正落地时少走弯路的关键。