% 飞机纵向飞行控制系统设计与仿真(波音737-800配置)
clear; close all; clc;
%% ======================== 1. 参数配置 ========================
params = struct(...
'aircraft', struct(...
'M_alpha', -1.2, 'M_q', -1.5, 'M_delta_e', -0.5, ...
'Z_alpha', -4.0, 'Z_q', -0.3, 'Z_delta_e', -0.2, ...
'Z_delta_th', 0.5, ... % 油门控制参数
'Xu', -0.05, 'Zu', -0.1, 'Xw', 0.1, 'Zw', -0.5), ... % 新增气动参数
'flight', struct(...
'V', 100, 'g', 9.81, 't_sim', linspace(0, 60, 600), ...
'rho', 1.225, 'S', 124.6, 'c', 4.17), ... % 新增空气动力学参数
'control', struct(...
'ref_pitch', 5, 'ref_speed', 100, ...
'Kp_pitch', 0.8, 'Ki_pitch', 0.15, 'Kd_pitch', 0.3, ... % 优化PID参数
'Kp_speed', 0.4, 'Ki_speed', 0.08, 'Kd_speed', 0.15, ...
'tau', 0.1), ... % 滤波器时间常数
'matlab_version', version('-release'));
%% ======================== 2. 构建状态空间模型 ========================
V_flight = params.flight.V;
g = params.flight.g;
M_alpha = params.aircraft.M_alpha;
M_q = params.aircraft.M_q;
M_delta_e = params.aircraft.M_delta_e;
Z_alpha = params.aircraft.Z_alpha;
Z_q = params.aircraft.Z_q;
Z_delta_e = params.aircraft.Z_delta_e;
Z_delta_th = params.aircraft.Z_delta_th;
Xu = params.aircraft.Xu;
Zu = params.aircraft.Zu;
Xw = params.aircraft.Xw;
Zw = params.aircraft.Zw;
% 状态变量: [u, w, q, theta]^T
% u: 前进速度变化, w: 法向速度变化, q: 俯仰角速率, theta: 俯仰角
A = [Xu, Xw, 0, -g*cosd(0);
Zu, Zw, V_flight, -g*sind(0);
0, 0, M_q, 0;
0, 0, 1, 0];
B = [0, Z_delta_th;
Z_delta_e, 0;
M_delta_e, 0;
0, 0];
C = [0 0 0 1; % 俯仰角输出
1 0 0 0]; % 速度输出
D = zeros(2,2);
sys = ss(A, B, C, D);
%% ======================== 3. PID控制器设计 ========================
fprintf('\nPID控制器参数:\n');
fprintf('俯仰角控制: Kp=%.2f, Ki=%.2f, Kd=%.2f\n', ...
params.control.Kp_pitch, params.control.Ki_pitch, params.control.Kd_pitch);
fprintf('速度控制: Kp=%.2f, Ki=%.2f, Kd=%.2f\n', ...
params.control.Kp_speed, params.control.Ki_speed, params.control.Kd_speed);
%% ======================== 4. 仿真与轨迹计算 ========================
t = params.flight.t_sim;
dt = t(2) - t(1);
% 初始化状态
x = [0; 0; 0; 0]; % [u; w; q; theta]
x_closed = zeros(length(t), 4);
u = zeros(length(t), 2); % [升降舵偏角; 油门]
% PID控制器变量
integral_pitch = 0;
integral_speed = 0;
prev_error_pitch = 0;
prev_error_speed = 0;
prev_derivative_pitch = 0;
prev_derivative_speed = 0;
% 低通滤波器参数
alpha = dt / (params.control.tau + dt);
for i = 1:length(t)
% 当前输出
y = C * x;
pitch = y(1);
speed = V_flight + y(2); % 绝对速度 = 初始速度 + 速度变化
% 参考信号
ref_pitch = params.control.ref_pitch;
ref_speed = params.control.ref_speed;
% 误差计算
error_pitch = ref_pitch - pitch;
error_speed = ref_speed - speed;
% PID控制器计算(带滤波和抗饱和)
% 俯仰角控制(使用升降舵)
integral_pitch = integral_pitch + error_pitch * dt;
derivative_pitch = (error_pitch - prev_error_pitch) / dt;
% 应用低通滤波器
filtered_derivative_pitch = alpha * derivative_pitch + (1-alpha) * prev_derivative_pitch;
delta_e = params.control.Kp_pitch * error_pitch + ...
params.control.Ki_pitch * integral_pitch + ...
params.control.Kd_pitch * filtered_derivative_pitch;
% 速度控制(使用油门)
integral_speed = integral_speed + error_speed * dt;
derivative_speed = (error_speed - prev_error_speed) / dt;
% 应用低通滤波器
filtered_derivative_speed = alpha * derivative_speed + (1-alpha) * prev_derivative_speed;
delta_th = params.control.Kp_speed * error_speed + ...
params.control.Ki_speed * integral_speed + ...
params.control.Kd_speed * filtered_derivative_speed;
% 更新误差和微分历史
prev_error_pitch = error_pitch;
prev_error_speed = prev_error_speed;
prev_derivative_pitch = filtered_derivative_pitch;
prev_derivative_speed = filtered_derivative_speed;
% 输入限幅和抗饱和处理
delta_e = max(min(delta_e, 25), -25); % 升降舵偏角限制在±25度
delta_th = max(min(delta_th, 1), 0); % 油门限制在0-1
% 积分抗饱和
if delta_e >= 25 || delta_e <= -25
integral_pitch = integral_pitch - error_pitch * dt;
end
if delta_th >= 1 || delta_th <= 0
integral_speed = integral_speed - error_speed * dt;
end
% 状态更新(使用ode45提高精度)
[~, x_temp] = ode45(@(t,x) A*x + B*[delta_e; delta_th], [0 dt], x);
x = x_temp(end, :)';
% 保存结果
x_closed(i, :) = x';
u(i, :) = [delta_e, delta_th];
end
% 轨迹积分计算
gamma = atan2d(x_closed(:,2), V_flight + x_closed(:,1)); % 航迹角
V_total = sqrt((V_flight + x_closed(:,1)).^2 + x_closed(:,2).^2); % 总速度
% 位置计算(仅用于性能分析,不显示)
x_pos = cumtrapz(t, V_total .* cosd(gamma));
z_pos = cumtrapz(t, V_total .* sind(gamma));
y_pos = zeros(size(t)); % 无侧向运动
%% ======================== 5. 创建主控制窗口 ========================
control_fig = figure('Position', [100, 100, 1000, 800], 'Name', '飞行控制面板');
set(control_fig, 'Color', [0.95 0.95 0.95]);
% --- 创建滑块控件 ---
uicontrol('Style', 'text', 'Position', [820 750 150 20],...
'String', '俯仰角参考值 (度)', 'BackgroundColor', [0.95 0.95 0.95]);
slider_pitch = uicontrol('Style', 'slider', 'Position', [820 720 150 20],...
'Min', -10, 'Max', 20, 'Value', params.control.ref_pitch,...
'Callback', @update_reference);
uicontrol('Style', 'text', 'Position', [820 680 150 20],...
'String', '速度参考值 (m/s)', 'BackgroundColor', [0.95 0.95 0.95]);
slider_speed = uicontrol('Style', 'slider', 'Position', [820 650 150 20],...
'Min', 80, 'Max', 150, 'Value', params.control.ref_speed,...
'Callback', @update_reference);
% PID参数调整滑块
uicontrol('Style', 'text', 'Position', [820 550 150 20],...
'String', '俯仰角Kp', 'BackgroundColor', [0.95 0.95 0.95]);
slider_Kp_pitch = uicontrol('Style', 'slider', 'Position', [820 520 150 20],...
'Min', 0, 'Max', 2, 'Value', params.control.Kp_pitch,...
'Callback', @update_pid);
uicontrol('Style', 'text', 'Position', [820 480 150 20],...
'String', '速度Kp', 'BackgroundColor', [0.95 0.95 0.95]);
slider_Kp_speed = uicontrol('Style', 'slider', 'Position', [820 450 150 20],...
'Min', 0, 'Max', 2, 'Value', params.control.Kp_speed,...
'Callback', @update_pid);
% --- 使用3x2网格布局 ---
% 高度变化
ax_height = subplot(3,2,1);
grid on; hold on;
title('高度变化'); xlabel('时间 (s)'); ylabel('高度 (m)');
h_height = plot(t, z_pos, 'r-', 'LineWidth', 1.5);
% 俯仰角变化
ax_pitch = subplot(3,2,2);
grid on; hold on;
title('俯仰角变化'); xlabel('时间 (s)'); ylabel('俯仰角 (度)');
h_pitch = plot(t, x_closed(:,4), 'g-', 'LineWidth', 1.5); % 第4个状态为俯仰角
h_ref_pitch = plot([t(1) t(end)], [params.control.ref_pitch params.control.ref_pitch], 'g--');
legend('实际值', '参考值');
% 攻角变化
ax_alpha = subplot(3,2,3);
grid on; hold on;
title('攻角变化'); xlabel('时间 (s)'); ylabel('攻角 (度)');
h_alpha = plot(t, atan2d(x_closed(:,2), V_flight + x_closed(:,1)), 'm-', 'LineWidth', 1.5);
% 速度变化
ax_speed = subplot(3,2,4);
grid on; hold on;
title('速度变化'); xlabel('时间 (s)'); ylabel('速度 (m/s)');
h_speed = plot(t, V_total, 'b-', 'LineWidth', 1.5);
h_ref_speed = plot([t(1) t(end)], [params.control.ref_speed params.control.ref_speed], 'b--');
legend('实际值', '参考值');
% 控制输入
ax_elevator = subplot(3,2,5);
grid on; hold on;
title('控制输入'); xlabel('时间 (s)'); ylabel('值');
h_elevator = plot(t, u(:,1), 'k-', 'LineWidth', 1.5, 'DisplayName', '升降舵');
h_throttle = plot(t, u(:,2), 'c-', 'LineWidth', 1.5, 'DisplayName', '油门');
legend('Location', 'best');
% 创建导出Simulink PID模型按钮
uicontrol('Style', 'pushbutton', 'Position', [820 350 150 30],...
'String', '导出Simulink PID模型', 'Callback', @export_simulink_pid);
% 创建导出完整Simulink模型按钮
uicontrol('Style', 'pushbutton', 'Position', [820 300 150 30],...
'String', '导出完整Simulink模型', 'Callback', @export_complete_model);
% 保存图形句柄
handles = struct(...
'control_fig', control_fig, ...
'h_height', h_height, 'h_pitch', h_pitch, 'h_alpha', h_alpha, ...
'h_speed', h_speed, 'h_elevator', h_elevator, 'h_throttle', h_throttle, ...
'h_ref_pitch', h_ref_pitch, 'h_ref_speed', h_ref_speed, ...
'x_pos', x_pos, 'y_pos', y_pos, 'z_pos', z_pos, 't', t, ...
'x_closed', x_closed, 'u', u, ...
'params', params, ...
'A', A, 'B', B, 'C', C, 'D', D, ... % 保存系统矩阵
'slider_pitch', slider_pitch, 'slider_speed', slider_speed, ...
'slider_Kp_pitch', slider_Kp_pitch, 'slider_Kp_speed', slider_Kp_speed ...
);
set(control_fig, 'UserData', handles);
% 设置关闭函数
set(control_fig, 'CloseRequestFcn', @(src,~) close_simulation(src));
%% ======================== 6. 回调函数 ========================
function update_reference(src, ~)
fig_handle = ancestor(src, 'figure');
handles = get(fig_handle, 'UserData');
% 获取新参考值
ref_pitch = get(handles.slider_pitch, 'Value');
ref_speed = get(handles.slider_speed, 'Value');
% 更新参考信号
t = handles.t;
dt = t(2) - t(1);
% 初始化状态
x = [0; 0; 0; 0];
% 初始化PID控制器变量
integral_pitch = 0;
integral_speed = 0;
prev_error_pitch = 0;
prev_error_speed = 0;
% 预分配存储
x_closed = zeros(length(t), 4);
u = zeros(length(t), 2);
for i = 1:length(t)
% 当前输出
y = handles.C * x;
pitch = y(1);
speed = handles.params.flight.V + y(2);
% 误差计算
error_pitch = ref_pitch - pitch;
error_speed = ref_speed - speed;
% PID控制器计算
integral_pitch = integral_pitch + error_pitch * dt;
derivative_pitch = (error_pitch - prev_error_pitch) / dt;
delta_e = handles.params.control.Kp_pitch * error_pitch + ...
handles.params.control.Ki_pitch * integral_pitch + ...
handles.params.control.Kd_pitch * derivative_pitch;
integral_speed = integral_speed + error_speed * dt;
derivative_speed = (error_speed - prev_error_speed) / dt;
delta_th = handles.params.control.Kp_speed * error_speed + ...
handles.params.control.Ki_speed * integral_speed + ...
handles.params.control.Kd_speed * derivative_speed;
% 更新误差
prev_error_pitch = error_pitch;
prev_error_speed = error_speed;
% 输入限幅
delta_e = max(min(delta_e, 25), -25);
delta_th = max(min(delta_th, 1), 0);
% 状态更新
dx = handles.A * x + handles.B * [delta_e; delta_th];
x = x + dx * dt;
% 保存结果
x_closed(i, :) = x';
u(i, :) = [delta_e, delta_th];
end
% 重新计算轨迹
gamma = atan2d(x_closed(:,2), handles.params.flight.V + x_closed(:,1));
V_total = sqrt((handles.params.flight.V + x_closed(:,1)).^2 + x_closed(:,2).^2);
z_pos = cumtrapz(t, V_total .* sind(gamma));
x_pos = cumtrapz(t, V_total .* cosd(gamma));
% 更新图形数据
set(handles.h_height, 'YData', z_pos);
set(handles.h_pitch, 'YData', x_closed(:,4));
set(handles.h_ref_pitch, 'YData', [ref_pitch, ref_pitch]);
set(handles.h_alpha, 'YData', atan2d(x_closed(:,2), handles.params.flight.V + x_closed(:,1)));
set(handles.h_speed, 'YData', V_total);
set(handles.h_ref_speed, 'YData', [ref_speed, ref_speed]);
set(handles.h_elevator, 'YData', u(:,1));
set(handles.h_throttle, 'YData', u(:,2));
% 更新存储数据
handles.x_closed = x_closed;
handles.u = u;
handles.x_pos = x_pos;
handles.z_pos = z_pos;
set(fig_handle, 'UserData', handles);
fprintf('参考值更新: 俯仰角=%.1f°, 速度=%.1fm/s\n', ref_pitch, ref_speed);
end
function update_pid(src, ~)
fig_handle = ancestor(src, 'figure');
handles = get(fig_handle, 'UserData');
% 获取新PID参数
Kp_pitch = get(handles.slider_Kp_pitch, 'Value');
Kp_speed = get(handles.slider_Kp_speed, 'Value');
% 更新PID参数
handles.params.control.Kp_pitch = Kp_pitch;
handles.params.control.Kp_speed = Kp_speed;
% 重新运行仿真
update_reference(handles.slider_pitch, []);
fprintf('PID参数更新: Kp_pitch=%.2f, Kp_speed=%.2f\n', Kp_pitch, Kp_speed);
end
function export_simulink_pid(src, ~)
fig_handle = ancestor(src, 'figure');
handles = get(fig_handle, 'UserData');
% 创建新的Simulink模型
model_name = 'Boeing737_PID_Controller';
new_system(model_name);
open_system(model_name);
% 添加PID控制器模块 - 使用正确的模块名称
pitch_pid_pos = [100, 100, 200, 150];
speed_pid_pos = [100, 200, 200, 250];
% 俯仰角PID控制器
pitch_pid = add_block('simulink/Continuous/PID Controller', [model_name '/Pitch_PID'], ...
'Position', pitch_pid_pos, ...
'P', num2str(handles.params.control.Kp_pitch), ...
'I', num2str(handles.params.control.Ki_pitch), ...
'D', num2str(handles.params.control.Kd_pitch), ...
'Name', '俯仰角PID');
% 速度PID控制器
speed_pid = add_block('simulink/Continuous/PID Controller', [model_name '/Speed_PID'], ...
'Position', speed_pid_pos, ...
'P', num2str(handles.params.control.Kp_speed), ...
'I', num2str(handles.params.control.Ki_speed), ...
'D', num2str(handles.params.control.Kd_speed), ...
'Name', '速度PID');
% 添加输入端口
pitch_ref = add_block('simulink/Sources/In1', [model_name '/Pitch_Ref'], ...
'Position', [50, 100, 80, 120], 'Name', '俯仰角参考');
speed_ref = add_block('simulink/Sources/In1', [model_name '/Speed_Ref'], ...
'Position', [50, 200, 80, 220], 'Name', '速度参考');
actual_pitch = add_block('simulink/Sources/In1', [model_name '/Actual_Pitch'], ...
'Position', [50, 150, 80, 170], 'Name', '实际俯仰角');
actual_speed = add_block('simulink/Sources/In1', [model_name '/Actual_Speed'], ...
'Position', [50, 250, 80, 270], 'Name', '实际速度');
% 添加输出端口
elevator_cmd = add_block('simulink/Sinks/Out1', [model_name '/Elevator_Cmd'], ...
'Position', [300, 100, 330, 120], 'Name', '升降舵指令');
throttle_cmd = add_block('simulink/Sinks/Out1', [model_name '/Throttle_Cmd'], ...
'Position', [300, 200, 330, 220], 'Name', '油门指令');
% 添加求和模块
sum_pitch = add_block('simulink/Math Operations/Sum', [model_name '/Sum_Pitch'], ...
'Position', [150, 100, 180, 130], 'IconShape', 'rectangular', ...
'Inputs', '|+-');
sum_speed = add_block('simulink/Math Operations/Sum', [model_name '/Sum_Speed'], ...
'Position', [150, 200, 180, 230], 'IconShape', 'rectangular', ...
'Inputs', '|+-');
% 连接模块 - 使用句柄而不是字符串名称
add_line(model_name, [getfullname(pitch_ref) '/1'], [getfullname(sum_pitch) '/1']);
add_line(model_name, [getfullname(actual_pitch) '/1'], [getfullname(sum_pitch) '/2']);
add_line(model_name, [getfullname(sum_pitch) '/1'], [getfullname(pitch_pid) '/1']);
add_line(model_name, [getfullname(pitch_pid) '/1'], [getfullname(elevator_cmd) '/1']);
add_line(model_name, [getfullname(speed_ref) '/1'], [getfullname(sum_speed) '/1']);
add_line(model_name, [getfullname(actual_speed) '/1'], [getfullname(sum_speed) '/2']);
add_line(model_name, [getfullname(sum_speed) '/1'], [getfullname(speed_pid) '/1']);
add_line(model_name, [getfullname(speed_pid) '/1'], [getfullname(throttle_cmd) '/1']);
% 保存并整理模型
save_system(model_name);
set_param(model_name, 'ZoomFactor', 'FitSystem');
fprintf('Simulink PID模型已导出: %s.slx\n', model_name);
fprintf('PID参数:\n');
fprintf(' 俯仰角控制: Kp=%.2f, Ki=%.2f, Kd=%.2f\n', ...
handles.params.control.Kp_pitch, ...
handles.params.control.Ki_pitch, ...
handles.params.control.Kd_pitch);
fprintf(' 速度控制: Kp=%.2f, Ki=%.2f, Kd=%.2f\n', ...
handles.params.control.Kp_speed, ...
handles.params.control.Ki_speed, ...
handles.params.control.Kd_speed);
end
function export_complete_model(src, ~)
fig_handle = ancestor(src, 'figure');
handles = get(fig_handle, 'UserData');
export_complete_simulink_model(handles);
end
function export_complete_simulink_model(handles)
% 创建新的Simulink模型
model_name = 'Boeing737_Longitudinal_Control';
new_system(model_name);
open_system(model_name);
% 设置模型参数
set_param(model_name, 'Solver', 'ode4', 'FixedStep', '0.01', 'StopTime', '60');
%% 添加飞机模型(状态空间)
aircraft_pos = [400, 100, 550, 250];
% 正确设置状态空间模型参数
aircraft_model = add_block('simulink/Continuous/State-Space', [model_name '/Aircraft_Model'], ...
'Position', aircraft_pos, ...
'A', mat2str(handles.A), ...
'B', mat2str(handles.B), ...
'C', mat2str(handles.C), ...
'D', mat2str(handles.D), ...
'X0', '[0;0;0;0]', ...
'Name', '飞机纵向模型');
%% 添加PID控制器 - 使用正确的模块名称
% 俯仰角PID
pitch_pid_pos = [200, 100, 300, 150];
pitch_pid = add_block('simulink/Continuous/PID Controller', [model_name '/Pitch_PID'], ...
'Position', pitch_pid_pos, ...
'P', num2str(handles.params.control.Kp_pitch), ...
'I', num2str(handles.params.control.Ki_pitch), ...
'D', num2str(handles.params.control.Kd_pitch), ...
'N', num2str(1/handles.params.control.tau), ...
'Name', '俯仰角PID');
% 速度PID
speed_pid_pos = [200, 200, 300, 250];
speed_pid = add_block('simulink/Continuous/PID Controller', [model_name '/Speed_PID'], ...
'Position', speed_pid_pos, ...
'P', num2str(handles.params.control.Kp_speed), ...
'I', num2str(handles.params.control.Ki_speed), ...
'D', num2str(handles.params.control.Kd_speed), ...
'N', num2str(1/handles.params.control.tau), ...
'Name', '速度PID');
%% 添加输入输出
% 参考信号
pitch_ref = add_block('simulink/Sources/Constant', [model_name '/Pitch_Ref'], ...
'Position', [50, 120, 80, 140], 'Value', num2str(handles.params.control.ref_pitch));
speed_ref = add_block('simulink/Sources/Constant', [model_name '/Speed_Ref'], ...
'Position', [50, 220, 80, 240], 'Value', num2str(handles.params.control.ref_speed));
% 输出显示
pitch_out = add_block('simulink/Sinks/Out1', [model_name '/Pitch_Out'], ...
'Position', [700, 120, 730, 140], 'Name', '俯仰角');
speed_out = add_block('simulink/Sinks/Out1', [model_name '/Speed_Out'], ...
'Position', [700, 170, 730, 190], 'Name', '速度');
elevator_out = add_block('simulink/Sinks/Out1', [model_name '/Elevator_Out'], ...
'Position', [700, 220, 730, 240], 'Name', '升降舵');
throttle_out = add_block('simulink/Sinks/Out1', [model_name '/Throttle_Out'], ...
'Position', [700, 270, 730, 290], 'Name', '油门');
% 添加示波器
scope = add_block('simulink/Sinks/Scope', [model_name '/Response_Scope'], ...
'Position', [600, 300, 650, 350]);
%% 添加求和模块
sum_pitch = add_block('simulink/Math Operations/Sum', [model_name '/Sum_Pitch'], ...
'Position', [150, 120, 180, 140], 'IconShape', 'rectangular', 'Inputs', '|+-');
sum_speed = add_block('simulink/Math Operations/Sum', [model_name '/Sum_Speed'], ...
'Position', [150, 220, 180, 240], 'IconShape', 'rectangular', 'Inputs', '|+-');
%% 添加速度转换模块
speed_add = add_block('simulink/Math Operations/Add', [model_name '/Speed_Add'], ...
'Position', [500, 170, 530, 190], 'Name', '速度转换');
v0 = add_block('simulink/Sources/Constant', [model_name '/V0'], ...
'Position', [450, 160, 480, 180], 'Value', num2str(handles.params.flight.V));
%% 连接所有模块 - 使用getfullname获取完整路径
% 参考信号连接
add_line(model_name, [getfullname(pitch_ref) '/1'], [getfullname(sum_pitch) '/1']);
add_line(model_name, [getfullname(speed_ref) '/1'], [getfullname(sum_speed) '/1']);
% 反馈连接
add_line(model_name, [getfullname(aircraft_model) '/1'], [getfullname(sum_pitch) '/2']);
add_line(model_name, [getfullname(aircraft_model) '/2'], [getfullname(speed_add) '/2']);
% PID连接
add_line(model_name, [getfullname(sum_pitch) '/1'], [getfullname(pitch_pid) '/1']);
add_line(model_name, [getfullname(sum_speed) '/1'], [getfullname(speed_pid) '/1']);
% 控制输入连接
add_line(model_name, [getfullname(pitch_pid) '/1'], [getfullname(aircraft_model) '/1']);
add_line(model_name, [getfullname(speed_pid) '/1'], [getfullname(aircraft_model) '/2']);
% 输出连接
add_line(model_name, [getfullname(aircraft_model) '/1'], [getfullname(pitch_out) '/1']);
add_line(model_name, [getfullname(speed_add) '/1'], [getfullname(speed_out) '/1']);
add_line(model_name, [getfullname(pitch_pid) '/1'], [getfullname(elevator_out) '/1']);
add_line(model_name, [getfullname(speed_pid) '/1'], [getfullname(throttle_out) '/1']);
% 速度转换连接
add_line(model_name, [getfullname(v0) '/1'], [getfullname(speed_add) '/1']);
% 示波器连接
add_line(model_name, [getfullname(pitch_ref) '/1'], [getfullname(scope) '/1']);
add_line(model_name, [getfullname(speed_ref) '/1'], [getfullname(scope) '/2']);
add_line(model_name, [getfullname(aircraft_model) '/1'], [getfullname(scope) '/3']);
add_line(model_name, [getfullname(speed_add) '/1'], [getfullname(scope) '/4']);
%% 添加模型注释
annotation_text = sprintf(['飞机纵向飞行控制系统\n', ...
'机型: 波音737-800\n', ...
'设计日期: %s\n', ...
'状态变量: [u, w, q, θ]\n', ...
'输入: [升降舵, 油门]'], datestr(now));
add_block('simulink/Note', [model_name '/Model_Info'], ...
'Position', [50, 300, 200, 350], 'Text', annotation_text);
% 保存并整理模型
save_system(model_name);
set_param(model_name, 'ZoomFactor', 'FitSystem');
fprintf('完整Simulink模型已导出: %s.slx\n', model_name);
fprintf('包含飞机模型和PID控制器\n');
end
function close_simulation(src, ~)
% 获取图形句柄
fig_handle = ancestor(src, 'figure');
handles = get(fig_handle, 'UserData');
% 关闭所有相关图形
if ishandle(handles.control_fig)
delete(handles.control_fig);
end
fprintf('仿真已关闭\n');
end
在matlabR2024a中出现
错误使用 LiveEditorEvaluationHelperE1200655152>export_simulink_pid (第 413 行)
Simulink 对象名称无效: 'Boeing737_PID_Controller/俯仰角参考/1'。
计算 UIControl Callback 时出错。
错误使用 LiveEditorEvaluationHelperE1200655152>export_complete_simulink_model (第 523 行)
Simulink 对象名称无效: 'Boeing737_Longitudinal_Control/Pitch_Ref/1'。
出错 LiveEditorEvaluationHelperE1200655152>export_complete_model (第 442 行)
export_complete_simulink_model(handles); - 显示完整堆栈跟踪
计算 UIControl Callback 时出错。
>>
如何修改
完整呈现代码