☰
倒立摆Simulink仿真:从非线性建模到PID/LQR控制实现
2026/10/16 14:59:51 网站建设 项目流程

简介:倒立摆是控制理论中经典的动力学系统,MATLAB Simulink环境下可对其建模、仿真与控制研究。压缩包面向自动化、控制工程方向的学习者,提供了完整的仿真实现方案。包内共9个文件,主要包含4个MATLAB脚本(.m)、Simulink模型(.slx、.mdl)以及配套的PPT讲解和DOC文档,整体大小372KB,轻量但覆盖从建模到控制的完整流程。目前已有2356人学习,适合课程设计或自学实践,也可作为控制类课程的辅助材料。内容从倒立摆角度与角速度的非线性状态方程入手,说明重力、摩擦力、驱动力影响下的模型搭建,随后对比PID、LQR等控制策略的参数整定与仿真效果;Simulink部分给出积分器、乘法器等模块构建子系统的思路,并介绍了时间步长、初始条件等仿真参数设置方法,便于直接运行、调整参数并观察系统响应,可有效加深对非线性系统建模、控制器设计以及MATLAB/Simulink工程应用的理解。

1. 倒立摆 Simulink 仿真:先让模型立起来,再谈控制

把一个小车加一根摆杆丢进 MATLAB 的 Simulink 库里,不加任何控制直接运行,默认参数下不到半秒就会躺平——这不是模型坏了,而是倒立摆本身就是开环不稳定的强非线性系统,角度稍有偏差就会指数级发散。这份资源要解决的事情很具体:把倒立摆从物理方程一路搭成可运行的 Simulink 模型,再把 PID 和 LQR 控制器接上去让它稳稳立住,最后讲清楚那些"看起来参数都对、一跑就翻车"的隐藏细节。适合两类人:控制方向的同学做课程验证,以及做机电一体化仿真、需要在 Simulink 下快速搭建控制原型的工程师。

2. 从运动方程到 Simulink 框图:倒立摆模型的落地过程

2.1 先确认模型假设和坐标约定

倒立摆通常指"小车-摆杆"系统:摆杆通过铰链安装在小车上,控制目标是让摆杆垂直向上立住。建模之前必须先固定坐标系和符号方向,否则后面控制器符号反了,整个闭环都会震荡。我采用的是最常见的约定:小车位移 x 向右为正,摆角 θ 从竖直向上位置顺时针为正,F 为施加在小车上的水平外力,向右为正。

单位这件事必须在第一步就锁死。θ 一律使用弧度,初始摆角设置为 0.1 rad 左右(约 5.7 度),这个角度既能让模型处在线性化近似有效范围内,又能让积分器在数值上有"看得见"的初始激励。杆长 l 这里取旋转中心到摆杆质心的距离,也就是半长,这一点会在第 2.4 节初始化脚本里体现。

系统的物理假设也要提前讲清楚:摆杆是刚性体,质量集中在质心;小车与导轨之间的摩擦忽略不计;铰链处无阻尼。这些假设让方程组保持简洁,也让后续控制器设计不用处理摩擦非线性。实际工程模型里摩擦不可忽略,但作为控制算法验证,这套简化已经够用。

2.2 运动方程的选择:非线性还是线性化

倒立摆的完整动力学方程可以用拉格朗日方法推出,我直接给出模型搭建时最常用的形式:

小车水平方向方程:

