自动控制性能指标与超前校正设计:基于Python的时域频域分析实践
2026/9/18 14:10:14 网站建设 项目流程

简介:《自动控制原理课件:6-2 性能指标与系统设计的基本思路》聚焦自动控制系统设计中的核心环节,面向自动化、电气及机电类专业学生与从事控制系统开发的工程技术人员。内容从系统分析与设计两大任务出发,梳理时域、频域、复数域三类性能指标,并针对串联校正、反馈校正、前馈校正和复合校正等常见方式逐一说明,帮助读者建立从指标确定到校正装置选型的完整设计思路。压缩包为单个PDF文件,大小821KB,包含大量系统设计例题,如根据稳态误差与相角裕度要求计算开环增益、利用根轨迹与MATLAB进行校正分析等,图文并茂地展示了带宽选择、频域指标与时域指标的关系,适合作为课堂讲义配套学习或考研复习参考。目前已有133人学习下载,PDF内容结构清晰,重点突出,便于快速查阅系统设计的基本思想与校正方法。

1. 自动控制原理性能指标:把“快、准、稳”变成可计算的约束

超调量不超过 30%、调节时间 0.5 秒、斜坡输入稳态误差低于 1%、相角裕度不低于 60°——当需求文档把这些数字压下来时,控制工程师真正要做的第一件事,不是打开整定界面去调 P、I、D,而是把这几个指标翻译成开环传递函数上的约束,再换算成校正器的零点和极点位置。自动控制原理课里“性能指标与系统设计的基本思路”这一节,讲的就是这条翻译链:性能指标是需求与控制模型之间的接口,设计过程是从指标反推控制器结构的求解过程。做运动控制卡、电源环路、机器人关节控制的人,几乎每天都在这个链路里来回走。下面我就按照时域指标、频域裕度、指标到设计的映射、仿真验证四条路径拆开讲,全程用 Python 的 scipy 和控制库复现,课程里用 MATLAB 的 stepinfo 逻辑也一并留给交叉验证用。

2. 时域性能指标提取:超调量、调节时间、稳态误差的量化路径

2.1 二阶闭环系统的四个读数

线性定常系统在闭环之后,如果存在一对离虚轴最近的主导极点,动态行为就可以用这对共轭复数极点 s = −ζωn ± jωn√(1 − ζ²) 来近似。控制课件反复讲的阻尼比 ζ 和自然频率 ωn,并不是为了计算而计算:ζ 决定振荡的收敛速度,ωn 决定响应的总体快慢,两者共同决定阶跃响应上的四个特征读数。

上升时间 tr 是输出从稳态终值的 10% 升到 90% 的花费时间;峰值时间 tp 是输出到达极大值的时刻;超调量 σ 是峰值相对稳态终值的超出百分比;调节时间 ts 是输出进入 ±2% 误差带之后不再离开的时间。这四个读数里,tr 与 tp 描述快慢,σ 描述过冲风险,ts 则把快与稳捏在一起,是工程合同里最常用的总指标。阻尼比与超调量的精确关系是 σ = exp(−πζ/√(1 − ζ²)),在 ζ 处于 0.4~0.8 范围内时,这个式子可以直接当查表关系用。ts 的快速估算则常见两种口径:2% 误差带取 ts ≈ 4/(ζωn),5% 误差带取 ts ≈ 3/(ζωn)。这里有一个容易踩的坑:两个近似公式都默认主导极点假设严格成立,如果被测系统存在零点或者附加极点离主导极点不远,公式给出的 ts 偏差经常超过 20%。所以做设计分析时公式只用来定初值,最终认定必须以阶跃响应数值曲线为准。

2.2 Python 里提取指标的最小脚本

先构造一个典型欠阻尼闭环二阶系统并把阶跃响应算出来:

import numpy as np from scipy import signal wn = 10.0 zeta = 0.45 sys = signal.TransferFunction([wn**2], [1, 2*zeta*wn, wn**2]) t, y = signal.step(sys, T=np.linspace(0, 2.0, 4001)) y_ss = y[-1]

这里 TransferFunction 分子是 ωn²,分母是 s² + 2ζωn s + ωn²,正好对应单位反馈下一阶惯性对象的闭环形态。step 在 0~2 秒范围内取 4001 个点,时间步长 0.5ms,后续判断 10%、90% 与峰值时刻时,分辨率足够。

提取三个读数的函数:

