手把手教你用Matlab/Simulink搭建小车倒立摆模型(附动画脚本)

手把手教你用Matlab/Simulink搭建小车倒立摆模型(附动画脚本)

手把手教你用Matlab/Simulink搭建小车倒立摆模型(附动画脚本)

倒立摆系统作为控制理论中的经典案例,不仅在教学演示中具有重要地位,更是工程实践中验证控制算法的理想平台。本文将带你从零开始,一步步完成小车倒立摆的物理建模、Simulink仿真实现以及运动动画生成,无需任何前置经验,只需跟随操作即可获得直观的可视化结果。

1. 环境准备与基础建模

1.1 系统参数定义

首先在Matlab脚本中定义系统物理参数,建议使用.m脚本统一管理:

% 系统物理参数 M = 0.5; % 小车质量(kg) m = 0.2; % 摆杆质量(kg) b = 0.1; % 小车摩擦系数(N/m/s) l = 0.3; % 摆杆长度(m) g = 9.8; % 重力加速度(m/s^2)

1.2 动力学方程推导

采用拉格朗日法建立系统动力学方程。关键推导步骤如下:

  1. 建立系统动能表达式:

    • 小车平动动能:$T_c = \frac{1}{2}M\dot{x}^2$
    • 摆杆复合动能:$T_p = \frac{1}{2}m(\dot{x}_p^2 + \dot{y}_p^2)$
  2. 建立系统势能表达式:

    • $V = mgl\cosθ$
  3. 构造拉格朗日函数:

    • $L = T - V = (T_c + T_p) - V$

最终得到的非线性微分方程:

$$ \begin{cases} (M+m)\ddot{x} + ml\ddotθ\cosθ - ml\dotθ^2\sinθ + b\dot{x} = F \ ml\ddot{x}\cosθ + ml^2\ddotθ - mgl\sinθ = 0 \end{cases} $$

2. Simulink模型搭建

2.1 非线性模型实现

在Simulink中按照以下结构搭建模型:

[F] → [Sum] → [1/(M+m)] → [Integrator] → [Velocity] ↑ ↑ └── [Feedback Terms] ← [Theta Calculation]

具体操作步骤:

  1. 新建Blank Model,从Library Browser添加以下模块:

    • Integrator×4(分别对应x, dx, θ, dθ)
    • Gain(设置质量参数)
    • Trigonometric Function(处理sin/cos项)
    • Product(处理耦合项)
  2. 关键配置参数:

    % 在Model Properties → Callbacks中添加初始化代码 set_param(gcs, 'Solver', 'ode45'); set_param(gcs, 'StopTime', '10');

2.2 线性化模型对比

在工作空间生成线性化模型:

% 在平衡点附近线性化 [A,B,C,D] = linmod('InvertedPendulum_Nonlinear'); sys_linear = ss(A,B,C,D);

通过以下命令验证线性化效果:

% 对比非线性与线性响应 initial_angle = 0.1; % 小角度验证 simOut = sim('InvertedPendulum_Nonlinear'); figure; plot(simOut.tout, simOut.theta); hold on; [y,t] = initial(sys_linear, [0;0;initial_angle;0]); plot(t, y(:,2), '--'); legend('Nonlinear','Linearized');

3. 控制系统设计

3.1 LQR控制器实现

设计状态反馈控制器:

% 权重矩阵设置 Q = diag([10 1 100 10]); % 重点控制角度偏差 R = 0.01; % 控制输入权重 % LQR求解 [K, S, e] = lqr(A, B, Q, R); % 闭环系统验证 sys_cl = ss(A-B*K, B, C, D); step(sys_cl);

典型调试经验:

  • 若小车位移响应过慢,增加Q矩阵中x的权重
  • 若控制力过大,减小R值
  • 角度振荡时可调整dθ的权重

3.2 状态观测器设计

当只有角度可测量时,设计Kalman滤波器:

% 观测矩阵调整(假设仅测量角度) C_obs = [0 0 1 0]; D_obs = 0; % 噪声协方差矩阵 Vd = diag([0.1 0.1 0.5 0.5]); % 过程噪声 Vn = 0.01; % 测量噪声 % Kalman增益计算 [Kf,P,E] = lqe(A, eye(4), C_obs, Vd, Vn);

4. 动画可视化实现

4.1 实时动画脚本

创建animate_pendulum.m脚本:

function animate_pendulum(t, x, theta) figure; h1 = plot([0], [0], 'k-', 'LineWidth', 2); % 小车 hold on; h2 = plot([0], [0], 'r-o', 'LineWidth', 2); % 摆杆 axis([-2 2 -0.5 1.5]); for k = 1:length(t) % 小车位置更新 car_x = [x(k)-0.2 x(k)+0.2]; car_y = [0 0]; set(h1, 'XData', car_x, 'YData', car_y); % 摆杆位置更新 pend_x = [x(k) x(k)+l*sin(theta(k))]; pend_y = [0 l*cos(theta(k))]; set(h2, 'XData', pend_x, 'YData', pend_y); drawnow; pause(0.01); end end

4.2 仿真结果可视化

在Simulink模型最后添加To Workspace模块,导出仿真数据后调用动画函数:

% 运行仿真 simOut = sim('InvertedPendulum_Full'); % 提取数据 t = simOut.tout; x = simOut.x.Data; theta = simOut.theta.Data; % 生成动画 animate_pendulum(t, x, theta); % 保存为视频(需要Image Processing Toolbox) writerObj = VideoWriter('pendulum_animation.mp4', 'MPEG-4'); open(writerObj); for k = 1:10:length(t) frame = getframe(gcf); writeVideo(writerObj, frame); end close(writerObj);

5. 常见问题排查

调试过程中可能遇到的典型问题及解决方案:

现象可能原因解决方法
仿真发散初始角度过大限制初始角度<0.3rad
小车跑出视野位移未限制在LQR中增加x权重
动画卡顿步长过大减小Simulink Max Step Size
观测器偏差大噪声参数不匹配调整Vd和Vn矩阵

实际项目中发现,当摆杆长度超过0.5m时,需要重新调整控制器参数。一个实用的调试技巧是先用PID稳定角度,再切换为LQR控制。