(M+m)x'' + mlθ''cosθ - ml(θ')²sinθ = F

摆杆转动方向方程:

mlx''cosθ + ml²θ'' - mglsinθ = 0

其中 M 是小车质量,m 是摆杆质量,l 是半长,g 是重力加速度。第一项是平动惯性,第二项是摆杆转动与小车平移之间的耦合,第三项是向心力项,右边是外力。第二个方程则是摆杆绕铰链转动的力矩平衡。

要在 Simulink 里直接搭这组方程,需要把它改写成显式解耦形式,把 x'' 和 θ'' 单独解出来。写成矩阵形式后,用行列式 D 去除:

D = (M+m)·ml² - (ml·cosθ)²

θ'' 的分子是摆杆自身的重力矩减去耦合项,x'' 的分子则包含外力、向心力以及耦合项。注意 D 在 θ 接近 ±90 度时趋近于零,模型会出现奇异,不过倒立摆正常工作范围远离这个区域,一般不会触发。

为什么不直接搭线性化模型?原因很简单:控制器设计时用线性化模型没问题,但仿真模型如果也是线性的,就永远发现不了控制器在大角度扰动下的真实表现。我习惯在 Simulink 里保留非线性项,控制器按线性模型去调,这样才能看到"调好的控制器到底能不能扛住非线性"。

2.3 在 Simulink 里搭模型的六个步骤

下面这套步骤只使用 Simulink 基础库模块,不依赖额外的物理建模工具箱,优点是每个增益、每个积分器都看得见摸得着。

第一步:新建 Simulink 模型,打开 Library Browser,拖入两个 Integrator 模块组成 θ'' → θ' → θ 的积分链,再拖入两个 Integrator 组成 x'' → x' → x 的积分链。

第二步:从 θ 引出信号线,分别接到 Math Function 模块的 sin 和 cos 输入端,得到 sinθ 和 cosθ。

第三步:用 Gain、Product、Add 模块搭建 θ'' 和 x'' 的表达式。这里要特别注意信号维度,Simulink 默认标量信号,如果用了向量化操作容易广播出错。把 θ' 信号做乘积得到 (θ')²,再乘 sinθ 得到向心力项。

第四步:用 Mux 模块把 x、x'、θ、θ' 四个状态合并成一路向量信号,方便后续控制器直接引用。Mux 的输入顺序必须固定,后续 LQR 增益向量按这个顺序排列。

第五步:将 θ'' 积分两次得到 θ,将 x'' 积分两次得到 x,反馈回表达式输入端。搭建完成的模型是一个带反馈的闭环结构。

第六步:在反馈回路里加一个 Memory 模块。这一步和第 4.2 节相关,Simulink 在检测到无延迟的代数环时可能报错,提前加 Memory 可以稳定结构。

还有一个更省事的替代方案是用 Simscape Multibody 直接拖刚体和关节。这个工具箱建模快,但参数封装在物理模块内部,调试时看不到中间变量,而且需要额外授权。表 2-1 给出两种方案的对比,我自己的经验是:如果重点是控制器算法验证,用基础模块搭方程;如果重点是机构本身,再考虑 Simscape。

表 2-1 Simulink 基础模块与 Simscape Multibody 对比

对比项基础模块搭方程Simscape Multibody
建模速度较慢,需要手写方程快,拖拽即可
可观测性每个中间信号可见需要额外传感器模块
依赖工具箱仅需要 Simulink需要 Simscape 全家桶
非线性保真度取决于你写的方程自带几何与接触模型
与控制器联调直接连信号线需要通过物理信号转换

2.4 初始化脚本与仿真参数

Simulink 模型里的参数不会凭空出现,我习惯用一个独立的 MATLAB 脚本统一初始化,这样改参数不用翻模型。下面是通用的初始化脚本:

% 倒立摆参数初始化 M = 0.5; % 小车质量 kg m = 0.2; % 摆杆质量 kg l = 0.3; % 摆杆半长 m(旋转中心到质心) g = 9.81; % 重力加速度 m/s^2 % 初始状态 theta0 = 0.1; % 初始摆角 rad,约 5.7 度 x0 = 0; % 初始小车位置 m xdot0 = 0; % 初始小车速度 m/s thetadot0 = 0; % 初始摆速 rad/s % 仿真配置 Tf = 10; % 仿真时长 s Ts = 1e-3; % 定步长采样时间 s

这段脚本的逻辑很直白:先定义物理参数,再定义初始状态,最后配置仿真步长。注意 l 是半长,如果换模型时改成了全长,θ'' 的数值计算结果会完全不同。一个快速自检方法是把参数代入线性化后的自然频率公式,大约 10 到 12 rad/s,对应的开环倒下时间在 0.5 秒左右,如果算出来差一个量级,说明参数或单位错了。

仿真步长配置这一步我在 Simulink 模型参数里单独设置,求解器选择定步长 ode4(四阶 Runge-Kutta),步长填 Ts。定步长比变步长更适合控制仿真,因为后续接入数字控制器时,仿真步长直接对应控制采样周期,变步长会导致离散系统模型不一致。

