☰
开环迭代学习控制TPDILC:从原理到Python仿真的轨迹跟踪实战指南
2026/9/25 23:24:02 网站建设 项目流程

简介:开环迭代学习控制(OL-ILC)资源包面向控制理论与应用方向的学习者,其中TPDILC为一种具体的开环迭代学习算法。包内共2个文件,压缩包约1.11MB,主要由MATLAB例程和配套论文PDF组成;.m文件给出TPDILC仿真实现,可直接运行并观察控制输入的逐次更新与误差收敛过程,也便于修改学习律和参数,对比不同设置对收敛速度的影响;PDF文献讨论制导控制一体化场景下的反馈线性化滑模控制方法,可作为与迭代学习结合的扩展阅读。开环ILC无需实时反馈,而是依据历次运行误差修正控制输入,适合周期性重复任务中追求终态收敛的场合;典型应用包括机械臂重复运动、批处理过程、精密定位等,资源运行门槛低,适合初步了解ILC原理、希望获得可运行示例的研究者或高年级本科生使用。目前已有334人学习下载,内容精简但针对性强,既适合快速上手迭代学习编程,又能通过论文拓展到非线性鲁棒控制设计,值得控制方向学习者参考。

1. TPDILC和开环迭代学习:拿上一轮误差修下一轮输入,先从这里下手

TPDILC 这个缩写放进今天的控制论文里,很像某个新框架的名字,拆开其实是条从 P 型、D 型迭代学习控制(ILC)里长出来的开环学习律:把学习增益做成随时间轴变化的量,每次试验只依赖上一轮误差修正输入,当前试验误差不做实时反馈。它专门解决高重复场景的轨迹跟踪问题——机械臂每天走同一条轨迹、伺服系统反复跑同一步序,能不能用一次次“做完再改”的方式把跟踪误差压下去,而不是靠调一次参数就一直硬扛。适合做机器人轨迹跟踪、重复运动控制、批次过程控制的工程师或者研究生。开环 ILC 结构轻、参数少、上收敛曲线快,但代价是抗噪声弱、对初始条件敏感,所以这篇笔记把数学形式、最小复现代码、收敛曲线横轴对齐和常见翻车点一次说清。

2. 从开环 P 型到 TPD 型学习律:数学形式、收敛条件和三个关键参数

2.1 开环 ILC 和闭环 ILC 的分水岭:只信上次误差,不碰当前误差

迭代学习控制的基本工作方式是让同一个受控对象在有限时间区间内反复执行同一个任务,每一轮称为一次试验(trial)或一次迭代(iteration)。第 k 轮试验得到误差轨迹 e_k(t),学习律拿这个误差轨迹生成第 k+1 轮的输入轨迹 u_{k+1}(t)。整个过程更像“批处理”:一次试验做完,数据攒齐,再统一更新下一次的指令,而不是在运动中实时修改。

开环 ILC 的意思是,更新时只用上一轮误差 e_k,不用当前误差 e_{k+1}。最常见的学习律形式为:

u_{k+1}(t) = u_k(t) + L * e_k(t)

其中 L 是学习算子,可以是比例、微分、比例微分、PID 的组合。因为当前轮量测不会在更新公式里出现,所以实现时只需要两个数组:一个存当前输入轨迹,一个存上一轮误差轨迹,试验结束后离线更新。闭环 ILC 则会在更新的同时把当前试验的反馈误差 e_{k+1} 也并进去,稳定性更强,但实现和调参都复杂一截。

对比项开环 ILC闭环 ILC
更新信息上一轮误差 e_k上一轮误差 + 当前反馈误差
典型形式u_{k+1} = u_k + L e_ku_{k+1} = u_k + L e_k + C e_{k+1}
噪声敏感度较高,误差里的噪声会被学进输入较低,当前反馈能抑制一部分
实现成本两个数组加一个循环需要在线计算反馈修正
适用场景批次过程、离线轨迹复现高精度实时伺服、强扰动工况

我在实际项目中做离线轨迹复现时优先开环,因为可以先验证想学的动态特性到底学不学得会。闭环 ILC 的反馈项会掩盖一部分模型问题,最后调试时很难区分是学习律不好,还是反馈参数拖了后腿。开环 ILC 缺点是遇到比较大的测量噪声时容易把噪声学进输入,后面在避坑章节会专门讲。

2.2 TPD 型学习律怎么写:把 P 和 D 的增益从常数改成时间 t 的函数

P 型 ILC 更新式里,学习增益 γ_P 是常数:

