倒立摆这个东西,控制专业的同学十有八九都绕不过去。说来也巧,最近有位读者私信问我:“传统PID加模糊PID,同一个倒立摆,到底哪个更能打?”我刚好整理完一份“基于模糊PID+传统PID的一阶倒立摆双PID稳定控制对比仿真设计”的项目笔记,把建模、双PID架构、参数整定、模糊规则设计、仿真对比以及写说明报告时该放哪些图表都捋了一遍。这篇就把整个思路摊开写出来,给正在做自平衡相关课程设计、毕业设计,或者纯粹想搞懂“模糊PID到底香在哪”的朋友做个可复现的参考。
先说结论:传统PID不是不能稳,只是稳得“很费劲”;模糊PID也不是万能药,但在响应速度、超调量、抗扰动这些硬指标上,确实能拉开明显差距。下面从模型开始,一步一步聊。
1. 为什么倒立摆值得做:开环不稳定还非最小相位,控制系统难得的好靶子
1.1 一阶倒立摆到底“难”在哪
一阶倒立摆,中文文献里常写作“一级倒立摆”,就是一根摆杆装在一辆小车上,摆杆可以绕小车上的转轴前后摆动。控制目标就两句话:让摆杆一直立在竖直位置,同时让小车回到轨道中心。听起来像玩具,但它的数学本质相当不友好。
首先,摆杆在竖直位置是开环不稳定的。你把它摆到正上方,任何一点点扰动都会让它加速倒下,而且倒得越来越快,这就是典型的正反馈失稳。其次,它是一个非最小相位系统,右半平面有零点,意味着你看到摆杆往左倒,小车必须先往左推一下、反而加速它的倾倒,之后才能真正把它扶正——这种“反直觉”的响应特性,让很多新手PID怎么调都调不稳。
更麻烦的是,系统是强耦合的:摆杆角度和车位移互相影响,你不能把这两个量分开看。单纯给角度一个PID,小车会一路狂奔冲出轨道;单纯控位置,摆杆早就倒了。所以工程上都用双PID级联:内环管角度,外环管位置,外环的输出作为内环的给定。这也是这个项目标题里“双PID”三个字的由来。
1.2 双PID的结构角色分工:角度环保稳,位移环保位
双PID结构拆开看其实很清晰:
- 内环(角度环):输入是摆杆角度,输出是作用在小车上的力。这一环直接决定系统的稳定性,响应必须快,通常以PD为主,积分项只加一点点用于消除静态偏差。
- 外环(位置环):输入是小车位移误差,输出是角度给定值。它不直接动手推车,而是告诉内环“往哪个方向斜一点才能把车拉回来”。这一环动作要慢,否则会和内环打架。
一句话总结:内环负责“站稳”,外环负责“归位”。仿真中先单独调内环,让摆杆能在任意初始角度下站起来;再接通外环,让小车从偏离位置自动回中。顺序反了,后面全是坑。
2. 数学建模是仿真的地基:从牛顿方程到状态空间的全推导
2.1 动力学方程与线性化假设
说句实在话,做仿真设计最怕的就是模型错了还调半天参数。倒立摆的建模套路很成熟,我用牛顿第二定律推一遍,关键步骤写清楚,大家可以直接抄去用。
假设小车质量M、摆杆质量m、摆杆质心到转轴距离l、重力加速度g,小车位移x,摆杆偏离竖直方向的角度θ,外力F。忽略摩擦和摆杆转动惯量误差,运动方程写出来是:
[ (M+m)\ddot{x} + ml\ddot{\theta}\cos\theta - ml\dot{\theta}^2\sin\theta = F ]
[ ml\ddot{x}\cos\theta + \frac{4}{3}ml^2\ddot{\theta} - mgl\sin\theta = 0 ]
这组方程是非线性的,直接拿去做控制器设计很麻烦。好在小角度条件下可以做线性化:(\cos\theta \approx 1),(\sin\theta \approx \theta),(\dot{\theta}^2 \approx 0)。代入化简后得到:
[ (M+m)\ddot{x} + ml\ddot{\theta} = F ]
[ ml\ddot{x} + \frac{4}{3}ml^2\ddot{\theta} = mgl\theta ]
注意,线性化的前提是θ足够小,一般控制在±0.2rad以内。真做实物时若摆杆倒到水平,这套模型基本失效,但做仿真对比实验是完全够用的。
2.2 状态空间表达式与可控性检查
从上面的线性方程可以解出(\ddot{x})和(\ddot{\theta})的显式表达式。我直接给结果:
[ \ddot{x} = -\frac{3mg}{4M+m}\theta + \frac{4}{4M+m}F ]
[ \ddot{\theta} = \frac{3(M+m)g}{l(4M+m)}\theta - \frac{3}{l(4M+m)}F ]
设状态向量(X = [x, \dot{x}, \theta, \dot{\theta}]^T),输入(u = F),状态空间就是:
[ \dot{X} = \begin{bmatrix} 0 & 1 & 0 & 0\ 0 & 0 & -\frac{3mg}{4M+m} & 0\ 0 & 0 & 0 & 1\ 0 & 0 & \frac{3(M+m)g}{l(4M+m)} & 0 \end{bmatrix} X + \begin{bmatrix} 0\ \frac{4}{4M+m}\ 0\ -\frac{3}{l(4M+m)} \end{bmatrix} u ]
我用一组常用参数做仿真:M=1.096kg,m=0.109kg,l=0.25m,g=9.8m/s²。算出来的系统矩阵中,与角度有关的特征值含有正实部,进一步验证了系统的开环不稳定性。建好模型后一定要先检查可控性矩阵的秩,满秩才能进行控制器设计,这一步很多教程会略过,但写进说明报告里很加分。
Matlab里检查可控性的代码很简单:
M = 1.096; m = 0.109; l = 0.25; g = 9.8; d = 4*M + m; A = [0 1 0 0; 0 0 -3*m*g/d 0; 0 0 0 1; 0 0 3*(M+m)*g/(l*d) 0]; B = [0; 4/d; 0; -3/(l*d)]; C = [1 0 0 0; 0 0 1 0]; D = [0; 0]; % 可控性矩阵 Co = ctrb(A,B); rank(Co) % 满秩4,说明系统可控2.3 Simulink模型搭建要点
模型搭建这块,很多人喜欢直接拖一堆增益模块,结果连线连成蜘蛛网,自己都看不清。我更推荐用“子系统封装”的思路:
- 把状态空间表达式封装成一个
State-Space模块,输入是力F,输出是([x, \dot{x}, \theta, \dot{\theta}])。 - 角度环PID输出限幅到[-30, 30]N,模拟电机的实际推力范围。
- 位移环PID输出作为角度给定,同样要限幅,防止内环给定角度过大。
一个容易忽略的细节是单位统一。角度一定要用弧度,而不是角度制。我见过有人把角度反馈直接接了deg,结果系统在仿真里疯狂震荡,根本稳不住。建议在模型里直接用“弧度/s”作为角速度单位,并且把外部给定、反馈、PID三者单位全部统一,能省一大半排查时间。
3. 传统PID参数整定:先让内环站起来,再让外环跑起来
3.1 内环角度控制:PD为主、积分缓加
传统PID整定这一步,我建议老老实实按“先内环、后外环”的次序来,不要一上来就两环同时调,否则出了问题根本分不清是哪一环在抖。
先断开外环,给内环角度PID一个固定的角度给定(比如0,即竖直方向)。内环我用的是“PD为主、Ki缓加”的策略:先把Ki设为0,调Kp和Kd让摆杆能稳定在0rad附近。
Kp太小,摆杆“没力气”回正,角度会有明显静差;Kp太大,系统开始高频抖动,甚至发散。我试出来的规律是:先给一个偏小的Kd,逐步加大Kp到系统开始出现等幅振荡,记录下临界增益,然后取临界增益的40%~60%作为实际Kp。接着调Kd,让角度曲线尽快回到零位且不振荡。
内环参数整定到这样一个效果就对了:给摆杆一个0.05rad的初始偏差,它能在0.6s左右回零,且超调不超过10%。我这组模型里内环最终取Kp=180、Kd=22、Ki=6。注意Ki这6不是一开始就加的,是在Kp和Kd已经让系统稳定后,再缓慢加积分,用于消除由于模型误差或摩擦造成的静态角度偏差。
3.2 外环位置控制:级联输出作为角度给定
内环稳定后,断开它的固定给定,把外环PID的输出接到内环的角度给定上,形成级联。外环的输出物理意义是“期望的摆杆角度”,所以也要限幅,我这里设在±0.2rad,防止外环一激动就丢出个大角度给定,内环根本追不上。
外环参数整定有一个习惯:外环比内环慢5~10倍。如果内环Kp用了180,外环Kp基本不会超过20。我这一组最终外环取Kp=6.5、Ki=0.8、Kd=3.2,整定目标是:小车从0.2m位置出发,能平稳回到0m,且不冲出轨道边界。
传统PID整定完成后,我记录了一组基准数据,用于后面和模糊PID做对比:角度阶跃响应上升时间约1.35s,超调量约19%,调节时间约3.7s,稳态误差基本为0。
3.3 参数整定顺序与仿真数据
把整定顺序整理成一个表格,写报告时可以直接用:
| 步骤 | 内容 | 目标 | 说明 |
|---|---|---|---|
| 1 | 内环PD整定 | 角度稳定回零 | Ki先置0,逐步加Kp,再加Kd |
| 2 | 内环KI缓加 | 消除角度静差 | Ki从小往大加,出现低频振荡就回退 |
| 3 | 外环PD整定 | 位置平稳回中 | 外环给定限幅±0.2rad |
| 4 | 外环KI微调 | 消除位置静差 | 实际模型有摩擦时才需要,仿真中Ki可很小 |
| 5 | 联合验证 | 抗扰动、鲁棒性 | 加脉冲扰动,观察恢复时间 |
这个顺序看着简单,但实际调参时非常考验耐心。我个人的经验是,每改一次增益就用阶跃响应看整体趋势,不要盯着曲线细节抠,否则很容易陷进“局部最优”里出不来。
4. 模糊PID设计:一条规则表搞定在线自整定
4.1 模糊PID整体结构:双输入三输出
模糊PID的思路,说白了就是让PID参数能跟着误差E和误差变化率EC实时变。误差大时,加大Kp追求快速响应;误差小时,减小Kp防止超调;误差变化率大时,加大Kd增强阻尼。
结构上,模糊控制器有2个输入(E和EC)、3个输出(ΔKp、ΔKi、ΔKd)。最终控制律写成:
[ K_p = K_{p0} + \Delta K_p ] [ K_i = K_{i0} + \Delta K_i ] [ K_d = K_{d0} + \Delta K_d ]
其中(K_{p0})、(K_{i0})、(K_{d0})是用传统PID整定出来的基准值。模糊控制器不重新发明PID,只是在基准值上做“微调”。这也是为什么我建议先做传统PID整定——因为模糊PID的基准参数几乎都来自传统PID的成熟整定结果。
4.2 隶属度函数与规则表怎么定
输入输出变量都定义成5个模糊子集:NB(负大)、NS(负小)、ZO(零)、PS(正小)、PB(正大)。论域范围我取E和EC都在[-1, 1],输入侧先用量化因子把实际误差和误差变化率归一到这个区间。隶属度函数用三角形,简单且运算量小,规则表可以根据经验直接写。
ΔKp的规则表是核心,我用的如下:
| E\EC | NB | NS | ZO | PS | PB |
|---|---|---|---|---|---|
| NB | PB | PB | PM | PM | PS |
| NS | PB | PM | PS | PS | ZO |
| ZO | PM | PS | ZO | NS | NS |
| PS | PS | ZO | NS | NM | NM |
| PB | ZO | NM | NM | NB | NB |
这个表的核心逻辑:误差大的时候给大Kp快速逼近期望值;误差小的时候减小Kp,避免来回震荡;误差趋向正方向时,控制力度也要随之变化,保持“纠偏不过头”。
ΔKi的规则表:
| E\EC | NB | NS | ZO | PS | PB |
|---|---|---|---|---|---|
| NB | NB | NB | NM | NS | ZO |
| NS | NB | NM | NS | ZO | PS |
| ZO | NM | NS | ZO | PS | PM |
| PS | NS | ZO | PS | PM | PB |
| PB | ZO | PS | PM | PB | PB |
ΔKd的规则表通常可以简化,只在系统响应进入稳态附近时起作用。我实际仿真中把ΔKd的权重设得很小,甚至在某些工况下直接置0也能用。这一点在写说明报告时特别值得写:模糊PID不是非要三输出全上,输出通道越多,仿真调试越麻烦。
模糊推理采用Mamdani型,解模糊用重心法,这些在Matlab的Fuzzy Logic Designer里都是下拉选项,不用自己写代码。
4.3 与Simulink的对接方法
Simulink里接模糊PID,最省事的方式是:
- 在Matlab命令行输入
fuzzyLogicDesigner,新建FIS文件,配置好输入输出变量和规则表。 - 导出为
.fis文件,用readfis('my_fis.fis')加载到工作空间。 - Simulink里拖一个
Fuzzy Logic Controller模块,填入FIS名称。 - 模块输出就是三个增量ΔKp、ΔKi、ΔKd,分别加上基准值后,接到PID模块的增益端口。
不过要注意:标准PID模块的增益端口不是直接输入数值就能在线修改的,需要勾选“P, I, D in external”选项,然后从外部引入三个变量。很多新手在这里找不到入口,卡住半天。我建议直接把模糊PID搭成增益调度形式,别用自带PID模块的内部参数修改,而是自己写一个“pu + i∫u + d*du”的公式,这样增益在线跳变时更直观,也方便后处理数据。
5. 同一模型下的对比:响应速度、超调量和抗扰动谁更强
5.1 阶跃响应的量化对比
搭建完两套系统后,我用完全相同的物理模型参数做对比仿真,保证唯一变量是控制器。给角度环一个0.1rad的阶跃给定,记录各项指标。
传统PID的结果是:上升时间1.35s,超调量18.7%,2%误差带调节时间3.6s,稳态误差0.001rad。模糊PID的结果是:上升时间0.78s,超调量6.4%,调节时间1.8s,稳态误差基本为0。
两组数据放一起,差距就很直观了。模糊PID的上升时间比传统PID快了大约42%,超调量从18.7%降到了6.4%,调节时间缩短了整整一半。原因也很好解释:传统PID的参数是固定死的,为了不让超调太大,Kp只能选得保守一点,响应自然偏慢。模糊PID则能在误差大的时候临时加大Kp,接近目标时自动减小Kp,相当于时刻在“换挡”,所以又快又稳。
5.2 抗扰动能力对比
阶跃响应只是基本功,倒立摆真正考验的是抗扰动。我在t=2s时给摆杆加了一个0.05rad的初始角度扰动,相当于手碰了一下摆杆,观察系统恢复情况。
传统PID大概用了2.4s才把角度拉回0.005rad以内,中间最大偏离达到了0.035rad,而且小车位移也被带出去0.08m左右。模糊PID用了1.1s恢复,最大偏离只有0.014rad,小车最大位移也小得多。
我还额外加了一组持续扰动测试:在t=3s到t=5s之间,给控制器输出叠加一个5N的常值偏置。传统PID出现了肉眼可见的静态角度偏差,模糊PID则很快把偏差吃掉。这个差异主要来自ΔKi规则表:传统PID的Ki一旦因为积分饱和被压住,就很难再出力;模糊PID的Ki在偏差出现时会自动增大,把积分项“顶”上去。
5.3 模糊PID的代价不能忽略
说完优点也得说代价。模糊PID不是白赚的,它的代价主要在三方面:
一是设计成本高。规则表怎么写、论域怎么选、量化因子怎么调,都需要经验。没有那组传统PID基准参数打底,模糊PID可能连稳定都做不到。
二是计算量变大。模糊推理在实时系统里会占用更多CPU,如果用到嵌入式板子上,采样频率可能上不去。仿真里无所谓,但工程落地必须考虑。
三是解释性变差。传统PID的每个参数都有明确的物理含义,出问题的时侯能凭直觉排查。模糊PID的规则表一多,有时候参数性能下降了,你都不知道该改哪条规则。
我把对比结果汇总成一张表,写报告可以直接引用:
| 指标 | 传统PID | 模糊PID | 改善幅度 |
|---|---|---|---|
| 上升时间 | 1.35s | 0.78s | 约42% |
| 超调量 | 18.7% | 6.4% | 约66% |
| 调节时间 | 3.6s | 1.8s | 50% |
| 扰动恢复时间 | 2.4s | 1.1s | 约54% |
| 扰动最大偏离 | 0.035rad | 0.014rad | 60% |
6. 仿真过程中容易踩的坑:积分饱和、采样时间和执行器限幅
6.1 积分饱和:启动瞬间“飞车”的元凶
这个坑我印象太深了。第一次做模糊PID和传统PID对比时,模糊PID在启动的瞬间竟然比传统PID还抖。查来查去,问题不在模糊规则,而是积分饱和。
系统刚开始运行时,角度误差非常大,PID的积分项会疯狂累加,很快冲到上限。等摆杆接近竖直位置时,这个“攒够了”的积分还在持续输出,直接把小车推过头,造成大幅超调甚至振荡。模糊PID虽然能在线调Ki,但Ki被放大时积分累加速度更快,反而更容易饱和。
解决办法有两个,我都试过,建议两个都做:一是对PID输出限幅,防止执行器饱和;二是给积分项单独加“抗积分饱和”逻辑——当输出达到上限时,停止积分累加。在Simulink里可以用Integrator模块的limit output选项配合外部重置信号实现,别图省事只用饱和模块。
6.2 采样时间:离散化和零阶保持器的影响
仿真阶段大家都喜欢用连续时间模型,但一旦换成离散仿真,采样时间选不好,模糊PID的优势会大幅缩水。我第一次把连续PID换成离散PID,采样时间定了0.01s,结果模糊PID的超调量从6.4%涨到了14%——一度以为规则表写错了。
原因在于,模糊控制器输出的ΔKp、ΔKi、ΔKd是离散更新的,更新频率受采样时间限制;而PID的积分项是连续累积的。两者步调不一致,等于模糊一直在“猜”当前状态,猜不准自然控制效果变差。
解决思路是:要么采用足够小的采样时间(比如0.002s),让离散化误差小到可以忽略;要么干脆把模糊PID的输出保持器改成零阶保持器、同步更新周期。仿真报告中建议把采样时间作为参数扫描一部分,展示不同采样率下的性能变化,这样报告的深度一下子就上去了。
6.3 执行器限幅与力约束
还有一个容易被忽略的点是执行器限幅。倒立摆仿真里如果不管力大小,传统PID和模糊PID都能调出“完美”曲线,但那些曲线没有任何工程意义。我建议在模型里给控制力加一个±30N的饱和模块,同时记录实际的控制力曲线。
加了限幅之后你会发现,传统PID为了追求速度,经常把控制力顶在饱和值上,结果就是系统持续震荡,响应反而变差;模糊PID由于在误差大时Kp增量不会给得过头,控制力很少顶到饱和,实际表现反而比“无限幅”时更加出色。这一点写进说明报告里很能体现工程思维:评价控制器好坏不能只看响应曲线,还要看执行器工作状态。
6.4 写说明报告时的数据呈现建议
既然项目标题里明确带了“仿真+说明报告”,最后这部分专门说说报告怎么写。
我的建议是:报告不是论文,重点突出“可复现性”。至少包含三部分内容:
- 模型与参数:列出小车质量、摆杆长度、重力加速度、PID基准参数、模糊规则表,所有参数都要给出具体数值,不要只写“经调试得到”。别人复现你的仿真时,最怕的就是参数缺失。
- 对比图表:至少放四张图——角度阶跃响应对比、位置响应对比、控制力曲线对比、扰动恢复曲线对比。不需要花哨的3D曲面图,清晰的黑白折线图就够。
- 结论分析:不要只写“模糊PID更好”,要写清楚好在哪些指标上、代价是什么、在什么条件下传统PID依然可用。比如离线整定好且工况变化小的场合,传统PID完全够用,还省去了模糊规则设计的调试成本。
报告最后可以加一段个人调试心得:整定过程中遇到过哪些预料之外的问题、怎么一步步解决的。这种东西技术文档里不会写,但对读者价值很高,也是让报告“活”起来的关键。
做完整套对比仿真后,我的体会是:模糊PID和传统PID不是谁取代谁的关系,而是前者在后者基础上多了一层“自整定”能力。传统PID的整定结果是模糊PID的起跑线,把这层关系理清楚,比单纯记住规则表重要得多。如果后续有时间,我打算在同样的模型上再对比一下LQR和滑模控制,看看在倒立摆这个平台上,现代控制方法和智能控制方法之间的差距到底有多大。大家如果也对这条路感兴趣,不妨从这份双PID对比仿真开始入手。