拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

重复控制:周期误差抑制、内模原理与机械臂伺服实践

重复控制:周期误差抑制、内模原理与机械臂伺服实践

1. 机器人里那些"每次都在同一个位置犯错"的误差

做机器人控制这些年,我最怕听到一句话:"这个误差是随机的,滤波器加大一点就好了。"因为我一听就知道,说这话的人大概率没分清周期误差和随机误差。随机误差确实是噪声,可以用均值、方差去描述,你加大滤波、做统计平均,它就会变小;但周期误差不是,它每一次运行都出现在同一个关节角、同一个时间点、同一个轨迹位置,你滤波滤不掉,PID加大增益只会把它放大成振荡。

这个问题在机器人动力学与控制里非常典型。比如一台SCARA机械臂做连续的拾放动作,末端每走一圈,在某个固定相位处就抖一下;再比如直驱电机带转台,每转一圈,在固定的机械角度位置,速度环就冒出一个周期性波动。这些误差的来源五花八门:减速机的齿隙和偏心、联轴器的不同轴、电机的齿槽转矩、连杆的重力补偿残差、轨迹规划本身留下的周期性加速度冲击。它们有个共同特征——周期性和轨迹周期严格相关。

PID控制器面对这种误差是很无力的。原因很朴素:PID是基于当前误差做比例、积分、微分的加权,它没有"记忆"能力,不知道上一个周期同一时刻发生了什么。积分项虽然能累积,但它是跨周期的、无差别的累积,会把周期误差和常值偏差搅在一起,最后要么收敛慢,要么造成相位滞后。

重复控制(Repetitive Control)就是为了解决这件事而生的。它的核心思想一句话说清楚:如果扰动是周期性的,那我就在控制器里内置一个和扰动同周期的信号发生器,让控制器自己"学会"在每个周期同一时刻输出对应的补偿量。这就是内模原理(Internal Model Principle)的直接应用——想彻底抑制一个信号,控制系统内部就必须包含这个信号的模型。

这一路笔记我打算把重复控制从原理到落地讲透:它为什么长成那个样子、延迟环节和低通滤波器各自在干什么、离散实现里N和相位补偿怎么算、稳定性到底在约束什么、放到机械臂和伺服电机上怎么和级联PID配合,以及我自己调试时踩过的一堆坑。内容偏实操,公式会讲,但更想讲清楚"为什么要这么做"。

1.1 从一次拾放动作说起

假设你有一台三轴机械臂,任务是从传送带A抓取工件,放到位置B,然后回来,循环往复。理想情况下,每次运动的轨迹完全一样,误差应该也完全一样。但你看实测的关节位置误差曲线,会发现它是一条周期性的波浪,而且每个周期的波形高度重合。

这说明什么?说明这个误差不是随机的,它是确定性的、可重复的。可重复,就意味着可补偿。这正是重复控制发挥作用的前提。

我第一次做这类项目时,试过最直接的办法:把上一周期的误差曲线录下来,反过来加一个前馈。效果非常好,误差直接掉了一个数量级。但问题也很明显——换一个轨迹,前馈表就废了,得重新录。手动前馈本质上是离线的一次性重复控制,而重复控制器做的事情,就是把这个过程自动化、在线化,让控制器自己边跑边学。

理解这一点很关键:重复控制不是凭空创造什么新能力,它只是把"人肉录误差、手动补前馈"这件事,用一个带延迟环节的反馈回路自动实现了。带着这个直觉去看它的结构,一切都会顺理成章。

1.2 周期误差和随机误差完全是两回事

在动手之前,分清楚这两类误差的"性格"很重要,因为它们的处理手段几乎不重叠。

误差类型典型来源特征主要处理手段
随机误差传感器噪声、电磁干扰、量化误差不可重复、零均值滤波、统计平均、提高信噪比
周期误差齿隙、偏心、齿槽转矩、轨迹冲击与运动周期严格同步、可重复重复控制、迭代学习、谐振控制
常值误差摩擦、重力常值偏差不随时间变化积分项、前馈补偿

你如果拿周期误差去喂滤波器,结果就是相位滞后越来越大,系统整体性能下降,误差却还在。反过来,你如果拿随机噪声去喂重复控制器,它会把噪声也当成"可学习的信号"记进延迟线里,然后每个周期原样放出来,等于给系统注入了一段周期性的噪声,越学越乱。所以重复控制前面通常会串一个低通滤波器,把高频随机噪声挡在学习通道之外,这一点后面细讲。

1.3 内模原理:想干掉一个信号,就得在回路里"养"一个它

内模原理的表述很学术:如果一个控制系统要实现对某类参考信号或扰动信号的无静差跟踪或抑制,那么控制器中必须包含该类信号的生成模型。

