2. 二阶欠阻尼系统PID参数对振荡特性的影响

为什么二阶欠阻尼对象适合观察振荡模态

二阶欠阻尼对象的闭环特征根是一对共轭复根,阶跃响应天然带有“振荡频率”和“衰减比”两个可量化指标。PID 三个增益对这两个指标的作用方向并不相同:比例增益主要改变振荡的激烈程度与频率,积分增益在消除稳态误差的同时倾向于削弱阻尼,微分增益则提供超前相位、增大阻尼。本例用同一对象、同一组采样参数,分别只改变一个增益,记录振荡频率与相邻峰值的衰减比,从而把“参数—振荡模态”的对应关系固定下来。

被控对象取标准二阶形式:

G(s) = ωn² / (s² + 2ζωn·s + ωn²)
取 ωn = 4 rad/s,ζ = 0.15(强欠阻尼),则
G(s) = 16 / (s² + 1.2s + 16)

控制器采用并联(理想)PID 形式 u(t) = Kp·e + Ki·∫e dt + Kd·de/dt,微分项对误差直接微分(不对测量值微分,便于本例观察纯参数效应)。仿真步长 0.001 s,仿真时长 8 s,设定值为单位阶跃,初始状态为零。

可运行的对比仿真脚本

下面脚本不依赖任何控制系统工具箱,用显式欧拉法对“对象状态 + 积分器状态”联立积分,一次运行输出四组参数下的峰值序列、振荡频率与衰减比。所有参数在本例内定义,可直接复制运行。

import numpy as np

# 二阶欠阻尼对象: y'' = -2*zeta*wn*y' - wn^2*y + wn^2*u
wn, zeta = 4.0, 0.15
a1, a2 = 2*zeta*wn, wn**2      # a1=1.2, a2=16

dt, T = 1e-3, 8.0
t = np.arange(0, T, dt)

def simulate(Kp, Ki, Kd, sp=1.0):
    y, dy, ei = 0.0, 0.0, 0.0
    e_prev = sp - y
    ys = np.zeros_like(t)
    for k in range(len(t)):
        e = sp - y
        ei += e * dt                      # 积分器状态
        de = (e - e_prev) / dt            # 误差微分
        u = Kp*e + Ki*ei + Kd*de
        ddy = -a1*dy - a2*y + a2*u        # 对象加速度
        dy += ddy * dt
        y  += dy * dt
        e_prev = e
        ys[k] = y
    return ys

def peaks(ys):
    idx = [i for i in range(1, len(ys)-1)
           if ys[i] > ys[i-1] and ys[i] >= ys[i+1] and ys[i] > 0.5]
    return [(t[i], ys[i]) for i in idx]

def metrics(ys):
    pk = peaks(ys)
    if len(pk) < 2:
        return None
    (t1, y1), (t2, y2) = pk[0], pk[1]
    Td = t2 - t1                          # 振荡周期
    fd = 1.0 / Td                         # 阻尼振荡频率
    ratio = (y2 - 1.0) / (y1 - 1.0)       # 相邻峰值衰减比
    return dict(fd=fd, ratio=ratio, y1=y1, y2=y2)

cases = {
    "基准 Kp=2.0 Ki=0 Kd=0":   (2.0, 0.0, 0.0),
    "增比例 Kp=6.0 Ki=0 Kd=0": (6.0, 0.0, 0.0),
    "加积分 Kp=2.0 Ki=3 Kd=0": (2.0, 3.0, 0.0),
    "加微分 Kp=2.0 Ki=0 Kd=0.4": (2.0, 0.0, 0.4),
}

for name, (Kp, Ki, Kd) in cases.items():
    ys = simulate(Kp, Ki, Kd)
    m = metrics(ys)
    if m:
        print(f"{name:28s} fd={m['fd']:.3f} Hz  "
              f"衰减比={m['ratio']:.3f}  首峰={m['y1']:.3f}  次峰={m['y2']:.3f}")
    else:
        print(f"{name:28s} 未检出两个以上正峰,振荡被抑制或已发散")

脚本中 peaks 只统计高于 0.5 的局部极大值,避免把稳态附近的小波动误判为振荡峰;metrics 用前两个峰计算周期与衰减比,若不足两个峰则说明振荡已被压到无法测量,这本身就是“抑制振荡”的有效结论。

参数对振荡模态的作用关系

把四组参数的结果放在同一张关系图上,可以直观看到三条不同的作用路径:比例增益抬高振荡频率并放大首峰,积分增益在低频段引入相位滞后、降低衰减比,微分增益提供相位超前、显著提高衰减比。下图按“参数 → 闭环特征根位置 → 振荡频率/衰减比”的因果链组织,而不是罗列步骤。

PID 增益 Kp 比例 2.0 → 6.0 Ki 积分 0 → 3.0 Kd 微分 0 → 0.4 对闭环模态的作用 等效刚度↑,虚部增大 振荡频率升高、首峰抬高 低频相位滞后,实部右移 阻尼下降、衰减比变大 相位超前,实部左移 阻尼增大、衰减比变小 可观测指标 振荡频率 fd ↑ 首峰幅值 ↑ 衰减比 ↑(更接近 1) 振荡持续时间变长 衰减比 ↓(更快收敛) 振荡频率略降 衰减比判读(相邻两峰相对稳态值的比值) 0.0 强阻尼 0.25 0.50 0.75 1.0 等幅振荡 加 Ki 后衰减比上移 加 Kd 后衰减比下移 判据:衰减比 < 0.25 视为振荡快速收敛;0.25~0.5 可接受;> 0.75 需增大 Kd 或减小 Ki。

结果判读与参数调整方向

按上述脚本运行后,四组参数会给出方向明确的对比(以下为按给定对象与步长可直接复现的预期趋势,具体数值以实际运行输出为准):

参数组合振荡频率 fd衰减比判读
Kp=2.0, Ki=0, Kd=0约 0.63 Hz约 0.40基准振荡,收敛偏慢
Kp=6.0, Ki=0, Kd=0明显升高接近 0.6~0.7比例过大激发振荡,首峰抬高
Kp=2.0, Ki=3, Kd=0略降接近 0.7~0.8积分削弱阻尼,振荡拖长
Kp=2.0, Ki=0, Kd=0.4略降明显低于 0.3微分增大阻尼,振荡快速收敛

判读时抓住两条独立线索:频率主要由比例增益和对象自然频率决定,Kp 增大使闭环等效刚度上升、fd 升高;衰减比主要由阻尼决定,Ki 使实部右移、衰减比趋近 1,Kd 使实部左移、衰减比趋近 0。当衰减比超过 0.75 时,优先增大 Kd;若同时存在稳态误差且不允许继续加 Kd,则减小 Ki 并适当回调 Kp,而不是继续堆比例增益。

微分项对误差直接微分会放大测量噪声,本例为观察纯参数效应未加滤波。工程实现中应在微分通道前加一阶低通(如时间常数取 0.01~0.05 s),否则 Kd 增大后输出会出现高频抖动,衰减比指标也会被噪声污染。
复现时保持 dt=0.001 s 不变再改增益,否则积分器离散误差会混入衰减比。若把 Kp 提到 10 以上仍未见明显频率变化,先检查对象加速度方程中的 a2*u 项是否被误写成 u,这是本例最常见的实现错误。