def rise_time(t, y, y_ss): i10 = np.where(y >= 0.10 * y_ss)[0][0] i90 = np.where(y >= 0.90 * y_ss)[0][0] return t[i90] - t[i10] def peak_overshoot(y, y_ss): return (np.max(y) - y_ss) / y_ss * 100 def settle_time(t, y, y_ss, tol=0.02): in_band = np.abs(y - y_ss) <= tol * y_ss if not in_band[-1]: return np.inf return t[np.where(in_band)[0][-1]]

rise_time 用两次 np.where 求首次越过 10% 和 90% 阈值的时间点再相减;peak_overshoot 用整条响应的最大值减去稳态值再归一化,返回的是百分数;settle_time 先把所有落进 ±2% 误差带的采样点标记出来,再取最后一个满足条件的时刻。判定里必须先检查 in_band[-1],如果最后一个采样点都不在误差带内,说明仿真时间不够长,函数应当返回无穷大而不是硬给一个数字。这三行逻辑对应 MATLAB stepinfo 内部的核心步骤,stepinfo 只是顺手连峰值时间、上升时间一起返回。多平台交叉验证时,注意核对误差带口径:MATLAB 的 SettlingTimeThreshold 默认 2%,换成 5% 需要显式声明,否则两组结果没有可比性。

2.3 稳态误差与系统型别的关系

时域指标的第二大类是稳态误差,它不关心过渡过程,只看 t → ∞ 时输出和指令的差。单位阶跃输入下,0 型系统输出必然存在静差,误差等于 1/(1+Kp),Kp 是开环增益;单位斜坡输入下,前向通路有至少一个积分环节时才有有限误差,大小等于 1/Kv,Kv 是速度误差系数。也就是说,斜坡误差写进指标的那一刻,系统型别和开环增益下限就都被锁定了。

这一步是“指标引导设计”的第一个落点:先由误差需求决定前向通路里积分环节个数,再由动态指标决定阻尼与频段,顺序不能反过来。设计前建议把三个输入类型和对应要求列成一张表:

输入信号系统型别要求误差系数稳态误差
单位阶跃至少 0 型(1 型后误差为零)Kp = lim_{s→0} G(s)1/(1+Kp)
单位斜坡至少 1 型Kv = lim_{s→0} sG(s)1/Kv
单位加速度至少 2 型Ka = lim_{s→0} s²G(s)1/Ka

表格里的“型别”指开环传递函数中 s=0 孤立极点的数量,也就是低频段 1/s 的幂次。项目里最常见的错误就是拿 0 型系统去跟伺服电机协议里“跟随速度指令”的要求对表,结果斜坡跟踪误差一直减不下去。设计阶段先答对这一点,后面校正器才不会白调。

3. 频域性能指标:相角裕度与幅值裕度的伯德图拆解

3.1 为什么设计动作要发生在开环曲线上

时域指标是交付给现场的外貌,但设计动作几乎都落在开环伯德图上。原因不在喜好,而在数学:闭环特征方程是 1+G(s)H(s)=0,稳定与否只看开环频率曲线绕没绕到 (-1, j0) 点,落到工程语言里就变成两个标量——相角裕度 PM 与幅值裕度 GM。

PM 是开环对数幅频曲线穿过 0dB 时,相位距离 -180° 还剩多少度;GM 是相位第一次越过 -180° 时,幅频比 0dB 低多少分贝。PM 支配动态过程,GM 支配发散倾向,两个指标缺一不可。工程规范里常见“PM≥45°且 GM≥6dB”这种成对写法,因为只保 PM 不保 GM,会在增益随温度或批次漂移时突然失稳;只保 GM 不保 PM,阶跃曲线会又慢又抖。

还要提醒一个被课件一带而过的细节:PM 的“度”数是相位差,不是相位本体。最小相位系统中,如果相频曲线在穿越频率附近不是单调下降,而是被某个局部零点暂时拉回来,单纯读 PM 会得到虚假的安全感。这时候必须展开整个相频曲线的形态判断,不能只看一个点。

3.2 在伯德数据上逐点读出 PM 与 GM

scipy.signal 的 bode 输出的是离散频率点上的幅值与相位,能否准确读到裕度,完全取决于频率网格密度。我一般把跨十个十倍频程的区间用 logspace 铺 4000 个点以上,才去判断符号穿越。

from scipy.signal import TransferFunction, bode import numpy as np G = TransferFunction([100], [1, 11, 10]) w = np.logspace(-1, 3, 4000) w_out, mag_db, phase_deg = bode(G, w) # 增益穿越:幅频由正转负的位置 idx_g = np.where(np.diff(np.sign(mag_db)) != 0)[0] if idx_g.size: wc = w_out[idx_g[0]] pm = 180 + phase_deg[idx_g[0]] else: wc, pm = np.nan, np.nan # 相位穿越:相位越过 -180° 的位置 idx_p = np.where(np.diff(np.sign(phase_deg + 180)) != 0)[0] if idx_p.size: wp = w_out[idx_p[0]] gm = -mag_db[idx_p[0]] else: wp, gm = np.nan, np.inf