翻译成人话:一个周期信号,本质上就是一个"能在自己内部无限循环"的信号。正弦信号可以用两个状态互相耦合循环生成,而任意周期信号(周期为T),可以用一根延迟时间为T的延迟线加正反馈来生成——信号从延迟线一端进去,转一圈从另一端出来,再被送回输入端,就自己循环起来了。

所以重复控制器的核心结构,就是一条延迟时间等于扰动周期的延迟线,配上正反馈。这条延迟线在离散域里就是个纯延迟z^-N,N是扰动周期内的采样点数。它像一个环形缓冲区,把上一个周期同一时刻的补偿信号原封不动地拿出来用。

这也是为什么重复控制被归为"学习型控制"——它每一圈都在积累经验,理论上只要系统稳定,误差会随着圈数增加而单调下降,最终收敛到接近零(在控制器带宽范围内)。

2. 重复控制器的三块积木:延迟、增益、低通

把重复控制器的方框图摊开,你会发现它其实非常简洁,就三块东西:一个延迟环节、一个学习增益、一个低通滤波器。下面我逐块拆解,讲清楚每一块存在的理由和它带来的副作用。

2.1 延迟环节是怎么"记住"上一个周期的

最朴素的重复控制器传递函数长这样:

C(s) = kr * e^(-sT) / (1 - e^(-sT))

分母的1 - e^(-sT)就是那条带正反馈的延迟线,kr是学习增益。这个结构的频域特性很有意思:在扰动频率的整数倍处(基频及其各次谐波),分母趋近于零,因此控制器的幅值增益趋近于无穷大。这意味着控制器在每一个谐波频点上都提供了近乎无穷大的开环增益,从而对每一个谐波分量都实现无静差抑制。

这是重复控制最漂亮的地方:它不是只针对某一个频率做调整,而是一次性覆盖了基频和它的所有谐波。对于机械臂轨迹跟踪这种含有大量高次谐波的场景,这个特性非常对胃口。

但这也埋了个雷:控制器在所有谐波频点都有无穷大增益,包括那些远高于系统带宽的高频谐波。高频段系统相位严重滞后,无穷大增益乘上错误相位,结果就是高频振荡甚至失稳。这个雷必须靠第三块积木——低通滤波器来排。

2.2 增益kr决定了收敛速度,也决定了危险程度

学习增益kr控制的是"每一圈从误差里学多少"。kr接近1,学习速度快,几圈就能收敛;kr小,收敛慢,但稳。

理论上,当kr=1且系统标称稳定时,误差会在一圈之内被完全消除(这是重复控制的经典结论)。但现实里kr=1非常少见,原因有两个:

  • 建模误差和未建模动态让"一圈消除"的假设不成立,实际会过冲、振荡。
  • 高增益下,任何一点周期性的测量噪声都会被放大进延迟线,越滚越大。

我的经验是,首次调试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 / Ts,T是扰动周期,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^(-N+m),即整体少延迟m个点,相当于提前补偿。

这里的m需要根据对象在各谐波频点的相位滞后去算,比较实用的办法是先测出对象在目标谐波频率处的相位,然后反推需要的超前点数。要注意的是,超前补偿会牺牲低频段的相位精度,所以通常只补一部分(比如补对象滞后的一半到三分之二),剩余部分交给反馈环的稳定性余量去消化。

3.3 一段可以直接跑的Python验证代码

我一般先用Python把重复控制器的离散逻辑跑一遍,看收敛和稳定性,再往控制器里移植。下面是一段最简版本,用来验证核心逻辑:

import numpy as np def repetitive_controller(N, kr=0.3, alpha=0.95, n_steps=2000): """ 最简离散重复控制器 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(N=200, kr=0.3, alpha=0.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 增益-频率曲线上的三个检查点

我不太喜欢把稳定性分析搞得过于抽象,实际调试时我会在增益-频率曲线上盯三个点:

  1. 低频谐波点:确认目标谐波频点处的合成增益确实被抬高了,这是效果保证。
  2. 对象共振点:这是最容易失稳的地方,确认Q(z)把这些点的增益压到了1以下。
  3. 高频衰减区:确认整个高频段是单调下降的,没有局部突起。

这三个点扫一遍,基本能判断参数能不能上机。

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该干的事继续干。

具体步骤:

  1. 先让级联PID单独跑,把轨迹跟踪误差录下来,确认误差是周期性的。
  2. 按轨迹周期和采样周期算出N,初始化重复控制器的延迟线。
  3. kr从0.1起步,跑50圈,观察误差波形的包络是否收敛。
  4. 逐步加到0.3左右,如果出现高频振荡立刻回退,并收紧Q(z)。
  5. 换速度或换轨迹后,重新评估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把系统跑稳,把延迟线长度的精度做足,再谈性能。这条线走扎实了,重复控制的收敛速度往往会给你惊喜。

返回列表