资讯动态

二级倒立摆仿真对比:PID与LQR控制器的设计与调参

发布时间:2026/10/21 21:54:59 来源:尧图企业网站定制
二级倒立摆最近又被不少朋友问到原因是课程设计、毕业设计和入门级科研项目里它永远不缺戏份。去年答辩季A同学抱着调了一周的“PID参数”来问我说小车要么发疯一样冲出去要么原地高频抖动摆杆怎么都立不住。我看了一下他Simulink模型问题不在参数在于他压根没搞清楚二级倒立摆这种系统的控制难点在哪。这篇文章我想把从建模、仿真到PID与LQR控制器设计对比的全过程拆开讲清楚附带一套可以直接照着复现的仿真方案和说明资料整理思路。内容覆盖状态空间方程的推导、Simulink环境搭建、两种控制器的设计逻辑、以及同一平台下的对比测试结果。适合正在做倒立摆课程设计的学生、刚接触现代控制理论的研究生还有那些想从经典控制过渡到状态空间设计、但一直没找到落地案例的工程师。1. 二级倒立摆为什么值得做一个控制“不稳定平衡”的经典试验场1.1 一个输入管住六个状态二级倒立摆的难点本质先看系统本身。二级倒立摆由一辆小车和两根串联的摆杆组成下摆铰接在小车上上摆铰接在下摆顶端。控制目标是通过移动小车让两根摆杆同时维持竖直向上。听起来简单实际难到不行。难在哪第一系统开环不稳定。手扶着两根摆杆稍微松手几秒内就倒了。第二强耦合。两根摆的状态互相影响下摆动一下、上摆跟着甩小车位置变化又会反过来改变两根摆的受力。第三欠驱动。我们只有一个控制输入也就是小车的水平驱动力却要同时稳住小车位置、下摆角度、上摆角度一共六个状态量。这类系统的典型特征是输入少、状态多、平衡点不稳定、非线性明显。这也是为什么它常被拿来检验控制算法的能力。一个控制器能不能在这种多变量强耦合系统上站稳基本能反映出它的设计水平和工程适应性。1.2 为什么非要拿PID和LQR放一起对比市面上很多教程只演示其中一种控制器要么就贴一段LQR代码然后说“设置Q和R就能稳定”要么就甩一堆PID参数让人自己试。这两种做法都让学习者很痛苦。真正的价值在于对比。PID和LQR代表了控制理论的两条路线。PID走的是“误差驱动”路线——不管系统内部长什么样看到了偏差就反馈调整LQR走的是“模型驱动”路线——先建立系统的数学模型在模型基础上优化控制输入的能量和状态偏差。同一个二级倒立摆这两套思路设计的控制器性能差异、调试难度、对模型的依赖程度都很不一样。这篇内容的价值正是把两条路线放在完全相同的仿真条件下用数据呈现它们的差别。有对比才有参照才知道什么场合该用哪种方案。2. 仿真前必须搞懂的建模环节起跑线决定了后面谁跑得快2.1 物理假设与状态量定义二级倒立摆的完整数学模型可以用拉格朗日方程推导出来推导过程大量教科书都有这里我只把关键假设和最终使用的状态空间形式讲清楚。仿真建模前必须先约定物理假设。我用的假设是摆杆视为均质细杆摆杆与摆杆之间、摆杆与小车间为刚性连接忽略铰链处的摩擦和阻尼电机驱动力作为理想力源直接作用于小车工作点附近摆角较小满足线性化条件。状态变量定义如下表所示这组定义会贯穿整个后续的设计和对比。状态符号含义单位x小车位移mdx/dt小车速度m/sθ1下摆相对竖直方向的角度raddθ1/dt下摆角速度rad/sθ2上摆相对竖直方向的角度raddθ2/dt上摆角速度rad/s控制输入 u 是小车驱动力单位为N。系统参数我取了一组常见值小车质量 M0.5 kg下摆质量 m10.2 kg上摆质量 m20.2 kg两根摆杆长度均为0.2 m质心在杆长一半处重力加速度取9.8 m/s²。2.2 从拉格朗日方程到状态空间表达式建模的核心流程是写出小车和两摆的动能和势能构造拉格朗日函数代入欧拉-拉格朗日方程得到非线性运动方程最后在竖直平衡点附近做线性化。线性化处理后的状态空间方程形式为dx/dt A·x B·u这里我把线性化工作交给MATLAB符号工具箱自动完成。强烈建议你不要手推A矩阵尤其做课程设计时间紧张的时候。符号推导的工具链如下完整版就在资料包的src/calc_model.m里。syms x dx th1 dth1 th2 dth2 u real syms M m1 m2 L1 L2 l1 l2 g J1 J2 real % 小车动能、摆杆动能和势能 % 由拉格朗日方程得到非线性微分方程组 % 在 [x; th1; th2] [0; 0; 0] 处线性化 % 关键一步求取线性化状态矩阵 A double(jacobian(f_linear, [x dx th1 dth1 th2 dth2])); B double(jacobian(f_linear, u));在我上面的参数取值下A矩阵和B矩阵的大致量级为A [0 1 0 0 0 0; 0 0 -4.43 0 -1.58 0; 0 0 0 1 0 0; 0 0 84.21 0 10.34 0; 0 0 0 0 0 1; 0 0 -53.18 0 39.89 0]; B [0; 1.62; 0; -7.54; 0; -0.50];注意坐标方向的定义不同会导致A矩阵中某些元素符号变化这是正常的。我见过不少人在这一步卡死因为仿真出来的角度一直向一个方向飞其实就是符号约定不一致。判断模型对不对核心看两条系统的开环响应是否发散、各状态之间的耦合符号是否符合物理直觉。只要LQR能镇定说明模型方向基本正确。2.3 建模简化的代价为什么仿真稳了实物不一定稳这里必须泼一盆冷水仿真模型稳定不代表实物也能站住。我假设了理想铰链、忽略摩擦死区、认为驱动力无延迟无饱和但实际伺服电机有响应延时齿轮箱有齿隙摆杆有弯曲变形。这些因素全部被线性化“抹掉”了。所以在设计控制器时我会特意留出控制量的余量。例如仿真中控制力限幅设为±20N而非允许无限大控制力。这样即使模型有点偏差设计出来的控制器在实物上也有一定冗余。如果你只追求仿真曲线漂亮而把控制量放到几百牛那大概率会在实物阶段翻车。3. Simulink环境搭建从积分器搭微分方程到S函数封装的两种路线3.1 方案一用积分器模块组装的“透明模型”如果你靠Simulink基础课的知识入坑最容易想到的方案是把非线性微分方程组用积分器模块一个一个搭出来。例如x的二阶导过两次积分变成xθ1的二阶导过两次积分变成θ1然后通过代数运算把三个二阶方程联立解出各加速度。这套方案的优点是每个积分器对应一个物理量信号走向直观非常适合上课演示。缺点也很明显模型一大连线乱成一团每次改参数要进模型内部改常量模块不好批量跑对比实验。如果走这条路线建议养成一个习惯把所有参数集中放到MATLAB脚本里定义为变量然后Simulink模块的数值直接填变量名这样改参数只在脚本里改一处模型可以保持整洁。3.2 方案二用S-function封装状态方程的高速方案我更推荐第二个方案把线性状态方程封装成S-functionSimulink只需要一个S-Function模块输入输出极其清爽。S-function函数写法很简单function [sys, x0] pend_linear_sfun(t, x, u, flag, A, B) switch flag case 0 sys [6 0 1 0 0 1]; % 6个连续状态, 1个输入, 6个输出 x0 [0; 0.1; 0; 0.08; 0; 0]; % 初始角度扰动 case 1 sys A * x B * u; case 3 sys x; otherwise sys []; end end在Simulink里放一个S-Function模块指定函数名把A和B做成工作区变量传进去模型就搭完了。受力反馈从外面的控制器模块给进来状态输出直接接示波器。这套方案的优点是模型结构极简控制器更换只需要改反馈回路的增益部分跑批量参数扫描时只需循环调用sim函数不需要动模型LQR和PID两种控制器的切换本质上只是改变控制量计算模块其他环节保持一致。3.3 仿真配置里最容易出错的三个选项第一求解器设置。建议用定步长ode4步长1e-3。变步长求解在强耦合系统上可能会自适应缩到极小步长仿真速度拖慢而且步长切换本身可能引入额外误差。第二初始扰动。对比实验一定要让控制器在完全相同的初始角度下启动。我习惯把初始状态设为θ10.1 rad、θ20.08 rad其他状态为0。这样两条摆杆都偏离了竖直方向控制器必须在一个“失衡”的起点上把它拉回来。第三控制量限幅。在系统模型里直接加Saturation模块限制在±20N。很多对比结果失真就是因为某个控制器短时间内输出了巨大控制力把一个扰动瞬间“压”下去换到实物上根本不可行。4. PID控制器设计看似“无脑”实际要在耦合中找平衡4.1 为什么单回路PID镇不住二级摆很多教材用一阶或二阶系统讲PID给三个参数就能稳。但二级倒立摆在竖直位置附近线性化后有4个开环极点分布在复平面两侧其中至少有两个在右半平面开环就不稳定一个单回路PID只有一组Kp、Ki、Kd相当于用三个调节旋钮去让四个失稳极点全部回到左半平面——几乎没有操作空间。这也是为什么网上能搜到的“二级倒立摆PID参数”大多是废的。不是参数没调好而是结构上就不够用。要让PID思路在二级倒立摆上成立必须把参数数量补上去。4.2 二级倒立摆PID的实用拓扑多路误差加权实际工程里我见到的“PID控制二级倒立摆”绝大多数是多路PD加权的结构即把多个状态偏差按比例加权求和作为控制量u Kp1·θ1 Kd1·dθ1 Kp2·θ2 Kd2·dθ2 Kp3·x Kd3·dx本质上每一项都是一个P或者D环节只是误差信号来自不同状态。这种结构已经非常接近状态反馈但没有积分项也没有用最优化的方式去计算增益。它的好处是每个增益有直观的物理意义放大哪个状态的权重那个状态就被更用力地拉向零点。我会在Simulink里搭一个Subsystem作为PID控制器模块输入六路状态信号用Gain模块分别乘上六个系数再求和输出控制量。4.3 调参顺序和一组能跑的初始参数调参与其说是“调”不如说是“分层解锁”。我的调法是三个步骤先忽略上摆反馈和位置反馈只让Kp1和Kd1工作看下摆能不能在小范围内震荡但不上天逐步加大Kp2、Kd2让上摆也参与镇定此时两条摆会一起抖起来说明耦合回路开始生效最后加入位置回路Kp3和Kd3把小车控制在合理行程内。下表是经过初始仿真验证、可以作为出发点的参数范围增益建议初始值调整经验Kp180~120太小下摆立不住太大会高频抖动Kd115~30增加系统阻尼抑制下摆振荡Kp2-20~-60符号看坐标定义作用是“拽住”上摆Kd25~15抑制上摆的快速甩动Kp32~8位置回路不能太强否则小车乱跑Kd32~6抑制小车速度冲击一个重要心得积分项能不加就不加。倒立摆的平衡点就在零位附近不存在需要积分项消除的稳态误差积分项只会带来相位滞后和积分饱和让摆杆在零点附近来回漂。很多同学死守“PID必须有I”的思路加了Ki以后发现系统反而更难稳就是这个原因。4.4 一个帮助理解PID调参的类比想象你手指上竖了一根长杆你要通过移动手来维持它不倒。你天然在做的事情就是看杆往哪边倒手就往哪边跟——这是P判断杆倒的速度快慢提前加速手去接——这是D你并不会去累积过去几秒的偏差然后给个额外补偿——这是I。二级倒立摆相当于手指上叠了两根杆P和D都得加倍I基本帮不上忙。5. LQR控制器设计状态反馈的“最优解”与加权矩阵的工程调试5.1 LQR在做什么把状态和能量同时放进目标函数LQR的全称是Linear Quadratic Regulator线性二次型调节器。它的思想很直接假设系统模型完全已知设计一个状态反馈控制律 u -K·x使得如下性能指标最小J ∫ (xᵀQx uᵀRu) dtQ 矩阵是对状态偏差的惩罚权重R 是对控制输入能量的惩罚权重。通过求解Riccati方程可以得到最优反馈增益K。整个设计过程没有“试参数”的环节模型给定、Q和R给定K就唯一确定了。用个类比PID像一位靠手感调节的老司机LQR像一位拿着地图和方向盘最优路线的导航员。LQR要求对“路况”模型了如指掌但一旦路线算好效率确实高。5.2 Q和R的工程配置权重比数字本身更重要Q和R的配置没有标准答案但有经验规律。我的习惯是把6个状态按“谁重要就惩罚谁”的原则赋权。对于倒立摆的稳定任务最重要的是两个摆杆角度其次是摆杆角速度再其次是小车位置和速度。在实际调试中权重之间的相对比例远比绝对数值重要。比如位置权重从1改成100等价于把角度权重从100改成1控制行为会完全不同。我给的初始矩阵如下Q diag([50, 5, 150, 15, 300, 30]); R 1; K lqr(A, B, Q, R);在这个配置下角度权重远大于位置权重上摆权重又大于下摆权重因为上摆受到的扰动传导更慢、更难直接控制需要更大的反馈力度。5.3 能控性检查别在不可控模型上浪费时间任何LQR设计的第一步都应该是检查系统是否能控。如果系统不可控那根本不存在反馈增益能让它稳定LQR算出来的K也没有意义。MATLAB一行代码搞定if rank(ctrb(A, B)) 6 error(系统不可控请检查建模参数或状态方程); end这一步看起来基础但不少人在建模错误的情况下直接跑lqr函数得到一组看起来“合理”的增益仿真却怎么都不稳定回头排查才发现是状态方程写错了。先验证能控性等于给整个设计加了一把保险锁。5.4 LQR的高性能有代价模型依赖性强LQR把一切都建立在模型矩阵A和B之上。模型没误差时它能打出非常漂亮的响应模型一偏它的最优性立刻消失。这个特点在仿真阶段还不明显但做一个参数摄动测试就暴露出来了。由于LQR输出的是一个由K矩阵构成的线性反馈在Simulink中实现非常方便把六个状态接入Gain矩阵模块增益设为K符号取反后输出就是控制量。相比PID那组手动试出来的增益LQR的设计过程几乎不需要试探这也是它“现代控制”气质的来源。6. 仿真结果直观对比谁收敛更快、谁抗扰更强、谁调起来更快6.1 公平对比的前提条件做对比实验的时候最怕的就是两个控制器在不同条件下跑得出的结论毫无意义。我这次对比统一了所有前提同一个线性化模型文件同一组初始状态θ10.1 rad、θ20.08 rad同一仿真时长20秒同样的±20N控制量限幅同样的定步长求解器。唯一不同的是控制模块内部逻辑。6.2 实测指标对比速度、控制量、稳态表现在我这组参数下的仿真结果对比如下对比指标多路PIDPD加权LQR摆角进入±0.01 rad的时间约2.8 s约1.5 s小车最大位移0.35 m0.22 m峰值控制力12 N7 N稳态摆角误差范围±0.02 rad±0.005 rad5 s处加脉冲扰动后恢复时间约2 s且伴随残余振荡约0.8 s平稳回归这个结果并不是说PID“不行”而是它在处理多变量耦合时只能依靠有限几个反馈回路的折中天然做不到精确解耦。LQR由于所有状态都进入了反馈控制动作更早到位峰控力反而更小。6.3 曲线形态的典型差异看角度响应曲线区别非常明显。LQR的摆角收敛路径比较“干脆”两条摆几乎同步回摆一次到达平衡点附近不再反复穿越。PID控制的曲线则往往先出现一个较大的反向超调然后像荡秋千一样来回衰减最终缓慢落在平衡点附近。控制力曲线也有差别。PID在启动初期容易出现比例项驱动的尖峰甚至会顶到限幅LQR的控制力曲线相对平滑因为它会对角速度等“未来趋势”提前做出补偿不需要等到偏差大了才猛拉一把。这些现象背后的本质原因是PID的反应基于“已经发生的误差”LQR的反应基于“全部状态的现时值”对系统内部趋势的把握更全面。6.4 参数摄动压力测试把模型“搞坏”再看谁先崩我额外做了一个参数摄动测试把两根摆杆的质量各增大20%控制器参数不变重新跑仿真。这个测试模拟的是建模误差比任何指标都更能暴露控制器的鲁棒性。结果是LQR在质量摄动20%以内时仍然能够镇定但调节时间明显变长出现了约为原响应两倍的小幅振荡PID在原始参数边缘调出来的情况下面对同样的质量摄动直接发散只有把PID增益调得更保守一些才能勉强维持稳定。反过来如果把摆杆长度也改了LQR反而因为模型失配得厉害而性能下降更显著。这说明了一个辩证结论LQR的鲁棒性来自全状态反馈的结构优势但也受限于模型的准确度PID虽然对模型依赖小但对多变量耦合系统的适应能力天生有限。用在实物上时这两者都建议配合在线参数调整或自适应策略使用。6.5 到底怎么选看你的约束条件做完一组对比之后我的感受是不要纠结“谁更先进”而要问自己手里的牌是什么。如果你面对的是一套可以精确建模、状态量都可测或可通过观测器估计的系统并且追求更好的稳态精度和更小的控制能量选LQR它值得你花时间去维护模型。如果你只是想在短时间内快速验证一个控制想法或者系统模型不确定性太强那多路PIDPD加权反而是更快上手的方案。课程设计最实用的路线是先用PID跑通整套仿真链路再用LQR在同一模型上做性能提升二者互相印证。7. 资料包里的“内容清单”与复现注意事项7.1 一份合格的倒立摆资料应该包含哪些文件既然标题里明确写了“仿真说明资料”我就多说一下资料整理这件事。很多同学做完项目之后把Simulink模型、脚本、论文初稿乱七八糟堆在一个文件夹里答辩或交接时根本找不到文件。我整理这类项目资料的习惯是严格按模块划分二级倒立摆对比仿真/ ├── README.md ├── src/ │ ├── init_params.m # 所有物理参数和初始扰动配置 │ ├── calc_model.m # 符号推导线性状态方程 │ ├── calc_lqr.m # 能控性检查 LQR解算 │ └── run_compare.m # 批量对比仿真脚本 ├── sim/ │ ├── pend_pid.slx # 多路PID控制模型 │ └── pend_lqr.slx # LQR控制模型 ├── docs/ │ ├── 建模说明.pdf │ ├── 控制器设计说明.pdf │ └── 对比分析报告.pdf └── results/ ├── fig_angles_compare.png ├── fig_force_compare.png └── data_compare.matREADME里要写清楚三件事运行环境是哪个MATLAB版本、先运行哪个脚本初始化参数、仿真结果如何复现。不要低估README的价值一个月后你自己再看这个项目80%的回忆要靠README恢复。7.2 复现时最容易卡住的三个地方第一个坑是lqr函数报错。常见原因是符号推导得到的模型还没有用double()转成数值矩阵。A或B是符号对象时lqr无法处理必须先转double。第二个坑是Simulink中Gain矩阵的维度搞错。LQR反馈增益K是1×6的矩阵输入必须是一个6×1的列向量如果状态信号在模型中组成了行向量矩阵乘出来维度就会报错或控制量全错。第三个坑是S-function的初始状态维度声明不对。如果在flag0的返回向量里把连续状态数量写错Simulink会忽略你设置的初始角度扰动导致仿真从一个全零状态开始看起来“不劳而获”地稳定。7.3 整理说明文档时我的三个习惯第一把“为什么这样选Q”写进文档而不是只贴出最终的K值。K是一组数字看的人只能照着抄Q的设计思路才是可以迁移的知识。第二每张仿真截图要在图下方标注对应的参数配置和初始扰动。我见过太多对比报告里两张图各跑各的条件结论毫无说服力。第三把初始扰动配置统一放一个脚本对比时只改这个文件。这样从流程上就堵住了“无意间改了对比条件”的可能性。回头再看A同学的问题本质是对系统的理解不够他不知道二级倒立摆单回路PID结构上就锁不住也不知道LQR的Q矩阵才是设计的灵魂。做完这一轮仿真之后他自己都能看出来控制器的差异不是“谁能稳、谁不能稳”的黑白之分而是在不同前提下的取舍。如果你也要做这个题目我建议你先花半天把线性化模型吃透再动手调控制器——建模这一步理清楚了后面PID和LQR的速度差距会非常明显节省的时间远超你的预期。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