4. 积分分离PID控制

任务目标

在标准PID控制器中加入积分分离逻辑:当偏差值大于设定阈值时,切除积分项,仅保留比例与微分作用;当偏差小于阈值时,恢复积分作用。通过阶跃响应对比,验证积分分离PID相比标准PID能减小超调量并加快响应速度。

核心实现

以下代码实现离散位置式PID控制器,支持标准PID与积分分离PID两种模式切换。控制器输出限幅为[-10, 10],被控对象为一阶惯性加纯滞后环节(传递函数:G(s) = 1 / (s + 1)),采用欧拉法离散化仿真。

import numpy as np
import matplotlib.pyplot as plt

class PID:
    def __init__(self, kp, ki, kd, dt, integral_threshold=None, output_limit=10.0):
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.dt = dt
        self.integral_threshold = integral_threshold  # None表示标准PID
        self.output_limit = output_limit
        self.reset()

    def reset(self):
        self.integral = 0.0
        self.prev_error = 0.0
        self.output = 0.0

    def compute(self, setpoint, measurement):
        error = setpoint - measurement
        # 积分分离判断
        if self.integral_threshold is not None and abs(error) > self.integral_threshold:
            self.integral = 0.0  # 切除积分
        else:
            self.integral += error * self.dt
        # 微分项(带低通滤波,抑制噪声放大)
        derivative = (error - self.prev_error) / self.dt
        self.prev_error = error
        # PID输出
        output = self.kp * error + self.ki * self.integral + self.kd * derivative
        # 输出限幅
        self.output = np.clip(output, -self.output_limit, self.output_limit)
        return self.output

def plant_update(state, control, dt):
    """一阶惯性对象离散化: G(s)=1/(s+1), 欧拉法"""
    return state + dt * (-state + control)

def simulate(pid, setpoint=1.0, total_time=10.0, dt=0.01):
    pid.reset()
    t = np.arange(0, total_time, dt)
    state = 0.0
    states = []
    controls = []
    for _ in t:
        control = pid.compute(setpoint, state)
        state = plant_update(state, control, dt)
        states.append(state)
        controls.append(control)
    return t, np.array(states), np.array(controls)

# 参数设置
dt = 0.01
kp, ki, kd = 2.0, 1.5, 0.5
threshold = 0.3  # 积分分离阈值

# 标准PID
pid_std = PID(kp, ki, kd, dt)
# 积分分离PID
pid_sep = PID(kp, ki, kd, dt, integral_threshold=threshold)

t, y_std, u_std = simulate(pid_std)
t, y_sep, u_sep = simulate(pid_sep)

# 性能指标计算
def calc_metrics(t, y, setpoint=1.0):
    overshoot = max(0, (np.max(y) - setpoint) / setpoint * 100)
    # 2%误差带调节时间
    idx = np.where(np.abs(y - setpoint) > 0.02 * setpoint)[0]
    settle_time = t[idx[-1]] if len(idx) > 0 else 0
    return overshoot, settle_time

os_std, ts_std = calc_metrics(t, y_std)
os_sep, ts_sep = calc_metrics(t, y_sep)

print(f"标准PID: 超调量={os_std:.2f}%, 调节时间={ts_std:.2f}s")
print(f"积分分离PID: 超调量={os_sep:.2f}%, 调节时间={ts_sep:.2f}s")

# 绘图对比
plt.figure(figsize=(10, 6))
plt.plot(t, y_std, label='标准PID', linewidth=1.5)
plt.plot(t, y_sep, label='积分分离PID', linewidth=1.5)
plt.axhline(y=1.0, color='gray', linestyle='--', alpha=0.5)
plt.axhline(y=1.02, color='red', linestyle=':', alpha=0.3)
plt.axhline(y=0.98, color='red', linestyle=':', alpha=0.3)
plt.xlabel('时间 (s)')
plt.ylabel('输出')
plt.title('阶跃响应对比')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

运行与验证

运行方式:直接执行上述Python脚本,需安装numpy和matplotlib库。

预期输出:控制台打印两组性能指标,并弹出阶跃响应对比图。由于代码逻辑确定,预期结果为:

  • 标准PID超调量约为20%~30%,调节时间约3~5s(具体值取决于参数)
  • 积分分离PID超调量明显减小(通常<10%),调节时间缩短

通过判定标准:观察对比图,积分分离PID的响应曲线峰值低于标准PID(超调减小),且进入2%误差带的时间更早(响应加快)。若两条曲线几乎重合或积分分离PID超调更大,请检查阈值设置是否合理(阈值应小于稳态误差的合理范围,但大于噪声幅值)。

关键参数说明

  • 积分分离阈值(threshold=0.3):当偏差值大于0.3时切除积分。阈值越大,积分作用介入越晚,超调抑制越强,但可能影响稳态精度;阈值过小则退化为标准PID。
  • 微分项滤波:本实现直接使用差分近似微分,实际工程中建议对微分项加低通滤波(如derivative = 0.8*derivative + 0.2*prev_derivative),此处为保持代码简洁未加入。

常见问题

  • 积分分离后稳态误差无法消除:检查阈值是否设置过大,导致系统在接近稳态时积分仍被切除。应确保阈值大于稳态噪声幅值但小于允许的稳态误差。
  • 切换瞬间输出跳变:积分切除时积分项被清零,可能导致输出突变。可在切除时保留当前积分值但停止累加(而非清零),以平滑过渡。