3. 控制器设计:PID 与 LQR 的整定路径

3.1 控制目标与线性化模型

倒立摆的控制目标拆开看有两条:一是让摆角 θ 稳定在 0 附近,二是让小车位移 x 不要跑飞。研究控制方案时,在线性化工作点附近把非线性方程展开,取 sinθ ≈ θ、cosθ ≈ 1、θ'² ≈ 0,可以得到四阶状态空间模型。状态向量取 [x, x', θ, θ'],控制量为外力 F。

从 F 到 θ 的开环传递函数含有一个右半平面极点,这正是倒立摆开环不稳定的数学本质。任何控制器要能立住摆,本质上是把右半平面极点拉回左半平面,这个任务 PID 和 LQR 都能完成,但路径不同。

3.2 PID 双环结构:先角度后位置

只反馈摆角是不够的。假设控制器只让 θ 归零,小车会为了维持摆角平衡而持续朝一个方向加速,直到撞到导轨边界。所以标准的 PID 方案采用双环嵌套:内环是角度环,输出直接控制力 F;外环是位置环,修正小车的漂移,输出叠加到角度环的设定值上。

整定顺序有讲究,我一般按"先内环后外环"走。第一步把位置环增益设为 0,只留角度环,从小到大调 Kp。观察摆角响应,Kp 太小摆会缓慢倒下,Kp 足够大时摆能立住但可能持续振荡。第二步加入微分项 Kd,抑制振荡。第三步放开位置环,用小增益把小车缓慢拉回零点。

表 3-1 给出一组可供起始调参的参考区间,注意这组数值对应 2.4 节的物理参数,换了模型参数需要重新扫描。

表 3-1 PID 双环参考增益区间

环路参数参考区间调参效果
内环角度Kp_theta50 ~ 150越大响应越快,过大会放大噪声并引发振荡
内环角度Kd_theta10 ~ 30增加阻尼,抑制来回摆动
外环位置Kp_x0.5 ~ 2让小车回零,过大会与角度环形成联动震荡

仿真环境里没有传感器噪声,所以 Kd 往往可以给得比较激进。但要注意:Kd 过大时控制器输出变化率会非常大,功耗和机械冲击在实物里完全不可接受,这是仿真与实物的一个重要差异,所以调参阶段就应当给控制器输出加 Saturation 限幅。在 PID Controller 模块内把输出上下限设为 [-20, 20],我在第 2.3 节说的物理力 F 在这个量级内可以保证模型稳定。

3.3 LQR 状态反馈:权重矩阵怎么设

LQR 的思路和 PID 完全不同:它要求全部四个状态都可测(仿真里这一点天然满足),通过最小化积分二次代价函数来求解一个最优状态反馈增益向量 K。代价函数里 Q 矩阵惩罚状态偏差,R 惩罚控制量,Q 和 R 的比值体现"摆得直"与"力气小"之间的权衡。

在 MATLAB 中用 lqr 函数求解很方便,关键是 A、B 矩阵必须和模型里的状态顺序一致。下面的代码先按第 2 章的物理参数构造线性化模型,再调用 lqr:

% 构造线性化状态空间模型 % 状态顺序:x, x', theta, theta' A = [0 1 0 0; 0 0 -m*g/M 0; 0 0 0 1; 0 0 (M+m)*g/(M*l) 0]; B = [0; 1/M; 0; -1/(M*l)]; % 权重矩阵 Q = diag([1, 1, 100, 1]); % 对角度偏差惩罚最重 R = 0.01; % 控制力惩罚较小 % 求解状态反馈增益 K = lqr(A, B, Q, R); % 查看增益向量 disp(K);

这段代码里 A 矩阵非零元素的位置很重要:A(2,3) 对应 x'' 中 θ 的贡献,A(4,3) 对应 θ'' 中 θ 的贡献,它们的符号由坐标约定决定。如果 θ 的方向定义改成了逆时针为正,这两个元素的符号都要变负,否则增益算出来是反的。

Q 矩阵四个对角元素分别对应 x、x'、θ、θ' 的权重。表 3-2 给出调整方向,便于快速理解每个权重对响应的影响。

表 3-2 Q/R 权重调整效果

