重复控制:周期误差抑制、内模原理与机械臂伺服实践
发布时间:2026/9/30 15:27:53 作者:尧图编辑部 阅读量:1,286

1. 机器人里那些每次都在同一个位置犯错的误差做机器人控制这些年我最怕听到一句话这个误差是随机的滤波器加大一点就好了。因为我一听就知道说这话的人大概率没分清周期误差和随机误差。随机误差确实是噪声可以用均值、方差去描述你加大滤波、做统计平均它就会变小但周期误差不是它每一次运行都出现在同一个关节角、同一个时间点、同一个轨迹位置你滤波滤不掉PID加大增益只会把它放大成振荡。这个问题在机器人动力学与控制里非常典型。比如一台SCARA机械臂做连续的拾放动作末端每走一圈在某个固定相位处就抖一下再比如直驱电机带转台每转一圈在固定的机械角度位置速度环就冒出一个周期性波动。这些误差的来源五花八门减速机的齿隙和偏心、联轴器的不同轴、电机的齿槽转矩、连杆的重力补偿残差、轨迹规划本身留下的周期性加速度冲击。它们有个共同特征——周期性和轨迹周期严格相关。PID控制器面对这种误差是很无力的。原因很朴素PID是基于当前误差做比例、积分、微分的加权它没有记忆能力不知道上一个周期同一时刻发生了什么。积分项虽然能累积但它是跨周期的、无差别的累积会把周期误差和常值偏差搅在一起最后要么收敛慢要么造成相位滞后。重复控制Repetitive Control就是为了解决这件事而生的。它的核心思想一句话说清楚如果扰动是周期性的那我就在控制器里内置一个和扰动同周期的信号发生器让控制器自己学会在每个周期同一时刻输出对应的补偿量。这就是内模原理Internal Model Principle的直接应用——想彻底抑制一个信号控制系统内部就必须包含这个信号的模型。这一路笔记我打算把重复控制从原理到落地讲透它为什么长成那个样子、延迟环节和低通滤波器各自在干什么、离散实现里N和相位补偿怎么算、稳定性到底在约束什么、放到机械臂和伺服电机上怎么和级联PID配合以及我自己调试时踩过的一堆坑。内容偏实操公式会讲但更想讲清楚为什么要这么做。1.1 从一次拾放动作说起假设你有一台三轴机械臂任务是从传送带A抓取工件放到位置B然后回来循环往复。理想情况下每次运动的轨迹完全一样误差应该也完全一样。但你看实测的关节位置误差曲线会发现它是一条周期性的波浪而且每个周期的波形高度重合。这说明什么说明这个误差不是随机的它是确定性的、可重复的。可重复就意味着可补偿。这正是重复控制发挥作用的前提。我第一次做这类项目时试过最直接的办法把上一周期的误差曲线录下来反过来加一个前馈。效果非常好误差直接掉了一个数量级。但问题也很明显——换一个轨迹前馈表就废了得重新录。手动前馈本质上是离线的一次性重复控制而重复控制器做的事情就是把这个过程自动化、在线化让控制器自己边跑边学。理解这一点很关键重复控制不是凭空创造什么新能力它只是把人肉录误差、手动补前馈这件事用一个带延迟环节的反馈回路自动实现了。带着这个直觉去看它的结构一切都会顺理成章。1.2 周期误差和随机误差完全是两回事在动手之前分清楚这两类误差的性格很重要因为它们的处理手段几乎不重叠。误差类型典型来源特征主要处理手段随机误差传感器噪声、电磁干扰、量化误差不可重复、零均值滤波、统计平均、提高信噪比周期误差齿隙、偏心、齿槽转矩、轨迹冲击与运动周期严格同步、可重复重复控制、迭代学习、谐振控制常值误差摩擦、重力常值偏差不随时间变化积分项、前馈补偿你如果拿周期误差去喂滤波器结果就是相位滞后越来越大系统整体性能下降误差却还在。反过来你如果拿随机噪声去喂重复控制器它会把噪声也当成可学习的信号记进延迟线里然后每个周期原样放出来等于给系统注入了一段周期性的噪声越学越乱。所以重复控制前面通常会串一个低通滤波器把高频随机噪声挡在学习通道之外这一点后面细讲。1.3 内模原理想干掉一个信号就得在回路里养一个它内模原理的表述很学术如果一个控制系统要实现对某类参考信号或扰动信号的无静差跟踪或抑制那么控制器中必须包含该类信号的生成模型。翻译成人话一个周期信号本质上就是一个能在自己内部无限循环的信号。正弦信号可以用两个状态互相耦合循环生成而任意周期信号周期为T可以用一根延迟时间为T的延迟线加正反馈来生成——信号从延迟线一端进去转一圈从另一端出来再被送回输入端就自己循环起来了。所以重复控制器的核心结构就是一条延迟时间等于扰动周期的延迟线配上正反馈。这条延迟线在离散域里就是个纯延迟z^-NN是扰动周期内的采样点数。它像一个环形缓冲区把上一个周期同一时刻的补偿信号原封不动地拿出来用。这也是为什么重复控制被归为学习型控制——它每一圈都在积累经验理论上只要系统稳定误差会随着圈数增加而单调下降最终收敛到接近零在控制器带宽范围内。2. 重复控制器的三块积木延迟、增益、低通把重复控制器的方框图摊开你会发现它其实非常简洁就三块东西一个延迟环节、一个学习增益、一个低通滤波器。下面我逐块拆解讲清楚每一块存在的理由和它带来的副作用。2.1 延迟环节是怎么记住上一个周期的最朴素的重复控制器传递函数长这样C(s) kr * e^(-sT) / (1 - e^(-sT))分母的1 - e^(-sT)就是那条带正反馈的延迟线kr是学习增益。这个结构的频域特性很有意思在扰动频率的整数倍处基频及其各次谐波分母趋近于零因此控制器的幅值增益趋近于无穷大。这意味着控制器在每一个谐波频点上都提供了近乎无穷大的开环增益从而对每一个谐波分量都实现无静差抑制。这是重复控制最漂亮的地方它不是只针对某一个频率做调整而是一次性覆盖了基频和它的所有谐波。对于机械臂轨迹跟踪这种含有大量高次谐波的场景这个特性非常对胃口。但这也埋了个雷控制器在所有谐波频点都有无穷大增益包括那些远高于系统带宽的高频谐波。高频段系统相位严重滞后无穷大增益乘上错误相位结果就是高频振荡甚至失稳。这个雷必须靠第三块积木——低通滤波器来排。2.2 增益kr决定了收敛速度也决定了危险程度学习增益kr控制的是每一圈从误差里学多少。kr接近1学习速度快几圈就能收敛kr小收敛慢但稳。理论上当kr1且系统标称稳定时误差会在一圈之内被完全消除这是重复控制的经典结论。但现实里kr1非常少见原因有两个建模误差和未建模动态让一圈消除的假设不成立实际会过冲、振荡。高增益下任何一点周期性的测量噪声都会被放大进延迟线越滚越大。我的经验是首次调试kr从0.1到0.3起步观察几圈收敛曲线确认没有振荡再逐步加。加的时候一定要盯住高频段的信号因为高频失稳往往不明显地表现在轨迹误差上而是先在一些你看不到的地方比如电流环、力矩信号悄悄放大。2.3 低通滤波器Q(z)牺牲一点精度换稳定性低通滤波器通常记作Q(z)在重复控制里的作用是把高频段的增益压下来让延迟线只对低频的、真正可学的周期成分起作用。加了Q(z)之后的重复控制器变成C(z) kr * Q(z) * z^(-N) / (1 - Q(z) * z^(-N))这时候曲线就不是在谐波频点无穷大了而是变成在谐波频点增益被抬高到某个有限值。Q(z)的截止频率越高抑制的谐波次数越多、精度越好但稳定性余量越小截止频率越低越稳但只能抑制低次谐波。工程上常见的Q(z)选择有这么几种Q(z)形式特点适用场景Q(z) 1无滤波理论精度最高系统模型极准、噪声极小一阶低通简单、相位滞后小大多数通用场景零相位低通正反两遍滤波无相位失真离线或半离线学习二阶及以上衰减更陡高频动态丰富、噪声大我个人最常用的是一阶低通Q(z) α/(1-(1-α)z^-1)α取0.9到0.97之间配合合适的N能在稳定性和谐波抑制之间取得不错的平衡。2.4 三块积木的相互制约关系这里必须点破一个新手常见的误区这三块积木不是独立调节的它们是耦合的。你把Q(z)截止频率提高允许更多高频谐波被学习那么为了保证稳定kr就得往下压kr压下去收敛速度变慢前几圈的误差就会比较难看。反过来你想让kr大一点、收敛快一点就得把Q(z)收紧牺牲一部分谐波精度。这个权衡没有标准答案取决于你的应用更在意什么。如果任务是重复轨迹跟踪我一般优先保证稳定把Q(z)收紧、kr保守让系统慢几圈收敛换长期可靠如果任务对某几阶特定谐波特别敏感比如某个共振点那就针对性设计Q(z)的形状甚至上谐振控制补那几阶。3. 离散实现N怎么算、相位怎么补、代码怎么写理论好看落地全是细节。重复控制最烦人的地方就在离散化N是不是整数、相位怎么补偿、边界条件怎么处理每一个都能让你调半天。3.1 周期内采样点数N的确定与取整误差N的计算很简单N T / TsT是扰动周期Ts是采样周期。比如电机转台转速为每分钟300转5转/秒采样频率1kHz那么一圈的时间是0.2秒N 0.2 / 0.001 200个点。问题是N往往不是整数。当转速变化或者采样频率不是整数倍关系时N会落在两个整数之间。这时候你有两个选择四舍五入取整简单但会造成周期估计偏差高频谐波处误差会被放大收敛后残留误差偏大。分数延迟fractional delay用拉格朗日插值或全通滤波器实现z^(-N)的小数部分精度高但增加了复杂度和相位失真。我的做法是低频谐波要求高的场合用分数延迟一般场合直接取整配合稍微收紧的Q(z)把高频压下去。取整带来的相位误差大致正比于谐波次数所以高次谐波受影响最重而高次谐波本来就是Q(z)要衰减的对象所以取整的代价在很多时候可以接受。3.2 相位超前补偿的两种做法实际系统里被控对象比如电机负载、机械臂关节在高频段都会引入相位滞后。重复控制器输出的补偿量如果带着滞后再作用到系统上本来该抵消的误差反而被延迟了效果打折甚至反向放大。解决办法是在重复控制器里引入相位超前补偿掉一部分对象滞后。有两种常见做法在Q(z)里做文章给滤波器加一个零相位超前环节或者用z^m做整数点超前。在延迟线长度上微调把z^(-N)改写成z^(-Nm)即整体少延迟m个点相当于提前补偿。这里的m需要根据对象在各谐波频点的相位滞后去算比较实用的办法是先测出对象在目标谐波频率处的相位然后反推需要的超前点数。要注意的是超前补偿会牺牲低频段的相位精度所以通常只补一部分比如补对象滞后的一半到三分之二剩余部分交给反馈环的稳定性余量去消化。3.3 一段可以直接跑的Python验证代码我一般先用Python把重复控制器的离散逻辑跑一遍看收敛和稳定性再往控制器里移植。下面是一段最简版本用来验证核心逻辑import numpy as np def repetitive_controller(N, kr0.3, alpha0.95, n_steps2000): 最简离散重复控制器 N : 周期内采样点数 kr : 学习增益 alpha : 一阶低通Q(z)系数 返回每步的控制量序列 buf np.zeros(N) # 延迟线环形缓冲区 q_state 0.0 # 低通滤波器状态 ptr 0 out [] for k in range(n_steps): # 假设误差为某周期性信号这里用正弦3次谐波模拟 t k err 0.05 * np.sin(2 * np.pi * t / N) 0.02 * np.sin(6 * np.pi * t / N) delayed buf[ptr] # 取出上一个周期同相位值 # 一阶低通y alpha*disturb (1-alpha)*y_{k-1} q_state alpha * delayed (1 - alpha) * q_state u kr * q_state # 加学习增益 buf[ptr] err q_state # 误差累加回延迟线 ptr (ptr 1) % N out.append(u) return np.array(out) # 跑一下看收敛 u repetitive_controller(N200, kr0.3, alpha0.95) print(末段控制量幅值:, np.max(np.abs(u[-200:]))) print(首段控制量幅值:, np.max(np.abs(u[:200])))这段代码不是工程级实现但足以验证你是否理解了三块积木的连接方式。跑出来你会看到第一段控制量还很小随着圈数增加控制量逐渐长成一个周期性波形最终稳定下来。那个稳定下来的波形就是重复控制器记住的补偿信号。移植到实际控制器比如DSP、STM32或工控机上的C代码时核心就是把这个环形缓冲区用数组实现ptr在每个采样周期递增取模注意浮点运算量和中断实时性。4. 稳定性的红线小增益定理到底在约束什么重复控制的稳定性分析是它理论里最劝退的部分但工程上你不需要背完整证明只需要理解小增益定理给出的那条约束然后在实践中用它来检查参数。4.1 把重复控制器拆成扰动通道传递函数重复控制系统的稳定性判据标准形式是把环路拆成两部分被控对象和稳定化控制器构成的标称传递函数 G(z)以及重复控制器本身的传递函数 C(z)。小增益定理告诉我们如果重复控制器那条延迟线的闭环增益也就是Q(z)*z^(-N)那个循环回路的增益小于1且被控对象标称稳定那么整个大回路就是稳定的。写成条件大致是| Q(z) * (1 - kr * G(z)) | 1 对所有频率成立这条式子给你的直觉是增益kr、低通Q、对象G三者的乘积必须处处被压住。低频段G的幅值通常大所以kr不能太大高频段G可能因为共振而突然抬升所以Q必须在那个频率点把增益狠狠压下去。4.2 增益-频率曲线上的三个检查点我不太喜欢把稳定性分析搞得过于抽象实际调试时我会在增益-频率曲线上盯三个点低频谐波点确认目标谐波频点处的合成增益确实被抬高了这是效果保证。对象共振点这是最容易失稳的地方确认Q(z)把这些点的增益压到了1以下。高频衰减区确认整个高频段是单调下降的没有局部突起。这三个点扫一遍基本能判断参数能不能上机。4.3 一张整定参数对照表下面这张表是我自己积累的经验值配合一阶低通Q(z)供参考。实际一定以你系统的实测频响为准不能照抄。场景N范围kr建议Q(z)一阶系数α备注机械臂重复轨迹跟踪100~20000.1~0.40.90~0.95关节共振点要单独看伺服电机转矩脉动抑制50~5000.2~0.50.92~0.97与电流环带宽解耦转台速度波动抑制200~20000.05~0.20.95~0.98转速越高N越小高精度定位平台500~50000.05~0.150.90~0.94建议配分数延迟注意上表只是起点。kr和α每次只动一个动完观察至少20圈不要两圈没看清就继续加。5. 放到真实平台上机械臂周期轨迹与电机转矩脉动原理讲完来说具体怎么用。重复控制在两类场景里最有用重复轨迹跟踪和周期性扰动抑制。我各举一个自己做过的例子。5.1 SCARA拾放和级联PID怎么配合机械臂的关节控制器一般是级联PID——位置环外套速度环速度环外套电流环。重复控制不要直接加在位置环上那样容易和速度环打架。我的做法是把重复控制器并联在速度环的输入端位置环输出的速度指令先减去重复控制器给出的补偿量再送进速度环。这样重复控制只影响速度指令不改变内环的稳定性结构级联PID该干的事继续干。具体步骤先让级联PID单独跑把轨迹跟踪误差录下来确认误差是周期性的。按轨迹周期和采样周期算出N初始化重复控制器的延迟线。kr从0.1起步跑50圈观察误差波形的包络是否收敛。逐步加到0.3左右如果出现高频振荡立刻回退并收紧Q(z)。换速度或换轨迹后重新评估N和相位补偿。这个结构中级联PID负责快速响应和常值误差重复控制负责周期性成分各司其职。5.2 伺服电机转矩脉动抑制与FOC电流环的接口电机侧的周期性扰动主要来自齿槽转矩和逆变器非线性。这类扰动和电机的机械角度强相关所以周期就是一圈的电气/机械周期。在FOC控制框架下电流环的q轴电流指令决定了转矩。我的做法是把重复控制器的输出叠加到q轴电流给定上专门抵消齿槽带来的周期转矩波动。关键点有两个周期要对准机械角因为齿槽转矩是位置周期性的不是时间周期性的。如果转速恒定二者等价如果转速变化必须用位置触发而不是时间触发来更新延迟线。和电流环带宽解耦重复控制的学习频率不能太高否则和电流环的快速动态冲突。一般重复控制的目标谐波次数限制在电流环带宽的十分之一以下。这一点在热词里提到的自适应频率控制、弱磁控制场景下尤其要小心因为转速变化剧烈时周期估算会跟着变处理不好会引起频率失配。5.3 实测数据该怎么看很多人调重复控制只盯着最终误差其实要看三个量误差包络圈数增加时误差幅值是单调下降还是振荡。单调下降说明参数偏保守但安全振荡说明kr偏大。延迟线内容把延迟线缓冲区的内容打出来看正常应该是一个平滑的周期波形如果看到毛刺或者尖峰说明有噪声混进去了需要收Q(z)。力矩/电流信号这是最容易被忽略的失稳前兆。有时误差看着挺好但力矩信号里已经有高频振荡在酝酿。6. 我踩过的那些坑从振荡到越修越差下面这段是我调试重复控制时踩过的真实坑每个都让我多花了半天到两天希望能帮你省时间。6.1 延迟长度差一个采样点效果天差地别第一次做的时候我把N算错了用了一个近似值。结果就是误差不但没下降还在慢慢发散。一开始我以为是kr太大一路往下调发现kr越小发散越慢但就是不发散。后来把延迟线长度精确对上周期瞬间就好了。教训N的精度直接决定系统能不能收敛。周期估算误差会让每个谐波点的相位都偏掉谐波次数越高偏得越多。上机前一定用信号源或者已知频率的扰动去标定N。6.2 采样频率抖动与周期不同步实时系统里采样周期总有抖动尤其是用操作系统调度而非硬件定时器触发的情况。这种抖动会让实际延迟时间和设定值产生偏差效果打折。解决办法是用硬件定时器严格触发采样和延迟线更新避免用软件延时。如果实在避不开就在控制周期里加一点余量让抖动相对于N是一个小量。6.3 高频段增益抬升引发啸叫有一次调完低频误差完美但电机开始发出高频啸叫。查了半天发现是对象在高频有个共振峰Q(z)没压住重复控制在那附近把增益抬起来了。把Q(z)截止频率往下调啸叫消失。这个坑的隐蔽之处在于啸叫频率往往是几千赫兹肉耳不易察觉但它在悄悄消耗系统寿命。6.4 首周期冲击与初始化问题重复控制器刚上电那一秒延迟线是空的输出为零这是正常的。但如果延迟线初始化不当比如填入了上次运行的残余数据第一圈就会输出一个莫名其妙的补偿造成冲击甚至报警。我的做法是上电时清零延迟线并给重复控制加一个软启动逻辑前几圈把kr线性从0拉到设定值。这样即使有残余误差也能平滑过渡。7. 什么时候不该用重复控制与迭代学习、谐振控制、滑模的边界重复控制不是万能钥匙用错地方会更麻烦。我把几种容易混淆的方法对比一下帮你在选型时少走弯路。7.1 重复控制 vs 迭代学习控制这两个经常被放在一起讲因为它们都在重复这件事上做文章。区别在于结构对比项重复控制迭代学习控制结构反馈型实时在线前馈型逐次迭代学习对象周期信号含所有谐波一次完整轨迹的输入是否需要轨迹信息不需要只要周期需要固定轨迹和起点同步轨迹变化时仍能工作周期不变需要重新学习典型应用转轴、振动、匀速旋转重复轨迹跟踪一句话选型轨迹固定、起点严格同步用迭代学习扰动周期固定、轨迹可变或其他用重复控制。很多系统其实两者可以叠加重复控制管扰动抑制迭代学习管轨迹跟踪。7.2 重复控制 vs 谐振/陷波如果扰动只是某几个固定频率的正弦比如一个共振点、一个电网频率干扰用谐振控制更划算。谐振控制器结构简单、整定直观、对单一频率抑制极强。重复控制适合的是含有大量谐波的复杂周期信号用一个延迟线覆盖所有谐波。如果谐波不多别上重复控制杀鸡用牛刀反而引入稳定性问题。7.3 和滑模、自适应控制的关系滑模控制擅长处理不确定性和非线性鲁棒性强但对周期性扰动没有针对性记忆跟踪周期轨迹时会出现稳态误差。重复控制可以叠加在滑模的外层专门处理周期成分。自适应控制处理的是参数变化和慢时变和重复控制处理周期扰动的角度不同两者也可以结合。至于级联PID它永远是基础重复控制是它上面的插件。我从不建议用重复控制去替换级联PID而是在它之上补足周期性抑制能力。选型的核心判断永远是那一句话先看清楚你的误差到底是周期性的还是随机性的、是不变的还是时变的再决定加什么。我调试这么久最省时间的做法从来不是多上一套算法而是先把误差的来源和性质分析清楚剩下的就是水到渠成。如果你也在做机器人重复轨迹或者旋转机械的周期扰动抑制建议先用最简单的一阶低通Q(z)加保守kr把系统跑稳把延迟线长度的精度做足再谈性能。这条线走扎实了重复控制的收敛速度往往会给你惊喜。