简介:本资源是一套面向自动化、控制工程专业本科生及初学者的二阶倒立摆控制系统MATLAB/Simulink实践教学包,聚焦经典非线性系统建模、稳定性分析与多种控制策略对比验证。压缩包共6个文件(3个Simulink模型.mdl、2个MATLAB脚本.m、1个模糊推理系统.fis),总大小仅19KB,轻量易用;其中.mdl文件实现PID、滑模等不同结构的闭环仿真,.m文件封装系统动力学模型与核心算法,.fis文件提供可调参的模糊控制器,便于理解规则设计与实时响应特性。已有1176人学习下载,适用于课程设计、控制原理实验及毕业设计前期验证。读者可直接运行仿真观察角位移/小车位置响应曲线,对比不同控制器在抗扰性、超调与稳态精度上的差异,并基于源码快速修改参数、替换控制律或拓展为状态反馈设计,是贯通理论推导—编程实现—仿真分析全流程的典型入门范例。
1. 项目缘起:从经典难题到动手实践
如果你在自动化、机械电子或者控制理论领域摸爬滚打过一阵子,大概率听说过“倒立摆”这个玩意儿。它不是什么新潮的科技产品,但绝对是控制领域里一块经久不衰的“试金石”。简单说,就是一根杆子,底部连接在一个可以水平移动的小车上,你的任务是通过控制小车的左右移动,让这根杆子保持竖直不倒。听起来有点像杂技演员用下巴顶着一根长杆,只不过我们是用算法和电机来代替人的肌肉和神经。
而“二阶倒立摆”,则是这个游戏的“地狱模式”。它有两根杆子,像一根钓鱼竿的竿稍又接了一节更细的梢子,两级串联,底部同样由小车驱动。它的不稳定性和非线性特性被急剧放大,对控制算法的鲁棒性、响应速度和抗干扰能力提出了近乎苛刻的要求。很多教科书上高大上的控制理论,比如状态反馈、最优控制、模糊控制乃至神经网络,都会拿它来做仿真验证和性能比拼。所以,当你看到“二阶倒立摆_matlab_控制系统”这个标题时,它背后隐含的是一系列非常具体的问题:这个系统的数学模型到底怎么建立?在MATLAB/Simulink里如何把它“搭建”出来?PID、LQR这些控制器该怎么设计和调试?仿真跑起来和理论分析有多大差距?
我最初接触这个项目,是为了给一门研究生课程的大作业“找点有挑战性的乐子”。课本上的单摆例子已经玩腻了,就想试试这个更刺激的。结果发现,虽然网上资料不少,但要么是只给理论公式,要么是只贴一张完美的仿真结果图,中间从推导到实现,从调参到分析的那些“脏活累活”和“坑”,很少有人系统性地讲透。这次,我就把自己从零开始,在MATLAB里构建、仿真并分析一个二阶倒立摆控制系统的完整过程,包括那些卡住我很久的细节和最终跑通后的心得,毫无保留地分享出来。无论你是相关专业的学生在做课程设计,还是工程师想验证某个先进控制算法,这篇文章都能提供一个可直接复现的、细节拉满的参考框架。
2. 核心原理拆解:二阶倒立摆的动力学建模
动手写代码之前,我们必须搞清楚要控制的这个“对象”到底遵循什么物理规律。这是所有控制设计的基石,模型建得准,后续仿真才有意义。二阶倒立摆是一个典型的欠驱动、多变量、强非线性系统,我们通常采用拉格朗日方程来推导其动力学模型,因为它能系统性地处理复杂约束,比牛顿-欧拉法更清晰。
2.1 系统定义与假设
我们先明确系统参数和假设,这是推导的起点:
- 小车质量:
M, 可以在水平导轨上无摩擦运动。 - 下摆杆质量:
m1, 长度2L1(质心在杆中点,距关节L1)。 - 上摆杆质量:
m2, 长度2L2。 - 小车位置:
x, 以初始位置为原点。 - 下摆杆与垂直向下方向的夹角:
θ1(顺时针为正)。 - 上摆杆与下摆杆的夹角:
θ2(相对于下摆杆,顺时针为正)。因此,上摆杆相对于绝对垂直线的角度是θ1 + θ2。 - 控制输入:作用在小车上的水平力
F。 - 假设:摆杆为均质细杆;所有关节为理想铰接,无摩擦;系统在二维平面内运动。
2.2 拉格朗日方程推导过程
拉格朗日方程的核心是计算系统的拉格朗日量L = T - V,其中T是总动能,V是总势能。
第一步:计算各部件质心坐标(在惯性坐标系中)
- 小车质心坐标:
(x, 0) - 下摆杆质心坐标:
(x + L1*sinθ1, L1*cosθ1) - 上摆杆质心坐标:这需要一点几何知识。它是下摆杆末端(坐标为
(x + 2L1*sinθ1, 2L1*cosθ1))再加上从上关节指向上摆杆质心的向量。这个向量在惯性系中的分量是(L2*sin(θ1+θ2), L2*cos(θ1+θ2))。 因此,上摆杆质心坐标为:(x + 2L1*sinθ1 + L2*sin(θ1+θ2), 2L1*cosθ1 + L2*cos(θ1+θ2))
第二步:计算各部件速度(对时间求导)对上述坐标求时间一阶导数,得到速度向量。这里以下摆杆质心速度的平方计算为例,这是一个关键的运算技巧:
v1x = dx/dt + L1*cosθ1*dθ1/dt v1y = -L1*sinθ1*dθ1/dt v1^2 = v1x^2 + v1y^2 = (dx/dt)^2 + (L1*dθ1/dt)^2 + 2*L1*cosθ1*(dx/dt)*(dθ1/dt)同理,可以求出上摆杆质心速度的平方v2^2,表达式会更复杂,因为它包含θ1,θ2,dθ1/dt,dθ2/dt和dx/dt的交叉项。
第三步:计算总动能 T 和总势能 V
- 动能 T:
- 小车平动动能:
0.5 * M * (dx/dt)^2 - 下摆杆动能:包含平动和转动。平动动能
0.5 * m1 * v1^2, 转动动能0.5 * I1 * (dθ1/dt)^2,其中I1 = (1/3)*m1*(2L1)^2 = (4/3)*m1*L1^2(细杆绕端点的转动惯量)。注意:如果我们用质心速度计算平动动能,那么转动惯量应取绕质心的值I1_cm = (1/12)*m1*(2L1)^2 = (1/3)*m1*L1^2。两种方法等价,但必须匹配。这里采用质心法更通用。 - 上摆杆动能:同理,
0.5 * m2 * v2^2 + 0.5 * I2_cm * (d(θ1+θ2)/dt)^2,I2_cm = (1/3)*m2*L2^2。
- 小车平动动能:
- 势能 V(以小车高度为势能零点):
- 下摆杆势能:
m1 * g * L1 * cosθ1 - 上摆杆势能:
m2 * g * (2L1*cosθ1 + L2*cos(θ1+θ2))
- 下摆杆势能:
第四步:建立拉格朗日方程并线性化将L = T - V代入拉格朗日方程:d/dt(∂L/∂q_i˙) - ∂L/∂q_i = Q_i其中,广义坐标q = [x, θ1, θ2]^T, 广义力Q = [F, 0, 0]^T(只有小车受到主动力 F)。
执行这个微分运算会得到三个非常复杂的二阶非线性微分方程。我们关心的平衡点是[x, θ1, θ2, dx/dt, dθ1/dt, dθ2/dt] = [0, 0, 0, 0, 0, 0],即小车在原点,两根杆都竖直向上倒立。
为了设计经典的线性控制器(如LQR),我们需要在平衡点附近对这个非线性模型进行线性化。线性化的方法是假设角度θ1,θ2及其导数都很小,并利用近似:sinθ ≈ θ,cosθ ≈ 1,(dθ/dt)^2 ≈ 0。将这些近似代入非线性方程,并忽略高阶小量,就能得到线性化后的状态空间方程:
M * d²q/dt² + C * dq/dt + K * q = B * F
经过整理,可以写成标准的状态空间形式:dx/dt = A * x + B * uy = C * x + D * u
其中,状态向量x = [x; θ1; θ2; dx/dt; dθ1/dt; dθ2/dt], 控制输入u = F。矩阵A和B的表达式由系统参数M, m1, m2, L1, L2, g决定,推导过程繁琐但机械。很多论文和教材会直接给出线性化后的系数矩阵,为了节省时间,我们可以借助符号计算工具(如MATLAB的Symbolic Math Toolbox)来辅助完成。
注意:这是整个项目最容易出错的地方。手动推导时一个正负号、一个系数错误,都会导致后续仿真完全失败。强烈建议:1)将你的推导过程用符号工具验证;2)在网上找一个可靠的、经过验证的模型表达式作为基准进行对照。我个人的经验是,花费在验证模型上的时间,远比仿真调参时因为模型错误而抓狂的时间要划算得多。
3. 在MATLAB/Simulink中构建仿真模型
有了数学模型,我们就可以在MATLAB/Simulink这个强大的仿真环境中将它“搭建”出来。这里有两种主流思路:一是基于状态空间方程直接搭建;二是利用物理建模工具Simscape进行更直观的多体动力学仿真。我两种都试过,各有优劣。
3.1 方法一:基于状态空间方程的Simulink模型
这是最经典、最直接,也是对理解控制系统最有帮助的方法。我们假设已经通过推导或查找,得到了线性化后的系统矩阵A,B,C,D。
步骤1:在MATLAB工作区定义系统参数和矩阵首先,我们给定一组合理的物理参数,并计算出A和B矩阵。例如:
M = 1.0; % 小车质量 (kg) m1 = 0.3; % 下摆质量 (kg) m2 = 0.1; % 上摆质量 (kg) L1 = 0.5; % 下摆半长 (m) L2 = 0.3; % 上摆半长 (m) g = 9.81; % 重力加速度 % 此处应放置根据参数计算A, B矩阵的代码。 % 为了示例,我们假设一个计算好的A,B(实际需要根据你的模型填充)。 % A = ... ; (6x6 matrix) % B = ... ; (6x1 matrix) % C = eye(6); % 假设输出全部状态 % D = zeros(6,1);步骤2:在Simulink中搭建模型
- 新建一个Simulink模型。
- 从库
Library Browser -> Simulink -> Continuous中拖入一个State-Space模块。双击它,在参数对话框中填入A, B, C, D矩阵,以及初始状态(例如,可以设一个很小的初始角度模拟扰动)。 - 这个模块的输入是控制力
F,输出是6维状态向量x。 - 接下来需要设计控制器。例如,我们可以拖入一个Gain模块作为状态反馈矩阵
K。K可以通过lqr函数计算得到。Q = diag([10, 100, 100, 1, 1, 1]); % 状态权重矩阵,调整Q和R是调参关键 R = 0.1; % 控制输入权重 K = lqr(A, B, Q, R); % 计算线性二次型最优状态反馈增益 - 将State-Space模块的输出连接到
K增益模块,然后连接到一个Sum模块(设置为负反馈),Sum模块的另一个输入可以接一个参考信号(比如期望的小车位置x_ref,通常为0)。Sum模块的输出即为控制力F,再反馈给State-Space模块的输入。这样就形成了一个闭环。 - 添加Scope模块观察状态变化,添加To Workspace模块将数据导出到MATLAB工作区以便后续分析。
步骤3:处理非线性与饱和上述模型是线性的,但实际系统存在非线性(如摆角过大时线性模型失效)和执行器饱和(电机出力有限)。为了仿真更真实,我们可以在控制力F输出后,加一个Saturation模块来限制最大控制力。同时,初始状态不要设得离平衡点太远,否则线性控制器会失效。
3.2 方法二:使用Simscape Multibody进行物理建模
如果你觉得推导方程太头疼,或者想验证你的推导是否正确,Simscape Multibody是更好的选择。它允许你以“搭积木”的方式构建机械系统,自动生成动力学方程。
步骤1:搭建物理结构
- 新建Simulink模型,打开
Library Browser,找到Simscape -> Multibody。 - 从库中拖入以下核心模块:
World Frame:定义全局坐标系和重力。Mechanism Configuration:设置求解器、重力等全局参数。Rigid Transform/Brick Solid/Cylindrical Solid:用来构建小车和摆杆的几何体与质量属性。你需要为小车、下摆杆、上摆杆分别创建Solid模块,并正确设置其质量、尺寸、惯量矩阵和质心位置。Prismatic Joint:模拟小车与地面之间的平移运动。这是我们的驱动关节,需要在此处添加Actuation力输入。Revolute Joint:模拟小车与下摆杆、下摆杆与上摆杆之间的旋转关节。通常设置为被动关节(无驱动)。Transform Sensor/Joint Sensor:用于测量小车位置、摆杆角度等状态,作为控制器的反馈信号。Solver Configuration:必须添加,用于配置物理网络求解器。
步骤2:连接与配置按照物理连接关系,用线条连接各个模块的B(Base) 和F(Follower) 端口。例如,World Frame连接到Prismatic Joint的B口,Prismatic Joint的F口连接到小车Solid的B口,小车Solid的F口再连接到第一个Revolute Joint的B口,以此类推。这是一个需要耐心和细心的过程,确保拓扑结构正确。
步骤3:集成控制器Simscape模型输出的是物理信号(Physical Signal),而我们的控制算法通常在Simulink的“信号流”世界中运行。因此,我们需要:
- 使用
PS-Simulink Converter模块将关节传感器(如角度、角速度)输出的物理信号转换为Simulink信号。 - 在Simulink部分搭建控制器(如PID或状态反馈),根据这些信号计算控制力。
- 使用
Simulink-PS Converter模块将计算出的控制力(Simulink信号)转换为物理信号,输入到Prismatic Joint的Actuation端口。
两种方法对比与选择
- 状态空间法:优点是与理论结合紧密,仿真速度极快,便于进行控制器设计(如LQR)和性能分析(如极点配置、频域分析)。缺点是模型是线性化的,无法研究大范围非线性动态。
- Simscape法:优点是模型直观,更接近物理真实,自动包含非线性、摩擦等复杂因素,是验证线性控制器鲁棒性的好工具。缺点是模型搭建稍复杂,仿真速度较慢,且“黑箱”特性使得基于模型的高级控制器设计不那么直接。
我的建议是:先用状态空间法(方法一)快速设计并调试好你的核心控制算法,因为它迭代快。然后用Simscape模型(方法二)作为一个“高保真测试平台”,来检验你的线性控制器在更真实、非线性环境下的表现。当Simscape模型能稳定时,你的控制器才算是真正有鲁棒性。
4. 控制器设计与参数整定实战
模型准备好了,接下来就是设计让这个不稳定系统立起来的“大脑”——控制器。我们重点讨论两种最实用、也最经典的方法:PID控制和线性二次型最优控制(LQR)。
4.1 串级PID控制:从单摆经验出发
对于单级倒立摆,单回路PID(通常是PD)控制角度就能奏效。但对于二阶倒立摆,由于存在两个耦合的摆角,直接控制一个角度会导致另一个失稳。一种行之有效的策略是串级PID控制。
控制思路:
- 内环:控制上摆杆相对于下摆杆的角度
θ2。这个环路的响应应该最快,因为它稳定的是最顶端、最不稳定的部分。我们使用一个PD控制器,输入是θ2和θ2的微分(角速度),输出是一个“虚拟力矩”,这个力矩试图让θ2归零。 - 外环:控制下摆杆相对于垂直方向的角度
θ1。但此时,外环的“被控对象”不仅仅是下摆杆本身,而是包含了内环闭环后的“等效对象”。外环也使用一个PD控制器,输入是θ1和θ1的微分,输出是另一个“虚拟力矩”。 - 最外环:控制小车位置
x。这个环路的响应最慢。使用一个P或PI控制器,输入是小车位置误差,输出最终作用于小车的控制力F。
在Simulink中的实现: 你需要搭建一个嵌套的控制结构。内环PD的输出,作为外环的一个前馈或附加设定值。最终,三个控制器的输出经过某种组合(通常是相加),形成总控制力F。调试顺序必须从内到外:先断开外环,只整定内环PID参数,让上摆杆能快速响应并稳定在θ2=0附近。然后闭合内环,整定中间环参数,最后整定最外环的小车位置环。
实操心得:串级PID调参是个体力活,非常依赖经验。我的经验法则是:内环重“微分”(D),用于抑制振荡;外环重“比例”(P),用于快速响应;最外环的“积分”(I)要非常小心,避免引起小车缓慢漂移或饱和。可以先给P一个较小值,D给一个中等值,I设为0。通过观察Scope中
θ2的响应,逐步增大P直到出现等幅振荡,然后增大D来阻尼这个振荡。内环调稳后,再以同样的思路调外环。整个过程可能需要反复数十次。
4.2 线性二次型最优控制(LQR):更优雅的全局方案
LQR是一种全状态反馈控制,它通过求解一个优化问题(最小化状态偏差和控制能量的二次型代价函数),直接得到一个最优状态反馈增益矩阵K。对于我们已经线性化并得到(A, B)矩阵的系统,LQR是天然匹配的。
设计步骤:
- 确定状态向量:
x = [x; θ1; θ2; dx/dt; dθ1/dt; dθ2/dt]。我们需要能测量或观测所有这六个状态。实践中,小车位置x和速度dx/dt可用编码器测量,两个角度θ1,θ2可用安装在关节处的编码器测量,两个角速度则可以通过对角度信号差分(或使用观测器)获得。 - 设计权重矩阵 Q 和 R:
Q:状态权重矩阵,通常是对角阵。Q(i,i)的值越大,表示我们对第i个状态的误差惩罚越重,控制器会花更多“精力”去让这个状态快速归零。R:控制输入权重标量(单输入情况)。R值越大,表示我们越“吝啬”使用控制力,控制器会倾向于更温和的控制,但响应可能变慢。
- 使用
lqr函数求解:
计算得到的% 假设 A, B 已定义 Q = diag([100, 1000, 1000, 10, 10, 10]); % 示例权重 R = 1; [K, S, P] = lqr(A, B, Q, R);K是一个1x6的行向量。控制律为u = -K * x。
参数整定技巧: LQR的调参就是调整Q和R。一个系统化的方法是:
- 先确定 R:根据执行器(电机)的最大出力
F_max,设定一个合理的R值。可以先将R设为1/F_max^2量级,作为一个起点。 - 再调整 Q:这是调参的核心。遵循一个原则:对越不稳定、越需要快速稳定的状态,给予越高的权重。对于倒立摆,角度
θ1和θ2是最不稳定的状态,因此它们的权重(Q(2,2)和Q(3,3))应该最大。角速度的权重次之,用于提供阻尼。小车位置x和速度dx/dt的权重通常可以设得小一些,因为系统的主要目标是“不倒”,而不是“不动”。 - 观察闭环极点:计算
lqr后返回的闭环极点P。理想的极点应该是一对或多对稳定的共轭复数(提供适当的阻尼振荡),以及一些更快的实极点。如果极点离虚轴太近,系统响应太慢;如果太远,可能对噪声敏感或需要过大控制力。通过调整Q和R,观察极点位置的变化,是一个很有效的调试手段。
在Simulink中实现LQR: 非常简单。将状态向量x乘以增益矩阵-K,输出就是控制力u。记得在前面加上一个Saturation模块来限制最大控制力,模拟执行器饱和。
4.3 控制器性能对比与鲁棒性测试
设计好控制器后,我们需要在仿真中全面评估其性能。
测试场景:
- 平衡稳定性:给定一个非零的初始角度(如
θ1=5°, θ2=3°),观察系统能否自行稳定到竖直位置。记录稳定时间、超调量。 - 抗干扰测试:在系统稳定后,在某一时刻施加一个短暂的脉冲干扰力(比如作用在小车上或摆杆上),观察系统能否恢复平衡。这考验控制器的干扰抑制能力。
- 跟踪测试:让小车的期望位置
x_ref从一个点缓慢移动到另一个点(如正弦波),观察两根摆杆在跟踪过程中的晃动情况。 - 参数鲁棒性:故意在控制器中使用的模型参数(如
m1, m2, L1)与实际Simscape模型参数之间设置一些偏差(例如±10%),观察控制器是否仍然能稳定系统。这是检验控制器鲁棒性的关键。
结果分析:
- PID控制器:通常能实现稳定,但在大干扰或参数变化时容易失稳。调试得当的串级PID响应速度可能很快,但各环之间的耦合需要精心解耦。
- LQR控制器:在模型准确的情况下,性能通常优于PID,能实现快速、平滑的稳定。其最优性保证了在给定权重下“最好”的性能。但LQR最大的弱点是对模型误差敏感,即鲁棒性可能不足。这也是为什么在LQR基础上发展出了
H∞、μ综合等鲁棒控制方法。
在我的仿真中,使用同一组系统参数,精心调试的LQR在稳定时间和抗小幅干扰方面表现略优于串级PID。但当我把Simscape模型中的摆杆质量增加20%而控制器模型参数不变时,PID控制器经过重新调参还能勉强工作,而原参数的LQR控制器则直接失稳了。这生动地说明了理论最优与工程鲁棒之间的差距。
5. 仿真实现、可视化与结果深度分析
控制器设计好了,最后一步就是让整个系统在仿真中跑起来,并把结果直观、专业地呈现出来。
5.1 完整的Simulink模型集成
无论你采用状态空间模型还是Simscape模型,最终都需要集成传感器、控制器、执行器(饱和限制)和被控对象。一个健壮的仿真模型还应包括:
- 参考信号生成:使用
Step、Sine Wave或Signal Builder模块生成x_ref。 - 噪声注入:为了模拟真实的传感器噪声,可以在状态反馈通道上加入
Band-Limited White Noise模块。这对于评估控制器的噪声抑制性能很重要。 - 数据记录:使用
To Workspace模块将关键信号(如时间t、所有状态x、控制力u、参考信号ref)以数组形式保存到MATLAB工作区。 - 手动切换开关:方便在仿真中动态施加脉冲干扰。
5.2 使用MATLAB脚本进行批量仿真与数据分析
Simulink跑一次仿真只是开始,我们通常需要改变参数(如不同的Q/R权重、不同的初始条件)进行多次仿真,并系统性地分析结果。这时就需要编写MATLAB脚本。
示例脚本框架:
clear; close all; clc; % 1. 定义系统参数和计算A,B矩阵 sysParams = defineSystemParameters(); % 自定义函数 [A, B] = linearizeModel(sysParams); % 自定义函数,计算线性化模型 % 2. 设计控制器(例如LQR) Q = diag([100, 1000, 1000, 10, 10, 10]); R = 1; K = lqr(A, B, Q, R); % 3. 准备Simulink模型参数 modelName = 'double_inverted_pendulum_sim'; load_system(modelName); % 加载模型 % 将参数K等设置到模型工作区或使用set_param set_param([modelName '/Gain_K'], 'Gain', mat2str(K)); % 4. 定义不同的仿真场景 scenarios = {'small_perturb', 'large_perturb', 'tracking'}; for i = 1:length(scenarios) scenario = scenarios{i}; % 根据场景设置模型初始条件、参考信号等 configureScenario(modelName, scenario); % 5. 运行仿真 simOut = sim(modelName, 'StopTime', '10'); % 6. 提取数据 t = simOut.tout; x_data = simOut.logsout.get('states').Values.Data; u_data = simOut.logsout.get('control_force').Values.Data; % 7. 绘图与分析 figure('Name', scenario); subplot(2,1,1); plot(t, x_data(:,1:3)); % 绘制位置和角度 legend('x', '\theta_1', '\theta_2'); grid on; subplot(2,1,2); plot(t, u_data); % 绘制控制力 legend('Force F'); grid on; xlabel('Time (s)'); % 8. 计算性能指标 settling_time = computeSettlingTime(t, x_data(:,2)); % 计算下摆杆稳定时间 max_control = max(abs(u_data)); fprintf('场景 %s: 稳定时间=%.3fs, 最大控制力=%.3fN\n', scenario, settling_time, max_control); end5.3 高级可视化:动画演示
静态曲线图虽然能分析数据,但远不如一个动态的动画直观。MATLAB提供了强大的动画绘制功能。
创建动画的基本步骤:
- 从仿真数据中提取出小车位置
x和两个摆角θ1,θ2。 - 根据这些数据,计算每一帧(每个时间点)小车和两个摆杆末端点的坐标。
- 使用
plot或line函数在循环中绘制这些坐标,并用pause(0.01)控制帧率。 - 使用
getframe和writeVideo函数可以将动画保存为视频文件(如MP4)。
一个简化的动画绘制代码片段:
figure('Position', [100, 100, 800, 600]); hold on; axis equal; grid on; xlim([-2, 2]); ylim([-0.5, 1.5]); % 根据你的系统尺寸调整 % 初始化图形对象 cart_plot = plot(0, 0, 's', 'MarkerSize', 20, 'MarkerFaceColor', 'b'); pend1_plot = line([0, 0], [0, 0], 'Color', 'r', 'LineWidth', 3); pend2_plot = line([0, 0], [0, 0], 'Color', 'g', 'LineWidth', 2); for k = 1:10:length(t) % 跳帧以提高速度 x_cart = x_data(k, 1); th1 = x_data(k, 2); th2 = x_data(k, 3); % 计算摆杆端点坐标 x_pend1_end = x_cart + 2*L1*sin(th1); y_pend1_end = 2*L1*cos(th1); x_pend2_end = x_pend1_end + 2*L2*sin(th1+th2); y_pend2_end = y_pend1_end + 2*L2*cos(th1+th2); % 更新图形对象数据 set(cart_plot, 'XData', x_cart); set(pend1_plot, 'XData', [x_cart, x_pend1_end], 'YData', [0, y_pend1_end]); set(pend2_plot, 'XData', [x_pend1_end, x_pend2_end], 'YData', [y_pend1_end, y_pend2_end]); title(sprintf('Time: %.2f s', t(k))); drawnow; pause(0.01); % 控制播放速度 end看着自己设计的控制器让两根杆子晃晃悠悠地立起来,那种成就感是看曲线图无法比拟的。动画还能帮你直观地发现一些问题,比如控制器虽然让角度归零了,但小车却漂移出了画面,这说明你的位置环可能需要加强积分作用或调整权重。
5.4 结果分析与报告撰写要点
仿真完成后,一份清晰的分析报告是必不可少的。你应该关注以下指标:
- 稳定性:所有状态量是否最终收敛到平衡点或期望轨迹?
- 动态性能:
- 上升时间:从扰动到首次到达平衡点附近的时间。
- 调节时间:进入并保持在最终值±2% (或5%) 误差带内的时间。
- 超调量:最大偏差与稳态值的百分比。对于倒立摆,我们希望超调尽可能小。
- 稳态误差:最终是否存在静态偏差?特别是小车位置
x。
- 控制效率:
- 控制力幅值:最大控制力是否超出执行器限制?
- 控制力变化率:控制信号是否平滑?剧烈的变化可能在实际电机中无法实现。
- 鲁棒性:在模型参数摄动、存在测量噪声和外部干扰时,上述性能指标恶化的程度。
在报告中,用对比图表来展示不同控制器(如PID vs LQR)或不同参数下的性能差异。例如,可以画一个子图,对比两者在相同脉冲干扰下的角度恢复曲线;另一个子图对比它们的控制力输出,看看谁更“省力”或更“平滑”。
最后,别忘了讨论仿真的局限性。我们的模型忽略了关节摩擦、电机响应延迟、数字控制器的离散化效应、传感器采样噪声的频谱特性等。这些因素在实物系统中都会出现。因此,一个在仿真中表现完美的控制器,在实物调试阶段几乎肯定需要再次调整。仿真最大的价值在于提供一个安全、低成本的原型验证和参数初选平台,大幅降低实物调试的试错成本。
本文还有配套的精品资源,点击获取