2. 模糊规则表设计

任务目标

设计一个二维模糊规则表,以误差 \( e \) 和误差变化率 \( ec \) 为输入,输出 PID 参数调整量 \( \Delta K_p \)、\( \Delta K_i \)、\( \Delta K_d \)。规则表采用标准 Mamdani 型,输入输出均使用 7 个对称三角形隶属度函数,论域为 [-3, 3]。

模糊论域与隶属度定义

输入 \( e \)、\( ec \) 与输出 \( \Delta K_p \)、\( \Delta K_i \)、\( \Delta K_d \) 均采用相同论域与语言值:NB(负大)、NM(负中)、NS(负小)、ZO(零)、PS(正小)、PM(正中)、PB(正大)。隶属度函数采用全交叠三角形,相邻函数交叠度为 0.5,保证任意输入至少激活两条规则。

规则表核心设计原则

  • \( \Delta K_p \):|e| 大时取大值以快速响应;|e| 中等时取中值;|e| 小时取小值,同时根据 ec 方向微调以避免超调。
  • \( \Delta K_i \):|e| 小时增大积分作用以消除稳态误差;|e| 大时减小积分作用以防积分饱和。
  • \( \Delta K_d \):|ec| 大时取大值以抑制动态偏差;|ec| 小时取小值以避免噪声放大。

关键完整代码(Python + NumPy)


import numpy as np

# 语言值索引: 0=NB,1=NM,2=NS,3=ZO,4=PS,5=PM,6=PB
labels = ['NB','NM','NS','ZO','PS','PM','PB']
centers = np.array([-3,-2,-1,0,1,2,3])  # 三角形中心
half_width = 1.0                        # 半宽,交叠度0.5

def tri_mf(x, center):
    """三角形隶属度函数"""
    return max(0.0, 1.0 - abs(x - center) / half_width)

def fuzzify(x):
    """将精确值映射为7维隶属度向量"""
    return np.array([tri_mf(x, c) for c in centers])

# ---------- 模糊规则表 (49条规则) ----------
# 每条规则: (e_idx, ec_idx) -> (dKp_idx, dKi_idx, dKd_idx)
# 规则表依据标准Ziegler-Nichols经验修正设计
rule_table = {}

# ΔKp 规则表 (7x7)
dKp_rules = np.array([
    [6, 5, 4, 4, 4, 5, 6],   # NB
    [5, 4, 3, 3, 3, 4, 5],   # NM
    [4, 3, 2, 2, 2, 3, 4],   # NS
    [3, 2, 1, 0, 1, 2, 3],   # ZO
    [4, 3, 2, 2, 2, 3, 4],   # PS
    [5, 4, 3, 3, 3, 4, 5],   # PM
    [6, 5, 4, 4, 4, 5, 6],   # PB
])  # 行=e, 列=ec

# ΔKi 规则表 (7x7)
dKi_rules = np.array([
    [0, 0, 1, 1, 1, 0, 0],   # NB
    [0, 1, 2, 2, 2, 1, 0],   # NM
    [1, 2, 3, 3, 3, 2, 1],   # NS
    [2, 3, 4, 4, 4, 3, 2],   # ZO
    [1, 2, 3, 3, 3, 2, 1],   # PS
    [0, 1, 2, 2, 2, 1, 0],   # PM
    [0, 0, 1, 1, 1, 0, 0],   # PB
])

# ΔKd 规则表 (7x7)
dKd_rules = np.array([
    [3, 2, 1, 1, 1, 2, 3],   # NB
    [2, 1, 0, 0, 0, 1, 2],   # NM
    [1, 0, 0, 0, 0, 0, 1],   # NS
    [0, 0, 0, 0, 0, 0, 0],   # ZO
    [1, 0, 0, 0, 0, 0, 1],   # PS
    [2, 1, 0, 0, 0, 1, 2],   # PM
    [3, 2, 1, 1, 1, 2, 3],   # PB
])

