ARTICLE DETAIL

资讯详情

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

ADRC自抗扰控制Simulink搭建与参数整定全攻略

ADRC自抗扰控制Simulink搭建与参数整定全攻略 1. 先别急着搭模型——ADRC到底在干什么很多做控制的小伙伴第一次接触ADRCActive Disturbance Rejection Control自抗扰控制时最大的感受不是原理难懂而是参数太多、太能飘。TD里有r和hESO里有β01、β02、β03和b0NLSEF里还有kp、kd、α、δ一列下来十几个参数完全不知道从哪下手调两天模型还是发散。当年我在韩京清研究员的那篇经典论文里翻来覆去看了好几遍才慢慢把“这堆参数到底是干嘛的”给捋顺。今天这篇就完全按实操来把TD、ESO、NLSEF三个模块拆开讲清楚配上可以直接抄作业的Simulink搭建步骤和完整参数表争取让你一天之内从“看到ADRC就慌”变成“心里有谱地开干”。先花一分钟说清楚ADRC是干什么的。传统PID的关键问题是把“系统自身的动态”和“外部扰动”混在一起处理比例、积分、微分三项各管一摊调参时互相牵制。韩京清研究员的核心思路其实很简单既然扰动总在影响输出那我直接把它估计出来然后从控制量里“扣掉”这个影响剩下的交给一个简单的控制器去处理。ADRC就是围绕这个思路拆出来的三大件TD跟踪微分器不光给你输入信号的平滑跟踪值还给你它的微分信号既能解决PID里“微分项放大噪声”的老毛病又相当于给系统加了一个快速又不振荡的“参考轨迹”。ESO扩展状态观测器这是ADRC的灵魂。它把系统的状态和总扰动内部动态加外部扰动的总和一起观测出来相当于给系统装了一个“扰动仪表盘”。NLSEF非线性状态误差反馈用非线性组合的方式把误差变成控制量配合ESO给出来的扰动补偿完成真正的闭环控制。所以ADRC调参这件事本质上是把十几个参数拆成三个独立的小问题去解而不是一个高维黑盒调优。TD的参数只影响跟踪速度和微分质量ESO的参数只影响扰动估计的准确度NLSEF的参数只影响误差反馈的增益。搞清楚这个边界你就能像我一样顺着模块一个一个调而不是对着整个系统瞎试。这篇文章适合刚被ADRC劝退的同学也适合已经搭过模型、但一直调不出理想波形的兄弟们。后面的所有公式都给出可直接复制到MATLAB里的离散形式所有参数都基于一个具体仿真对象来演示你完全能照着跑一遍再替换成自己的被控对象。2. TD跟踪微分器——先解决“输入怎么进”的问题2.1 TD的数学原理和最常用离散形式跟踪微分器的作用是给一个输入信号安排一条过渡轨迹同时提取它的微分。你看PID调那种阶跃指令时如果指令直接怼上去误差突变微分项会蹦出很大的尖峰积分项也会被这个阶跃带出一大段超调。TD的意义就是在这里它输出的v1是对输入v的平滑跟踪v2是v1的导数而不是直接对v求导。这样既避免了“对带噪信号微分”这个灾难级操作又给系统一个缓冲。最常用的是韩京清研究员给出的离散跟踪微分器公式用于Simulink搭建时可以直接写成一个S函数或者用MATLAB Function模块实现x1(k1) x1(k) h * x2(k) x2(k1) x2(k) h * fhan(x1(k)-v(k), x2(k), r, h0)其中fhan是最速控制综合函数表达式为d r * h0^2 a0 h0 * x2 y x1 - v a0 a1 sqrt(d*(d8*abs(y))) a2 a0 sign(y)*(a1-d)/2 ay (sign(yd) - sign(y-d))/2 a (a0y-a2)*ay a2 fhan -r * ( sign(a) - sign(a-d) ) / 2这套公式看起来有点吓人但你在Simulink里只需要把它封装成一个函数就行不需要手推。我这里直接给一段可运行的MATLAB Function代码你放到MATLAB Function模块里就能用function [x1, x2] TD_update(x1, x2, v, h, r, h0) % 最速跟踪微分器离散更新 d r * h0^2; a0 h0 * x2; y x1 - v a0; a1 sqrt(d * (d 8 * abs(y))); a2 a0 sign(y) * (a1 - d) / 2; ay (sign(y d) - sign(y - d)) / 2; a (a0 y - a2) * ay a2; fh -r * (sign(a) - sign(a - d)) / 2; x1 x1 h * x2; x2 x2 h * fh; end2.2 Simulink搭建TD的三种常用方式这里有一点要说明上面的代码里h是仿真步长h0是TD内部的滤波因子两者可以取一样大也可以不一样。实际工程中为了让微分信号更平滑h0通常取仿真步长的整数倍。搭建方式有三种我一个个说优缺点。第一种是直接用MATLAB Function模块写上面的离散递推式可以带两个memory保持x1和x2的状态好处是灵活适合把TD封装成子系统参数用mask对话框输进去后面改起来很方便。第二种是用Simulink里已有的“Transfer Fcn”搭一个线性近似TD比如写成k/(τs1)或者二阶线性跟踪器但这样拿不到“最速跟踪”的效果微分信号容易偏。第三种是在外部用S-Function写周期采样函数适合后续把代码直接生成到嵌入式控制器里。初学者我建议先用第一种理解清楚以后再用S-Function去做工程化。2.3 TD关键参数r和h0怎么选这才是TD调参的核心。r叫快速因子它决定跟踪速度r越大v1跟踪v越快但同时v2会越高、越尖。h0叫滤波因子它决定微分信号的平滑度h0越大v2越平滑但相位滞后也越明显。我之前调一个伺服系统位置环的TD对象惯性比较大开始取r1000结果v2跟踪位置指令微分的时候尖峰能到几千后面控制器直接饱和。后来把r降到200跟踪大概慢了0.05秒但微分信号就平顺多了。经验法是先给定一个r让v1跟踪一个斜坡信号看跟踪延时是不是你能接受的范围一般v1滞后时间大约在2倍到5倍步长量级。如果滞后太大就加r如果微分毛刺多就加h0。再强调一点如果你对系统的抗扰速度要求比较高TD的r可以适当给大一点但前提是控制输出不能饱和太久。TD说到底只是一个信号预处理环节它的响应时间不能比对象的执行速度快太多否则只是把相位提前问题变成了饱和问题。2.4 TD实操心得单独调试TD的时候别一上来就连ESO和NLSEF。你可以把TD的输出接到一个Scope给一个阶跃或方波输入看着v1和v2的波形来调。我自己的调试顺序是先固定h为仿真步长0.001h0取0.005然后从小到大试验r50、100、200、500。每组都看v1的超调和v2的平滑度。最终选的r一般是我能容忍的跟踪时间比如要求0.1秒内跟上对应的最小值。再说一个小技巧如果你需要TD提供二阶微分比如加速度信号你可以串联两个相同的TD第二个TD输入接第一个的v2输出就是平滑的二阶微分。但串联会导致相位滞后叠加所以不是特别需要就少用。3. ESO扩展状态观测器——ADRC的“灵魂模块”3.1 ESO到底在观测什么ESO的思想特别朴素假设被控对象可以写成x f(x, x, w) b*u其中f是系统内部动态加外部扰动的总和这是“总扰动”b是输入增益的估计值。ESO把状态x1xx2xx3f当作三个状态一起观测。x3就是那个“扩展状态”它实时估计了总扰动。控制量里只要用u(u0-x3)/b0这种形式把x3估计出来的扰动抵消掉系统就变成了一个近似纯积分串联结构这样剩下的控制器只需要对“双积分对象”工作自然比直接对复杂对象工作容易得多。注意这里的b0是你对b的一个估计值不是真实值。这是ADRC参数里最敏感的一个。我们后面会专门说怎么凑b0。3.2 三阶ESO的标准形式最常见的ADRC对被控对象作二阶建模因此ESO是三阶的。连续形式是e z1 - y z1_dot z2 - β01 * e z2_dot z3 - β02 * fal(e, 0.5, δ) b0 * u z3_dot -β03 * fal(e, 0.25, δ)其中fal是非线性函数fal(e, a, δ) e / δ^(1-a), 当|e| ≤ δ fal(e, a, δ) |e|^a * sign(e), 当|e| δ注意第一个方程里的误差e是线性反馈后面两个用了非线性fal。这样设计的好处是当观测误差小的时候增益放大让稳态估计更准当误差大的时候增益收缩避免超调和振荡。这也是ADRC名字里“自抗扰”的由来。3.3 ESO参数β01、β02、β03和b0的关系这是ADRC调参里最绕人的地方。先说结论β01、β02、β03决定ESO收敛速度和观测精度b0不参与观测的动态行为但它决定扰动补偿的准确性。你完全可以把ESO的参数调节和对b0的校正分开进行。在仿真里如果你用的是线性形式的ESO把fal替换成纯线性观测器就变成了一组线性状态观测器β01、β02、β03可以通过带宽法整定。假设你希望ESO的观测带宽是ωo那么β01 3 * ωo β02 3 * ωo^2 β03 ωo^3这是一个非常实用的速调公式。ωo越大ESO观测越灵敏但噪声会被放大仿真步长也必须足够小否则数值上容易发散。我一般从ωo20开始然后逐步加倍看ESO对扰动的估计是否跟得上。如果z3滞后明显就加大ωo如果z3抖动严重就减小ωo。但你需要记住带宽法给出的是初始值不是终值。实际调参时我会以初始值附近再加减30%~50%来微调。对非线性ESO来说初始值也可以参考这个线性整定结果。另外δ这个参数也很关键它定义了非线性区间的宽度一般取0.01到0.1之间。δ取得太大非线性就接近线性δ取得太小容易在零点附件跳动数值上要小心。3.4 Simulink搭建ESO的细节搭建ESO我推荐用积分器模块Integrator加MATLAB Function组合的方式。三个积分器分别对应z1、z2、z3把每个导数表达式写清楚z3的导数里不需要加扰动输入因为扰动是被估计出来的不是已知输入。这里有三个细节要认真处理。第一Integrator的初始值要和被控对象的初始状态匹配否则ESO启动瞬间会有很大的暂态波动。第二离散仿真里建议用离散积分器采样时间设为控制器周期Ts否则连续积分器可能给你一个“看起来收敛但其实依赖连续求解器”的错误安全错觉。第三b0*u这一项要从外部输入并且单位要和被控对象的输入匹配常见的坑是把b0的单位搞错导到ESO明明收敛但控制量是歪的。3.5 ESO调参中的常见误区我见过太多人在ESO上翻车核心原因就是“用观测器的输出去核对真实扰动”。扰动往往是不可测的所以你无法直接判断z3是否准确只能通过闭环控制效果来间接验证。我调试ESO时是先让控制量为零给对象一个固定扰动然后看z3能否收敛到扰动值这样能单独验证ESO估计能力。等ESO的扰动估计能跟上恒定扰动、对阶跃扰动有快速响应后再接入NLSEF。对时变扰动ESO的跟踪能力受限于ωo。如果你的系统存在高频扰动就必须提高ωo但这会放大噪声所以ESO的ωo最终是“抗扰需求”和“噪声容忍度”的折中。这里可以类比音响的均衡器低音调太多整体声音会浑浊高音拉太多底噪也起来了。你得找到一个平衡点。4. NLSEF非线性状态误差反馈——真正的控制器在这里4.1 NLSEF的公式和fal函数的作用ESO把扰动估计出来后剩下的控制量就可以用一个很简单的非线性组合来生产。常规的NLSEF形式是e1 v1 - z1 e2 v2 - z2 u0 kp * fal(e1, α1, δ) kd * fal(e2, α2, δ) u u0 - z3 / b0这里α1一般取0.5α2取1或者1.25δ和ESO里的δ可以一致也可以略作调整。fal函数的核心魅力在于小误差区域有高增益大误差区域有低增益这让控制器在靠近目标时更“细腻”远离目标时不会猛冲本质上接近一种自适应PID思想。4.2 kp、kd的整定方法和PID的关系如果把ESO观测理想化假设z1x, z2x, z3f均精确那么整个闭环系统退化成u0kpfal(e1,...)kdfal(e2,...)对象是两个积分串联这时系统的闭环特性变得非常清晰。按照线性近似来看闭环特征方程能写成s^2kd*skp0。这给了我们一个初始整定梯度kp ωc^2 kd 2 * ωc其中ωc是期望的闭环带宽。也就是说理论上你想要多快的响应就定多大的ωc然后按上面的公式给kp和kd一个初始值。这个初始值比瞎猜靠谱太多了。但注意这个整定是建立在“ESO完全补偿了扰动”的理想前提下。实际ESO还有观测误差所以kp和kd在初始值基础上要留有余量。如果系统在目标附近震荡优先降低kp保守一点就同时降kp和kd。如果响应太慢优先提高kp但一定要关注是否激发了ESO噪声。4.3 控制量合成和扰动补偿最后一步u u0 - z3/b0是整个ADRC的点睛之笔。这里z3/b0就是ESO估计出来的扰动折算成控制端的补偿量。正是这一项让ADRC对未建模动态和外部扰动都有很强的抑制能力。你需要特别注意u0的单位和对象输入单位一致补偿项也是直接加在同一个单位上不要做任何滤波。有人觉得z3抖动想给补偿项加个低通滤波这其实是把ESO的高频估计优势给滤没了。如果z3抖动严重正确做法是降低ωo或增大δ给ESO本身降噪而不是在控制量合成处做滤波。5. 完整Simulink搭建流程从零搭一个ADRC速度环5.1 仿真对象示例为了让你能完整复现我这里用一个简单的二阶对象做演示它模拟了一个典型的电机位置伺服系统在速度环层面的动态简化为二阶惯性环节G(s) 21.6 / (s^2 3*s 4)对象有两个状态x1、x2下面在Simulink里用积分器搭出来。在实际工程里你可能是从电机模型或者机械传动力学里得到这个传递函数。先把它调通再替换成你自己的对象逻辑是一样的。5.2 用Simulink基本模块搭建ADRC控制回路打开Simulink新建模型采样时间我设成Ts0.001秒。我建议把求解器设成固定步长步长取0.001选ode4四阶龙格库塔。这一步很关键因为离散ADRC设计时假定仿真周期控制周期。如果你偷懒选变步长后面S函数和离散积分器的行为可能和理论对不上调试起来会特别容易怀疑人生。系统结构按下面的顺序连阶跃信号作为参考输入v默认阶跃从0到1在Step模块里把Step time设成0.1秒方便看初始响应。把v接到TD子系统TD输出v1和v2。把被控对象的输出y和输入u都接到ESO子系统ESO输出z1、z2、z3。把v1-v2和z1-z2分别接到NLSEF计算模块计算出u0。把u0和z3按照u u0 - z3/b0合成得到u送给对象。TD和ESO里的MATLAB Function我前面已经给出核心代码NLSEF部分你需要写一个带fal函数的MATLAB Functionfunction [u0, u] NLSEF(v1, v2, z1, z2, z3, kp, kd, alpha1, alpha2, delta, b0) e1 v1 - z1; e2 v2 - z2; u0 kp * fal(e1, alpha1, delta) kd * fal(e2, alpha2, delta); u u0 - z3 / b0; end function y fal(e, a, delta) if abs(e) delta y e / delta^(1-a); else y abs(e)^a * sign(e); end end注意MATLAB Function里要支持if判断直接写成上面的函数形式即可。由于ESO里的fal也要用建议把fal子函数写成公共函数文件或直接在对应Function里复制一份保持独立性。5.3 完整参数表以下是我按前面给出的对象调试出来的一组比较稳定的ADRC初始参数你可以直接拿去仿真再按自己的对象微调。参数表的分项如下模块参数含义建议取值公共Ts仿真步长/控制周期0.001 sTDr快速因子200TDh0微分滤波因子0.005ESOωo观测器带宽30ESOβ01线性增益13*ωo 90ESOβ02线性增益23*ωo^2 2700ESOβ03线性增益3ωo^3 27000ESOb0输入增益估计21.6ESOα1fal第一个指数0.5ESOα2fal第二个指数0.25ESOδfal线性区间0.01NLSEFkp比例增益ωc^2 100NLSEFkd微分增益2*ωc 20NLSEFα1误差fal指数0.5NLSEFα2微分误差fal指数1.0NLSEFδ非线性区间0.01这张表非常有用你可以把它打印出来贴在屏幕上每次调一个参数就在表格里做标记。我强烈建议把表里的公式栏保留下来这样你换对象的时候只需要根据b0和期望带宽重新算一遍初值。5.4 逐步调试波形检查方法把参数填进去后先不要直接看控制效果按下面的顺序逐步验证单独给对象一个阶跃输入确认对象本身响应没问题记录开环阶跃曲线初步估算出稳态增益和响应时间。把TD接上输入为阶跃查看v1和v2波形。v1应该平滑地升到1没有超调v2是一个平滑的脉冲状波形宽度大概和跟踪时间差不多。如果你的v2特别尖或者来回抖说明r太大或h0太小。接入ESO先不给NLSEF输出让u0给对象一个恒定扰动比如在对象输入端加一个2.0的常数信号。看z3是否收敛到2附近z1是否基本跟随y。如果z3收敛太慢加大ωo如果z3振荡减小ωo。最后接入NLSEF形成闭环看y对阶跃指令的跟踪曲线。如果系统振荡先降低kp如果出现稳态误差检查ESO补偿是否有效特别是b0是否偏得离谱。5.5 调参过程中的一次真实调试记录以这个对象为例我最初设置ωc20即kp400kd40配合TD r500。仿真前0.2秒还行后面开始有高频振铃。看了输出后发现z3上叠加了明显的高频分量问题出在ωo50上ESO太灵敏把对象模型里的高频动态都当成了扰动。后来我把ωo降到30β参数按表格更新振铃就消失了输出曲线变得很干净。换第二个对象时我故意把b0估计错设成10.8而不是21.6。结果发现响应变慢而且有大约10%的稳态误差。这个现象特别典型当b0偏小控制量被过度补偿ESO估计出来的z3偏大输出收敛不到目标。通过这个案例你应该体会到了b0的敏感性。b0不能靠猜最可靠的做法是让对象加一个已知的输入u等稳态后量测稳态输出的变化率反算出b0。对二阶对象估算b0大致等于稳态输出加速度增量除以输入增量。6. 常见问题与故障排查实录ADRC调试过程中你大概率会遇到下面几个经典问题。我整理了一个速查表你在现场调试时可以直接对照。现象可能原因排查与解决思路整个闭环一上电就发散b0符号不对或数量级错误ESO初值没设好求解器用了变步长先检查b0正负号和量级再固定步长、减小ωo输出稳定但有明显稳态误差b0偏大ESO没收敛NLSEF里u0中没有积分项调小b0增大ωo或换用带积分项的NLSEF变体控制量高频抖振ESO的ωo过大δ太小采样步长不够小降低ωo增大δ减小Ts对阶跃响应的上升沿有超调但随后回落TD的r过大跟踪太快kp偏大降低TD的r按带宽法重新整定kp、kdESO的z3噪声严重反馈信号本身噪声大ωo过高给反馈信号先做适度滤波但注意控制周期不能太大NLSEF的fal函数在零点附近跳动δ太小将δ从0.01增大到0.05再测试换对象后控制效果完全不成b0没有按新对象重新估算用开环实验重新标定b0另外我在实际使用中发现一个特别容易踩的坑很多人把ESO里的b0和实际对象增益b混为一谈。ESO模型里 b*u 是为了让观测器的状态变化跟上对象这里的b只要不偏离实际增益太远ESO都能通过z3去估计误差但b0如果偏差过大控制量补偿就会失真。所以b0不是越准越好而是要稳定。你可以在仿真里故意让b0偏离20%到30%观察z3是否有能力补偿过来。如果补偿不了说明ESO带宽不够而不是b0不准。关于采样时间我还要多说一句。ADRC是典型的“依赖高频观测”的方法ESO的带宽和你的控制频率必须匹配。工程上一般要求控制频率至少是ESO带宽的5到10倍。如果你的系统只能运行在1kHz你强行把ωo设到100以上数值上必定出问题。实际调参顺序应该是先把采样时间固定下来再设定ωo小于采样频率的十分之一然后再去推kp和kd。我也遇到过一种情况阶跃给定切换后输出有明显的“爬坡”现象但响应时间是够的人眼看上去很慢。检查后发现ESO的z3不是跳到新扰动值而是以很大的时间常数慢慢爬。问题其实出在ωo太小。把ωo提到40之后z3的响应立刻跟上了整个闭环的动作也利索了。这再次验证了ESO的ωo是整个ADRC响应的“天花板”它不够NLSEF怎么调都补不回来。最后再分享一个小技巧如果你是在Simulink里做批量调参可以给TD、ESO、NLSEF分别封装成子系统然后把每个参数设成子系统的mask变量。这样你可以跑一组脚本循环修改参数把阶跃响应的超调量、调节时间都记录下来做对比比自己手动一遍遍点仿真要高效得多。我甚至会把多个参数组用数组存储跑一个for循环自动生成Bode图和阶跃响应曲线这样整个ADRC调试过程就变成了一种可视化寻优。ADRC调参并不是玄学它的核心逻辑就是这三步先用TD解决输入信号和参考轨迹的问题再用ESO解决动态估计和扰动补偿的问题最后用NLSEF在标准的积分串联对象上做带宽整定。你在实际调试时遇到任何问题按这个逻辑去归因基本都能找到答案。跑通这个示例之后你可以慢慢把对象换成自己的真实模型、把噪声加进去、把执行器饱和约束加进去届时你会发现ADRC这套从“模型知道得越少越好”出发的思想恰恰能让你的控制系统在各种不确定环境下保持从容。
返回列表