简介:大连理工大学2021年系统仿真大作业以龙门吊车系统为对象,适合正在学习Matlab/Simulink仿真与GUI设计的在校生,可作为课程作业或综合设计的直接参考。压缩包共14个文件,主体为2个slx仿真模型和6个mat数据文件,另配有m脚本、fig人机界面、jpg背景图及xml配置等,整体仅约101KB,轻量易用。已有1164人学习下载,在系统仿真类资源中具有不错的关注度。借助其中完整的Simulink模型、GUI界面与配套数据,可以清晰看到龙门吊车系统的建模过程、控制算法、仿真参数配置和界面回调编写思路,对于理解运动学仿真与图形化交互设计有实际帮助。需特别留意的是,资源不含报告说明,更适合已有一定Matlab基础、希望从代码与模型层面借鉴方案的同学,对比自己的实现查缺补漏。
1. 大连理工系统仿真大作业里的龙门吊车,到底在仿真什么
“2021 系统仿真大作业 · 龙门吊车系统仿真”这类题目的第一印象像是机械结构演示,实际上手才发现,它考查的是从对象到数学、从数学到代码的完整链路:把台车、吊绳和吊重简化为两自由度欠驱动系统,输入一组驱动信号,仿真程序输出台车位置、速度和吊重摆角的时间历程。所谓系统仿真,核心并不在画图,而在状态方程是否经得起推敲、数值积分是否能稳定复现动力学行为。
课程评分不会要求造一台真实龙门吊,而是压两条主线:动力学模型是否正确,控制方案是否能让吊重在规定时间内到达目标位置并抑制摆动。几十行代码跑完模型,报告里要有方程、参数表、Simulink/Python 截图和结果曲线,最后所有文件打包进一个 zip,名称通常就叫“系统仿真大作业-龙门吊车系统仿真.zip”。
这篇文章按多数学校能接受的交付物来写:先建模,再仿真,再调控制器,最后把结果整理成能说明白、能复现、解压后不报错的项目压缩包。即使你手上没有原课程附带的模型文件,按照下面这套流程也能复现一个可运行、可出图、可写进报告的完整版本。
2. 龙门吊车系统仿真的动力学建模:从拉格朗日方程到状态空间
2.1 自由度划分与假设条件,先定下来再写方程
平面龙门吊车可以看成一辆台车在横梁上水平运动,一条无质量刚性绳连接吊重。台车位移 (x) 描述台车在横梁上的位置,吊绳摆角 (\theta) 描述绳与竖直方向的夹角,这就是系统的两个自由度。教科书题目里常见的默认条件包括:绳长固定、绳无质量、吊重看作质点、台车与轨道无摩擦、只在铅垂平面内运动。
这些假设的不同会直接改变仿真结果。加入摩擦系数之后,台车需要更大的驱动力才能起步,摆角峰值也会变小,控制器参数必须重新整定。多数课程题目仍按理想模型处理,或者是只加一个线性阻尼项,因此在缺少明确参数时按下面这张基线表建模最稳妥。
| 符号 | 物理含义 | 基线值 |
|---|---|---|
| (M) | 台车质量 | 5 kg |
| (m) | 吊重质量 | 2 kg |
| (l) | 吊绳长度 | 1.2 m |
| (g) | 重力加速度 | 9.81 m/s² |
| (x) | 台车水平位移 | 初始 0 m |
| (\theta) | 吊绳摆角 | 初始 0.1 rad |
初始摆角不一定取零。很多作业会特意给出 (5^\circ\sim10^\circ) 左右的初始偏角,用于观察控制器能否把摆动压回零,这也是后续模型校验的基本输入之一。
2.2 用拉格朗日方程推出台车与吊重的联立运动方程
这一步建议自己完整推一遍,而不是从网上直接抄最终公式。台车动能取 (T_c=\frac{1}{2}M\dot{x}^2),吊重位置为 ((x+l\sin\theta,\ -l\cos\theta)),对时间求导得到两个速度分量:
[ v_{px}=\dot{x}+l\dot{\theta}\cos\theta,\qquad v_{py}=l\dot{\theta}\sin\theta ]
把速度分量代入动能表达式,得到吊带动能:
[ T_p=\frac{1}{2}m\left[(\dot{x}+l\dot{\theta}\cos\theta)^2+l^2\dot{\theta}^2\sin^2\theta\right] ]
展开后为 (\frac{1}{2}m\dot{x}^2+ml\dot{x}\dot{\theta}\cos\theta+\frac{1}{2}ml^2\dot{\theta}^2)。势能以吊绳最低点为参考点,取 (V=-mgl\cos\theta)。定义拉格朗日量 (L=T_c+T_p-V),再代入第二类拉格朗日方程:
[ \frac{d}{dt}\left(\frac{\partial L}{\partial \dot{q}_i}\right)-\frac{\partial L}{\partial q_i}=Q_i ]
整理后得到龙门吊车系统仿真的核心方程组:
[ (M+m)\ddot{x}+ml\cos\theta,\ddot{\theta}-ml\sin\theta,\dot{\theta}^2=F ]
[ ml\cos\theta,\ddot{x}+ml^2\ddot{\theta}+mgl\sin\theta=0 ]
两个方程的含义值得在报告中写清楚。第一式描述台车驱动力与惯性、摆动的耦合关系;第二式描述吊重摆动的纯动力学。台车加速瞬间,吊重会因为惯性滞后于台车,摆角被拉起来;反过来摆角的存在又会通过 (ml\cos\theta) 项反作用于台车。正因为这种双向耦合,仿真时不能把两个方程拆开独立积分。
2.3 状态空间形式与仿真初值设置方法
如果作业只要求仿真,不要求显式状态矩阵,也可以按上面两个式子直接搭建模型。不过为了后续设计控制器,通常仍然把二阶方程组写成标准状态空间形式再处理。取状态向量 ([x,\dot{x},\theta,\dot{\theta}]^T),把两式看成关于广义加速度的二元一次方程:
[ \begin{bmatrix} M+m & ml\cos\theta\ ml\cos\theta & ml^2 \end{bmatrix} \begin{bmatrix} \ddot{x}\ \ddot{\theta} \end{bmatrix}
\begin{bmatrix} F+ml\sin\theta,\dot{\theta}^2\ -mgl\sin\theta \end{bmatrix} ]
每一步积分先解出 ((\ddot{x},\ddot{\theta})^T),再更新速度和位置。求解这个 2×2 方程组可以先写一个最小函数:
function qdd = crane_acc(x, v, th, w, F, M, m, l, g) % 输入状态与驱动力,返回 [台车加速度; 摆角加速度] A = [M + m, m * l * cos(th); m * l * cos(th), m * l^2]; b = [F + m * l * sin(th) * w^2; -m * g * l * sin(th)]; qdd = A \ b; endA \ b是 MATLAB 左除,比显式求逆更稳定。这个函数保留了完整的非线性项,可以直接被 Simulink 的 MATLAB Function 块调用,也可以在命令行单独传参测试。返回值是 (2\times1) 列向量,第一行是台车加速度,第二行是摆角加速度。
初值通常设置为 (x(0)=0,\dot{x}(0)=0),摆角单独指定。即便 (\theta(0)=0),只要驱动力阶跃输入,台车加速瞬间仍会激发出摆角,所以初始摆角为零并不会掩盖控制器效果,报告里把初值约定写明即可。
3. 用 Simulink 与 Python 把龙门吊车系统仿真跑起来
3.1 用 Simulink 搭建龙门吊车系统仿真的最小积分回路,以及 MATLAB Function 封装
在 Simulink 里做龙门吊车系统仿真,最怕把所有公式写进一个大型 Fcn 块,运行之后符号错误极难排查。更稳妥的做法是把动力学求解封装成 MATLAB Function,外部只保留两层积分器:一层积出 (x,\dot{x}),另一层积出 (\theta,\dot{\theta}),再把四维状态合并送给函数块,函数块返回广义加速度后送回积分器,形成一个完整闭环回路。
MATLAB Function 块内部代码可以直接复用 2.3 节的crane_acc函数:
function [ddx, ddth] = crane_plant(x, v, th, w, F, M, m, l, g) % 龙门吊车两自由度动力学模型 A = [M + m, m * l * cos(th); m * l * cos(th), m * l^2]; b = [F + m * l * sin(th) * w^2; -m * g * l * sin(th)]; qdd = A \ b; ddx = qdd(1); ddth = qdd(2); end外部接线时,积分器的初始条件对应状态初值:第一个积分器链初始化为 (x=0,\dot{x}=0),第二个积分器链初始化为 (\theta=0.1,\dot{\theta}=0)。注意不要在求和模块前额外加一个常量偏移,那样会掩盖真正的初值设置。
Simulink 求解器推荐用变步长 ode45,相对误差设置为 (10^{-5})。如果运行报出“无法求解代数环”之类的错误,几乎都是把动力学方程直接连成了反馈环,正确的处理方式是像上面那样用 MATLAB Function 块以“计算加速度—积分”的结构接线。
3.2 用 Python 复算龙门吊车仿真:一份可以对照的 RK45 脚本
Simulink 搭好之后,还应该用另一套语言把同样方程跑一遍,交叉验证两边曲线是否一致。Python 脚本写起来更轻,适合在早期就把模型错误挡在门外。
import numpy as np from scipy.integrate import solve_ivp import matplotlib.pyplot as plt M, m, l, g = 5.0, 2.0, 1.2, 9.81 def crane_rhs(t, y): # y = [x, xdot, theta, thetadot] x, v, th, w = y A = np.array([ [M + m, m * l * np.cos(th)], [m * l * np.cos(th), m * l * l], ]) b = np.array([ 40.0 + m * l * np.sin(th) * w**2, # 恒力 40 N -m * g * l * np.sin(th), ]) ddx, ddth = np.linalg.solve(A, b) return [v, ddx, w, ddth] sol = solve_ivp(crane_rhs, [0, 10], [0.0, 0.0, 0.1, 0.0], max_step=0.01, rtol=1e-6, atol=1e-8) fig, ax1 = plt.subplots() ax1.plot(sol.t, sol.y[0], label="x (m)") ax1.legend(loc="upper left") ax2 = ax1.twinx() ax2.plot(sol.t, np.degrees(sol.y[2]), color="C1", label="theta (deg)") ax2.legend(loc="upper right") plt.savefig("open_loop_response.png", dpi=150)crane_rhs的入参保留t是为了匹配solve_ivp的签名;如果后续要变成可变力,直接在该函数体内写if t < 2: return 40 else: return 10即可。max_step=0.01是刻意设置的,龙门吊摆动周期通常在 2 秒量级,默认最大步长可能跳过波峰,摆角幅度看起来偏小,这不是控制器效果好,而是积分器偷步。
3.3 仿真结果对比与求解器参数选择
按同一组初值与输入跑完 Simulink 和 Python 后,两条曲线应当只差浮点级误差。对比时优先看两个量:台车前 2 秒的位移斜率,以及摆角第一个波峰出现的时间。波峰时间差超过 0.1 秒,基本可以断定两边的模型或初值不一致。
| 仿真环节 | 推荐配置 | 判断依据 |
|---|---|---|
| Simulink 连续系统 | ode45,相对误差 1e-5 | 非刚性问题,默认配置够用 |
| Simulink 含离散控制 | 固定步长 1~5 ms | 避免连续/离散混叠 |
| Python 连续系统 | solve_ivp RK45,max_step=0.01 | 控制结果采样分辨率 |
| 后处理滤波 | 截止频率 10~30 Hz | 只滤数值噪声,不改变主振 |
如果最终交付的是纯 Simulink 工程,仍然建议把 Python 脚本作为附加验证文件保留,回答模型细节时可以直接用脚本里的参数复现一组结果,比口头解释更加可信。
4. 定位与防摆:龙门吊车系统仿真控制器的参数整定路线
4.1 先线性化再设计 LQR,Q、R 权重矩阵怎么设定
龙门吊车控制题目最常见的要求是:台车从 0 运动到 1 m,最大摆角不超过 (5^\circ),在 20~30 秒内进入稳定状态。实现方案里 LQR 是接受度最高的一种。
设计 LQR 前先做小角度线性化。如果控制输入取台车加速度 (u=\ddot{x}),则 (\sin\theta\to\theta,\cos\theta\to1),摆方程简化为:
[ \ddot{\theta}=-\frac{1}{l}u-\frac{g}{l}\theta ]
据此可以写状态矩阵并在 MATLAB 中直接计算反馈增益:
A = [0 1 0 0; 0 0 0 0; 0 0 0 1; 0 0 -g/l 0]; B = [0; 1; 0; -1/l]; Q = diag([200, 10, 80, 5]); R = 0.1; K = lqr(A, B, Q, R);反馈增益矩阵 (K) 是一行四列,控制律是 (u=-Kz),其中 (z=[x,\dot{x},\theta,\dot{\theta}])。权重设定的逻辑是:(Q(1,1)) 管位置误差,(Q(2,2)) 管台车速度,(Q(3,3)) 管摆角,(Q(4,4)) 管摆角速度。
初调时先让位置权重大于摆角权重,例如上面这组参数;如果台车到位后摆角收敛太慢,就把 (Q(3,3)) 从 80 加到 150 左右。反过来的情况是台车迟迟不到位,这时优先减小 (R) 而不是继续加 (Q(1,1))。需要注意,位置权重过大会让仿真里的加速度指令接近阶跃,真实电机会出现扭矩饱和,因此不要把 (Q(1,1)) 拔得太高。
4.2 用 PID 加防摆环节做整定,参数可以先记住一张表
如果题目允许手动设计控制器,PID 是另一条稳定的路。直接用单纯 PID 控制台车位置,结果往往会有残留摆角;常见的补救方案是在位置 PID 输出上叠加摆角反馈:
[ u=K_p(x_r-x)-K_v\dot{x}+K_\theta\theta+K_\omega\dot{\theta} ]
这个式子里面,(K_p e) 负责把台车拉向目标,(K_v\dot{x}) 是速度阻尼,(K_\theta\theta) 根据当前摆角给出反向修正,(K_\omega\dot{\theta}) 起到压摆速的作用。四个增益的整定顺序与起始值如下:
| 增益 | 作用 | 首调范围 | 调参方向 |
|---|---|---|---|
| Kp | 台车定位刚度 | 0.6~1.5 | 到位太慢加 Kp |
| Kv | 台车速度阻尼 | 2~6 | 超调大加 Kv |
| Kθ | 摆角反馈增益 | 3~8 | 摆动幅度大加 Kθ |
| Kω | 摆角阻尼增益 | 0.5~2.5 | 高频微摆时加 Kω |
手动整定时先把 (K_\theta,K_\omega) 置零,调好台车位置环;再加入 (K_\theta),观察台车是否出现“先过头再拉回来”的周期性车摆现象,一旦出现就降低 (K_\theta)。最后加入 (K_\omega),把残余的持续微摆吸收掉。固定取 (K_p=1,K_v=3,K_\theta=5,K_\omega=1.2),在本模型参数下已经能得到较平滑的过渡过程。
4.3 用量化指标验证控制器,而不是只看波形图
整理报告时,控制效果不能只靠“看起来稳定”,要计算收敛时间和最大摆角。下面这段脚本用数组布尔运算完成指标提取:
xr = 1.0 # 目标位置 reach = np.abs(sol.y[0] - xr) < 0.02 swing = np.abs(sol.y[2]) < np.deg2rad(0.5) both = reach & swing time_idx = np.where(both)[0] if time_idx.size: ts = sol.t[time_idx[0]] theta_max = np.max(np.abs(sol.y[2])) print(f"settling_time = {ts:.2f} s, max_angle = {np.rad2deg(theta_max):.2f} deg") else: print("not settled within simulation horizon")判断逻辑中reach和swing必须同时成立,否则会出现“台车到位但摆角还很大”时误判收敛。每次收敛判定还要考虑持续性,更严谨的做法是检查索引之后 0.5 秒内条件是否仍然成立,防止某一瞬间误入阈值窗口被当成稳定点。
5. 把龙门吊车系统仿真作业整理进 zip 前的校验与交付要点
5.1 模型自检:先用阶跃输入检查开环响应
打包提交前先做一次开环阶跃试验:给台车施加一个 40 N 的恒定驱动力,持续 3 秒后清零。正常响应是台车持续加速,吊绳在启动瞬间向后拉出一个负角度,随后进入周期性摆动。如果摆角一开始就朝正方向飞出去,重点检查 2.3 节方程中 (F+ml\sin\theta,\dot{\theta}^2) 的正负号。
另一种有效的自检是把重力加速度设成 0。此时摆动力学退化为无恢复力结构,恒定力作用下台车应近似匀加速,摆角只能由初始角速度激发。这个测试可以隔离数值积分问题,帮助判断发散是来自模型还是来自求解器。
5.2 目录结构与“解压后能直接复现”的验证命令
作业收上去后,助教第一步就是解压 zip 再运行。减少沟通成本的关键是把目录整理成下面这种结构:
gantry_crane_2021/ ├── README.md ├── model/ │ ├── crane_sim.slx │ └── crane_sim.py ├── main.m ├── figs/ │ ├── open_loop.png │ ├── lqr_response.png │ └── pid_comparison.png └── report/ └── 系统仿真大作业报告.pdf打包前使用两条命令验证压缩包完整性:
python -m zipfile -l GantryCrane.zip unzip -t GantryCrane.zipzipfile -l会把内部文件清单全部打出来,检查有没有../这类危险路径;unzip -t做 CRC 校验,损坏文件会在这一步暴露。压缩包内第一层最好是一个文件夹而不是散落文件,README 里写明“双击 main.m 即可运行”,且main.m中只使用相对路径引用模型文件,避免写入固定的C:\Users\...绝对路径。
5.3 一个值得保留的验证技巧:把关键结果导出成 CSV
最后的进阶技巧是把仿真数据导出成 CSV 文件,而不是只保留图片。图表适合阅读,但从 CSV 可以随时用脚本重新计算收敛时间和最大摆角,不需要重新打开 Simulink。
writematrix([t, x, v, th, w], 'sim_results.csv');Python 脚本中等效写法是np.savetxt('sim_results.csv', np.column_stack((t, x, v, th, w)), delimiter=',')。把这份 CSV 放在result/文件夹里与图表并存,即使评审机器的 Simulink 版本不兼容,model/里的模型文件打不开,对方也能直接读数据文件验证曲线是否真实、参数是否合理。用于答疑时,这一份数据通常比模型截图更有说服力,因为曲线可以重新绘制,原始数据也不会因为渲染风格变化而失真。
本文还有配套的精品资源,点击获取