u_{k+1}(t) = u_k(t) + γ_P * e_k(t)

PD 型 ILC 增加误差导数项:

u_{k+1}(t) = u_k(t) + γ_P * e_k(t) + γ_D * ė_k(t)

TPDILC 的核心变化,是把 γ_P、γ_D 从常数推广成关于时间 t 的函数,也就是:

u_{k+1}(t) = u_k(t) + γ_P(t) * e_k(t) + γ_D(t) * ė_k(t)

γ_P(t) 和 γ_D(t) 可以是分段常数、正弦函数、指数衰减函数,也可以按采样点逐点给出。这样做的原因是真实系统的摩擦、惯量、力矩特性在一条轨迹的不同时间点差异很大。比如一个点到点运动中,启动阶段要克服静摩擦,末端要克服弹性回弹,如果在整个时间轴上用同一个学习增益,通常是取最保守的值,导致某些阶段学习速度很慢。给它加上时间变化能力,等于让每个时间段可以有自己的学习强度。

常见的工程做法是只把增益表做成数组,即使第一版跑通的时候全部填常数也行。先把变量位置留出来,后面处理摩擦力突变、负载变化时才不用重构代码。下面这段伪代码表达了增益数组如何参与更新:

# 增益可以是常值数组,也可以按时间变化 import numpy as np N = 1001 # 一次试验的采样点数 t = np.linspace(0, 1, N) # 常数版本,先跑通再改 gamma_P = 0.5 * np.ones(N) gamma_D = 0.1 * np.ones(N) # TPD版本:启动阶段加比例增益,末段增加微分阻尼 gamma_P_tpd = 0.5 * (1.0 + 0.3 * np.sin(2 * np.pi * t)) gamma_D_tpd = 0.1 * (1.0 - 0.5 * np.exp(-5 * t))

增益数组和误差轨迹逐点相乘,本质上是在时间轴上做逐采样点学习。要注意的是,γ_P(t) 和 γ_D(t) 不能同时都很大,比例增益大会加速收敛但容易振荡,微分增益大能抑制振荡但会把噪声放大。TPD 的复杂度也在这里:增益从两个数变成两个数组,需要的调参空间变大。我一般先将两个增益都设成常数去跑通收敛,再在误差持续时间段上逐段调。

2.3 收敛条件和 λ 范数:跑仿真前先确认这个学习律有机会收敛

开环 ILC 不是随便给一组增益都能收敛。考虑线性被控对象 G(s),P 型开环 ILC 的误差传递关系是:

E_{k+1}(s) = (1 - γ_P * G(s)) * E_k(s)

每一轮迭代误差都要乘一个传递函数,想让误差幅度越来越小,在频域上就要满足:

max | 1 - γ_P * G(jω) | < 1

这个条件对 γ_P 的选择施加了直接约束。PD 型 ILC 的误差传递变成:

E_{k+1}(s) = (1 - (γ_P + γ_D * s) * G(s)) * E_k(s)

实际仿真中我不会每次都手推这个条件,而是画出被控对象频率响应,再大致估计增益边界。对相对阶较高或者存在大时滞的对象,简单 P 型开环 ILC 往往很难收敛,这时候 PD 型或者带超前补偿的 ILC 才可行。这是选型问题,不是调参问题。

ILC 理论里还常提到 λ 范数,公式是:

‖x(t)‖_λ = sup_{t∈[0,T]} e^{-λt} * ‖x(t)‖

它实质上是把时间轴末端的信号乘上指数衰减权重,再取上确界。引入 λ 范数后,可以把时间轴上的耦合关系压缩成一个常数,从而用压缩映射证明开环 ILC 在有限时间区间上的收敛。对工程人员来说,最重要的是记住一件事:ILC 收敛是在“有限时间区间、重复任务、相同初始条件”三个前提下讨论的,只要有一个被破坏,收敛性就不再被保证。后面避坑章节里好几个翻车案例都能追溯到这里。

3. 用 Python 复现最小开环 ILC:单连杆轨迹跟踪仿真

3.1 被控对象与参考轨迹:先有“重复过程”才有“学习”

我通常用一个带阻尼和轻微非线性的二阶系统模拟简单机械臂,因为二阶系统足够表现出 ILC 的收敛过程,参数也不多。被控对象用以下状态空间形式:

