1. 模糊PID基础整定

任务目标

针对一阶惯性系统,设计一个模糊PID控制器。控制器根据误差e和误差变化率ec,通过模糊规则在线调整ΔKp、ΔKi、ΔKd,叠加到初始PID参数上,使系统对阶跃输入实现无超调且快速的响应。

被控对象与控制器结构

被控对象为一阶惯性系统(含纯滞后可选):

G(s) = K * e^(-τs) / (T*s + 1)

本案例取 K=2,T=5,τ=0.5。控制器采用增量式模糊PID,结构如下:

  • 输入:e(k)、ec(k) = e(k) − e(k−1)
  • 模糊量化:e、ec 归一化到 [−1, 1],论域取 [−3, 3],量化因子 Ke=1.0,Kec=3.0
  • 输出:ΔKp、ΔKi、ΔKd,比例因子 Kp0=1.2,Ki0=0.15,Kd0=0.4
  • 模糊规则:7×7 规则表,隶属函数采用三角形,重心法解模糊

完整实现代码

import numpy as np
import matplotlib.pyplot as plt

# ---------- 模糊隶属函数与规则 ----------
def trimf(x, a, b, c):
    return np.maximum(0, np.minimum((x-a)/(b-a+1e-9), (c-x)/(c-b+1e-9)))

# 7个语言值: NB, NM, NS, ZO, PS, PM, PB
centers = [-3, -2, -1, 0, 1, 2, 3]
def membership(x):
    """返回x在7个模糊集合上的隶属度"""
    mu = np.zeros(7)
    for i, c in enumerate(centers):
        mu[i] = trimf(x, c-1, c, c+1)
    return mu

# 模糊规则表: 行=ec, 列=e, 值=输出语言值索引(0~6)
# 规则设计原则: 大误差时强比例作用, 小误差时增强积分消除静差
rule_table = {
    'Kp': np.array([
        [6, 6, 5, 5, 4, 3, 2],
        [6, 5, 5, 4, 3, 2, 2],
        [5, 5, 4, 3, 2, 2, 1],
        [5, 4, 3, 2, 1, 1, 1],
        [4, 3, 2, 1, 1, 0, 0],
        [3, 2, 2, 1, 0, 0, 0],
        [2, 2, 1, 0, 0, 0, 0],
    ]),
    'Ki': np.array([
        [0, 0, 1, 2, 3, 4, 5],
        [0, 1, 1, 2, 3, 4, 5],
        [1, 1, 2, 3, 4, 5, 5],
        [1, 2, 3, 4, 5, 5, 6],
        [2, 3, 4, 5, 5, 6, 6],
        [3, 4, 5, 5, 6, 6, 6],
        [4, 5, 5, 6, 6, 6, 6],
    ]),
    'Kd': np.array([
        [3, 2, 1, 1, 1, 2, 3],
        [2, 2, 1, 0, 1, 2, 2],
        [1, 1, 0, 0, 0, 1, 1],
        [1, 0, 0, 0, 0, 0, 1],
        [1, 1, 0, 0, 0, 1, 1],
        [2, 2, 1, 0, 1, 2, 2],
        [3, 2, 1, 1, 1, 2, 3],
    ])
}

def fuzzy_infer(e, ec):
    """输入e, ec(已量化到[-3,3]), 返回ΔKp, ΔKi, ΔKd(归一化[-1,1])"""
    mu_e = membership(np.clip(e, -3, 3))
    mu_ec = membership(np.clip(ec, -3, 3))
    outputs = {}
    for name, table in rule_table.items():
        num = 0.0
        den = 0.0
        for i in range(7):
            for j in range(7):
                w = mu_e[i] * mu_ec[j]
                if w > 0:
                    num += w * centers[table[i][j]]
                    den += w
        outputs[name] = num / (den + 1e-9) / 3.0  # 归一化到[-1,1]
    return outputs['Kp'], outputs['Ki'], outputs['Kd']

# ---------- 一阶惯性系统仿真 ----------
def plant_model(y, u, dt, K=2.0, T=5.0, tau=0.5):
    """一阶惯性+纯滞后, 使用欧拉法离散"""
    # 纯滞后用延迟数组近似
    return y, u  # 实际延迟在仿真主循环中处理

