迭代学习控制实战:从原理到仿真与参数整定避坑指南
简介面向自动化与控制工程方向的初学者这套迭代学习控制ILC入门演示程序聚焦重复性任务中的轨迹跟踪问题无需精确系统模型即可通过多次迭代逐步修正控制输入提升输出精度。资源包共四个文件包含两个MATLAB脚本、一篇ILC英文综述论文以及一个用于补充归档的压缩包整体约914KB轻量且结构清晰便于快速查看与运行。脚本实现了ILC核心迭代更新逻辑用户可自行修改迭代次数观察不同迭代轮次下系统跟随性能的变化直观理解误差校正与收敛过程同时通过对比曲线还能体会学习率、收敛速度与计算代价之间的平衡。附带的综述PDF对从基础概念到研究进展做了系统梳理便于理论结合实践。目前这套程序已有812人学习下载适合希望快速建立ILC概念并动手仿真的初学者作为入门参考。1. 迭代学习不是玄学重复任务越做越准的背后逻辑做运动控制的人应该都有过这种经历同一台设备同一个轨迹每次跑下来都有差不多的跟踪误差怎么调反馈参数都压不下去。调大增益就开始嗡嗡响调小了又跟不上最后只能把误差指标放宽。事实上这类重复出现的误差根本不需要靠反馈去硬扛思路反过来就行把这批误差记下来下一批开始前把修正量直接加进输入序列系统就会一次比一次准。这就是迭代学习控制ILC。它适合所有“同一个动作反复执行”的场合机械臂往返、点胶路径、伺服压装、注塑曲线、贴片机XY平台。这篇笔记从原理讲到可复现的仿真再到参数整定和现场排坑目标是让你看完能判断自己的设备值不值得上ILC并知道第一版怎么搭。适合人群是不满足于“反馈调参调到头”的工程师以及想把重复精度做一个台阶的自动化和运动控制从业者。2. ILC的工作原理与学习律选型从误差方程看收敛条件2.1 它与反馈控制互补不是替代先把ILC的位置讲清楚。反馈控制PID是实时把当前误差映射成纠偏动作它对“本批次刚发生的、不可预知的扰动”有效但对“每次都一样的那部分误差”没法根治。重复误差往往来自系统建模偏差、负载周期波动、摩擦特性不一致等反馈只能用一个较大增益去实时抵抗代价是噪声放大甚至失稳。ILC的做法完全相反它在批次之间工作拿上一批误差去批量修正下一批的控制输入信号。它不追求环路的实时响应而是让控制输入序列本身蕴含对系统特性的补偿。所以最稳妥的工程组合是“反馈打底、ILC精修”反馈压非重复扰动ILC磨重复偏差。我一般会在评估项目时先抓一次误差曲线让同一轨迹连续跑五遍把五条误差曲线叠在一起看。如果重复占比超过60%ILC就有明显机会如果每次误差形态完全不同说明非重复因素占主导先把机构松动、负载波动、定位基准这些硬问题解决再谈学习。判断任务适不适合上ILC就看三条参考轨迹是否重复、初始状态能否基本一致、系统动态是否稳定可复现。这三条都是硬门槛缺一条就要先解决再谈学习。比如点胶机每个产品的位置有偏差靠视觉引导重新生成轨迹后轨迹之间是相似但不完全相同的这种场合传统ILC需要配合轨迹对齐或缩放才能用不是默认就能成立的。2.2 迭代学习律的本质误差从上一批到下一批的压缩数学上把一个线性系统在批次k的输出近似写作y_k P u_k d_r d_n(k)其中P是输入到输出的映射d_r是每批都一样的重复扰动d_n(k)是随批次变化的非重复扰动。ILC学习律的通用形式为u_{k1} Q(u_k L e_k)e_k y_d - y_k。Q是鲁棒性滤波器L是学习增益。若先忽略Q误差演化可以写成e_{k1} ≈ (I - L P) e_k 非重复项。只要算子(I - L P)在任务频段内的谱半径小于1每一批误差就会被等比压缩这正是“越学越准”的原因。把谱半径翻译成工程师语言如果当前批误差在某个频率分量上被放大了下一批那个频率就会更严重这就是发散。ILC在低频段几乎总是容易收敛的因为对象在低频的幅值和相位都比较规整L又是个正实数增益难办的是高频段模型不确定性大、采样延时明显(I - L P)在高频处很容易超过1。如果不加抑制ILC会把高频噪声当成“真经验”学进去这是新手最常见的翻车点。实验上验证收敛很简单每次迭代算一次误差向量的RMS均方根值画成一条随批次下降的曲线。如果曲线单调下降并进入平台说明学习有效如果在中途掉头向上说明某个频段被放大需要回头检查L和Q。2.3 工程上常见的三种学习律P、PD、PI型怎么选工程落地上很少有人一上来就上一套复杂高阶学习律绝大多数应用都是绕着三种经典形式转。学习律更新式略去Q特点常见场合P型u_{k1} u_k L_p e_k实现最简单需要对象有较好模型或低频增益稳定伺服运动、SCARA轨迹补偿、XY平台PD型u_{k1} u_k L_p e_k L_d é_k带误差导数相位超前收敛速度更快但D项放大噪声必须配合滤波机器人关节、负载惯性变化较大的场合PI型u_{k1} u_k L_p e_k L_i ∫e_k dt对重复性稳态偏差积累作用强压装力控制、注塑压力/温度轨迹、慢过程批次选型的实际经验是第一步默认用P型加低通Q滤波先把重复误差观察到能收敛如果前几代误差下降很慢再考虑加一点D项加快收敛。遇到每批末尾都存在同一方向剩余偏差、像“差一点到位”这种情况再加I项。不要一上来就PD加PI全上参数多了很难排查谁在制造噪声。很多商业控制器里内置的ILC模块默认就是“P型Q滤波”。原因不是理论简单而是这套组合在大部分设备上都能先跑起来后续再根据误差形态决定要不要加更多项。学习律选定之后剩下的工作就是调三个量学习增益、Q滤波器、批次停止条件这正好是第4章要展开的内容。3. 用Python跑通ILC控制器二阶模型、P型学习律与误差收敛曲线3.1 仿真对象设置为什么用二阶模型一个带阻尼的惯量-刚度对象电机轴带动负载近似为二阶机械系统是运动控制仿真里最典型的选择。它体现谐振、有限带宽、相位滞后正好用来观察ILC怎么把反馈压不掉的误差学掉。参数取自然频率wn10 rad/s、阻尼比zeta0.7、采样周期dt0.005s参考轨迹时长2秒。import numpy as np from scipy.signal import TransferFunction, cont2discrete # 二阶机械对象wn 自然频率zeta 阻尼比 wn 10.0 zeta 0.7 num [wn**2] den [1, 2*zeta*wn, wn**2] sys_c TransferFunction(num, den) dt 0.005 N int(2.0 / dt) # 400 步2 秒轨迹 # 零阶保持离散化最接近实际 DAC 行为 sys_d cont2discrete(sys_c, dt, methodzoh) A_d, B_d, C_d, D_d sys_d[0], sys_d[1], sys_d[2], sys_d[3]零阶保持离散化保证输入在两个采样点之间恒定和真实设备里DAC输出零阶保持器一致。如果用欧拉离散化低频特性会偏移仿真结论搬到现场时容易对不上。参考轨迹我用一个梯形速度曲线生成先加速到0.8m/s匀速一段再减速到零。这样轨迹本身的频率含量不高方便观察ILC的收敛过程。t np.arange(N) * dt yd np.zeros(N) v 0.0 for i in range(1, N): if t[i] 0.2: a 4.0 # 0~0.2s 加速 elif t[i] 1.1: a 0.0 # 0.2~1.1s 匀速 elif t[i] 1.3: a -4.0 # 1.1~1.3s 减速 else: a 0.0 v a * dt yd[i] yd[i-1] v * dt加速段0.2秒对应主频大约5Hz轨迹能量基本集中在10Hz以内。如果参考轨迹本身带毛刺要先做平滑规划否则ILC会把规划不平滑带来的误差也学进去。3.2 写一个最小ILC闭环P型学习律的完整仿真被控对象是单输入单输出系统输出为位置。仿真里我加了一个重复性扰动模拟负载力矩带来的周期性误差。逐批加入少量随机噪声模拟每批不一样的非重复部分。# 重复性扰动每批一样模拟周期性负载/摩擦 rep_dist 0.02 * np.sin(2 * np.pi * 0.5 * t) def simulate(u, noise): x np.zeros(2) y np.zeros(N) for i in range(N): y[i] C_d.dot(x) float(D_d[0,0]) * u[i] x A_d.dot(x) B_d[:,0] * u[i] return y rep_dist noise # 初始输入为零P型ILC u np.zeros(N) learn 0.5 rms_history [] for it in range(25): noise 0.003 * np.random.randn(N) # 非重复扰动 y simulate(u, noise) e yd - y rms_history.append(np.sqrt(np.mean(e**2))) u u learn * e # 学习律更新我的实验参数下第一次迭代RMS约0.04到0.05第10次降到0.006附近第25次收敛到0.002左右。收敛下限主要由每批不同的随机噪声决定如果把噪声去掉误差能收敛到接近机器精度。这说明ILC对重复误差的压缩能力极强但对非重复部分无能为力。逻辑说明每次迭代里u是整个输入序列不是某个标量增益。学习更新是整个序列一起更新这正是ILC和反馈控制最大的差异——反馈控制实时修正的是当前控制量ILC批量修正的是下一批的整条控制命令。参数learn0.5表示每批把误差的一半叠加到输入序列上。系统低频增益接近1时误差大致按0.5倍等比下降learn取太小收敛慢取太大高频容易先炸。3.3 对照实验反馈控制与ILC的误差极限为了判断ILC是不是“自嗨”我跑一个纯比例反馈做对照。这里反馈有一拍延时因为离散控制器的输出要经过一个周期才作用于对象这和实际控制系统一致。Kp 10.0 u_fb np.zeros(N) y_fb np.zeros(N) x np.zeros(2) for i in range(N): y_fb[i] C_d.dot(x) err_fb yd[i] - y_fb[i] u_fb[i] Kp * err_fb x A_d.dot(x) B_d[:,0] * u_fb[i] rms_fb np.sqrt(np.mean((yd - y_fb)**2)) print(pure feedback rms , rms_fb)这个反馈闭环的RMS大约在0.02到0.03如果把Kp再拉大系统会因为相位裕量不足开始振荡。而ILC跑完25代后RMS已经到0.002量级差距接近一个数量级。反馈控制对重复误差的压制依赖环路增益环路增益又受稳定性和噪声限制ILC则把误差当作历史信息逐步补偿不需要靠实时高增益去硬顶。需要说明的是这个对照里反馈组没有逐批学习能力它在抗非重复扰动上其实有优势。工程上最终方案往往是ILC前馈加一个低增益反馈二者各管一段而不是让ILC完全替代反馈。4. 三个必调参数与整定顺序学习增益、Q滤波与批次停止4.1 学习增益L从收敛慢到发散只在一瞬间学习增益是第一个要调的参数也是最容易拍脑袋的。它的本质是控制误差反馈到输入修正的比例直接决定每代误差压缩多少。对低频增益接近1的对象L取0.3到0.5是大概率安全区如果现场对模型不确信L从0.2起步。判断依据很简单跑10代看RMS曲线每代下降率。下降率小于10%可以加0.1如果某一次RMS比上一代还高立刻把L减半。L调大并不会出现一个“渐变”的恶化过程。在临界值以下收敛变快越过临界值高频分量开始逐年放大可能从收敛状态直接跳到发散中间过渡很窄。血泪经验仿真里L取0.8很正常现场往往只能用到0.2到0.4因为真实设备有模型误差、时滞和量化噪声高频段的真实谱半径比仿真模型大得多。还要注意L的量纲与被控对象直流增益的关系。如果对象的低频增益不是1比如速度环对象是积分特性学习增益就不能直接理解为“误差的百分比”要先估算对象在工作频段内的增益量级。常见做法是用开环阶跃响应估算输入1对应稳态输出大约多少再让L乘以这个值落在0.3到0.5区间。4.2 Q滤波器把噪声留在没学过的状态Q滤波器是决定ILC能否从仿真走向现场的关键。学习律u_{k1} Q(u_k L e_k)里Q不是加在误差上而是对整条更新后的输入序列做滤波。最常见的设计是零相位低通滤波器截止频率取轨迹带宽的3到5倍。from scipy.signal import butter, filtfilt # 参考轨迹主要能量低于5HzQ截止取20Hz f_cut 20.0 order 2 b, a butter(order, f_cut / (0.5 / dt), btypelow) for it in range(25): noise 0.003 * np.random.randn(N) y simulate(u, noise) e yd - y u_raw u learn * e # 零相位滤波避免相位误差进入学习回路 u filtfilt(b, a, u_raw)Q的作用是把高频噪声从“学习”里剔出去。误差里既有真实需要补偿的低频重复成分也有传感器噪声和机械高频抖动。如果不滤波ILC会逐年把噪声当真实误差学进输入表现为误差先降后升、电机高频嗡嗡声越来越明显。提示filtfilt是非因果滤波只能用于离线批处理或先算好前馈序列再注入。在线实时系统无法直接使用常见替代方案是设计零相位特性的FIR滤波器并补偿固定延时或者在每次更新后对输入序列做一次双向滑动平均。截止频率选太低会牺牲学习精度选太高等于没过滤。我一般先抓一次误差的功率谱看能量主要集中到哪个频率再乘3倍作为Q的截止频率。把20Hz作为初始值对2秒、主频5Hz的轨迹足够。采样率5ms对应奈奎斯特频率100HzQ截止20Hz相当于只学20Hz以下频段给高频留出足够衰减空间。4.3 批次停止条件误差平台期与固化前馈ILC不是跑越多越好。一般跑15到25代RMS曲线就会从快速下降转入平台期。工程上我习惯看连续三次迭代的RMS变化如果每次下降不足2%就认为进入了平台可以把当前u序列导出为前馈命令表。# 停止条件示例连续3次迭代下降率均小于2% for it in range(30): y simulate(u, noise) e yd - y rms np.sqrt(np.mean(e**2)) rms_history.append(rms) u u learn * e if len(rms_history) 4: recent np.diff(rms_history[-4:]) / rms_history[-4:-1] if np.all(recent -0.02): # 下降不足2% break固化前要检查输入序列的幅值是否在驱动器允许范围内。很多设备输出了超限的前馈驱动器一限幅实际效果和仿真差很多。固化后的u只在当前负载、当前轨迹下有最优意义换规格、换速度、换负载重量通通需要重新学习。5. 迭代学习落地避坑5个现场最容易翻车的问题与排查5.1 坑1越学越抖误差先降后升把高频噪声当成了经验现象前5代误差明显下降第10代开始又抖起来电机有高频啸叫误差RMS曲线先降后升。原因学习律把每个采样时刻的误差都当成真实误差去修正而实际误差里包含传感器噪声和机械高频抖动。误差在低频被压住高频被逐批放大最终盖过低频收益。解决把Q截止频率降到轨迹带宽的2到3倍检查采样周期是否足够短建议采样频率至少是Q截止频率的50倍以上。另一个有效手段是对误差序列先做时间平均再学习相当于在批次域做低通能直接压掉随批变化的高频成分。5.2 坑2初始点每次不一样第一批直接发散现象设备每次启动位置有0.1到0.5mm偏差ILC前几代误差忽大忽小曲线不收敛。原因ILC收敛性假设初始状态一致。初值不一致等价于每批多了一个额外输入扰动误差里含有无法由固定输入序列补偿的成分。解决先回零消除初值偏差回零精度不够就在启动段做学习率衰减前0.2秒内不更新输入让反馈先把系统拉回重复段或者从第二批开始学习把第一批当预热。5.3 坑3反馈带宽和ILC打架机械谐振被学出来现象ILC一开伺服轴出现高频“吱吱”声甚至机械接头处可见振动。关掉ILC后噪声消失。原因对象在机械谐振峰附近幅值高、相位变化剧烈(I - L P)在这个频段不收敛谐振分量被逐批放大。解决先做扫频或白噪声激励测出对象频率响应找到谐振峰位置。Q截止频率取谐振峰频率的80%以下如果谐振峰非常尖锐考虑在对象侧加陷波器再让ILC学习陷波之后的系统。这个坑在刚性不足、带长负载的设备上尤其常见不能靠单纯减小L解决。5.4 坑4换轨迹就得全部重学记性好但不会迁移现象把参考速度从0.8m/s改成0.5m/sRMS回到第一代水平之前学的全白费。原因ILC学到的是“针对固定参考轨迹的最佳输入序列”它本质上是时间轴上的查表曲线和轨迹绑定。解决保留多条历史u序列新轨迹先找时间缩放后的近似u作为初始输入再跑10代收敛。插值之后的u要先做一次低通滤波避免时间缩放引入台阶电压。如果轨迹形状变化频繁考虑用点对点ILC或基元学习方案只学工艺关心的几个关键点。5.5 坑5上位机算完一帧要好几毫秒输入时序对不齐现象仿真收敛良好实机一跑就振荡。查了机械、查了反馈都没问题。原因ILC要求误差序列在时间轴上严格对齐。如果控制周期抖动、操作系统抢占严重批次之间的u和y无法对应学习律会把时序抖动当成误差学进去。解决在实时核或中断里固定采样周期学习更新放在非实时线程但用时间戳对u和误差做重采样对齐。现场快速验证时可以把Q带宽余量加大容忍几毫秒的时序抖动代价是学习精度下降。6. 进阶用法与验证技巧把ILC从仿真搬到真实设备的三种姿势6.1 轨迹时间轴缩放把旧经验“拉伸”给新曲线当新轨迹和旧轨迹形状相同、速度不同可以通过时间缩放迁移旧前馈。若旧轨迹时长T1新轨迹时长T2把旧u按比例映射到新时间轴上再做一次低通滤波。6.2 点对点ILC只学工艺关心的关键位置很多设备只要求某几个点位精度比如停止位、压装到位点、变距位置。点对点ILC只在这些关键点更新输入不学整条曲线。优点是抗噪声能力强、对相位不敏感可以在只有点位没有完整期望轨迹的设备上使用。6.3 ILC加反馈复合把误差拆成两块批间ILC负责上一批观察到的重复误差批内反馈负责实时扰动。实现时注意让ILC学习的是“去除反馈补偿效果”之后的等效误差否则会把反馈的贡献也学进去造成两倍补偿。常见结构是ILC输出作为前馈反馈输出叠加其上。我在一个伺服压装项目里吃过亏跳过Q滤波直接上ILC试验曲线第一轮很好第二轮开始高频抖动大半个晚上都以为是机械松动最后发现是误差功率谱里30Hz附近的噪声被逐批放大。从那时起我养成一个习惯任何ILC上机前先抓一批误差FFT把候选Q的截止频率写在调试表第一行。ILC这个方向对重复任务的价值是实打实的只要摸清重复误差占比照上面这套走通常能把精度提升一个量级。希望帮到你。本文还有配套的精品资源点击获取