import numpy as np import matplotlib.pyplot as plt # 时间参数:一次试验 1 秒,采样 1ms T = 1.0 dt = 1e-3 N = int(T / dt) + 1 t = np.linspace(0, T, N) # 被控对象参数 wn = 2 * np.pi * 4.0 # 自然频率 4 Hz zeta = 0.35 # 阻尼比 A = np.array([[0.0, 1.0], [-wn**2, -2.0 * zeta * wn]]) B = np.array([[0.0], [wn**2]]) C = np.array([[1.0, 0.0]]) def run_trial(u_seq, x0): x = x0.copy() y_hist = [C @ x] for k in range(N - 1): x_dot = A @ x + B.flatten() * u_seq[k] x = x + x_dot * dt # 库仑摩擦近似:速度接近零时阻力增大,给学习留一点非线性的量 friction = 0.05 * np.tanh(10.0 * x[1]) x = x + np.array([0.0, -friction]) * dt y_hist.append(C @ x) return np.array(y_hist).flatten()

参考轨迹采用五次多项式,从 0 平滑过渡到 1,两端速度和加速度为零,避免给 ILC 输入一个需要无穷大加速度的参考信号。轨迹参数在代码里是这样写的:

# 五次多项式平滑轨迹 def smooth_ref(amp=1.0, t_t=0.0): s = np.clip((t - t_t) / (T - t_t), 0.0, 1.0) return amp * (10.0 * s**3 - 15.0 * s**4 + 6.0 * s**5) yd = smooth_ref(amp=1.0)

这里让输出量纲保持无单位,便于比较误差。注意 fy 输出和参考 y 都是从 0 开始的,这很重要——ILC 对初始偏移极其敏感,如果参考轨迹起点是 0 而系统输出从别的位置开始,后面不管怎么学都学不稳。

3.2 核心迭代循环:存储上一轮输入,整条轨迹统一更新

开环 ILC 主循环不需要神经网络,也不需要优化器,就是一个数组更新。核心代码如下:

# TPD 型时间变化增益 gamma_P = 0.8 * (1.0 + 0.2 * np.sin(2 * np.pi * t)) # 比例增益 gamma_D = 0.15 * (1.0 + 0.3 * np.sin(4 * np.pi * t)) # 微分增益 # 初始输入为零,从第一轮试验开始学 u = np.zeros(N - 1) x0 = np.zeros(2) rms_list = [] peak_list = [] err_last = None for trial in range(30): y = run_trial(u, x0) e = yd - y de = np.gradient(e, dt) # 开环更新:只依赖上一轮误差 corr = gamma_P * e + gamma_D * de u = u + corr[:-1] # 输入序列长度 N-1,去掉最后一个采样点 rms = np.sqrt(np.mean(e**2)) peak = np.max(np.abs(e)) rms_list.append(rms) peak_list.append(peak) err_last = e.copy()

这段代码里有两个容易弄错的地方。第一,输入序列 u 的长度是 N-1,因为最后一个控制步从 t = (N-2)dt 作用到 (N-1)dt,不需要为最终时刻再给定输入;误差 e 是全长度 N 的,所以做修正时要 corr[:-1]。第二,np.gradient 求的是数值导数,如果 dt 不够小,误差峰值附近会出现明显的高频噪声,后面避坑章节会专门说。

增益 gamma_P 和 gamma_D 都带时间变化项,这就是从普通 PD 型向 TPD 型过渡的写法。在仿真初期,我建议先在代码里把增益数组改成常数跑一遍,看到误差收敛后再引入时间变化,这样能把问题隔离成“模型问题”和“增益设计问题”,避免一起排错。

3.3 从误差曲线判断收敛:RMS 和峰值误差不能只看其中一个

开环 ILC 仿真的输出通常画三条曲线:误差 RMS 随迭代次数变化、误差峰值随迭代次数变化、以及其中某几轮试验的误差轨迹叠加。绘图代码:

# 输出曲线 plt.figure(figsize=(8, 4)) plt.subplot(1, 2, 1) plt.plot(range(len(rms_list)), rms_list, marker='o', label='RMS') plt.plot(range(len(peak_list)), peak_list, marker='x', label='Peak') plt.xlabel('Trial') plt.ylabel('Error') plt.legend() plt.yscale('log') plt.subplot(1, 2, 2) # 绘制第 1、5、20 轮误差轨迹 for trial_show in [1, 5, 20]: u_show = np.zeros(N - 1) for i in range(trial_show): y_show = run_trial(u_show, x0) e_show = yd - y_show de_show = np.gradient(e_show, dt) u_show = u_show + (gamma_P * e_show + gamma_D * de_show)[:-1] plt.plot(t[:-1], e_show[:-1], label=f'trial {trial_show}') plt.xlabel('time (s)') plt.ylabel('error') plt.legend() plt.tight_layout()

