
简介面向控制工程与自动化专业学习者这份资源围绕球杆系统的建模与稳定性分析展开结合理论推导与MATLAB实现适合正在学习线性系统理论、现代控制原理或机械动力学课程的学生用于实践。压缩包内共3个文件包含两个可直接运行的.m脚本和一个Word文档整体仅605KB体积紧凑。.m脚本分别用于判断系统的能控能观性和极点配置Word文档则完整梳理了球杆系统的动力学建模过程涉及牛顿-欧拉定律、拉格朗日方程、特征值稳定性判据等内容并可作为课程报告或实验笔记的参考。资源目前已有1443人学习下载对于希望借助机械系统实例快速上手MATLAB控制系统分析的读者能提供从模型建立、仿真验证到稳定性校验的完整思路尤其适合控制类课设或入门研究。1. 球杆系统分析为什么这套 MATLAB 源码值得拆开看做控制入门和数学建模仿真的人迟早会撞上球杆系统Ball and Beam这个经典对象。它比倒立摆看着简单真上手建模才发现坑不少变量多、自由度耦合、非线性项藏在运动方程里线性化取哪个工作点、状态变量怎么排都直接影响后续的稳定性判断。这套“球杆系统分析、建模和稳定性分析 MATLAB 源码包”就是把这条路完整走了一遍——从牛顿-欧拉和拉格朗日两种建模思路的取舍到状态空间表达式、能控能观性判别、极点配置仿真代码和文档是对应的适合正在做课程设计、数学建模赛前热身或自学现代控制理论的读者。你拿到手不只是两个 .m 文件而是一整套可复现的分析流程改改参数就能复用到类似的机电系统上。2. 球杆系统的动力学建模从运动方程到状态空间的完整推导球杆系统的物理构成并不复杂一个球放在一根可绕支点转动的杆上杆的一端由电机或伺服机构驱动通过改变杆的倾角来控制球在杆上的位置。系统有两个自由度——球的平动和杆的转动但两者通过球的滚动约束耦合在一起。建模时最关键的决策是用牛顿-欧拉法还是拉格朗日方程。源码包里应对前者做了尝试后者则用于规整推导两者的结果在理想条件下等价但推导路径和出错点完全不同。2.1 牛顿-欧拉法先看受力再决定要不要保留滚动摩擦项用牛顿-欧拉法建模第一步是对球做受力分析。假设球的半径为 R质量为 m杆的倾角为 α球在杆上距离支点 x 处把坐标系固定在杆上。球沿杆方向的受力有重力沿杆方向的分量 mg·sinα杆对球的法向支反力对此方向无贡献球与杆接触处的静摩擦力 f 则出现在球的无滑动滚动中。球的平动方程可以直接写为m·ẍ mg·sinα - f球绕自身质心的转动方程为J·ω̇ f·R对于实心球J (2/5)m·R²。无滑动滚动约束是 ẋ -R·ω注意符号取决于坐标取向本文按球向 x 正方向运动时 ω 为负的约定代入后能把 f 消掉得到标准的球运动微分方程ẍ (5/7)·g·sinα这个方程非常简洁但需要注意的是它只在“滚动无滑动”的假设下成立。如果杆面较光滑实际系统会进入滑动模式需要额外引入滑动摩擦模型。通常的做法是先用无滑动模型做控制器设计再在仿真中加入摩擦力矩扰动来验证鲁棒性。拿到源码包后我一般会先看它使用的是哪一种假设再决定后续调整方向。2.2 拉格朗日方程视角与线性化在哪一点展开决定了模型适用范围拉格朗日法的优势在于用能量观点统一处理多自由度耦合。定义广义坐标 q₁ x、q₂ α系统的动能包含球平动动能、球转动动能和杆绕支点的转动动能。势能只来自球的重力势能杆在水平状态时势能为零。拉格朗日方程通过求动能与势能之差对广义速度的偏导得到两个二阶非线性微分方程。核心非线性项是 sinα 出现在球坐标的强迫项中。极值设计的工作点是杆水平且球静止即 x 0, α 0在该点把 sinα 线性化为 α。这是整个线性化分析中最关键的步骤也是源码包里 “极点配置.m” 能生效的前提。线性化的使用边界通常约定在 |α| ≤ 10° 范围内超过这个角度线性模型与非线性模型的响应偏差会快速放大。在使用 MATLAB 做验证时我习惯同时用 ode45 求解非线性方程与线性状态空间模型的响应对比确认系统在这一范围内才谈得上“稳定性”。2.3 从运动方程到状态空间状态变量排序影响后续所有矩阵计算有了线性化后的二阶方程就可以写出系统的状态空间表达式。选取状态向量为 [x; ẋ; α; α̇]输入为杆的角加速度 u α̈这也是源码中常见的做法把执行器的高频环节抽象为一个理想分块输出为球的位移 x。于是得到四阶状态矩阵 A、输入矩阵 BA [0 1 0 0; 0 0 (5/7)g 0; 0 0 0 1; 0 0 0 0] B [0; 0; 0; 1]其中 g 取 9.8 m/s²。输出方程通常设为 C [1 0 0 0]D 0。这里值得注意的一个细节是四个状态变量的排列顺序是 x、ẋ、α、α̇对应 MATLAB 的 ctrb 和 obsv 函数中矩阵 A 的行列顺序不能随意调换。否则能控性判别矩阵的秩虽然不变但后续极点配置时 K 向量的物理含义会错位仿真里球的位置输出也会张冠李戴。3. 能控能观性判别用 MATLAB 算矩阵更要能读懂秩的含义拿到状态空间模型后第一件该做的事情是判断这个系统在理论上能不能控、能不能观。球杆系统是教科书里的经典案例它在这个状态空间表达下是能控且能观的但通过代码验证这个过程能让你对现代控制理论里的秩判据有一个实际的感知而不是只停留在课本公式上。源码包中的“判断系统能空能观.m”正是为此准备的。3.1 能控性判别ctrb 矩阵的秩要算更要看它和输入位置的关系A [0 1 0 0; 0 0 (5/7)*9.8 0; 0 0 0 1; 0 0 0 0]; B [0; 0; 0; 1]; C [1 0 0 0]; D 0; Co ctrb(A, B); if rank(Co) size(A, 1) disp(系统完全能控); else disp(系统不完全能控); endctrb函数会构造能控性矩阵 [B, AB, A²B, A³B]rank返回矩阵的秩。四阶系统满秩即 rank 4 时完全能控。这里需要注意B 矩阵只在最后一个分量上有非零值也就是输入 u 直接影响的是杆的角加速度它是一个积分链的末端。正因为输入作用在积分链的最后一级系统才能通过控制角加速度来间接控制杆倾角 α、进而控制球速度 ẋ 和球的位置 x。如果你改写状态方程时把 B 中的非零项放到了第二个位置系统会陷入“输入能直接影响速度却控制不了角度”的尴尬局面能控性矩阵也会降秩。3.2 能观性判别单输出系统为什么依然能观测全部状态Ob obsv(A, C); if rank(Ob) size(A, 1) disp(系统完全能观); else disp(系统不完全能观); endobsv构造能观性矩阵行列要求与ctrb一致。读者如果只看到 C [1 0 0 0]可能会认为只能测量球的位移其他三个状态不可观测。但实际上一次积分链结构的系统具有“输入完全已知、状态由输出及其导数唯一确定”的特性四个状态均能重构。这一点对于设计状态反馈控制器的读者很关键——它意味着只要球的位置可以被传感器测到理论上就可以设计状态观测器来估计球速和杆的倾角角速度不需要额外安装更多传感器。当然在实际工程中微分级联会放大噪声所以多数成型方案还是在杆端加编码器、在基座加角速度陀螺仪直接测量状态MATLAB 仿真里则仍然按理想状态反馈来处理。3.3 建模和仿真时的参数一致性在跑这些脚本前务必先统一 g 的数值和单位制。源码中使用 g 9.8 m/s²如果你的数值取 9.81不会改变能控能观性结论但会影响极点配置后闭环极点的具体位置与仿真动态。工程上建议用 g 9.80665 作为精确参考值仿真入门阶段用 9.8 足够。另一个容易忽略的是状态矩阵 A 中第 2 行第 3 列的数值来源——(5/7)·g 是滚动球体的有效重力加速度系数如果你的系统用的是空心球壳转动惯量 J (2/3)mR²系数会变为 (3/5)g。这一步替换若不改后续一切分析都建立在错误的模型上。4. 极点配置实战把控制器设计从课本搬到可跑通的状态反馈代码极点配置法的基本思想是通过设计状态反馈增益矩阵 K将闭环系统的极点放到期望位置从而满足超调量、调节时间、稳态误差等指标。球杆系统的优势在于它完全能控所以可以用任意极点位置来设计控制器。源码包里的“极点配置.m”就是这个环节的核心实现这一节将把它拆开逐一说明选择、计算和验证。4.1 期望极点的选择策略主导极点决 定响应其他极点不能拖后腿设计闭环极点前先明确性能指标。若希望调节时间大约 3 秒、超调量不超过 5%则可以选择一对共轭主导极点使阻尼比约为 0.7无阻尼自然频率约为 2 rad/s。即主导极点s -1.4 ± j·1.8剩余的两个非主导极点需要选在复平面左侧更远处通常取它们的实部为-10左右这样它们对动态响应的影响可以忽略。源码中常见的做法是设置 p [-1.41.8i; -1.4-1.8i; -8; -10]。这里建议的一个检验法则是最右侧极点的实部到虚轴距离与次右极点实部到虚轴距离的比值至少为 3 到 5否则暂态中会明显出现“慢极点拖尾”现象实际响应比主导极点给出的预估慢得多。4.2 用 place 和 acker 求状态反馈增益适用边界要分清A [0 1 0 0; 0 0 (5/7)*9.8 0; 0 0 0 1; 0 0 0 0]; B [0; 0; 0; 1]; p [-1.41.8i; -1.4-1.8i; -8; -10]; K place(A, B, p); disp(状态反馈增益 K ); disp(K);place函数基于鲁棒特征值配置算法能较好处理多变量系统对期望极点有一定容错能力。需要注意place要求期望极点集合中复数必须共轭成对它不允许系统包含重极点的情况——如果两个极点完全相同且系统包含代数重数place可能报错。这时可以用acker函数做备选。acker使用的是 Ackermann 公式适用于单输入单输出系统特别适合本模型这样的单输入四阶系统缺点是数值稳定性略差。我在实际使用中极点放得比较开就会用acker取值在-10到-15级别时两者差异不大但极点绝对值超过-20后place的数值结果更可靠。K向量中的四个元素分别对应四个状态变量的反馈系数。仿真时控制器输出 u -K·x即杆角加速度指令由当前状态的线性组合决定。K 的第一项是位置反馈系数第二项是速度反馈第三项是倾角反馈第四项是角速度反馈。读输出结果时你会发现第一项可能是正的、第四项是负的这正反映了系统需要“朝哪边立、往哪边转”的反向调节逻辑。4.3 完整闭环仿真状态空间响应看不出的问题换 ode45 立刻现形极点配置完成不等于控制器真正可用还要做闭环仿真验证。最简单的方式是用lsim仿真线性状态空间模型sys_cl ss(A - B*K, B, C, D); t 0:0.01:10; u zeros(size(t)); % 零输入初始状态扰动 x0 [0.1; 0; 0.05; 0]; % 球的初始位置 0.1m杆初始倾角 0.05rad [y, t, x] lsim(sys_cl, u, t, x0); plot(t, x(:, 1), LineWidth, 1.5);初始状态选择x0 [0.1; 0; 0.05; 0]表示初始时球位于偏离支点 0.1 米处同时杆有 0.05 弧度的初始倾角。这比只给单一扰动更接近实际调试场景。若响应曲线收敛到零且调节时间在设定范围内线性层面的设计就走通了。然后马上切换到非线性方程验证dx (t, x) [x(2); (5/7)*9.8*sin(x(3)); x(4); -K*x]; [t_nl, x_nl] ode45(dx, [0 10], x0); plot(t_nl, x_nl(:, 1));这里dx中第四行写作-K*x因为输入是角加速度 u而状态反馈 u -Kx。第三行是角度对时间的导数角速度第二行包含非线性项 sinα不再用线性化近似。两组曲线在小角度初始条件下应高度重合。如果看到显著分离优先怀疑初始扰动超出线性范围或极点位置不对应实际闭环动态。5. 避坑指南球杆系统建模与仿真的五个典型翻车现场这套源码包本身很短小但它真正值钱的地方在于帮你少走弯路。下面这些坑是我自己和不少同行在这个系统上反复踩过的每一条都按“现象、原因、解决”来还原。5.1 状态矩阵里 sinα 直接写成 α仿真却用大角度初始化——发散不背锅现象非线性仿真发散线性仿真正常有些人直接认定“极点配置失败了”。原因线性化模型只在小角度有效初始化给 30° 倾角早就超出近似范围。解决始终在小角度范围内验证例如 α₀ ≤ 0.2 rad约 11.5°如果确实需要大角度启动改用反步法或滑模控制等非线性设计而不是硬套 LQR。5.2 place 报错无法处理重极点不是你的模型错了现象place(A, B, p)报错说不能配置重极点。原因place在期望极点含重根或多输入系统下会失效它是基于鲁棒特征值分配改良的但在重根条件下数值上出现秩亏损。解决换用acker(A, B, p)直接计算它专门针对单输入系统或者把期望极点中的重根稍微拉开一点点比如 -8 和 -8.01原理上几乎无差别但数值上避开了退化。5.3 能控性矩阵满秩仿真却失控——极点位置数字掩耳盗铃现象rank(Co) 4满秩极点配置也成功K 有数值输出但闭环响应发散。原因K 计算时使用的模型与实际仿真模型不一致典型原因是 B 矩阵在状态空间和 ode45 中的对齐关系弄错或 A 矩阵里 (5/7)g 那一项被无意中替换成 g。解决用一个简单的检查脚本在初始化函数里对 A 矩阵逐项打fprintf打印数字逐个核对。我曾经花一上午查发散原因最后只是把 0.7 写成了 0.07。5.4 状态变量排序不统一K 向量照搬导致系统行为诡谲现象别人分享的 K 值拿来直接用结果系统不稳定或响应方向完全相反。原因对方的状态变量排序可能是 [x; α; ẋ; α̇]而你的代码是 [x; ẋ; α; α̇]K 向量里的每一项对应错了物理量。解决拿到任何 K 向量先列出自己代码的状态顺序再写一行注释标明“K(1) 对应 xK(2) 对应 ẋ …”。调试时故意把初始状态设成只含一个非零量观察控制器输出方向和预期是否一致。5.5 阻尼被完全忽略现实中球会滚出杆面现象仿真里系统稳定收敛放到硬件或更真实的机理模型上系统振荡不断并最终失稳。原因球杆系统在纯滚动假设下没有阻尼极点配置设计出的控制器对抗动扰动能力很弱真实系统中摩擦、气隙、电机延迟都是额外相位延迟会吞噬稳定裕度。解决在设计阶段就往仿真里加一阶惯性环节模拟执行器延迟例如传递函数 1/(0.1s1)重新设计 K同时在仿真里加入等效阻尼项 c·ẋ 到球运动方程中检验控制器对参数变化的鲁棒性。5.6 控制器输出饱和未建模——仿真稳定实物启动就甩飞现象控制器给出的角加速度指令大于电机的实际输出能力仿真时因为理想模型没有饱和限制系统依然稳定实物一启动执行器憋在极限输出上系统进入非线性区振铃严重甚至失稳。解决在仿真里加饱和函数u_sat max(min(u, u_max), -u_max)在 u_max 值从 1000 逐步降低到实际电机可输出的水平比如 50 rad/s²重新审视极点是否仍可达成。你会发现极点越远所需输出力越大设计时要留足裕量。6. 参数扫描与响应归一化把一台仿真器变成设计工具最后这个章节当然不是收尾总结而是分享一个我在复现这套源码时最常用的调试技巧——参数扫描加响应归一化。很多人拿到代码后改一个参数跑一次仿真再把曲线叠在一起看这种方法效率低而且看不出“哪个极点最优”。我的习惯是写一个循环脚本把期望极点根的位置扫成网格同时把响应曲线归一化到同一幅图里一眼就能锁定参数区间。ks linspace(0.5, 2.0, 5); % 自然频率范围 sigmas -linspace(0.8, 2.5, 5); % 实部范围 for i 1:length(sigmas) for j 1:length(ks) sigma sigmas(i); wn ks(j); p [sigma 1i*wn*sqrt(1-0.7^2); sigma - 1i*wn*sqrt(1-0.7^2); -8; -10]; K acker(A, B, p); sys_cl ss(A - B*K, B, C, D); [y, t] initial(sys_cl, x0); % 归一化处理所有响应除以初始位移 plot(t, y / x0(1), LineWidth, 1); hold on; end end这段脚本用initial函数替代lsim直接计算零输入时初始状态引起的自由响应。归一化后所有曲线都从 1 开始重叠程度表征动态品质的一致性观察曲线族之间的分离程度和收敛快慢就能非常直观地了解极点位置对响应的影响。特别是当你在做设计汇报或者课程设计答辩需要论证某个极点配置“为什么好”的时候这种图比你贴十行代码有说服力得多。参数选择方面阻尼比固定为 0.7 是控制工程里的常用起点它能兼顾超调量和调节时间。如果追求更快的调节时间可以把 σ 的绝对值调大但注意 K 也会变大控制器输出加强。我通常用“扫描两步法”先粗扫 σ 在 -1 到 -3 的区间找到调节时间满足指标的范围再细扫 ωn 在 1 到 3 之间观察超调量变化趋势。在完成参数扫描之后再把选定的极点带回到非线性方程里用 5.3 节那个 ode45 脚本跑一遍最终验证。从那以后我每次拿到一个新的线性化模型都会强制走一遍“能控性检查 → 极点配置 → 非线性校验 → 参数扫描”这个流程不再看到 K 有输出就觉得大功告成。套用一句我们这行的老话仿真里翻过的车最终都会在实物上再翻一次前期把这些坑填平后面才能省心。希望这套源码和这篇拆解能帮到你。本文还有配套的精品资源点击获取