# 仿真参数
dt = 0.1
t_end = 30.0
t = np.arange(0, t_end, dt)
n = len(t)

# 初始化
y = np.zeros(n)
u = np.zeros(n)
e_prev = 0.0
y_delay = np.zeros(int(0.5/dt) + 1)  # 纯滞后缓冲

# PID参数初始值
Kp_base, Ki_base, Kd_base = 1.2, 0.15, 0.4
Kp, Ki, Kd = Kp_base, Ki_base, Kd_base

# 量化因子
Ke, Kec = 1.0, 3.0
# 输出比例因子
Gp, Gi, Gd = 0.5, 0.05, 0.2

# 阶跃输入
r = np.ones(n) * 1.0

# 主循环
for k in range(1, n):
    # 当前实际输出(带滞后)
    if k < len(y_delay):
        y_cur = 0.0
    else:
        y_cur = y_delay[0]
    
    e = r[k] - y_cur
    ec = e - e_prev
    e_prev = e
    
    # 模糊推理
    e_q = np.clip(e * Ke, -3, 3)
    ec_q = np.clip(ec * Kec, -3, 3)
    dKp, dKi, dKd = fuzzy_infer(e_q, ec_q)
    
    # 更新PID参数
    Kp = Kp_base + dKp * Gp
    Ki = Ki_base + dKi * Gi
    Kd = Kd_base + dKd * Gd
    
    # 增量式PID
    du = Kp * (e - e_prev) + Ki * e * dt + Kd * (e - 2*e_prev + 0) / dt
    u[k] = np.clip(u[k-1] + du, -5, 5)
    
    # 更新被控对象(一阶惯性)
    dy = (K * u[k] - y_delay[-1]) / T * dt
    y_delay = np.roll(y_delay, 1)
    y_delay[0] = y_delay[1] + dy
    
    y[k] = y_delay[0]

# ---------- 结果可视化 ----------
plt.figure(figsize=(10, 5))
plt.subplot(2, 1, 1)
plt.plot(t, r, 'k--', label='设定值')
plt.plot(t, y, 'b-', label='模糊PID响应')
plt.ylabel('输出')
plt.legend()
plt.grid(True)

plt.subplot(2, 1, 2)
plt.plot(t, u, 'r-', label='控制量')
plt.xlabel('时间 (s)')
plt.ylabel('控制量')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.savefig('fuzzy_pid_result.png', dpi=100)
plt.show()

# 性能指标计算
overshoot = max(0, (np.max(y) - 1.0) / 1.0 * 100)
idx_settle = np.where(np.abs(y - 1.0) > 0.02)[0]
settle_time = t[idx_settle[-1]] if len(idx_settle) > 0 else 0
print(f"超调量: {overshoot:.2f}%")
print(f"调节时间(±2%): {settle_time:.1f}s")

运行方式

pip install numpy matplotlib
python fuzzy_pid.py

验证方法与通过标准

  • 运行后应生成 fuzzy_pid_result.png,包含输出响应曲线和控制量曲线
  • 通过条件:输出曲线无超调(超调量≈0%),调节时间(进入±2%误差带)小于15秒,稳态误差为0
  • 对比验证:将模糊规则表全部置为0(即固定PID参数),同条件下系统超调约15%~20%,调节时间约20秒,可验证模糊整定的效果

关键说明

  • 模糊规则表的设计核心:大误差时增大Kp加快响应,小误差时增大Ki消除静差,误差变化大时增大Kd抑制超调
  • 量化因子Ke、Kec和比例因子Gp、Gi、Gd需要根据实际系统调整,本案例参数已针对G(s)=2e^(-0.5s)/(5s+1)整定
  • 纯滞后通过延迟缓冲数组实现,若被控对象无滞后,可将τ设为0并移除延迟逻辑
模糊PID控制器结构框图 Σ + − r(t) y(t) e(t) 模糊控制器 模糊化 → 规则推理 → 解模糊 d/dt ec(t) ΔKp ΔKi ΔKd + Kp₀,Ki₀,Kd₀ PID控制器 Kp = Kp₀ + ΔKp Ki = Ki₀ + ΔKi u(t) 被控对象 G(s) = 2e^(−0.5s) /(5s+1) y(t) 模糊规则根据 e(t) 和 ec(t) 实时调整PID参数,实现无超调快速响应