代码用“符号变化”替代手工找交点:幅频从正变负对应 0dB 穿越点,相频从大于 -180° 变成小于 -180° 就是相位穿越点。PM 用 180 加该点相位得到正值,GM 取该点幅值的负号,因为稳定系统的相位穿越点幅值通常小于 0dB。如果整个频段都没有相位穿越,说明开环相位没有低到 -180°,此时 GM 判为无穷,对应系统在设计频带内没有增益失稳边界。这里要注意 np.diff 返回的索引比原数组少一个,取到 idx[0] 后去访问 w_out[idx[0]] 是安全的;如果直接把 diff 结果当原数组下标用,会错一位。

MATLAB 的 margin(G) 一行就能给出同样的数,但它不会告诉你频点密度的影响。遇到在谐振峰附近的边缘情况,我用 MATLAB 和 Python 各算一遍,两个结果落入同一个采样间隔内才算通过。

3.3 PM 与阻尼比及超调量的对应关系

最小相位系统里,PM 和闭环阻尼比的经验关系是 ζ ≈ PM/100(PM 以度计),在 PM 从 30° 到 70° 的区间内误差通常不超过±0.05。这个换算常常被人误当成精确公式,实际上它只是二阶闭环精确关系的线性拟合,适合用来定设计起点。

常用对应表:

相位裕度等效阻尼比阶跃超调量约适用场景
30°0.3037%强扰动、大惯量,宁可多振几下
45°0.4223%通用伺服,性能与鲁棒的折中
60°0.609%高精度定位,留出调试余量
70°0.753%数控与精密平台,强调平稳

表中“等效阻尼比”是指一对主导极点对应的ζ,并不代表系统真是二阶。高阶系统中两个不同对象可以拥有相同的 PM 但差出几个百分点的超调,所以边界设计必须把 PM 多留 5°~10°,最终用手部曲线复核。这也是很多工程师“PM 明明挺高,超调还是超了”的原因——零点前移、高频极点叠加都可能破坏这个对照,PM 只能作为初筛。

4. 性能指标引导的系统设计思路:从指标分解到超前校正

4.1 设计前的指标分解三步

系统设计的基本思路,可以拆成三步漏斗:

第一步,根据误差指标确定系统型别和最小开环增益。这是前面 2.3 那张表的直接延伸,增益下限定了,后面校正器的每一分增益都必须压在这个限定之内。

第二步,根据调节时间确定穿越频率目标。把 ts≈4/(ζωn) 反解出 ωn,再近似认为开环穿越频率 ωc 与闭环带宽处于同一量级。这一步给出的是频率轴上的锚点,后面校正器的最优相位频率要和它对齐。

第三步,根据超调量或 PM 要求确定校正器需要提升的相位量。“超调 20%”先换算成 ζ≈0.45,再换算成 PM≈50°,随后与未补偿系统的 PM 相减,就得到校正器至少需要补进的最大相位角。

这三步的顺序不能换。第 1 步定增益,第 2 步定频段,第 3 步定相角形状。实际项目里我通常在第一轮设计前就把目标穿越频率写进仿真脚本注释里,避免后续反复猜起始点。

4.2 超前校正设计:从 PM 目标到控制器零极点

超前校正网络的标准形式是 C(s)=K×(Ts+1)/(αTs+1),α 小于 1。分子零点产生超前相位,分母极点把超前作用收住,最大超前角出现在几何中心频率 ωm=1/(T√α) 处,数值为 φmax=arcsin((1−α)/(1+α))。

以被控对象 G(s)=100/[s(s+10)] 为例,设计指标取 Kv≥50 s⁻¹、PM≥50°。先用 Kv 约束把总增益定为 K=5,使 Kv=5×100/10=50 恰好在线上;随后用脚本自动完成超前网络参数搜索:

import numpy as np from scipy.signal import TransferFunction, bode G = TransferFunction([100], [1, 10, 0]) G1 = G * 5 # 满足 Kv=50 的开环 w = np.logspace(-1, 4, 5000) wout, mag_db, phase_deg = bode(G1, w) # 1) 未补偿穿越频率与 PM idx0 = np.where(np.diff(np.sign(mag_db)) != 0)[0] wc0, pm0 = wout[idx0[0]], 180 + phase_deg[idx0[0]] # 2) 目标相位增量,预存 8° 消除耦合损失 phi_max = 50 - pm0 + 8 alpha = (1 - np.sin(np.radians(phi_max))) / (1 + np.sin(np.radians(phi_max))) # 3) 找新穿越频率:未补偿幅值落到 -10lg(α) 的位置 target_gain = -10 * np.log10(alpha) idx_new = np.argmin(np.abs(mag_db - target_gain)) wc_new = wout[idx_new] T = 1 / (wc_new * np.sqrt(alpha)) C = TransferFunction([T, 1], [alpha * T, 1]) print(f"pm0={pm0:.1f}° alpha={alpha:.3f} wc_new={wc_new:.2f} T={T:.4f}")

