ThreatSourceLibaray/docs/examples/Integration/matlab_example.m

277 lines
8.9 KiB
Matlab

%% Matlab/Simulink 威胁源库集成示例
% 演示如何在Matlab中使用ThreatSource仿真库
%
% 前置条件:
% 1. 将 ThreatSource.dll 复制到 Matlab 路径
% 2. 将 data/ 目录复制到当前工作目录
% 3. 确保 Matlab 支持 .NET 8.0
%% 清理环境
clear; clc; close all;
%% 加载 .NET 程序集
fprintf('正在加载 ThreatSource.dll...\n');
try
% 假设 dll 文件在当前目录或 Matlab 路径中
dll_path = 'ThreatSource.dll';
if ~exist(dll_path, 'file')
dll_path = fullfile(pwd, 'ThreatSource.dll');
end
if exist(dll_path, 'file')
NET.addAssembly(dll_path);
fprintf('成功加载威胁源库\n');
else
error('找不到 ThreatSource.dll 文件');
end
catch ME
fprintf('加载失败: %s\n', ME.message);
return;
end
%% 创建适配器实例
fprintf('创建 Matlab 适配器...\n');
try
% 注意:这里使用完整的命名空间路径
adapter = NET.createGeneric('MatlabSimulinkAdapter', {});
fprintf('适配器创建成功\n');
catch ME
fprintf('适配器创建失败: %s\n', ME.message);
return;
end
%% 初始化仿真
fprintf('初始化仿真系统...\n');
time_step = 0.01; % 10ms 时间步长
success = adapter.StartSimulation(time_step);
if ~success
fprintf('仿真初始化失败\n');
return;
end
fprintf('仿真系统初始化成功,时间步长: %.3f 秒\n', time_step);
%% 创建仿真场景
fprintf('\n=== 创建仿真场景 ===\n');
% 目标参数
target_id = 'target_001';
target_pos = [5000, 0, 1000]; % 位置: [x, y, z] 米
target_vel = [-50, 0, 0]; % 速度: [vx, vy, vz] 米/秒
% 创建目标
success = adapter.CreateTarget(target_id, ...
target_pos(1), target_pos(2), target_pos(3), ...
target_vel(1), target_vel(2), target_vel(3));
if success
fprintf('成功创建目标: %s\n', target_id);
fprintf(' 位置: [%.0f, %.0f, %.0f] 米\n', target_pos);
fprintf(' 速度: [%.1f, %.1f, %.1f] 米/秒\n', target_vel);
else
fprintf('目标创建失败\n');
return;
end
% 导弹参数
missile_id = 'missile_001';
missile_pos = [0, 0, 100]; % 发射位置: [x, y, z] 米
% 创建红外制导导弹
success = adapter.CreateIRMissile(missile_id, ...
missile_pos(1), missile_pos(2), missile_pos(3), target_id);
if success
fprintf('成功创建红外制导导弹: %s\n', missile_id);
fprintf(' 发射位置: [%.0f, %.0f, %.0f] 米\n', missile_pos);
fprintf(' 目标: %s\n', target_id);
else
fprintf('导弹创建失败\n');
return;
end
%% 运行仿真循环
fprintf('\n=== 开始仿真 ===\n');
% 仿真参数
sim_duration = 5.0; % 仿真持续时间(秒)
num_steps = int32(sim_duration / time_step);
update_interval = 50; % 每50步显示一次状态
% 存储仿真数据
time_data = zeros(num_steps, 1);
missile_data = zeros(num_steps, 10); % [x,y,z,vx,vy,vz,roll,pitch,yaw,active]
target_data = zeros(num_steps, 10);
fprintf('仿真参数:\n');
fprintf(' 持续时间: %.1f 秒\n', sim_duration);
fprintf(' 时间步长: %.3f 秒\n', time_step);
fprintf(' 总步数: %d\n', num_steps);
% 仿真主循环
for step = 1:num_steps
% 更新仿真
success = adapter.UpdateSimulation(time_step);
if ~success
fprintf('第 %d 步仿真更新失败\n', step);
break;
end
% 记录时间
current_time = adapter.GetCurrentTime();
time_data(step) = current_time;
% 获取实体状态
missile_state = adapter.GetEntityState(missile_id);
target_state = adapter.GetEntityState(target_id);
% 转换 .NET 数组为 Matlab 数组
if ~isempty(missile_state)
missile_data(step, :) = double(missile_state);
end
if ~isempty(target_state)
target_data(step, :) = double(target_state);
end
% 定期显示状态
if mod(step, update_interval) == 0 || step == 1
fprintf('时间: %6.2f 秒 | ', current_time);
if ~isempty(missile_state) && length(missile_state) >= 10
fprintf('导弹位置: [%6.0f, %6.0f, %6.0f] | ', ...
missile_state(1), missile_state(2), missile_state(3));
fprintf('活动: %s\n', missile_state(10) > 0.5 ? '是' : '否');
else
fprintf('导弹状态获取失败\n');
end
end
% 检查导弹是否仍然活动
if ~isempty(missile_state) && length(missile_state) >= 10
if missile_state(10) < 0.5 % 导弹已失活
fprintf('导弹在第 %.2f 秒失活\n', current_time);
break;
end
end
end
%% 显示仿真结果
fprintf('\n=== 仿真结果分析 ===\n');
% 获取所有实体ID
entity_ids = adapter.GetAllEntityIds();
fprintf('仿真中的实体数量: %d\n', length(entity_ids));
for i = 1:length(entity_ids)
fprintf(' - %s\n', char(entity_ids(i)));
end
% 计算统计信息
valid_steps = sum(time_data > 0);
fprintf('有效仿真步数: %d / %d\n', valid_steps, num_steps);
if valid_steps > 0
% 导弹轨迹分析
missile_pos = missile_data(1:valid_steps, 1:3);
target_pos_final = target_data(1:valid_steps, 1:3);
% 计算导弹飞行距离
if size(missile_pos, 1) > 1
distances = sqrt(sum(diff(missile_pos).^2, 2));
total_distance = sum(distances);
fprintf('导弹总飞行距离: %.1f 米\n', total_distance);
end
% 计算最终距离
if valid_steps > 1
final_missile_pos = missile_pos(end, :);
final_target_pos = target_pos_final(end, :);
final_distance = norm(final_missile_pos - final_target_pos);
fprintf('最终导弹-目标距离: %.1f 米\n', final_distance);
end
end
%% 绘制仿真结果
if valid_steps > 10 % 确保有足够的数据点
fprintf('\n绘制仿真轨迹...\n');
figure('Name', '威胁源仿真轨迹', 'Position', [100, 100, 1200, 800]);
% 3D轨迹图
subplot(2, 2, 1);
plot3(missile_data(1:valid_steps, 1), missile_data(1:valid_steps, 2), ...
missile_data(1:valid_steps, 3), 'r-', 'LineWidth', 2);
hold on;
plot3(target_data(1:valid_steps, 1), target_data(1:valid_steps, 2), ...
target_data(1:valid_steps, 3), 'b--', 'LineWidth', 2);
xlabel('X (米)'); ylabel('Y (米)'); zlabel('Z (米)');
title('3D 轨迹图');
legend('导弹', '目标', 'Location', 'best');
grid on; axis equal;
% 高度vs时间
subplot(2, 2, 2);
plot(time_data(1:valid_steps), missile_data(1:valid_steps, 3), 'r-', 'LineWidth', 2);
hold on;
plot(time_data(1:valid_steps), target_data(1:valid_steps, 3), 'b--', 'LineWidth', 2);
xlabel('时间 (秒)'); ylabel('高度 (米)');
title('高度变化');
legend('导弹', '目标', 'Location', 'best');
grid on;
% 速度vs时间
subplot(2, 2, 3);
missile_speed = sqrt(sum(missile_data(1:valid_steps, 4:6).^2, 2));
target_speed = sqrt(sum(target_data(1:valid_steps, 4:6).^2, 2));
plot(time_data(1:valid_steps), missile_speed, 'r-', 'LineWidth', 2);
hold on;
plot(time_data(1:valid_steps), target_speed, 'b--', 'LineWidth', 2);
xlabel('时间 (秒)'); ylabel('速度 (米/秒)');
title('速度变化');
legend('导弹', '目标', 'Location', 'best');
grid on;
% 导弹-目标距离vs时间
subplot(2, 2, 4);
distances = sqrt(sum((missile_data(1:valid_steps, 1:3) - target_data(1:valid_steps, 1:3)).^2, 2));
plot(time_data(1:valid_steps), distances, 'g-', 'LineWidth', 2);
xlabel('时间 (秒)'); ylabel('距离 (米)');
title('导弹-目标距离');
grid on;
% 保存图像
saveas(gcf, 'threat_source_simulation_result.png');
fprintf('仿真结果图已保存为: threat_source_simulation_result.png\n');
end
%% 清理资源
fprintf('\n=== 清理资源 ===\n');
try
adapter.StopSimulation();
fprintf('仿真已停止\n');
catch ME
fprintf('停止仿真时出错: %s\n', ME.message);
end
fprintf('Matlab 威胁源库集成示例完成\n');
%% 辅助函数:导出数据到文件
function export_simulation_data(time_data, missile_data, target_data, filename)
try
% 创建数据表
data_table = table(time_data, ...
missile_data(:,1), missile_data(:,2), missile_data(:,3), ...
missile_data(:,4), missile_data(:,5), missile_data(:,6), ...
target_data(:,1), target_data(:,2), target_data(:,3), ...
target_data(:,4), target_data(:,5), target_data(:,6), ...
'VariableNames', {'Time', ...
'Missile_X', 'Missile_Y', 'Missile_Z', ...
'Missile_VX', 'Missile_VY', 'Missile_VZ', ...
'Target_X', 'Target_Y', 'Target_Z', ...
'Target_VX', 'Target_VY', 'Target_VZ'});
% 保存为CSV文件
writetable(data_table, filename);
fprintf('仿真数据已导出到: %s\n', filename);
catch ME
fprintf('导出数据失败: %s\n', ME.message);
end
end