调整项调整方向预期效果
Q(3,3) 增大100 → 500摆角偏差更小,但小车来回幅度变大
R 增大0.01 → 0.1控制力变小,响应变慢,抗扰变差
Q(1,1) 增大1 → 10小车位置更贴近原点,需警惕联动震荡

3.4 在 Simulink 里把状态反馈接上

LQR 控制器在 Simulink 里的实现比 PID 更直接:状态反馈不需要误差积分,直接把四路状态信号乘 K 得到控制力 F。接线方式是:从 2.3 节搭建的 Mux 输出引出状态向量,接入一个 Gain 模块,Gain 的增益值填 K 向量(注意是行向量),输出就是要施加的力 F,再接回模型的外力输入端。

这里有一个我踩过不止一次的关键点:如果是手动拆分 K 的四个分量,一个一个用 Gain 模块乘,必须严格对照 Mux 输入顺序。假设 Mux 顺序是 [x, x', θ, θ'],那 K 的第一个分量乘 x,以此类推,顺序错了模型立马发散。

PID 接入方式略有不同,用 PID Controller 模块时,输入偏差是 θ_setpoint - θ。位置环输出要接到角度环的给定端而不是直接相加,否则两环作用方向会打架。这一点在 3.2 节的接线里要特别注意。

控制器输出加 Saturation 限幅这一步不能省略。仿真模型不加限幅,LQR 算出多大的力就施加多大的力,看起来一切正常;一旦实物执行器有饱和,性能就会急剧下降。在仿真阶段提前加入限幅,才能看到控制器在真实约束下的表现。

4. 避坑指南:倒立摆仿真里最容易翻车的五个问题

4.1 模型刚启动积分器就爆掉

现象:仿真开始的一瞬间,Scope 里显示角度信号达到 10 的几十次方量级,模型直接变成一条竖线。

原因:积分器默认初值为 0,但 θ = 0 是倒立摆的不稳定平衡点。数值仿真中哪怕一个微小的舍入误差,都会被右半平面极点指数放大,很快就超过数值范围。这是开环不稳定的数学特性,不是模型搭建错误。

解决:在 Simulink 模型的两个 Integrator(对应 θ)里手动设置初始值,θ 的初始值设为 theta0 = 0.1 rad,θ' 的初始值设为 0。这样系统一开始就处在偏离平衡点但可控的区域,控制器才能发挥纠正作用。从那以后我每次搭建倒立摆模型,第一步永远是检查积分器初值,而不是检查控制器参数。

4.2 Simulink 报"Algebraic loop"错误

现象:点击 Run 之后,Simulink 弹出提示检测到代数环,仿真无法启动或异常缓慢。

原因:状态反馈信号的通道没有经过任何延迟模块,θ'' 的表达式直接依赖 θ,而 θ 又由 θ'' 积分得到,在数值求解的同一时刻形成了无延迟循环。Simulink 需要迭代求解这个循环,轻则变慢,重则直接报错。

解决:在反馈回路中加一个 Memory 模块,人为引入一拍延迟,打破代数环。代价是控制信号晚一个步长到达,相当于在控制回路中串联了一个零阶保持器。如果步长 Ts 很小、增益很大,这一拍延迟会带来数字振荡,需要适当降低 LQR 增益或 PID 增益来换回稳定。记住一个经验:能不加 Delay 就不加,加了之后必须重新检查稳定裕度,这是很多人忽略的隐藏坑。

4.3 角度单位混用弧度与度

现象:控制器看起来方向是对的,摆杆却一直小幅度振荡,怎么调增益都消不掉。把曲线放大看,振荡频率非常缓慢,和模型参数完全对不上。

原因:有人在模型里把 θ 的单位当成度,直接把 5.7 作为数值传入 sin 模块。sin(5.7) 约等于 -0.55,而真实角度 0.1 rad 的 sin 值约等于 0.1,符号和幅值全都错了,整个模型等价于在一堆错误系数下运行。

解决:全链路统一用弧度,没有例外。在初始化脚本的注释里明确标注 theta0 的单位是 rad,同时在 Math Function 模块前加一个 Unit Conversion 模块(如果用的是 Simscape)做强制转换。这个坑最隐蔽的地方在于:模型不会崩,控制器也有响应,只是性能始终不对劲,很多人会误以为是调参问题,浪费大量时间。