判断是否收敛,我习惯用两个条件同时看。RMS 下降到原来的 1/100 甚至更低,说明整体跟踪误差被压下去了;峰值误差也要小于轨迹幅值的 5%,因为很多工程关心的其实是最大偏差,而不是整条轨迹的平均偏差。峰值误差如果迟迟不降,通常指示在某个特定时间点上有滞后或振荡,这时去误差曲线上找尖峰位置,就能确定是运动段的哪一部分出现问题。

还有一个经验:ILC 的误差曲线是带记忆的,前几轮可能上升再下降。如果第 1 轮误差很大,并不意味着方案失败,先跑 10 轮再判断方向。真正有问题的是“降了几轮后停住不再动”——那就是增益或者控制器的频带不够。

4. 和 PSO、强化学习画在同一张图时,横轴迭代次数怎么对齐

4.1 三种算法的“一次迭代”完全不是一回事

群里最常遇到的问题,就是 PSO 一类群体优化算法和强化学习放在一起做对比实验,画收敛曲线时发现横轴单位对不上。PSO 的“一次迭代”是种群一代,RL 的“一次迭代”是 episode,ILC 的“一次迭代”是 trial。三者表面上都叫迭代,但样本成本完全不同。

对 ILC 来说,一次 trial 就是对完整参考轨迹从头到尾跑一遍,得到一条误差轨迹;对 PSO 来说,一次迭代要评估整个种群,比如 30 个粒子就是 30 次完整轨迹评估;对强化学习来说,一个 episode 通常也是一轮完整交互,但训练过程中还可能包含经验回放采样、策略更新等额外开销。

算法横轴单位一次迭代实际次数总评估量跨度
开环 ILCtrial1 条轨迹20 ~ 100 次
PSOgeneration种群大小条轨迹10^3 ~ 10^4 次
强化学习episode1 条交互轨迹10^3 ~ 10^6 次

所以直接把三种算法各自的迭代次数画到同一个横轴上,不光数值不对,连曲线的含义都站不住。ILC 往往 50 次 trial 内就收敛,而 PPO 可能 3000 个 episode 还在上升,一张图里一边撑到 5000,一边在 50 处早早贴着底线,看上去确实很“难看”。

4.2 统一到“总轨迹评估次数”,并给每个算法设置独立停止条件

我常用的做法是把横轴统一成“轨迹评估次数”而不是“算法迭代次数”。对 ILC,评估次数等于 trial 数;对 PSO,评估次数等于“种群大小乘以代数”;对强化学习,评估次数等于用于计算收敛指标的完整 episode 数。

具体操作分三步。第一步先为每种算法单独跑预实验,确定它的大致收敛区间:ILC 50 轮能收敛,PSO 40 代 * 30 个体等于 1200 次评估,RL 大概 4000 个 episode 开始平稳。第二步定总预算,一般取最慢方法收敛评估数的 1.5 到 2 倍,比如 RL 需要 4000,预算就给 6000 或 8000。第三步是每个算法都记录“评估次数”和“当前误差指标”两条序列,曲线绘制时以评估次数为横轴,并且每类算法自身的指标都做相同平滑处理。参考代码:

def check_convergence(history, rel_tol=0.05, patience=10): if len(history) < 2 * patience: return False recent = history[-patience:] before = history[-2 * patience:-patience] mean_recent = np.mean(recent) mean_before = np.mean(before) if abs(mean_recent) < 1e-10: return True return abs(mean_recent - mean_before) / abs(mean_recent) < rel_tol

这个停止条件的意思是:连续 10 个评估点的指标平均值相比前 10 个点没有明显下降,就认为算法已经收敛。不同算法收敛所需的评估次数往往差出两个数量级,这是它们的真实特性,不需要强行拉齐终点。

如果还是希望所有曲线终点都落在同一个横轴位置,可以把每个算法自己的预算作为终点,在图中注明各自的预算值,比如标注“ILC: 60 trials, PSO: 2400 evals, PPO: 4000 episodes”。这样读者看到的是在同一张图中比较样本效率,而不是假装三种算法迭代次数单位一样。

4.3 收敛曲线绘制中的三个常见翻车点:早停、抖动与差异被掩盖