# 构建规则表字典
for i in range(7):
    for j in range(7):
        rule_table[(i, j)] = (dKp_rules[i, j], dKi_rules[i, j], dKd_rules[i, j])

def fuzzy_inference(e, ec):
    """
    模糊推理: 输入精确值 e, ec,输出调整量 ΔKp, ΔKi, ΔKd
    采用 Mamdani 推理 + 重心法去模糊化
    """
    mu_e = fuzzify(np.clip(e, -3, 3))
    mu_ec = fuzzify(np.clip(ec, -3, 3))

    # 收集所有规则后件隶属度
    out_centers = np.zeros(3)   # 加权和
    out_weights = np.zeros(3)   # 权重和

    for i in range(7):
        for j in range(7):
            # 规则激活度 = min(前件隶属度)
            fire_strength = min(mu_e[i], mu_ec[j])
            if fire_strength <= 0:
                continue

            kp_idx, ki_idx, kd_idx = rule_table[(i, j)]

            # 重心法累加
            out_centers[0] += fire_strength * centers[kp_idx]
            out_centers[1] += fire_strength * centers[ki_idx]
            out_centers[2] += fire_strength * centers[kd_idx]
            out_weights += fire_strength

    if np.sum(out_weights) == 0:
        return np.array([0.0, 0.0, 0.0])

    return out_centers / out_weights

# ---------- 最小验证闭环 ----------
if __name__ == "__main__":
    # 测试用例1: e=0, ec=0 (稳态) -> 输出应接近0
    dKp, dKi, dKd = fuzzy_inference(0.0, 0.0)
    print(f"e=0, ec=0 -> ΔKp={dKp:.3f}, ΔKi={dKi:.3f}, ΔKd={dKd:.3f}")
    # 预期: 三者均接近0 (因ZO规则占主导)

    # 测试用例2: e=3, ec=0 (大误差) -> ΔKp应较大
    dKp, dKi, dKd = fuzzy_inference(3.0, 0.0)
    print(f"e=3, ec=0 -> ΔKp={dKp:.3f}, ΔKi={dKi:.3f}, ΔKd={dKd:.3f}")
    # 预期: ΔKp接近3, ΔKi接近0, ΔKd接近0

    # 测试用例3: e=0, ec=3 (大误差变化率) -> ΔKd应较大
    dKp, dKi, dKd = fuzzy_inference(0.0, 3.0)
    print(f"e=0, ec=3 -> ΔKp={dKp:.3f}, ΔKi={dKi:.3f}, ΔKd={dKd:.3f}")
    # 预期: ΔKd接近3, ΔKp接近0, ΔKi接近0

运行与验证方法

  1. 运行环境:Python 3.8+,仅需 NumPy(pip install numpy)。
  2. 执行方式:将上述代码保存为 fuzzy_rules.py,在终端运行 python fuzzy_rules.py。
  3. 通过条件:
    • 测试1输出三个值均接近 0(值 < 0.1);
    • 测试2输出 ΔKp 接近 3(2.5~3.0),ΔKi、ΔKd 接近 0;
    • 测试3输出 ΔKd 接近 3(2.5~3.0),ΔKp、ΔKi 接近 0。

规则表可视化

ΔKp 规则表(颜色越深表示输出越大) PB PM PS ZO NS NM NB NB NM NS ZO PS PM PB 输出强度 大 (PB) 中 (ZO) 小 (NS)

常见问题

  • 输出超出 [-3,3] 范围:输入 e/ec 超出论域时被 clip 到边界,输出由重心法保证在论域内。
  • 规则表对称性:ΔKp 表关于 ZO 行/列对称,ΔKi 表关于 ZO 行对称,ΔKd 表关于 ZO 行/列对称,符合 PID 调参的对称特性。
  • 实际应用:推理得到的 ΔKp、ΔKi、ΔKd 需乘以各自量化因子(如 \( K_{up}, K_{ui}, K_{ud} \))后叠加到初始 PID 参数上,量化因子需根据被控对象另行整定。