ARTICLE DETAIL

资讯详情

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

跟踪微分器TD详解:从PID误解到自抗扰仿真调参

跟踪微分器TD详解:从PID误解到自抗扰仿真调参 简介面向自动控制领域学生与工程师这份资料聚焦跟踪微分器在自抗扰控制中的仿真实现解决建模、参数调整及干扰估计等实际应用问题。跟踪微分器可平滑提取微分信号、抑制高频噪声是自抗扰控制器设计中的关键前置环节。包内共五十八个文件以数据文件、C语言源码、Simulink模型和动态库文件为主同时包含编译中间文件覆盖算法设计、S函数编写到仿真验证的完整流程压缩包约五百四十一KB。已有一千四百零三人学习下载。借助其中的模型与源码可直观理解跟踪微分器如何提取快速信号并配合自抗扰控制器工作也可参考C语言实现迁移到嵌入式场景。通过模型仿真与代码注释读者能快速掌握参数调节技巧缩短自抗扰控制的学习曲线。适合正在学习韩京清自抗扰理论、需要动手仿真验证或进行控制器调试的读者。1. 跟踪微分器TD是自抗扰仿真里最先要装上的那个模块做电机转速闭环时PID里的微分项一加示波器上全是毛刺把微分增益调小相位又不够系统像在跟你较劲。问题不在PID参数而在“从信号里取导数”这件事本身。TD跟踪微分器Tracking Differentiator正是为这个动作设计的动态系统它输出一路v1紧紧跟上输入信号再输出另一路v2作为导数估计既不放大高频噪声也不产生超调断了工程师硬扛噪声的念想。在自抗扰控制ADRC里TD通常装在参考输入前面负责安排过渡过程并生成参考速度是TD、ESO、控制律三大件中的第一环。标题里的TD不是PID整定单上的微分时间而是一个算法模块。下面把它的离散递推式、仿真实现、参数规律和排错一次讲透顺手把“pid中pb ti td”和“安路td”这两类同名不同义的名词也做个了断。2. TD到底是不是微分时间先和PID里的TD撇清关系2.1 从PID参数单上的TD说到跟踪微分器TD看PID整定表格时常看到PB、TI、TD三项。PB是比例带TI是积分时间TD是微分时间单位秒。经典PID输出式写为uKp(e1/TI·∫e dtTD·de/dt)这里的TD是个标量系数乘的是误差的导数。很多工程师第一次看自抗扰仿真文章里的“TD”直接套PID思路认为TD是个微分增益这是最大的误解来源。跟踪微分器TD它是一个动态系统不是一个参数。它的输入是参考信号v输出两个状态v1跟踪vv2跟踪v的导数。结构写作x1x2 x2fhan(x1-v, x2, r, h)fhan是最速综合函数r是速度因子h是滤波因子。x1对信号v的跟踪是渐近的、无超调的x2则给出x1变化率的估计。内部没有独立的高通微分通道而是靠两个积分器把导数“逼”出来所以高频噪声不会被像差分那样直接放大。理解了这一层再回头看“pid中pb ti td”就知道两者只是缩写撞车算法上没有任何继承关系。2.2 为什么理想微分在自抗扰仿真里撑不住理想微分器传递函数D(s)s幅频特性随频率线性增长测量噪声在高频段被成倍放大。仿真里一旦给信号加上白噪声微分输出几乎全是噪声。工程上常搭s/(Ts1)做近似微分但这又引入相位滞后滞后量与噪声抑制直接冲突。TD不走这个路线。它从轨迹规划的角度求最速跟踪每步都在算一条受加速度上限约束的跟踪轨迹。由于加速度上限r的存在TD对高频分量天然不响应v2携带的是跟踪轨迹中的低频导数。换句话说滤波能力不是附加的而是来自加速度限制本身。仿真里这点很直观输入带噪方波时差分输出在跳变沿打出一串尖刺TD输出是一个有界脉冲高度和宽度随r变化。TD在自抗扰控制里还有一个绑定任务对参考输入安排过渡过程。参考输入若是阶跃直接送进控制器会让初始控制量过大、对象受冲击经过TD后v1变成平滑轨迹v2变成轨迹速度控制器面对连续给定执行器不再撞限。三种取导数的方式放一起对比方式结构噪声增益相位行为自抗扰仿真里的用途理想微分 s纯高通频率越高放大越大无滞后基本不用仿真发散近似微分 s/(Ts1)高通低通组合高频受限T越大滞后越明显只做低位替代跟踪微分器TD双积分fhan受r限幅可控折中参考过渡、状态估计组合2.3 顺带清理重名安路td和TD有什么关系搜索“跟踪微分器”时偶尔会在结果里混进“安路td”。安路TD是FPGA厂商安路科技的一个产品系列代号和本标题里的跟踪微分器TD没有算法关系。真正把两者联系起来的场景是把自抗扰控制器部署到FPGA平台时许多团队会把fhan函数做定点化放到安路TD系列或同类FPGA芯片上。检索时看到“TD”字样先看上下文是参数表还是算法图别把器件选型和控制模块搞混。下面进入仿真实现。3. 用Python跑通TD的最小离散递推式先看到第一张曲线3.1 fhan函数的离散表达式与逐行实现韩京清提出的二阶最速跟踪微分器每一步只需要一次fhan计算加两个积分累加。给定采样周期dt和滤波因子h0离散递推式写为x1(k1)x1(k)dt·x2(k) x2(k1)x2(k)dt·fhan(x1(k)-v(k), x2(k), r, h0)fhan内部按最速控制规律计算加速度关键是把线性段和最速段拼成连续表达式避免符号切换引起震荡。完整Python实现如下import math def _sign(x): return 1.0 if x 0 else (-1.0 if x 0 else 0.0) def fhan(y, x2, r, h0): # y x1 - v误差信号h0 是滤波因子 d r * h0 * h0 y0 y h0 * x2 # 由最速控制终点条件求出的根 a0 math.sqrt(d * (d 8.0 * abs(y0))) # 未限幅的目标加速度 a1 h0 * x2 (a0 - d) * 0.5 * _sign(y0) # 用 sy 判断 y0 是否落在线性段内 sy (_sign(y0 d) - _sign(y0 - d)) / 2.0 a (h0 * x2 y0 - a1) * sy a1 # 用 sa 判断 a 是否进入饱和段 sa (_sign(a d) - _sign(a - d)) / 2.0 return -r * (a / d - _sign(a)) * sa - r * _sign(a) class TrackingDifferentiator: def __init__(self, r, h0, x1_00.0, x2_00.0): self.r r self.h0 h0 self.x1 x1_0 self.x2 x2_0 def step(self, v, dt): # 先算最速控制量再做两次积分更新状态 u fhan(self.x1 - v, self.x2, self.r, self.h0) self.x1 dt * self.x2 self.x2 dt * u return self.x1, self.x2代码说明dr·h0²决定最速切换边界|y0|≤d时先生成一个线性控制量避免符号函数在原点抖动a0来自最优控制终点条件其开方运算在FPGA定点化时通常换成CORDIC或查表。调用step时先算fhan再积分顺序不能颠倒否则x2会用更新后的值离散模型变成隐式更新。3.2 给TD一个阶跃输入跑出跟踪和微分曲线仿真脚本如下输入在0.2s处从0跳到1fs 1000 # 仿真频率 Hz dt 1.0 / fs T 1.0 n int(T * fs) td TrackingDifferentiator(r20.0, h010.0 * dt, x1_00.0, x2_00.0) t_list, v_list, x1_list, x2_list [], [], [], [] for k in range(n): t k * dt v 1.0 if t 0.2 else 0.0 x1, x2 td.step(v, dt) t_list.append(t) v_list.append(v) x1_list.append(x1) x2_list.append(x2) print(fx1_end{x1_list[-1]:.4f}) print(fx2_max{max(x2_list):.4f}) print(fx2_min{min(x2_list):.4f})运行结果里x1最终停在1.0附近不超调上升时间约0.4s量级x2是一段正脉冲峰值约20这就是阶跃输入对应的等效导数。脉冲越窄r越大跟踪越快。这里h0取10倍dt如果h0dt滤波几乎等于没有x2会明显抖动如果h020倍dt曲线平滑但滞后又偏大。用这个脚本改不同的r和h0能比空看公式更快建立手感。3.3 从曲线形状判断实现是否正确拿到波形先看三点。第一x1单调上升不超调最终停留在输入值上第二x2是单脉冲正峰值不超过r脉冲宽度随r增大而变窄第三输入是方波时x2在每个跳变沿各出一个正负脉冲不会像差分那样在跳变后留下持续抖动。若看到x1振荡或x2持续高频抖动先从h0取太小、r取太大查起。h0过小fhan进入饱和段过于频繁离散步长下等效为一个高增益开关噪声全被激发r过大则v2峰值超过执行器能力闭环后表现为控制量频繁撞限。把这些现象和参数对应起来调参时就不会盲目。4. 自抗扰仿真里TD的4个必调参数与3个坑4.1 先记住这张参数表调参顺序就出来了参数含义增大后的影响建议范围r速度因子决定最大跟踪加速度跟踪快x2幅值大噪声容忍度下降按执行器限幅的5~10倍推算h0滤波因子决定最优切换的线性区范围滤波强跟踪变慢相位滞后增大5~20倍采样周期dt采样周期或调用间隔影响离散误差取大后fhan线性区含义改变不高于对象动态周期的1/20x1(0)TD输出初值与输入初值不符时会产生大跳变对齐v(0)调参顺序固定先定dt再按执行器允许的最大控制量估算r然后按噪声水平选h0最后检查x1是否超调。若闭环后系统振荡多数情况不是TD的问题而是后面的ESO带宽或控制器增益有问题。TD只负责提供干净的参考轨迹和参考导数背不了整条回路的锅。4.2 坑1把h0当成仿真步长用很多实现把fhan里的h0直接传成dt然后抱怨噪声滤不掉。原因在于h0同时出现在dr·h0²和线性区判断里当h0dt时算法只是普通离散欧拉逼近对噪声完全开放。我一般让h0取10倍左右采样周期起步h0越大x2越平滑但x1的相位滞后按约h0/2的时间量级增加。在采样周期有抖动的系统中必须保证dt固定否则h0与dt不一致会引入额外离散误差。仿真里先把求解器设成固定步长再谈滤波效果顺序不能反。4.3 坑2初值不同步带来的第一拍尖峰TD是带初值的动态系统。输入v从0开始TD的x1(0)默认也是0没问题。但工程场景常是给定从当前转速2000rpm开始TD初值却是0第一拍误差为2000fhan直接输出满幅加速度rx2瞬间冲到很大的值。这个尖峰进入ESO后总扰动估计会饱和控制器输出撞限实际系统表现为起动瞬间明显前冲。解决方法是每次启动或参考值切换时把TD的x1重置为当前输入信号x2重置为当前速度估计。若输入本身是阶跃则保留x1重启前的值再让TD自然过渡。代码里就是在初始化时传x1_0v(0)而不是默认0。4.4 坑3Simulink代数环与求解器不匹配的异常自激Simulink里若把TD用连续传递函数形式搭再把输出反馈回去可能连成代数环仿真步长会自动切小出现低频自激。更常见的是用变步长求解器跑离散TD状态在不同步长下被重复计算曲线像随机扰动。规范做法是Solver: Fixed-step Fixed-step size: 0.001在Simulink中把TD写成MATLAB Function状态用Unit Delay保存按离散顺序逐拍更新。MATLAB Function核心代码如下function [x1_next, x2_next] td_step(x1, x2, v, r, h0, dt) %#codegen u fhan(x1 - v, x2, r, h0); x1_next x1 dt * x2; x2_next x2 dt * u; end function u fhan(y, x2, r, h0) d r * h0 * h0; y0 y h0 * x2; a0 sqrt(d * (d 8 * abs(y0))); a1 h0 * x2 (a0 - d) * 0.5 * sign(y0); sy (sign(y0 d) - sign(y0 - d)) / 2; a (h0 * x2 y0 - a1) * sy a1; sa (sign(a d) - sign(a - d)) / 2; u -r * (a / d - sign(a)) * sa - r * sign(a); endMATLAB的sign(0)返回0和Python里的处理一致。使用S-Function时若把状态当作连续状态输出又把输出即连回输入也会触发代数环正确做法是用DWork或Unit Delay保存离散状态每个调用周期更新一次。做FPGA移植时同理例如在安路TD系列芯片上定点化h0用整数周期数表示sqrt用CORDIC展开避免浮点运算吃满DSP块。另外TD参数和“pid中pb ti td”里的微分时间没法换算自抗扰里没有微分增益的概念直接用误差做d控制容易把TD的v2当成PID的D通道来加结果系统抖得厉害。v2只作为参考速度前馈或状态反馈不承担噪声抑制任务。4.5 用三组输入验证TD是否调到可用状态别只看阶跃曲线。有效的验证方式是同时跑三个输入阶跃v1验证无超调跟踪和x2峰值斜坡vt验证稳态误差理想情况下x2稳态等于1正弦vsin(2πft)验证相移和幅值误差。上升时间可以由最速轨迹理论估算理论值约为2/√r实测值略大参数扫描脚本如下for r in [10.0, 40.0, 160.0]: td TrackingDifferentiator(r, h00.01) # 重复3.2的阶跃循环记录上升时间、x2峰值、相位滞后 print(r, rise_time, peak, phase_deg)不同r的趋势如下r理论最小上升时间2/√rx2峰值相位滞后趋势10约0.63s不超过10较大40约0.32s接近40中等160约0.16s接近160较小r增大x2峰值同步增大相位滞后减少。但这个趋势只在h0不变时成立若同步加大h0相位损失会重新变大。TD调好的标准不是“最快”而是让整个自抗扰回路的控制量不撞限、噪声不放大、相位损失能被ESO补偿。5. 自抗扰控制里把TD和ESO串起来的最小实现5.1 ADRC三部件里TD的位置和连接关系二阶自抗扰控制器回路中TD放在给定端ESO放在被控对象测量端两者一起提供完整的系统状态。连接顺序参考输入r→TD(r)→v1,v2 对象输出y←ESO(z1,z2,z3) 控制律 u0 kp·(v1-z1)kd·(v2-z2) u u0 - z3/b0TD负责过渡过程和干净的参考速度v2ESO估计对象内部状态z1、z2以及总扰动z3。控制律用误差和误差导数对应PID的P和D但积分功能由总扰动补偿完成不直接存在于误差通道。这个结构决定了TD快慢必须与ESO带宽匹配。5.2 一个最小完整仿真循环用Python一条龙跑下来ESO类先写上用线性扩张状态观测器class ESO: def __init__(self, w050.0, b01.0, dt0.001): self.w0 w0 # 观测器带宽 self.b0 b0 # 对象控制增益估计 self.dt dt self.z1, self.z2, self.z3 0.0, 0.0, 0.0 def update(self, y, u): # 增益按带宽配置3w0, 3w0^2, w0^3 e self.z1 - y self.z1 self.dt * (self.z2 - 3.0 * self.w0 * e) self.z2 self.dt * (self.z3 - 3.0 * self.w0**2 * e self.b0 * u) self.z3 self.dt * (-self.w0**3 * e) return self.z1, self.z2, self.z3ESO带宽w0越大估计越快但噪声越高。b0是控制增益的粗略估计误差会被z3吸收不需要精确标定。TD与ESO带宽匹配原则TD的跟踪带宽一般取ESO带宽的1/3到1/2。若TD太快过渡过程形同虚设且微分噪声进来若ESO比TD快太多参考跟踪能力受限。把TD、ESO、控制律、被控对象放进一个循环kp wc * wc kd 2.0 * wc wc 20.0 # 控制器带宽 td TrackingDifferentiator(r50.0, h010.0*dt, x1_00.0, x2_00.0) eso ESO(w080.0, b02.0, dtdt) y 0.0 yd 0.0 for k in range(n): t k * dt ref 1.0 if t 0.5 else 0.0 # TD生成参考状态 v1, v2 td.step(ref, dt) # 控制器与扰动补偿 u0 kp * (v1 - eso.z1) kd * (v2 - eso.z2) u u0 - eso.z3 / eso.b0 # 简单被控对象二阶积分加未知摩擦力 ydd 0.5 * yd 2.0 * u yd dt * ydd y dt * yd # ESO根据测量y和实际输入u更新 z1, z2, z3 eso.update(y, u)这个循环把TD和ESO完整串起来。TD的输出v1、v2给参考通道ESO的z1、z2给反馈通道z3作为总扰动补偿实时抵消模型不确定性。观察y曲线应无超调、稳态无静差。5.3 串起来后的第1个坑v2直接往后接的限幅问题TD的v2在阶跃输入时会出现高度接近r的脉冲这个脉冲若直接作为速度前馈叠加启动瞬间控制量远大于稳态。仿真里表现为起动冲击实际系统里可能触发过流保护。常见处理是在v2后面加一阶滤波或限幅但更推荐限制r本身。r应小于执行器峰值加速度的80%而不是越大越好。调参时先看x2曲线峰值再看对象输出曲线是否过冲。自抗扰仿真有个好处TD和ESO参数可以分开调试。先关掉ESO令z1y、z2取差分、z30单独看TD响应再关掉TD检查ESO跟踪效果。分开调通再合并定位问题会快得多。6. 验证TD实现正确与否的干净技巧斜坡测精度正弦测相位长期困扰自抗扰仿真调试的问题是TD在跑但不知道是“真跟踪”还是“滤波后的巧合”单看阶跃曲线不够。我用斜坡-正弦联合检验法两次运行就能把动态响应和稳态误差分开。第一次运行斜坡输入vt。若TD实现正确x1最终以斜率1跟踪输入稳态滞后约为h0/2x2收敛到1.0附近。检查x2最后500点的统计量均值与1的误差大于0.01说明r偏小或h0偏大均值为1但方差大说明h0偏小噪声未压住。统计代码片段如下import numpy as np # 假设最后一次斜坡运行已得到 x2 列表 tail tail x2_list[-500:] err np.mean(tail) - 1.0 print(ferr_mean{err:.4f}, x2_std{np.std(tail):.4f})第二次运行正弦vsin(2πft)记录v2与理论导数信号的相位差和幅值。命令行写法python td_validation.py --input ramp python td_validation.py --input sine --freq 5 --r 50输出示例ramp : err_mean0.0062, x2_std0.0210 sine : phase_deg-8.5, amp_ratio0.94快速判定不等式相位损失超过20度或幅值比例低于0.9时直接提高r而不是盲目增加h0相反相位满足但x2高频抖动明显再单独加大h0。另外注意fhan里的符号边界sign(0)必须返回0不能把它改写成sign(x)/|x|那样会把原点附近的导数全打乱。接入完整ADRC系统后再做一次初值对齐测试把v(0)设为100确认第一个控制周期内控制量不出现幅值脉冲。通过这两次验证和一次对齐测试就能确认TD实现正确、参数在可用范围后续问题不会甩锅给跟踪微分器。本文还有配套的精品资源点击获取
返回列表