第一个常见坑是早停条件不一致。ILC 的误差下降非常快时,如果只设了一个很低的误差阈值,可能在 20 轮就停;而强化学习如果也按同样的误差阈值判断,几千个 episode 都停不下来。这样画出来的曲线会呈现“ILC 早早收敛,RL 永远在跑”,但真正原因是停止条件设置不统一。我的做法是给每个算法使用相同的阈值和相同的耐心窗口,比如都采用上面的 check_convergence,并设置相同的最大预算。

第二个坑是抖动曲线盖住趋势。RL 的单 episode 回报通常震荡很大,直接画出来是一团毛刺;ILC 的误差下降也可能在前几轮有波动。如果横轴拉长到几千,ILC 那条 50 步内就到底的曲线会被压成一条竖线,完全看不出收敛过程。解决办法是横轴改用对数刻度,或者把 RL 指标做滑动平均,再用半透明置信区间包起来。

第三个坑是比较指标选错,导致两条曲线的差异被掩盖。如果只看最终单次运行误差,PSO 可能 2000 次评估后误差接近 ILCS 的 60 次结果,但分布情况完全看不到。我会额外画“达到指定误差阈值所需的评估次数”柱状图,每种算法重复 5 到 10 次取中位数和四分位距,这个图比单纯收敛曲线更能说明样本效率。收敛曲线只能回答“降得多快”,阈值命中图才能回答“多可靠”。

5. 开环 ILC 仿真避坑与排错:五条能直接上手的检查清单

5.1 误差停在某个平台瓶颈:先查 D 增益和误差求导是否引入高频噪声

现象是:误差曲线前几轮快速下降,到第 8 轮左右停住,RMS 下降率明显变缓,甚至轻微反弹;误差曲线上能看到细密的锯齿。

原因是:γ_D 增益对误差导数项过于敏感,数值梯度把参考轨迹的高频分量和测量噪声同时放大了。开环 ILC 会把上一轮噪声学进下一轮输入,积累到一定程度形成一个“噪声底”就压不下去。

解决方法是先把 γ_D(t) 整体缩小,或者给误差导数加一阶低通滤波。一种常见改法是先用误差平滑后的信号计算导数,代码里用:

from scipy.signal import butter, filtfilt b, a = butter(2, 0.2) e_smooth = filtfilt(b, a, e) de = np.gradient(e_smooth, dt)

如果误差仍然停在平台上,再把 dt 减小到 0.5ms,确认是采样分辨率的问题还是增益问题。检查顺序:先降微分增益,再滤波,最后才加密采样。

5.2 末端总有个尖峰收不下去:非因果更新和参考边界条件不匹配

现象是:其他时间段的误差都降了,但轨迹末端最后 10ms 始终有个尖峰,而且随迭代次数增加尖峰不消失,有时还会一点点变宽。

原因是:开环 ILC 用整条误差轨迹做更新,等于用 t 时刻附近误差去修正整条输入序列,本质上带有预测性。参考轨迹如果末端加速度不为零,输入需要提供对应的末端力矩,而受控对象的动态响应滞后会让末端出现“换向尖峰”。另一个常见来源是初始的 u(N-1) 没有对应的误差数据,导致末端积分不闭合。

解决方法是:把参考轨迹设计成末端速度和加速度都严格归零,比如代码里用的五次多项式就是一种可行设计;同时对学习修正做边界截断,不让最后一个采样点把极端值扩展到整段。检查时看最后一个采样点的误差和倒数的误差,如果一直是同一符号,就是参考边界条件没闭合。

5.3 迭代几十轮后误差突然反弹:忽略遗忘因子和频带边界

现象是:前面 30 轮 RMS 一直下降,第 35 轮开始突然回升,而且回升幅度明显,不是噪声抖动。

原因是:开环 ILC 的输入在迭代中不断累积修正量,遇到被控对象建模误差或者非线性扰动时,高频成分会有累积,一旦越过收敛条件里对频率带的要求,误差就从收敛变成发散。很多线性分析只保证“小误差附近收敛”,不保证“无限累积后还收敛”。

解决方法是在更新公式里加入遗忘因子 β,常见形式是:

u_{k+1}(t) = (1-β) * u_k(t) + γ_P(t) * e_k(t) + γ_D(t) * ė_k(t)

β 通常取 0.05 到 0.2。遗忘因子让输入不再无限累积,旧信息按比例淘汰,对抑制长期漂移非常有效。代价是最终误差无法降到理论最小值,因为算法不再保留全部历史信息。工程上这是一个必要取舍,我一般从 β=0.1 开始,观察 50 轮误差曲线上是否还有长期回升趋势。

