ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

自抗扰控制ADRC核心原理与工程实践:从PID到ESO扰动抑制

自抗扰控制ADRC核心原理与工程实践:从PID到ESO扰动抑制 搞自控这些年PID几乎是所有人的“第一口奶”。但做工程做得越久越会发现PID在对付强耦合、大惯量、参数时变、外部扰动明显的对象时调参调到头秃还是压不住超调、稳不住精度、扛不住扰动。大概十年前我接触到韩京清先生提出的自抗扰控制ADRC那种“原来扰动还能这样处理”的感觉至今记得。这篇内容就围绕ADRC的核心构成、算法原理和实际案例把我从理论到仿真再到样机调试的完整套路拆给大家看。无论你是刚接触ADRC的研究生还是已经在现场被PID折磨多年的工程师这篇文章都能给你一条清晰可落地的路径。ADRC全称Active Disturbance Rejection Control直译是“主动扰动抑制控制”。它厉害的地方在于不依赖精确的被控对象数学模型而是把系统内部的未建模动态和外部扰动统一看成“总扰动”然后通过扩张状态观测器ESO实时估计并补偿掉。这个思想在工程上极有价值——我们搞控制的人真正怕的不是已知的非线性而是“不知道还有什么力在作用”的系统。ADRC用一套通用框架解决这个问题从数学模型到仿真代码到实际电机/温控/飞控场景都能复用。1. 内容整体设计与思路拆解1.1 从PID痛点说起为什么ADRC能“另辟蹊径”传统PID基于“误差消除误差”的思想。你去调节一个系统看到偏差就加大比例看到偏差变化率就加微分看到稳态误差就加积分。这套逻辑在单输入单输出、线性时不变、扰动缓慢的场景下非常顺手可一旦换到强非线性、强耦合、负载突变的环境PID就暴露两个先天问题。第一PID的误差信号直接来自目标值和反馈值但目标值突变的时候误差突然变大比例项会猛推执行机构造成大幅超调。现场调试最典型的画面就是设定值一阶跃电机转速“呜”的一声冲过头然后再慢慢回调。为了压超调只能牺牲响应速度控制器的比例项越调越小结果外部扰动一来又压不住了。第二PID的积分项靠时间累积消除稳态误差但积分累积过快会引起积分饱和导致系统振荡。尤其是在存在执行机构限幅时积分项一直堆等到误差反向时根本退不出来。你会在现场看到那种“均匀呼吸式”的振荡频率不高但一直存在就是积分在作怪。ADRC的逻辑完全不同。它不直接对阵目标值变化而是先利用跟踪微分器TD对设定值安排一个平滑过渡过程让被控量有时间跟上指令变化而不产生激进的冲击。同时ESO把系统内部非线性、参数不确定性、外部负载变化全部打包成“总扰动”在控制量计算时反向抵消。这个框架本质上是在告诉控制器你不要猜测扰动是什么我观测出来然后在控制量里直接减掉。1.2 ADRC三大核心构成TD、ESO、NLSEF的整体分工韩京清先生提出的ADRC经典结构包含三个环节跟踪微分器、扩张状态观测器、非线性状态误差反馈控制律。有些工程简化版可以去掉TD或者用线性组合替代NLSEF但要想完整理解ADRC的体系必须从这三个环节入手。跟踪微分器解决“目标值突变带来的输出冲击”问题。它接收设定值输出两个信号跟踪信号v1平滑后的设定值和近似微分v2设定值的变化率。即便设定值是一个阶跃信号经过TD之后得到的v1也是一个连续可导的过渡过程而v2则是这个过渡过程的导数。扩张状态观测器是整个ADRC最核心的模块也是我下面会重点拆解的内容。它利用被控对象的输入量和输出量实时估计出系统的各个状态并额外扩张出一个状态来表示“总扰动”。ESO的厉害之处在于它不区分模型误差和外部扰动而是统一处理。你不需要精确建模只需要知道系统的大致增益b0再把模型误差和外部扰动全归入总扰动。非线性状态误差反馈控制律则负责最终的控制决策。它把TD输出和ESO估计值之间的误差进行非线性组合生成初始控制量u0再减去总扰动补偿量得到最终控制量。这里的非线性组合函数通常采用韩京清提出的fal函数也可以用线性形式简化差别主要体现在响应速度和抗扰动性能上。这三个环节的衔接关系可以这样理解TD帮你“铺路”让设定值变化不那么突然ESO帮你“看清战场”把总扰动识别出来NLSEF帮你“做决策”在已知扰动的基础上精准操控执行机构。三者配合形成一个不依赖精确模型的鲁棒控制框架。2. 核心细节解析与实操要点2.1 跟踪微分器原理与fhan函数的秘密跟踪微分器解决的是工程中“差分放大噪声”的经典难题。很多控制系统需要信号的微分项但直接对测量信号做差分噪声会被急剧放大。比如转速信号叠加了几十毫伏的噪声差分后可能变成几伏的尖峰脉冲控制器根本没法用。韩京清提出的TD本质上是一个二阶最速控制系统。它利用最速综合函数fhan来构造让跟踪信号能以最快的速度跟上设定值同时又没有超调。fhan函数的表达式包含目标值和跟踪值之间的误差、跟踪速度以及线性区间宽度等参数具体形式是fs -r * (a / (abs(a) δ)) 近似形式完整的fhan函数需要计算两组临时变量核心逻辑是根据误差和误差变化率判断当前处于什么“状态”然后给出最速控制量。这个函数的本质是求解二阶积分器的最速控制问题让系统能在有限时间内到达目标且不产生超调。在工程实现上TD的采样周期需要和主控制周期一致。r参数越大跟踪速度越快但也会要求执行机构有更强的快速响应能力。r太小系统响应会过于迟钝r太大TD输出的过渡过程接近阶跃失去平滑意义。一般先按系统执行机构能承受的最大速度整定再根据仿真或现场表现微调。我最初在电机调速系统里用TD时设置r600过渡时间大约0.1秒效果很好。后来又换到温控系统惯性很大r只能设到10左右。这提醒大家TD的时间尺度必须和被控对象的动态时间尺度匹配不能一套参数走天下。2.2 扩张状态观测器ESO的核心机理与公式拆解ESO是整个ADRC的灵魂。理解ESO要从“扩张状态”这四个字说起。一个二阶被控对象通常有两个状态位置和速度。ESO除了估计这两个状态外还额外扩张一个状态用来估计系统的总扰动。这样一来观测器从二阶变成了三阶多出来的那个状态就是“扩张状态”。以一个典型的二阶系统为例被控对象可以写成x1_dot x2 x2_dot f(x1, x2, w(t)) b0 * u y x1其中f(x1, x2, w(t))表示系统内部非线性、参数不确定性、外部扰动w(t)的总和也就是我们要估计的“总扰动”。b0是控制增益的估计值。ESO的形式为z1_dot z2 β1 * (y - z1) z2_dot z3 β2 * (y - z1) b0 * u z3_dot β3 * (y - z1)三个观测器状态分别估计z1估计输出yz2估计x2z3估计总扰动f。这里的β1、β2、β3是观测器增益。观测器的核心逻辑是利用输出误差y - z1来修正各个状态的估计值而z3在观测误差收敛后就会趋近于系统的总扰动。数学上只要观测器增益配置得当z3就能在有限时间内收敛到总扰动的真实值。这个收敛过程不需要知道f的具体表达式也就是说你不需要建模扰动只要观测器带宽足够它就能“看见”扰动。关于增益整定的经典做法是高志强老师推广的带宽法。令观测器特征方程配置到理想极点形式s³ β1s² β2s β3 (s ω₀)³展开后得到β1 3ω₀β2 3ω₀²β3 ω₀³。ω₀就是观测器带宽。这个方法的工程意义极大你只需要整定一个参数ω₀就能确定整个ESO的三个增益大幅降低了调参难度。ω₀越大观测器收敛越快估计精度越高但不能无限增大。因为ω₀增大意味着β值增大观测器对测量噪声的放大也越厉害。实际工程中一般取系统控制带宽的3到10倍。样机测试时比PID调参更直观的趋势是ω₀太小系统动态响应慢、抗扰动差ω₀太大会出现高频噪声甚至导致执行机构剧烈抖动。2.3 控制律设计线性 vs 非线性怎么选早期ADRC教材里最经典的是非线性状态误差反馈控制律误差经过fal函数处理后再进行比例和微分组合。fal函数的表达式是fal(e, α, δ) e / δ^(1-α) 当|e| ≤ δ fal(e, α, δ) |e|^α * sign(e) 当|e| δfal的思想是当误差较大时用小于1的指数α如0.5得到一个“亚线性”增益避免控制量过大误差较小时线性区间δ保证增益平滑不会产生抖振。本质上是实现“小误差大增益、大误差小增益”的非线性控制效果。这个方法理论上很优雅但工程实践中有一个绕不开的困难非线性函数的参数α和δ对控制器性能很敏感不同工况下最优值差别很大。而且非线性ESO在高增益条件下的稳定性分析比较复杂想从理论上证明闭环系统的稳定性难度不小。因此我在实际项目中更推荐线性ADRC作为入门和工程落地的第一选择。线性ADRC将ESO简化为线性观测器结构控制律直接采用PD组合形式u0 kp * (v1 - z1) kd * (v2 - z2) u (u0 - z3) / b0其中kp ωc²kd 2ωcωc是控制器带宽。这样做的好处是参数整定从“调一堆α、δ、b0”变成“调两个带宽ω₀和ωc”再有b0这个唯一的模型参数。整定规则非常明确大脑负担小很多。不过非线性ADRC在学习研究和特定高性能场景中还是有价值的。如果你的对象需要极致的快速性和扰动抑制能力而被控对象的执行机构余量较大非线性fal的“小误差大增益”特性确实能带来性能提升。我的建议是先用线性版本跑通整个控制链路理解系统行为再按需引入非线性环节。直接上非线性参数太多互相纠缠出了问题很难定位。3. 实操过程与核心环节实现3.1 案例对象带非线性摩擦和负载扰动的电机位置伺服系统为了把ADRC讲透这里用一个工程上常见的电机位置伺服系统作为案例对象。假设被控对象是一个直流电机驱动的转台系统的动态可以写成θ_ddot -a * θ_dot - c * sign(θ_dot) b * u d(t)其中θ是转台角度a是阻尼系数c是库仑摩擦力矩相关的系数sign是符号函数d(t)是外部负载扰动u是电压控制输入。这个对象的难点在于摩擦非线性项c * sign使得低速时系统难以精确到位而外部负载扰动d(t)会直接影响稳态精度和动态性能。现在用ADRC控制器来设计位置环。为了简化处理选取b0作为控制增益的估计值它不需要精确等于b只要量级正确即可。这就是ADRC的优势之一不需要知道确切的b值ESO会把真实b与b0之间的差异也当作总扰动的一部分在z3中估计并补偿掉。系统是二阶的所以控制器设计一个二阶ADRC。ESO扩张一个状态来估计总扰动因此ESO是三阶的。我们用常微分方程组描述整个ADRC闭环系统然后在仿真工具中搭建模型。如果你用的是MATLAB/Simulink建议用S-Function或者MATLAB Function模块来写离散ADRC控制器这样从仿真迁移到嵌入式代码时只需要把C语言版本的函数移植过去。3.2 仿真模型搭建与核心算法代码实现在Simulink中搭建的步骤大致如下首先建立被控对象模型写入电机动力学方程包含非线性摩擦和负载扰动。然后建立ADRC控制器子系统包含三个模块跟踪微分器、扩张状态观测器、非线性状态误差反馈控制律。最后把控制器输出接到被控对象的输入端形成闭环。下面给出一个可供直接参考的二阶线性ADRC离散化代码以MATLAB Function形式编写function [u, z1, z2, z3, v1, v2] adrc_controller(y, v, ts, w0, wc, b0) % 输入y-实际输出v-设定值ts-采样周期 % 输入w0-观测器带宽wc-控制器带宽b0-控制增益估计 % 输出u-控制量z1 z2 z3-状态估计v1 v2-过渡信号及其导数 persistent z1p z2p z3p v1p v2p if isempty(z1p) z1p 0; z2p 0; z3p 0; v1p 0; v2p 0; end % 跟踪微分器TD离散最速形式简化为线性跟踪 r wc * 3; v1 v1p ts * v2p; v2 v2p ts * (-r * (v1p - v) - 2 * sqrt(r) * v2p); % 扩张状态观测器ESO离散欧拉法 beta1 3 * w0; beta2 3 * w0^2; beta3 w0^3; e y - z1p; z1 z1p ts * (z2p beta1 * e); z2 z2p ts * (z3p beta2 * e b0 * u_prev); z3 z3p ts * (beta3 * e); % 控制律线性PD 扰动补偿 u0 wc^2 * (v1 - z1) 2 * wc * (v2 - z2); u (u0 - z3) / b0; % 更新持久变量 z1p z1; z2p z2; z3p z3; v1p v1; v2p v2; end这段代码有个细节值得注意u_prev。ESO的更新需要用到上一时刻的控制量u但在Simulink的MATLAB Function里u是在当前步计算出来的直接用会造成代数环。解决办法是把u也声明为persistent变量用上一拍的值参与ESO计算。这是工程实现中很容易踩的坑很多人仿真直接报错就是因为这个。参数初设方面被控系统真实b值大约在2.5左右b0可以设成2。采样周期ts取0.001秒。观测器带宽w0先取30控制器带宽wc取10。后续根据响应曲线再调整。仿真时长到2秒设定值在0.2秒时从0阶跃到1负载扰动在1秒时加入幅值为0.5的阶跃检验系统的抗扰能力。3.3 参数整定方法与仿真结果分析参数整定的顺序非常重要。我第一次用ADRC的时候把三个模块的参数混在一起调结果根本分不清是哪个参数引起的振荡。后来总结出正确的操作顺序。第一步先不接TD直接让设定值走阶跃只调试ESO和控制律参数。第二步把ESO的w0固定在一个适中值让控制律的wc从较小的值逐步增大。观察系统在阶跃响应下的超调量和上升时间。第三步把wc固定下来再逐步提升w0。观察系统在负载扰动下的恢复时间。最后再引入TD用平滑过渡消除剩余超调。在这个案例中我以w030、wc10为初始参数运行系统上升时间约0.35秒无超调但1秒加入负载扰动后转速有约0.08的偏差恢复到稳态大约需要0.3秒。将wc提高到15上升时间降到0.22秒仍然无超调。将w0提高到50后扰动引起的偏差降到0.03恢复时间缩短到0.15秒。和PID对照实验很能说明问题。我调试了一个经典PID控制器用工程整定法试了很多组参数最终做到无超调和快速响应之间平衡。在同样的阶跃设定下PID上升时间约0.3秒但扰动恢复需要将近0.5秒而且负载突变瞬间的偏差比ADRC大两倍以上。这说明ADRC在“抗扰动”这一点上确实是碾压级的表现。这个案例中因为被控对象带有库仑摩擦PID在低速趋近稳态时容易因摩擦非线性产生极限环振荡——位置在小范围内来回抖动。而ADRC的ESO实时估计了摩擦力的影响并补偿掉低速段平稳收敛没有抖动。这一点对高精度定位应用非常有价值。4. 常见问题与排查技巧实录4.1 高频振荡当心观测器带宽拉太高ESO带宽w0参数是ADRC双刃剑。w0越大扰动估计越及时抗扰性能越好但超过临界值后观测器会对测量噪声产生严重的放大效应。现象就是控制量u在高频剧烈抖振执行机构发出尖锐的嗡鸣声严重时直接损坏执行器。排查方法先操作执行机构不动记录控制量波形。如果控制量在无输入时就有高频抖动说明是观测器把噪声放大后补偿项z3/b0产生了高频分量。解决办法是把w0降下来或者在测量信号进入ESO之前加一阶低通滤波。不过滤波会带来相位延迟建议滤波截至频率至少取ESO带宽的3倍以上减少相位损失。另一种更隐蔽的高频振荡来自于ESO补偿通道直接作用于执行机构。因为总扰动估计值z3包含高频成分直接除以b0然后加到控制量里高频噪声就被注入到物理系统。工程上可以在u0中增加小量的减振项或在z3补偿路径中串联低通滤波器。很多老工程师会在ADRC外围加个简单二阶低通非常有效。4.2 初值跳变引发的积分型尖峰当系统从停止状态启动时如果ESO的初始状态变量都是0而实际被控对象的位置存在偏差观测误差会很大。β1乘上大误差会瞬间产生一个巨大的z1修正量控制量可能出现尖峰脉冲。解决方案有两种。第一种是在启动时将ESO的状态初值重置为当前测量值。在数字实现里检测到首次上电或使能信号边沿时把z1初始化为当前的y值z2和z3保持为0。这样观测器从零误差状态起步不会产生启动冲击。第二种方案是采用“软启动”策略把设定值经过TD生成平滑过渡的同时把ESO的z3经过一个斜坡启动。在实际工程中很多运动控制系统要求上电时输出轴不能突然动作这个斜坡策略能保证执行机构平滑启动。我在一次现场调试中遇到过启动瞬间电流直接顶到驱动器限幅值的问题排查半天确认ESO初值没设置对。后来在代码中加了初值对齐逻辑启动冲击完全消失。这个问题非常隐蔽仿真时因为模型初始状态基本都是0不容易暴露但一到实物上就原形毕露。4.3 b0漂移导致估计失准的应对方法b0是ADRC中唯一需要依赖对象知识的参数。b0取值偏离实际值b时ESO会把(b - b0)u这一项也当成扰动估计出来。只要b0和真实b在一个量级范围内系统仍然能工作但性能会有所下降。b0比实际值偏小会导致补偿不足偏大会导致过补偿和振荡。对参数变化大的对象比如负载惯量随工况大幅变化的机械臂固定b0可能导致性能波动。解决办法是引入自适应机制让b0随着系统惯量或增益的变化在线调整。工程上比较实用的做法是用一个增益调度表根据可测的工况信号切换不同的b0值。更轻量的做法是“范围自适应”。设定b0在额定值的0.5倍到2倍之间线性变化通过ESO的估计误差来修正。这个方法不要求精确建模但需要有明确的可测关联信号。如果对象增益变化完全不可测那就只能靠提高观测器带宽来兜底让ESO更快地跟踪总扰动变化。4.4 常见问题速查表故障现象可能原因排查方法控制量高频抖振w0过高噪声放大降低w0或在测量通道加低通滤波启动瞬间冲击电流大ESO初值未对齐启动时用当前测量值重置z1初值设定值阶跃时超调明显TD的r参数过大或wc过高减小r或wc延长过渡过程稳态精度差b0偏差太大重新辨识b0或提高w0抗扰恢复时间过长w0和wc偏小逐步增大w0并配合提升wc系统低速抖动摩擦非线性补偿不足提高w0确保ESO及时估计摩擦项实战中定位问题要有边界思维。先判断是跟踪问题设定值响应还是抗扰问题扰动响应然后分别对应TD/控制律参数和ESO参数。不要一上来就全面调整那个折腾劲我深有体会。5. 进阶经验从仿真迁移到嵌入式系统的几个关键细节5.1 离散化与采样周期的取舍大多数ADRC理论推导基于连续时间但实际控制器必须在数字处理器上离散执行。最常用的是欧拉法和双线性变换法。观测器通常采用欧拉法即可因为实际采样率足够高时精度差异不明显。采样周期ts的选择是ADRC能否成功落地的关键。理论上采样频率至少是观测器带宽的10倍以上否则离散化误差会严重影响估计精度。也就是说如果w0取50采样频率至少要500Hz实际中我建议取到1000Hz以上留足裕量。在DSP或ARM上ADRC的计算量并不大每秒1000次控制在现代芯片上毫无压力。采样周期固定后TD的离散化也需要同步。如果TD采用最速控制函数的精确离散形式复杂度稍高但能保证稳态精度。简化版线性TD在采样周期很短时可以正常工作我实测20kHz控制周期下两者几乎没有差别。5.2 限幅和抗饱和处理ADRC的ESO在控制量u被限幅时会出现观测器发散风险。原因在于发生限幅后实际输入到被控对象的不是u而是限幅值但ESO使用的是计算出的u两者不一致导致ESO的状态估计产生偏差。如果限幅持续较长时间偏差会累积z3的估计值会持续增大最终失控。解决方案有两种。一种是做“条件积分”式处理检测到限幅后冻结z3的更新防止扰动估计无限增大。另一种更彻底构建ESO时使用实际输出到被控对象的限幅后控制量而不是计算出的控制量。具体实现上在代码里要先算u然后做限幅用限幅后的u_sat去更新ESO。这个细节不处理好系统在接近限幅的工况下非常容易失控。我见过不少仿真里好好的代码一加限幅就炸都是因为这个原因。5.3 代码移植时的数据结构和性能优化从MATLAB迁移到C代码最自然的方式是将ADRC核心函数封装为独立的模块。建议用结构体保存所有状态参数方便在多个控制轴之间复用。例如typedef struct { float ts; float w0; float wc; float b0; float z1, z2, z3; float v1, v2; float beta1, beta2, beta3; float limit; } ADRC_Handle;初始化函数负责根据w0和wc预计算beta1、beta2、beta3以及kp、kd。主控制周期函数接收目标值v和反馈值y返回控制量u。所有状态更新都在函数内部完成外部只需要保持一个实例。性能上ADRC的主要计算量集中在ESO和三阶状态更新使用float类型即可满足大部分控制场景但在精度要求较高或需要长时间积分时建议用double。代码中尽量避免使用三角函数和除法尤其是除法在DSP上耗时较高。b0的除法可以通过预计算1/b0在运行时改为乘法。5.4 现场调试口诀多年调试下来ADRC现场参数的获得让我总结了一套很实用的“口诀”先定采样周期再定b0量级这是地基。b0可以用阶跃响应法粗测从控制量阶跃到输出变化率的比值获得。wc从小到大调直到系统响应速度满意且不振荡。这一步相当于调PD的增益。w0从wc的3倍开始往上涨直到扰动抑制效果满意或噪声开始明显。TD的r参数最后调用来平衡超调与快速性。口诀的要点是“分层整定逐步逼近”。每一个参数都只在特定方向上有主导影响分开调就不容易迷路。切记不要同时动两个参数。5.5 和现代控制方法的融合思路ADRC并不是孤立的。近年来很多研究把它和模型预测控制、滑模控制、模糊控制等方法结合形成混合控制方案。比如在MPC框架里用ESO做扰动估计可以减少MPC对精确模型的需求在滑模控制中引入ESO可以削弱抖振因为扰动被前馈补偿后滑模增益不需要设得过大。如果你已经在工程中熟练使用PID可以尝试把ESO只作为扰动前馈模块接入现有PID环路中。这种改造方式对现有系统影响最小又能显著提升抗扰能力。我实测过在温控系统中做这种改造设定值响应曲线几乎不变但负载阶跃引起的温度波动幅度下降了60%以上。从更宏观的视角看ADRC的“观测-补偿”思想可以被迁移到任何需要估计未知动态的系统中比如数据驱动控制、故障诊断、观测器设计等领域。韩京清先生当年提出这套体系的初衷就是“让控制更贴近工程实践”今天这个目标依然有很强的现实意义。
返回列表