4.4 LQR 算完增益接进模型却站不稳

现象:按 3.3 节算出 K 后接入模型,初始 1 到 2 秒内摆杆确实立住了,随后开始缓慢漂移,最终大幅震荡发散。

原因:状态顺序不匹配。我遇到的情况是,LQR 脚本里按 [θ, θ', x, x'] 的顺序构造了 A、B 矩阵,算出的 K 向量的分量顺序与 Simulink 模型中的 Mux 通道顺序 [x, x', θ, θ'] 不一致。K 的四个数值被错误地施加到了不同物理量上,短时间内小角度下还能维持,随着状态偏差积累,问题被放大。

解决:接线前先把 K 打印出来,对照 Mux 的输入顺序逐一确认。更稳妥的做法是不拆开 K,直接把 Gain 模块的增益填为 K 行向量,让 Simulink 的向量乘法自动按顺序处理。如果模型中状态顺序变了,只需要调整 Mux 的输入顺序,不要手动改 K 的每一个分量。

4.5 曲线锯齿状,看起来"数字化"

现象:Scope 里角度曲线不是平滑弧线,而是带明显台阶的锯齿,缩小步长有改善但仿真变得非常慢。

原因:模型使用的是变步长求解器,默认 ode45 在控制器切换和饱和限幅触发的瞬间会自动缩小步长以保证精度,Scope 显示的是非均匀采样点,看起来就是锯齿状。这不是模型错误,但会让后续分析响应和相位裕度变得困难。

解决:把求解器改成定步长 ode4,步长设为 1ms。如果控制器是数字 PID,还要注意把控制周期与仿真步长区分开:仿真步长是物理模型积分步长,控制周期是控制器执行间隔,两者不要混为一谈。定步长仿真跑完后,可以再用变步长复核一遍关键指标,如果差别过大说明积分步长不够小。

5. 进阶验证:加扰动后看控制器还撑不撑得住

仿真模型立住只是一个开始,工程上更关心的是"撑不撑得住"。我常用的验证手段有三种,每种都能迅速暴露控制器的边界。

第一种是加脉冲扰动。在控制力信号上并联一个 Pulse Generator,设置幅值 5、周期 3 秒、脉冲宽度 1%,在模型运行 2 秒后踢一脚。看摆角曲线的回落时间:LQR 通常能在一秒内恢复,PID 双环则要看内环阻尼调得够不够。如果脉冲过后摆杆持续振荡超过两个周期,说明阻尼不足,需要回第 3 章调大 Kd 或加大 Q(4,4)。

第二种是扫 Q 矩阵的权重。把 Q(3,3) 从 50 一路加到 1000,分别仿真 10 秒,记录摆角最大偏差和控制力峰值。权重加大会发现摆角越来越硬朗,但控制力峰值也在涨,小车位移幅度也在变大。这个过程中你能直观看到"性能是用控制能量换来的"这层物理含义。注意观察是否存在某个临界增益之后系统突然失稳,如果出现,多半是第 4.2 节的延迟效应开始主导。

第三种是刻意减配。把控制输出 Saturation 从 ±20 收紧到 ±5,看控制器是否还能维持稳定。LQR 在面对饱和时会出现明显的"先冲过头再拉回来"行为,PID 则更容易进入积分饱和。这时候能真正理解为什么我一直强调仿真阶段就要加限幅——不加限幅,你看到的是理想控制器的性能,加了限幅,你看到的是真实执行器下的性能。这两者的差距,就是设计与实际的差距。

做这些验证时有个小技巧:在模型里加一个 To Workspace 模块,把状态和输出记录到 MATLAB 工作区,然后写一段循环脚本自动修改参数并批量仿真。这样一次能跑完十组参数,把摆角峰峰值和控制力均方根整理成表格,一目了然。我现在做控制器参数选型,都会先跑这样一轮批量扫描,而不是手工一次一次点运行。

从那以后,我每次做完倒立摆仿真都会强制走一遍这个流程:检查单位,检查状态顺序,加好限幅,再加三类扰动各跑一轮。这个习惯救过我很多次,也让"看起来能立住"变成"怎么折腾都能立住"。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询