MATLAB仿真一级倒立摆程序
一级倒立摆系统数学模型
系统参数与变量
| 符号 | 含义 | 典型值/单位 |
|---|---|---|
| \(M\) | 小车质量 | 1.0 kg |
| \(m\) | 摆杆质量 | 0.1 kg |
| \(l\) | 摆杆长度 | 0.5 m |
| \(I\) | 摆杆转动惯量 | ( \(\frac{1}{12}ml^2\) ) |
| \(b\) | 小车摩擦系数 | 0.1 N·s/m |
| \(g\) | 重力加速度 | 9.81 m/s² |
| $x $ | 小车位置 | m |
| \(\theta\) | 摆杆角度(垂直向上为0) | rad |
| $F $ | 施加给小车的力 | N |
非线性动力学方程
通过拉格朗日法推导:
\(\begin{aligned} &(M+m)\ddot{x} + b\dot{x} + ml\ddot{\theta}\cos\theta - ml\dot{\theta}^2\sin\theta = F \\ &(I+ml^2)\ddot{\theta} + mgl\sin\theta + ml\ddot{x}\cos\theta = 0 \end{aligned}\)
线性化模型(在平衡点 (\theta \approx 0))
\(\begin{aligned} &\ddot{x} = \frac{-(I+ml^2)b}{p}\dot{x} + \frac{m^2gl^2}{p}\theta + \frac{I+ml^2}{p}F \\ &\ddot{\theta} = \frac{-mlb}{p}\dot{x} + \frac{mgl(M+m)}{p}\theta + \frac{ml}{p}F \end{aligned}\)
其中 \(p = (I+ml^2)(M+m) - m^2l^2\)
完整MATLAB仿真程序
1. 主仿真脚本
%% 一级倒立摆系统MATLAB仿真主程序
clear; clc; close all;
%% 1. 系统参数设置
params.M = 1.0; % 小车质量 (kg)
params.m = 0.1; % 摆杆质量 (kg)
params.l = 0.5; % 摆杆长度 (m)
params.g = 9.81; % 重力加速度 (m/s^2)
params.b = 0.1; % 小车摩擦系数 (N·s/m)
params.I = params.m * params.l^2 / 12; % 摆杆转动惯量
fprintf('========== 一级倒立摆仿真参数 ==========\n');
fprintf('小车质量 M = %.2f kg\n', params.M);
fprintf('摆杆质量 m = %.2f kg\n', params.m);
fprintf('摆杆长度 l = %.2f m\n', params.l);
fprintf('摩擦系数 b = %.2f N·s/m\n', params.b);
fprintf('=======================================\n\n');
%% 2. 线性化状态空间模型
[A, B, C, D] = linearize_inverted_pendulum(params);
% 显示系统特性
fprintf('系统特征值:\n');
eig_val = eig(A);
disp(eig_val);
% 检查能控性
Co = ctrb(A, B);
rank_Co = rank(Co);
if rank_Co == size(A, 1)
fprintf('系统完全能控 (能控性秩 = %d)\n', rank_Co);
else
fprintf('系统不完全能控 (能控性秩 = %d)\n', rank_Co);
end
%% 3. 控制器设计
% 状态向量: x = [小车位置; 小车速度; 摆杆角度; 摆杆角速度]
% = [x; dx/dt; theta; dtheta/dt]
% 3.1 LQR控制器设计
Q = diag([10, 1, 100, 1]); % 状态权重矩阵
R = 0.1; % 控制输入权重
[K_lqr, S, E] = lqr(A, B, Q, R);
fprintf('\nLQR控制器增益 K = [');
fprintf('%.2f ', K_lqr);
fprintf(']\n');
% 3.2 PID控制器参数(用于对比)
Kp_theta = 50; % 角度比例增益
Ki_theta = 5; % 角度积分增益
Kd_theta = 10; % 角度微分增益
Kp_x = 2; % 位置比例增益
Ki_x = 0.1; % 位置积分增益
Kd_x = 5; % 位置微分增益
%% 4. 非线性系统仿真
% 4.1 初始条件
x0 = [0; 0; deg2rad(10); 0]; % 初始角度10度
% 4.2 仿真时间
tspan = [0 10]; % 仿真10秒
% 4.3 选择控制器类型
controller_type = 'LQR'; % 可选 'LQR' 或 'PID'
% 4.4 运行仿真
fprintf('\n开始非线性仿真...\n');
options = odeset('RelTol', 1e-6, 'AbsTol', 1e-9);
[t_nl, x_nl] = ode45(@(t,x) inverted_pendulum_dynamics(t, x, params, K_lqr, controller_type), tspan, x0, options);
% 提取状态变量
x_pos = x_nl(:, 1); % 小车位置
x_vel = x_nl(:, 2); % 小车速度
theta = rad2deg(x_nl(:, 3)); % 摆杆角度(度)
theta_vel = rad2deg(x_nl(:, 4)); % 摆杆角速度(度/秒)
%% 5. 线性系统仿真(用于对比)
fprintf('开始线性仿真...\n');
% 闭环系统矩阵
A_cl = A - B * K_lqr;
sys_cl = ss(A_cl, zeros(4,1), eye(4), zeros(4,1));
[Y_lin, T_lin, X_lin] = initial(sys_cl, x0, tspan(2));
%% 6. 可视化结果
figure('Position', [100, 100, 1200, 800]);
% 6.1 状态响应对比
subplot(3, 2, 1);
plot(t_nl, x_pos, 'b-', 'LineWidth', 2);
hold on;
plot(T_lin, X_lin(:,1), 'r--', 'LineWidth', 1.5);
grid on;
xlabel('时间 (s)');
ylabel('小车位置 (m)');
title('小车位置响应');
legend('非线性模型', '线性模型');
xlim([0 tspan(2)]);
subplot(3, 2, 2);
plot(t_nl, theta, 'b-', 'LineWidth', 2);
hold on;
plot(T_lin, rad2deg(X_lin(:,3)), 'r--', 'LineWidth', 1.5);
grid on;
xlabel('时间 (s)');
ylabel('摆杆角度 (°)');
title('摆杆角度响应');
legend('非线性模型', '线性模型');
xlim([0 tspan(2)]);
ylim([-15 15]);
% 6.2 相平面图
subplot(3, 2, 3);
plot(theta, theta_vel, 'b-', 'LineWidth', 1.5);
hold on;
plot(rad2deg(X_lin(:,3)), rad2deg(X_lin(:,4)), 'r--', 'LineWidth', 1.5);
grid on;
xlabel('角度 θ (°)');
ylabel('角速度 dθ/dt (°/s)');
title('相平面图 (角度 vs 角速度)');
legend('非线性模型', '线性模型');
% 6.3 控制力
subplot(3, 2, 4);
% 计算控制力
F_control = zeros(length(t_nl), 1);
for i = 1:length(t_nl)
if strcmp(controller_type, 'LQR')
F_control(i) = -K_lqr * x_nl(i, :)';
else
% PID控制力计算
F_control(i) = calculate_pid_control(x_nl(i, :)', t_nl(i), Kp_theta, Ki_theta, Kd_theta, Kp_x, Ki_x, Kd_x);
end
end
plot(t_nl, F_control, 'b-', 'LineWidth', 2);
grid on;
xlabel('时间 (s)');
ylabel('控制力 F (N)');
title('控制力变化');
xlim([0 tspan(2)]);
% 6.4 能量分析
subplot(3, 2, 5);
% 计算系统总能量
E_total = zeros(length(t_nl), 1);
for i = 1:length(t_nl)
E_total(i) = calculate_total_energy(x_nl(i, :)', params);
end
plot(t_nl, E_total, 'b-', 'LineWidth', 2);
grid on;
xlabel('时间 (s)');
ylabel('总能量 (J)');
title('系统总能量变化');
xlim([0 tspan(2)]);
% 6.5 动画演示按钮
subplot(3, 2, 6);
axis off;
text(0.1, 0.7, '仿真控制选项:', 'FontSize', 12, 'FontWeight', 'bold');
uicontrol('Style', 'pushbutton', 'String', '播放动画', ...
'Position', [50 100 100 30], ...
'Callback', @(src,event) animate_pendulum(t_nl, x_nl, params));
%% 7. 性能指标计算
fprintf('\n========== 性能指标 ==========\n');
% 调节时间 (2%误差带)
theta_final = theta(end);
theta_settled = find(abs(theta - theta_final) > 0.02*abs(theta(1)-theta_final), 1, 'last');
if ~isempty(theta_settled)
settling_time = t_nl(theta_settled);
fprintf('调节时间 (2%%): %.3f s\n', settling_time);
else
fprintf('调节时间 (2%%): < %.3f s\n', t_nl(1));
end
% 超调量
[theta_peak, idx_peak] = max(abs(theta));
overshoot = (theta_peak - abs(theta_final)) / abs(theta(1)) * 100;
fprintf('角度超调量: %.2f%%\n', overshoot);
% 控制力统计
fprintf('最大控制力: %.3f N\n', max(abs(F_control)));
fprintf('平均控制力: %.3f N\n', mean(abs(F_control)));
%% 8. 鲁棒性分析
fprintf('\n========== 鲁棒性分析 ==========\n');
% 参数变化分析
param_variations = 0.8:0.1:1.2; % 参数变化范围
stability_margin = zeros(length(param_variations), 1);
for i = 1:length(param_variations)
params_test = params;
params_test.m = params.m * param_variations(i); % 改变摆杆质量
[A_test, B_test] = linearize_inverted_pendulum(params_test);
A_cl_test = A_test - B_test * K_lqr;
eig_test = max(real(eig(A_cl_test)));
stability_margin(i) = -eig_test; % 稳定裕度
end
figure('Name', '参数鲁棒性分析');
plot(param_variations, stability_margin, 'bo-', 'LineWidth', 2);
grid on;
xlabel('参数变化系数');
ylabel('稳定裕度');
title('控制器对摆杆质量变化的鲁棒性');
2. 核心函数定义
%% 线性化模型函数
function [A, B, C, D] = linearize_inverted_pendulum(params)
% 一级倒立摆线性化状态空间模型
% 状态: x = [位置; 速度; 角度; 角速度]
M = params.M;
m = params.m;
l = params.l;
g = params.g;
b = params.b;
I = params.I;
% 计算中间变量
p = (I + m*l^2)*(M + m) - (m*l)^2;
% 状态空间矩阵 A
A = zeros(4, 4);
A(1, 2) = 1;
A(2, 1) = 0;
A(2, 2) = -(I + m*l^2)*b / p;
A(2, 3) = (m^2 * g * l^2) / p;
A(3, 4) = 1;
A(4, 1) = 0;
A(4, 2) = -(m*l*b) / p;
A(4, 3) = (m*g*l*(M + m)) / p;
% 输入矩阵 B
B = zeros(4, 1);
B(2, 1) = (I + m*l^2) / p;
B(4, 1) = (m*l) / p;
% 输出矩阵 C (全状态输出)
C = eye(4);
% 直接传输矩阵 D
D = zeros(4, 1);
end
%% 非线性动力学方程
function dxdt = inverted_pendulum_dynamics(t, x, params, K, controller_type)
% 一级倒立摆非线性动力学方程
% x: 状态向量 [位置; 速度; 角度; 角速度]
% 提取参数
M = params.M;
m = params.m;
l = params.l;
g = params.g;
b = params.b;
I = params.I;
% 提取状态变量
x_pos = x(1); % 小车位置
x_dot = x(2); % 小车速度
theta = x(3); % 摆杆角度
theta_dot = x(4); % 摆杆角速度
% 根据控制器类型计算控制力
if strcmp(controller_type, 'LQR')
% LQR控制
F = -K * x;
else
% PID控制
F = calculate_pid_control(x, t, 50, 5, 10, 2, 0.1, 5);
end
% 非线性动力学方程
denom = (M + m)*(I + m*l^2) - (m*l*cos(theta))^2;
dxdt = zeros(4, 1);
% 小车加速度
dxdt(1) = x_dot;
dxdt(2) = (F - b*x_dot + m*l*theta_dot^2*sin(theta) ...
- m*g*l*sin(theta)*cos(theta)/(l)) / denom * (I + m*l^2);
% 摆杆角加速度
dxdt(3) = theta_dot;
dxdt(4) = (m*l*cos(theta)*(F - b*x_dot) ...
+ (M + m)*m*g*l*sin(theta) ...
- (m*l)^2*theta_dot^2*sin(theta)*cos(theta)) / (denom*l);
end
%% PID控制器函数
function F = calculate_pid_control(x, t, Kp_theta, Ki_theta, Kd_theta, Kp_x, Ki_x, Kd_x)
% PID控制器计算
persistent integral_theta integral_x prev_theta_error prev_x_error prev_t
% 初始化持久变量
if isempty(integral_theta) || t == 0
integral_theta = 0;
integral_x = 0;
prev_theta_error = 0;
prev_x_error = 0;
prev_t = 0;
end
% 期望值
theta_desired = 0; % 希望摆杆垂直向上
x_desired = 0; % 希望小车在原点
% 当前状态
x_pos = x(1);
theta = x(3);
% 计算误差
theta_error = theta_desired - theta;
x_error = x_desired - x_pos;
% 积分项更新
dt = t - prev_t;
if dt > 0
integral_theta = integral_theta + theta_error * dt;
integral_x = integral_x + x_error * dt;
end
% 微分项
if dt > 0
dtheta_error = (theta_error - prev_theta_error) / dt;
dx_error = (x_error - prev_x_error) / dt;
else
dtheta_error = 0;
dx_error = 0;
end
% PID控制力
F_theta = Kp_theta * theta_error + Ki_theta * integral_theta + Kd_theta * dtheta_error;
F_x = Kp_x * x_error + Ki_x * integral_x + Kd_x * dx_error;
% 总控制力
F = F_theta + F_x;
% 控制力限幅
F_max = 20; % 最大控制力
if F > F_max
F = F_max;
elseif F < -F_max
F = -F_max;
end
% 更新持久变量
prev_theta_error = theta_error;
prev_x_error = x_error;
prev_t = t;
end
%% 能量计算函数
function E = calculate_total_energy(x, params)
% 计算系统总能量
m = params.m;
M = params.M;
l = params.l;
g = params.g;
x_pos = x(1);
x_dot = x(2);
theta = x(3);
theta_dot = x(4);
% 动能
T = 0.5 * M * x_dot^2 + ...
0.5 * m * (x_dot^2 + l^2 * theta_dot^2 + 2 * x_dot * l * theta_dot * cos(theta));
% 势能
V = m * g * l * (1 - cos(theta));
% 总能量
E = T + V;
end
%% 动画演示函数
function animate_pendulum(t, x, params)
% 创建动画窗口
fig_anim = figure('Name', '倒立摆动画演示', 'Position', [200, 200, 800, 600]);
% 设置动画参数
l = params.l;
cart_width = 0.2;
cart_height = 0.1;
% 动画循环
for i = 1:10:length(t)
clf;
% 小车位置和摆杆角度
x_pos = x(i, 1);
theta = x(i, 3);
% 计算摆杆端点坐标
pendulum_x = x_pos + l * sin(theta);
pendulum_y = l * cos(theta);
% 绘制轨道
plot([-2, 2], [0, 0], 'k-', 'LineWidth', 2);
hold on;
% 绘制小车
rectangle('Position', [x_pos - cart_width/2, -cart_height/2, cart_width, cart_height], ...
'FaceColor', [0.2, 0.6, 0.8], 'EdgeColor', 'k', 'LineWidth', 2);
% 绘制摆杆
plot([x_pos, pendulum_x], [0, pendulum_y], 'r-', 'LineWidth', 3);
% 绘制摆锤
plot(pendulum_x, pendulum_y, 'ko', 'MarkerSize', 15, 'MarkerFaceColor', 'r');
% 设置图形属性
axis equal;
xlim([-2, 2]);
ylim([-0.5, 1.5]);
grid on;
title(sprintf('一级倒立摆动画 (t = %.2f s)', t(i)));
xlabel('位置 (m)');
ylabel('高度 (m)');
% 显示状态信息
text(-1.8, 1.3, sprintf('小车位置: %.3f m', x_pos));
text(-1.8, 1.2, sprintf('摆杆角度: %.1f°', rad2deg(theta)));
drawnow;
% 控制动画速度
pause(0.01);
end
end
3. Simulink模型(可选)
%% 创建Simulink模型(如果在MATLAB中运行)
function create_simulink_model()
% 创建新的Simulink模型
model_name = 'InvertedPendulum_Simulink';
new_system(model_name);
open_system(model_name);
% 添加模块
% 1. 状态空间模块
add_block('simulink/Continuous/State-Space', [model_name '/Pendulum Model']);
% 2. LQR控制器
add_block('simulink/Math Operations/Gain', [model_name '/LQR Gain']);
% 3. 示波器
add_block('simulink/Sinks/Scope', [model_name '/Scope']);
% 4. 输入源
add_block('simulink/Sources/Step', [model_name '/Step Input']);
% 连接模块
add_line(model_name, 'Step Input/1', 'LQR Gain/1');
add_line(model_name, 'LQR Gain/1', 'Pendulum Model/1');
add_line(model_name, 'Pendulum Model/1', 'Scope/1');
% 保存模型
save_system(model_name);
end
仿真结果分析要点
控制器性能对比
| 控制器类型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| LQR | 全局最优,理论保证稳定 | 需要精确模型,参数整定复杂 | 精确模型已知的系统 |
| PID | 简单易实现,鲁棒性好 | 多变量耦合处理困难 | 初步调试和教学演示 |
| 滑模控制 | 强鲁棒性,抗干扰 | 存在抖振现象 | 存在参数不确定性和干扰 |
参数整定建议
-
LQR权重矩阵:
- 加大Q(3,3)(角度权重)→ 摆杆更快稳定
- 加大R值 → 减小控制力,但响应变慢
- 典型初值:\(Q = diag([1, 0.1, 10, 0.1]), R = 0.1\)
-
PID参数:
- 先调角度环(\(Kp_theta\)),再调位置环(\(Kp_x\))
- 积分项防止稳态误差,但可能引起振荡
- 微分项抑制超调,但对噪声敏感
参考代码 一级倒立摆MATLAB仿真程序 www.3dddown.com/cnb/97769.html
扩展功能建议
- 鲁棒控制:添加参数不确定性分析
- 自适应控制:在线调整控制器参数
- 神经网络控制:使用深度学习补偿非线性
- 硬件在环:连接实际倒立摆硬件
- 能量控制:基于能量整形的控制器设计
浙公网安备 33010602011771号