4. 滑模控制:对抗匹配干扰的利器

说实话,搞了这么多年控制工程,最让我头疼的就是非线性干扰。你设计得好好的一个系统,突然来个未知扰动,性能立马打折扣。但有一招,对付特定类型的干扰特别管用——滑模控制。

我最早接触滑模控制是在一个电机伺服项目里。当时被一个低频扰动折磨得够呛,PID调来调去就是压不住。后来一个老前辈跟我说:「试试滑模吧,专治各种匹配干扰。」一试,果然见效。

4.1 什么是匹配干扰?

先搞清楚一个概念。匹配干扰,说白了就是干扰信号和你的控制输入作用在同一个通道上。

用数学语言描述一下:

系统模型:ẋ = f(x) + g(x)u + d(x,t)

其中 d(x,t) 是干扰项
如果 d(x,t) 可以写成 g(x)·Δ(x,t) 的形式
那么 d(x,t) 就是匹配干扰

什么意思?干扰 d 和控制 u 共享同一个输入矩阵 g(x)。你想想看,这种情况下,控制器可以直接「抵消」干扰的影响。

核心观点:滑模控制对匹配干扰有天然的鲁棒性。不匹配干扰?那得另想办法,后面章节会讲。

4.2 滑模控制的基本思想

滑模控制的思路其实很直观。我习惯这么跟新人讲:

第一步,设计一个滑模面 s(x)=0。这个面代表你期望的系统行为。

第二步,设计控制律,迫使系统状态跑到这个面上。

第三步,一旦上了面,就让状态沿着面滑向平衡点。

整个过程分两阶段:趋近阶段和滑模阶段。

滑模控制核心逻辑 阶段一:趋近阶段 状态从任意初始点 向滑模面 s(x)=0 运动 控制律:s·ṡ < 0 阶段二:滑模阶段 状态保持在滑模面上 沿 s(x)=0 滑向平衡点 等效控制维持滑动 滑模控制的关键特性 ✅ 对匹配干扰完全鲁棒——一旦进入滑模阶段 ✅ 系统降阶——滑模面决定动态行为 ⚠️ 抖振问题——理想切换无法实现,实际有高频振荡 💡 解决方案:边界层法、高阶滑模、自适应增益

4.3 一个简单的例子

拿一个一阶系统来演示,这样最清楚。

系统:ẋ = u + d(t)
其中 d(t) 是匹配干扰,|d(t)| ≤ D

设计滑模面:s = x
控制律:u = -k·sign(s),k > D

分析:
s·ṡ = x·(u + d) = x·(-k·sign(x) + d)
     = -k|x| + x·d ≤ -k|x| + D|x| = -(k-D)|x| < 0

所以 s→0,系统稳定。

你看,只要 k 选得比干扰上界 D 大,系统就一定收敛。这就是滑模控制鲁棒性的来源。

实战技巧:我一般把 k 选为 D 的 1.2~1.5 倍。太小了鲁棒性不够,太大了抖振严重。这个比例是我在多个项目中试出来的经验值。

4.4 抖振问题与对策

抖振是滑模控制绕不开的话题。理想情况下,控制器以无穷大频率切换,但现实中做不到。

我曾经在一个液压伺服系统里用滑模控制,结果抖振把阀芯都磨坏了。从那以后,我对抖振问题格外上心。

常用的抖振抑制方法:

方法 原理 优缺点
边界层法 用饱和函数 sat(s/Φ) 代替 sign(s) 简单有效,但牺牲鲁棒性
高阶滑模 将切换作用到控制量的高阶导数上 效果好,但设计复杂
自适应增益 根据干扰大小动态调整 k 灵活,但需要额外算法
观测器补偿 用干扰观测器估计 d(t) 并前馈补偿 精度高,但依赖模型

注意:边界层法虽然简单,但 Φ 选大了会失去滑模控制的鲁棒性优势。我建议 Φ 取滑模面幅值的 5%~10%,先试再调。

4.5 滑模面设计要点

滑模面怎么设计?我个人的习惯是:

  1. 线性滑模面:s = c₁x₁ + c₂x₂ + ... + xₙ,系数按极点配置来选
  2. 积分滑模面:加入误差积分项,消除稳态误差
  3. 终端滑模面:s = ẋ + β|x|^α·sign(x),有限时间收敛

实际项目中,我90%的情况用线性滑模面。简单、可靠、好调。积分滑模面虽然能消除静差,但容易引起积分饱和,需要加抗饱和措施。

4.6 一个完整的仿真示例

下面是一个二阶系统的滑模控制代码。我习惯用 Python 做快速验证。

import numpy as np
import matplotlib.pyplot as plt

# 系统参数
m = 1.0  # 质量
b = 0.5  # 阻尼
k = 2.0  # 刚度

# 滑模控制器
def sliding_control(x, xd, params):
    c = params['c']      # 滑模面系数
    eta = params['eta']  # 切换增益
    phi = params['phi']  # 边界层厚度
    
    # 滑模面
    s = c * (x[0] - xd[0]) + (x[1] - xd[1])
    
    # 等效控制
    u_eq = m * (xd[2] - c*(x[1]-xd[1])) + b*x[1] + k*x[0]
    
    # 切换控制(带边界层)
    if abs(s) < phi:
        u_sw = -eta * s / phi
    else:
        u_sw = -eta * np.sign(s)
    
    return u_eq + u_sw

# 仿真主循环
dt = 0.001
t = np.arange(0, 5, dt)
x = np.array([0.0, 0.0])
xd = np.array([1.0, 0.0, 0.0])  # 目标位置、速度、加速度

params = {'c': 5.0, 'eta': 3.0, 'phi': 0.05}

for i in range(len(t)):
    u = sliding_control(x, xd, params)
    # 加入匹配干扰
    d = 2.0 * np.sin(10*t[i])
    # 系统更新
    x_ddot = (u + d - b*x[1] - k*x[0]) / m
    x[1] += x_ddot * dt
    x[0] += x[1] * dt

调试经验:我调滑模参数有个顺序——先定滑模面系数 c,再调切换增益 η,最后微调边界层厚度 φ。c 决定收敛速度,η 决定鲁棒性,φ 决定抖振大小。别一上来就三个参数一起调,容易乱。

4.7 实际应用中的注意事项

最后说几个我在项目中踩过的坑:

  • 传感器噪声:滑模控制对噪声敏感,尤其是求导后的信号。我一般加低通滤波,截止频率取系统带宽的 3~5 倍。
  • 执行器饱和:控制量太大执行器会饱和。建议加抗饱和逻辑,或者用模型预测做约束。
  • 离散化影响:数字实现时采样频率要够高。我一般要求采样频率是滑模切换频率的 10 倍以上。

嗯,滑模控制就讲到这里。记住一句话:匹配干扰不可怕,滑模控制搞定它。但前提是——你得把滑模面设计好,把抖振控制住。

公众号:蓝海资料掘金营,微信deep3321