脚本第 2 步里的 +8° 是留给相位曲线在穿越频率附近非理想叠加的缓冲。第 3 步的推导依据是:超前网络在最大相位频率点的幅值正好是 1/√α,换算成分贝是 -10lgα,把未补偿幅值猜到这一数值的位置作为新穿越频率,补偿后的幅频才能恰好落回 0dB。

脚本输出后,用补偿后的开环重读一次 PM:

G2 = G1 * C _, mag2, ph2 = bode(G2, w) idx1 = np.where(np.diff(np.sign(mag2)) != 0)[0] wc1 = wout[idx1[0]] pm1 = 180 + ph2[idx1[0]] print(f"PM={pm1:.1f}° @ ωc={wc1:.2f} rad/s")

如果 pm1 落在 50°~55°,方向就对了;差太多时把第二步的 8° 改成 12° 再跑一轮,一般两轮收敛。注意这个设计里 GM 最终校验必须在控制器离散化并加上一拍延迟之后做,纯连续系统没有有限 GM,这是课件里很少强调但工程里绕不开的差异。

4.3 设计检查点与常见误用

四类问题最常出在指标到设计的翻译环节:

阶段必查项出现偏差时的处理
指标分解系统型别是否正确、Kv 是否贴上限先加积分类别或提高增益
ωc 定位穿越频率是否避开机械谐振峰把 ωc 降半格,或加陷波器
相位补偿PM 是否留了 5°~10° 缓冲重算 φmax 的缓存量再迭代
幅值分配高频段幅值是否被传感器噪声抬起来加滞后段压高频增益

检查表第二行值得多说一句:很多运动控制系统把穿越频率选在了负载弹性引起的谐振峰附近,伯德图上 PM 看着正常,实测阶跃响应却持续微振。判据是看谐振峰对幅频曲线的抬升量是不是超过了 6dB,超过就说明 ωc 选得太近。

5. 性能指标达成度的三种校验方式与一台微调技巧

5.1 用阶跃响应重读四个时域指标

超前校正参数定了之后,需要把闭环单位反馈模型组装起来,再用 step 响应核对全部指标。Python 控制库的一行 feedback 比手工拼接传递函数更省事:

import control as ct Gc = ct.TransferFunction([100], [1, 10, 0]) Cc = ct.TransferFunction([T, 1], [alpha * T, 1]) cl = ct.feedback(Gc * 5 * Cc, 1) info = ct.step_info(cl) print(info["Overshoot"], info["SettlingTime"])

这里 Overshoot 是百分数形式的峰值超调,SettlingTime 按 2% 误差带计算。如果项目合同写的是 5% 误差带,必须在 step_info 里把 SettlingTimeThreshold 改掉,否则报上来的数字会跟现场刻录的对不上。这个口径问题,评审会上经常被当成验收风险单拎出来。

5.2 台架前的三项边界验证

仿真验证不能只做标称模型。我一般会同时跑三组变体:负载转动惯量正负 30% 时重复闭环阶跃;输入分别用单位阶跃和等效斜坡,看稳态误差是否落在规格线上;把连续校正器用 Tustin 变换离散化,加上一拍延迟后再测一次闭环。第三组是数字控制系统最容易暴露 PM 缩水的地方,一拍延迟在高频段贡献的相位亏损通常在 3°~8°,连续域设计遗留的 8° 缓冲正好在这里派上用场。

5.3 一个微调技巧:把穿越频率往回拉半格

如果实测超调量始终偏高、PM 读数却已经在规定值上,不再怀疑相位不够,先怀疑穿越频率是不是压在了未建模的高频拐点上。这时候把超前网络的最大相位频率从 ωm 下挪 20%~30%,也就是增大 T 而 α 不动,让 ωc 跟着回落。回落之后高频噪声与建模误差的敏感度明显下降,调节时间通常多出几毫秒,换来的是更接近时域指标的超调量。改完重跑 5.1 和 5.2,只要 PM 变化在 5° 以内、超调回到目标区间,这轮设计就算收口。

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

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

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

立即咨询