5.4 换成 ode 积分器后前面迭代白跑:采样网格与插值方法不一致

现象是:用 scipy.integrate.solve_ivp 或 MATLAB 的 ode45 替换简单欧拉积分后,原本收敛的误差曲线突然振荡,甚至第一轮误差就比原来大。

原因是:变步长积分器在每个 trial 返回的时间点不完全一致,参考轨迹和误差轨迹要重采样同一套时间网格;同时被控对象的相对阶在连续时间仿真和高散化仿真里表现不同,而数值导数又对采样点位置极其敏感。开环 ILC 把时间轴当成对齐的格子来学习,只要格子对不上,积累修正量就会互相抵消。

解决方法是固定同一个采样网格,并在每个 trial 开始时从那个网格上重新插值参考轨迹。如果可以,先用定步长仿真验证算法,再迁移到 ode 求解器。ILC 的学习本质上依赖“重复任务中的时间对齐”,时间不对齐是这个算法最忌的事。

5.5 初始状态和参考起点对不上,ILC 从第一轮就在学错误的东西

现象是:ILC 迭代过程中误差在前几十毫秒总是很大,RMS 降到一定程度就停住,无论怎么调增益都压不到更低水平。

原因是:初始状态和参考轨迹起点不一致,比如参考起点是 0 但系统状态初始值是 [0.1, 0],这时第一轮误差本身就带着初始偏移,ILC 会试图在输入上产生一个大脉冲去补偿这个偏移。由于被控对象动态响应需要时间,这个脉冲很难被轨迹末端吸收掉,形成“前段完全靠输入硬扳”的失真轨迹。

解决方法是在每次试验前把系统状态复位到参考轨迹对应的初始状态,或者在误差计算中将前几拍强制忽略掉,等系统先进入参考轨迹的邻域再开始学习。实际实现时我在代码里检查第一点和参考第一点的差:

if np.abs(yd[0] - y[0]) > 1e-6: x0 = np.array([yd[0], 0.0])

注意这样做的本质是换了一个“任务初始条件”,必须保证所有对比算法使用同样的初始条件,否则互相比较时数据不公平。

6. 判断一套开环 ILC 方案值不值得用的三个验证手段

先看它在纯仿真里到底能不能稳定收敛,再看它扛不扛扰动,最后看它换一条轨迹后会不会“过拟合”。这三个验证做完,基本就知道值不值得投进实际设备。

第一个手段是标准化收敛性验证:固定同一参考轨迹,跑三组不同的初始误差,各组都连续迭代 100 轮。画 RMS 曲线,看是否都单调下降到同一水平。如果三条曲线最终停在相差较大的水平,说明存在多收敛点或者模型不确定性影响显著,这时不要急着上设备。范数条件也好、谱分析也好,最后都要落在这三条重复试验曲线是否稳定上。

第二个手段是鲁棒性验证:在每一轮 trial 的输入或状态上注入小幅随机扰动,例如给控制输入加一个 0.02 幅值的高斯噪声,连续跑 30 轮。开环 ILC 对噪声的学习行为直接反映的是增益是否过于激进。如果噪声注入后误差曲线明显变粗,说明 γ_D(t) 和 γ_P(t) 仍偏大;如果曲线快速回到正常水平,说明学习律有自我纠正能力,这个系统会更接近实际工况。

第三个手段是泛化能力验证:把参考轨迹从幅值 1 改成幅值 1.2 但保持相同时间长度,继续从已有的输入序列开始迭代 20 轮,观察初始误差是否很大,以及能否快速收敛。开环 ILC 本质是“记住任务细节”,不是“学到一个控制器”,所以换轨迹后必然需要一个重新学习的过程。遗忘因子和 TPD 增益能让这个过程更快,但不会做到立刻无误差。我习惯把换轨迹后的前 10 轮误差也画出来,如果第 10 轮能把误差降到同量级,说明学习结构合理,值得继续做;如果 10 轮后依然比原轨迹高一个量级,说明增益设计过度贴合原任务,需要降低学习率。

在这些验证之外,还有一个我坚持的习惯:每次试验结果都存成一个带时间戳的 CSV 文件,保存本轮使用的 γ_P(t)、γ_D(t)、β 和遗忘因子版本。因为 ILC 的收敛结果严重依赖参数,参数稍微改了一点就不容易复现,这一步虽不起眼,却能在调参调烦时当真后悔药。希望这条经验在你跑 TPDILC 时也能省一点返工时间,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询