简介:资源聚焦自抗扰控制(ADRC)在迟滞非线性系统中的应用,面向自动控制领域的研究人员、工程师及相关专业学生,旨在解决压电执行器、智能结构等场景中迟滞带来的控制难题。内容围绕迟滞模型、迟滞非线性、迭代控制、ADRC跟踪及非线性ADRC展开,提供基于模型逆和D型迭代学习控制的MATLAB实现代码。两个m文件分别对应模型逆补偿与D型迭代学习策略,前者用于补偿系统的非线性特性,后者通过迭代更新控制输入提升重复任务下的跟踪精度,可直接用于算法仿真与性能对比。资源包为1KB的RAR压缩包,共2个文件,均为MATLAB脚本,现有468人学习下载。对于需要掌握ADRC扩展应用、迟滞非线性补偿或迭代学习控制实现的读者,这份代码提供了简洁的参考实现,有助于快速理解核心思路并复现实验结果。
1. 迟滞非线性与 ADRC 的匹配逻辑
压电陶瓷或磁致伸缩执行器在精密定位时,输入电压与输出位移之间并不是单值对应:同样一个电压点,在上升段和下降段会输出两个不同的位移,形成迟滞环。这个环的存在让正弦轨迹跟踪出现相位滞后、拐角变圆,严重时一个 1 Hz 的往复扫描就能累积几十微米的跟踪误差。普通 PID 把迟滞当作可线性化的高频扰动来处理,结果往往是积分项越拉越紧,极限环反而更明显。
ADRC 的立场则不同:它不追求精确描述迟滞环,而是把未建模的迟滞项归入总扰动,由扩张状态观测器实时估计并在控制量里抵消。把迟滞模型、迭代控制和 ADRC 放在同一个仿真框架中,目标就是验证重复轨迹跟踪下误差能被压到接近执行器分辨率。这个组合适合三类人:做精密运动平台的工程师、研究智能材料驱动器控制的研究生,以及想快速验证非线性控制算法的 MATLAB 用户。下面按实现顺序把每个环节拆开讲。
2. ADRC 的 ESO 与非线性反馈:迟滞系统的补偿边界
2.1 韩京清提出的 ADRC 核心构成
韩京清提出的 ADRC 核心构成分三段:跟踪微分器(TD)、扩张状态观测器(ESO)和非线性状态误差反馈(NLSEF),外加一个扰动补偿回路。TD 先对参考信号安排过渡过程,避免阶跃或快速变化直接把迟滞环的尖锐拐角激励出来;ESO 是核心,它把系统输出和总扰动分别扩张成不同的状态变量,一个估计输出,一个估计扰动;NLSEF 用非线性函数组合跟踪误差和误差导数;最后用 ESO 的扰动估计值 z2 做前馈补偿。
对迟滞系统来说,ESO 估计出的“总扰动”里包含迟滞非线性、未建模动态和外部负载。这里有一个容易误判的点:并非必须使用非线性 ESO 才能处理迟滞。线性 ESO 配上足够的观测器带宽,也能把迟滞当作时变扰动估计出来,性能差别主要体现在抗噪能力和收敛速度上。ADRC_with_DtypeILC.m和ADRC_with_model_inverse_typeILC.m这两个文件里的反馈层,用的基本都是线性 ESO 加扰动补偿,区别只在前馈层如何加入迭代学习。
2.2 迟滞模型选型与仿真对象
仿真中建立迟滞对象,常见做法是选 Bouc-Wen 类微分方程模型,而不是 Preisach 模型。Preisach 精度高但需要存储二维分布函数,离线辨识和实时逆运算都比较重;Bouc-Wen 参数少、递推格式简单,适合与 ESO 放在同一个定步长循环里做数值仿真。简化的离散 Bouc-Wen 模型可以写成下面的函数:
function [xh_new, y] = boucwen_step(u, du, xh, dt, p) % p = [alpha, beta, gamma, n, kx, ku] % alpha 控制迟滞环高度 % beta, gamma 控制环的胖瘦与形状 % n 通常取 1~2,n=1 时呈饱和型迟滞 dxh = p(1)*du - p(2)*abs(du)*abs(xh)^(p(4)-1)*xh ... - p(3)*du*abs(xh)^(p(4)); xh_new = xh + dt*dxh; y = p(5)*xh_new + p(6)*u;调用时,外部主循环每次传入当前输入增量 du 和上一拍的内部状态 xh。p(5) 是迟滞分量到输出的比例系数,p(6) 是输入直通项系数,两者共同决定输出幅值。实际整定时,先固定 p(6) 让系统在低频段近似线性,再用 p(1) 和 p(2) 调节环的宽度。这个模型的不光滑导数会给 ESO 的差分计算带来高频分量,所以后面观测器带宽要留有余量。
2.3 ESO 离散化与带宽参数
线性 ESO 的离散递推非常直接,Euler 法就够用。状态 z1 跟踪输出,z2 跟踪包含迟滞在内的总扰动:
function [z1, z2] = eso_step(z1, z2, y, u, b0, h, w0) % 线性扩张状态观测器,Euler 离散 % w0 观测器带宽,决定估计速度与噪声抑制的折中 beta1 = 2*w0; beta2 = w0^2; e = z1 - y; % 输出估计误差 z1 = z1 + h*(z2 - beta1*e + b0*u); z2 = z2 + h*(-beta2*e); end这里 b0 是控制增益估计值,是 ADRC 里最敏感的参数。它不要求精确,但方向不能错。若 b0 与实际增益偏差超过约 30%,ESO 会把一部分已知动态也当作扰动,z2 的波形会明显滞后于真实扰动。w0 一般取系统开环穿越频率的 5 到 20 倍,采样频率足够高时再往上加;一旦 z2 出现高频毛刺,说明 w0 已经大到把传感器噪声也估计进去了。
| 参数 | 作用 | 整定建议 |
|---|---|---|
| w0 | ESO 带宽 | 5~20 倍穿越频率,毛刺明显时下调 |
| b0 | 控制增益估计 | 阶跃响应辨识,偏差控制在 ±30% 内 |
| h | 采样/仿真步长 | 小于最快时间常数的 1/10,Bouc-Wen 需要小步长保证数值稳定 |
需要强调,ESO 的扰动补偿能力只保证“估计得出来”,不保证“补偿得干净”。迟滞环在输入方向反转时斜率发生突变,z2 的导数会在反转点附近出现尖峰,这会给后面的迭代学习提供错误参考。因此实际工程里,ADRC 反馈层负责把系统变成了一个“带残差的积分器型对象”,ILC 层再针对残差做批次前馈学习,两层职责必须分开。
3. 迭代控制叠加:D 型 ILC 与模型逆型 ILC 的实现差异
3.1 ILC 的适用前提:重复批次
迭代学习控制(ILC)不是什么场景都适用,它有一个明确前提:任务重复、轨迹固定、初始状态一致。迟滞系统恰好符合这个前提,因为执行器在每次扫描前都会被复位到同一个机械位置,输入电压轨迹相同,迟滞环的历史依赖反而变成了一种“可学习的重复性误差”。如果每次开始前迟滞内部状态 xh 没有复位到同一值,ILC 学到的前馈会和学习批次错位,越学越差。
在 MATLAB 主循环里,I L C 通常作为外层批次循环,ADRC 作为内层实时反馈循环。外层存下来的前馈信号是时间的函数,下一轮直接叠加在 ADRC 输出上。D 型和模型逆型两种 ILC 的差别,就在于“如何根据上一轮的误差构造修正量”。
3.2 D 型 ILC 更新律与 MATLAB 片段
D 型 ILC 的更新依据是误差的导数或差分。离散形式写为:
% D 型迭代学习:利用误差差分更新前馈 for t = 2:N e_dot = (e_k(t) - e_k(t-1)) / h; % 误差变化率 u_ff_next(t) = u_ff_k(t) + Ld * e_dot; end参数 Ld 是学习增益,符号必须与对象方向一致。若第一轮学习后误差 RMS 不降反升,多半是 Ld 正负号反了。D 型的优势是不需要对象模型,只要知道误差在增大还是减小就够了;缺点是误差信号里的高频噪声会被差分放大。通常做法是先把误差序列做一次低通滤波,再去计算差分,否则几轮迭代后前馈里会充满毛刺。
ADRC_with_DtypeILC.m文件的思路就是让 ADRC 保证闭环稳定,同时把每轮误差记录下来,用 D 型学习率把误差变化趋势折算成前馈修正。因为 D 型对瞬态变化敏感,它更适合参考轨迹里带快速加减速的段,比如三角波扫描的拐角附近。
3.3 模型逆型 ILC 与零相位信号处理
模型逆型 ILC 并不直接使用误差的原始时间序列,而是先把误差经过一个逆模型整形,再作为学习修正量叠加。这里的“逆模型”并不是严格数学意义的迟滞逆,而是对线性化主通道的近似逆,常见做法是用系统辨识得到的二阶传递函数逆,或简化的线性增益。更新结构如下:
% 模型逆型 ILC:误差先整形再学习 e_filt = filtfilt(B_f, A_f, e_k); % 零相位低通,避免群延迟 u_ff_next = u_ff_k + Lm * inv_model(e_filt);注意这里我用的是filtfilt,不是filter。离线批次数据可以整段处理,用filtfilt可以让滤波前后相位延迟为零;如果换成filter,误差信号会被延迟几十个采样点,更新出的前馈和实际轨迹错位,迭代根本不会收敛。这是两个实现差异里最容易踩的坑。逆模型的幅值不需要很准,ILC 本身会逐步把残余误差压下去,但相位对齐必须保证。
模型逆型 ILC 的优点是学习量更平滑,噪声不会被直接放大;缺点是过度依赖辨识精度。若逆模型相位错误或增益显著偏小,学习速度会非常慢,看起来像停滞在实际误差平台上。
3.4 两种 ILC 与 ADRC 的输出叠加方式
无论哪种 ILC,最终控制量都是 ADRC 反馈量和前馈量的代数和。区别在更新位置上:D 型学习的是误差的差分,模型逆型学习的是误差经逆模型后的形状,两者的物理含义完全不同。
| 对比项 | D 型 ILC | 模型逆型 ILC |
|---|---|---|
| 更新依据 | 误差差分 | 逆模型整形后的误差 |
| 模型依赖 | 基本不需要 | 需要近似逆模型 |
| 相位敏感性 | 差分本身带半拍延迟 | 低,可用零相位滤波 |
| 噪声敏感度 | 高 | 低 |
| 适用阶段 | 快变段、拐角处 | 全频段稳态跟踪 |
| 对应文件 | ADRC_with_DtypeILC.m | ADRC_with_model_inverse_typeILC.m |
实际运行时,ADRC 的 z2 已经把包括迟滞在内的慢变扰动抵消了大部分,ILC 处理的对象只是残余的、重复性的小误差。因此 ILC 的学习增益通常给得比较保守:Ld 和 Lm 从 0.01 到 0.05 起步,每轮观察 RMS 变化,而不是一步到位。若增益过大,前馈会产生振荡,这种振荡往往只在第三四轮迭代才暴露出来。
4. MATLAB 脚本结构、参数整定与收敛性判断
4.1 仿真主循环与批次外循环
这两个.m文件的整体结构高度相似:外层是迭代学习次数循环,内层是单个周期的实时控制循环。外层变量是 u_ff 和 e_k,内层变量是状态、ESO 状态和每一时刻的控制量。骨架如下:
% ADRC + ILC 批次循环骨架 for k = 1:K_max xh = 0; % 每批开始前复位迟滞内部状态 z1 = 0; z2 = 0; % 观测器状态归零,保持初始条件一致 u_ff_k = u_ff; % 当前批的前馈信号 for t = 1:T_steps % 计算ADRC反馈量 [z1, z2] = eso_step(z1, z2, y(t), u_adrc, b0, h, w0); u0 = nlsef(ref(t), y(t), z1); % 简化的非线性反馈 u_adrc = (u0 - z2) / b0; % 叠加迭代前馈 u_full = u_adrc + u_ff_k(t); % 调用带迟滞的对象模型 [xh, y(t)] = boucwen_step(u_full, du(t), xh, dt, p); end e_k = ref - y; u_ff = update_ilc(u_ff, e_k, type); % 选择 D 型或模型逆型 end这段骨架里最关键的是每批开始时把 xh 和 ESO 状态一律清空。迟滞模型的内部状态 xh 记录了输入历史,若不清空,下一批的迟滞环和上一批不重合,ILC 学习的参考轨迹就失真了。ESO 状态清不清空影响相对小,但保持初始条件一致总归是安全的工程习惯。
4.2 参数整定顺序与优先级
多数人拿到脚本会先调学习增益,这是顺序上的错误。正确顺序是先把 ADRC 反馈层调稳,再开 ILC。先用纯 ADRC 跑一个批次,看跟踪误差 RMS 是什么量级;这个量级就是 ILC 的起点。如果纯 ADRC 下系统已经振荡,ILC 学到的全是振荡模式,后面不可能收敛。
| 步骤 | 操作 | 检查指标 |
|---|---|---|
| 1 | 固定 w0、b0,关闭 ILC | 阶跃响应无振荡,误差 RMS 稳定 |
| 2 | 从极小 Ld/Lm 起步 | RMS 随迭代次数单调下降 |
| 3 | 逐步提高误差滤波截止频率 | 前馈信号是否出现高频毛刺 |
| 4 | 微调 b0 ±10% | RMS 是否进一步下降,z2 是否更平滑 |
参数整定里,b0 对 ILC 的影响常被忽略。b0 偏差较大时,ADRC 反馈回路本身的作用被扭曲,残差里的一半是真正的迟滞,另一半是控制器自身失配造成的伪误差。ILC 会把伪误差也学进去,等下一批迟滞状态变化时,这部分前馈反而变成干扰。所以如果 ILC 连续迭代 5 轮以上都停在同一个误差平台,先回头调 b0,而不是继续加大学习增益。
4.3 收敛性判断与发散处理
迭代学习的收敛不是看单轮误差,而是看相邻两轮误差的变化趋势。常见判断方法是在批次之间做 RMS 比较:
% 相邻两轮误差 RMS 对比 rms_k = sqrt(mean(e_k.^2)); rms_prev = sqrt(mean(e_prev.^2)); if rms_k > 1.5 * rms_prev % 误差不降反升,优先检查学习增益符号和滤波截止频率 warning('ILC 发散,减小增益或检查前馈方向'); break; end if abs(rms_k - rms_prev) < tol % 进入平台期,说明当前参数下已到极限 fprintf('误差平台期,RMS=%.4f\n', rms_k); end1.5 倍这个阈值不是固定标准,但作为发散判据很灵敏:正常收敛时相邻两轮误差不会大幅反弹,一旦反弹说明学习方向错了或增益大了。发散处理顺序是:先减半学习增益,再看滤波频率是否过高,最后检查迟滞内部状态复位是否生效。还有一种隐蔽问题,就是参考信号本身的零点偏移和误差序列均值不为零,ILC 会把直流偏置慢慢累积进前馈,表现为每轮 RMS 都降,但最后前馈信号被抬到离谱的幅值。
5. 两个 .m 文件对比分析:跟踪误差与参数微调技巧
5.1 观察两个文件输出差异的三个指标
分别运行ADRC_with_DtypeILC.m和ADRC_with_model_inverse_typeILC.m,不要只盯着最终误差曲线图,重点看三个中间量:第一轮误差频段分布、第五轮前馈信号形状、以及 z2 估计扰动在输入方向反转处的尖峰幅值。D 型文件的第一轮误差通常在高频段更突出,因为它的学习律本身就会放大误差变化;模型逆型文件的前馈则更平滑,但收敛速度会慢一到两轮。
判断优劣不能脱离轨迹类型。如果参考信号是正弦,两个文件最终 RMS 差别不大;如果是带快速折返的三角波或梯形轨迹,D 型的瞬态修正优势会更明显,模型逆型则在稳态段表现更好。实际工程里我会用脚本记录每轮 RMS,画成曲线,看哪条曲线先进入平台期,平台期越低说明前馈与迟滞环匹配越准确。
5.2 零相位滤波与初始状态复位技巧
最后一个值得固化的技巧是在 ILC 更新前对误差信号做去均值和零相位滤波。直接用filter会引入群延迟,这个延迟对反馈闭环可能无感,但对迭代学习是致命的,因为它会让前馈永远落后参考轨迹几个采样周期;改用filtfilt离线滤波后,零相位对齐,学习内容才反映真实的迟滞形变。滤波截止频率取跟踪信号基频的 5 到 10 倍:取太小会削掉拐角信息,取太大会把迟滞环转折处的尖峰学进前馈。
每批开始时,除了把 ESO 状态清零,还要把误差序列的均值减掉再进入更新律。迟滞环本身不一定关于零点对称,若误差均值不消除,D 型学习会把直流偏置一步步累积成前馈的常数项,最后抵消掉 ADRC 的积分作用。把第 4 章的收敛判断嵌进主循环,在每次更新前先执行 detrend 去掉趋势项,再交给 D 型或模型逆型更新律,这样两类 ILC 在前几轮的学习效率都能明显提高,而且不会在电压边界附近出现前馈饱和。
本文还有配套的精品资源,点击获取