From 1017af871e8e574c1009e9745469bf01462d4b52 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Thu, 5 Jun 2025 18:12:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=20Matlab/Simulink?= =?UTF-8?q?=20=E9=9B=86=E6=88=90=E7=A4=BA=E4=BE=8B=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=92=8C=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 7 +- docs/articles/intro.md | 73 +-- docs/examples/Integration/README.md | 207 +++++++ docs/examples/Integration/SimulinkExample.cs | 599 +++++++++++++++++++ docs/examples/Integration/matlab_example.m | 277 +++++++++ 5 files changed, 1090 insertions(+), 73 deletions(-) create mode 100644 docs/examples/Integration/SimulinkExample.cs create mode 100644 docs/examples/Integration/matlab_example.m diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a8f64..7d96136 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,6 @@ ## [未发布] ### 计划功能 -- Matlab/Simulink 仿真环境适配器 - - 支持与 Simulink 模型的数据交互 - - 实现实时仿真数据同步 - - 处理不同时间步长的协调 - dll 库的接口有效性验证 - 所有威胁源的参数规范化,增加默认参数配置 - 规范第三方仿真环境使用 dll 库的场景和事件类型 @@ -26,7 +22,8 @@ - 增加了命中概率的计算和实现 - 增加了导弹运动状态的随机噪声,并根据飞行阶段设置不同的噪声系数 - 同步 dll 库的文档,api 文档、使用说明、工作原理 -- 增加了性能测试,优化了仿真管理器和红外成像制导的性能,并做了记录 +- 增加了性能测试,优化了仿真管理器、红外成像制导、毫米波制导的性能,并做了记录 +- 增加了 Matlab/Simulink集成示例代码和说明 ## [1.1.21] - 2025-05-24 - 增加了升力加速度的计算 diff --git a/docs/articles/intro.md b/docs/articles/intro.md index 7b03277..465e0dd 100644 --- a/docs/articles/intro.md +++ b/docs/articles/intro.md @@ -145,72 +145,7 @@ class Program ### C++版本 -C++项目有两种使用方式: - -#### 方式一:动态加载(推荐) - -这种方式适合纯C++项目,不需要配置CLR支持。 - -1. 下载 ThreatSourceNative 包并解压 -2. 将 bin 目录下的所有 DLL 文件复制到程序目录 -3. 将 include/threat_source.h 添加到项目中 -4. 按照标准结构部署数据文件 - -示例代码: - -```cpp -#include "threat_source.h" -#include - -int main() { - // 初始化仿真 - if (TS_CreateSimulation() != THREATSOURCE_SUCCESS) { - printf("Failed to create simulation\n"); - return 1; - } - - // 创建导弹(使用配置文件) - const char* missile_id = "missile1"; - const char* missile_model = "lsgm_001"; // 激光半主动制导导弹 - const char* target_id = "target1"; - - int result = TS_CreateMissileFromConfig( - missile_id, - missile_model, - target_id, - 0, 0, 0, // 初始位置 - 0, 0, 0 // 初始朝向 - ); - - if (result != THREATSOURCE_SUCCESS) { - char error[256]; - TS_GetLastError(error, sizeof(error)); - printf("Failed to create missile: %s\n", error); - return 1; - } - - // 激活并发射导弹 - TS_ActivateMissile(missile_id); - TS_FireMissile(missile_id); - - // 仿真主循环 - double deltaTime = 0.01; - int is_active = 1; - - while (is_active) { - TS_UpdateSimulation(deltaTime); - TS_IsMissileActive(missile_id, &is_active); - } - - // 清理 - TS_DestroySimulation(); - return 0; -} -``` - -#### 方式二:CLR 集成 - -如果需要使用 .NET 的完整功能,可以选择 CLR 集成方式: +C++项目的使用方式(CLR集成): 1. 配置项目属性: - C/C++ -> 常规 -> 公共语言运行时支持:/clr @@ -473,11 +408,13 @@ var dataManager = new ThreatSourceDataManager(); 4. ✅ 确保应用程序有读取数据目录的权限 5. ✅ 测试自动路径解析功能 -## 更多示例 +## 第三方仿真环境集成 +- [集成示例](../examples/Integration/README.md) +## 更多示例 更多详细示例和高级用法请参考: - [仿真示例](../examples/Simulation/README.md) -- [集成示例](../examples/Integration/README.md) + ## 故障排除 diff --git a/docs/examples/Integration/README.md b/docs/examples/Integration/README.md index 3f42263..79248a6 100644 --- a/docs/examples/Integration/README.md +++ b/docs/examples/Integration/README.md @@ -7,9 +7,100 @@ - .NET 8.0 或更高版本 - ThreatSource.dll 库文件 - 对应的第三方引擎开发环境 + - **Unity**:2020.3或更高版本 + - **Unreal Engine**:4.27或更高版本 + - **Matlab/Simulink**:R2019b或更高版本(需要.NET 8.0支持) ## 示例文件 +### [SimulinkExample.cs](SimulinkExample.cs) + +Matlab/Simulink集成示例,展示了: + +- 基于.NET Assembly直接调用的Matlab/Simulink集成 +- 简化的API接口,便于Matlab调用 +- 实时仿真数据交换和时间同步 +- 与Simulink时间步长的协调 + +#### 核心功能 + +```csharp +using ThreatSource.Simulation; +using ThreatSource.Data; +using ThreatSource.Missile; +using ThreatSource.Equipment; +using ThreatSource.Utils; + +/// +/// Matlab/Simulink适配器类,演示如何将威胁源库集成到Matlab/Simulink中 +/// +public class MatlabSimulinkAdapter +{ + private ISimulationManager _simulationManager; + private ThreatSourceDataManager _dataManager; + private Dictionary _matlabEntities; + + public bool StartSimulation(double timeStep = 0.01) + { + _simulationManager.StartSimulation(timeStep); + return true; + } + + public bool CreateTarget(string entityId, double posX, double posY, double posZ, + double velX, double velY, double velZ) + { + var targetPos = new Vector3D(posX, posY, posZ); + var targetVel = new Vector3D(velX, velY, velZ); + + var tank = new Tank(entityId, tankProperties, tankInitialMotion, _simulationManager); + _simulationManager.RegisterEntity(entityId, tank); + + return true; + } + + public double[] GetEntityState(string entityId) + { + // 返回 [x,y,z,vx,vy,vz,roll,pitch,yaw,isActive] 格式 + var entity = _simulationManager.GetEntityById(entityId); + return ConvertToMatlabStateArray(entity); + } +} +``` + +#### Matlab调用示例 + +详见 [matlab_example.m](matlab_example.m) 文件,展示了完整的Matlab集成流程: + +```matlab +%% 加载威胁源库 +NET.addAssembly('ThreatSource.dll'); + +%% 创建适配器 +adapter = MatlabSimulinkAdapter(); + +%% 启动仿真 +success = adapter.StartSimulation(0.01); % 10ms时间步长 + +%% 创建目标和导弹 +adapter.CreateTarget('target_001', 5000, 0, 1000, -50, 0, 0); +adapter.CreateIRMissile('missile_001', 0, 0, 100, 'target_001'); + +%% 仿真循环 +for i = 1:1000 + adapter.UpdateSimulation(0.01); + missile_state = adapter.GetEntityState('missile_001'); + % 处理数据... +end +``` + +#### Simulink S-Function集成 + +详见本文档的"Matlab/Simulink集成"部分,获取完整的Simulink集成指南,包括: +- S-Function封装 +- 实时数据可视化 +- 与Simulink Control System闭环仿真 +- 性能优化和故障排除 + ### [UEExample.cs](UEExample.cs) 虚幻引擎(Unreal Engine)集成示例,展示了: @@ -698,3 +789,119 @@ public class CustomMissileRenderer } } ``` + +## Matlab/Simulink集成 + +### Matlab/Simulink特定注意事项 + +1. **版本兼容性**:确保Matlab版本支持.NET 8.0(R2019b或更高版本) +2. **时间同步**:使用固定步长求解器确保时间同步准确性 +3. **数据类型转换**:注意.NET数组与Matlab数组之间的转换 +4. **S-Function集成**:在Simulink中使用S-Function封装威胁源库调用 + +### Matlab集成示例 + +#### 基本初始化 +```matlab +%% 加载威胁源库 +NET.addAssembly('ThreatSource.dll'); + +%% 创建适配器 +adapter = MatlabSimulinkAdapter(); +adapter.StartSimulation(0.01); +``` + +#### 实时仿真循环 +```matlab +%% 仿真主循环 +for step = 1:1000 + % 更新仿真 + adapter.UpdateSimulation(0.01); + + % 获取实体状态 + missile_state = adapter.GetEntityState('missile_001'); + target_state = adapter.GetEntityState('target_001'); + + % 数据处理和可视化 + if ~isempty(missile_state) + updateVisualization(missile_state, target_state); + end +end +``` + +#### S-Function封装 +```matlab +function [sys,x0,str,ts,simStateCompliance] = threat_source_sfun(t,x,u,flag) +% 威胁源库S-Function包装器 + +switch flag, + case 0, + [sys,x0,str,ts,simStateCompliance] = mdlInitializeSizes; + case 3, + sys = mdlOutputs(t,x,u); + case 9, + sys = mdlTerminate(t,x,u); +end + +function [sys,x0,str,ts,simStateCompliance] = mdlInitializeSizes +% 初始化S-Function +global threat_adapter; +if isempty(threat_adapter) + NET.addAssembly('ThreatSource.dll'); + threat_adapter = MatlabSimulinkAdapter(); + threat_adapter.StartSimulation(0.01); +end + +function sys = mdlOutputs(t,x,u) +% 输出实体状态数据 +global threat_adapter; +threat_adapter.UpdateSimulation(0.01); +missile_state = threat_adapter.GetEntityState('missile_001'); +sys = double(missile_state); +``` + +### Simulink模型集成步骤 + +1. **添加S-Function块**:在Simulink模型中添加S-Function块 +2. **配置参数**:设置S-Function名称为`threat_source_sfun` +3. **连接数据流**:将S-Function输出连接到显示或分析模块 +4. **配置求解器**:使用固定步长求解器,时间步长设为0.01秒 + +### 数据格式规范 + +#### 实体状态数组格式 +``` +索引 | 含义 | 单位 +-----|-------------------|------ +0-2 | 位置(x,y,z) | 米 +3-5 | 速度(vx,vy,vz) | 米/秒 +6-8 | 姿态(roll,pitch,yaw) | 弧度 +9 | 活动状态 | 0/1 +``` + +#### Matlab示例完整流程 + +参见 [matlab_example.m](matlab_example.m) 了解完整的集成流程,包括: +- 系统初始化和库加载 +- 仿真场景创建 +- 实时数据获取和处理 +- 结果可视化和分析 +- 资源清理和异常处理 + +## 文件结构 + +``` +docs/examples/Integration/ +├── README.md # 本文档 +├── SimulinkExample.cs # Matlab/Simulink集成示例代码 +├── matlab_example.m # Matlab调用示例脚本 +├── UnityExample.cs # Unity集成示例代码(方法一) +├── UnityPackageExample.cs # Unity Package集成示例代码(方法二) +└── UEExample.cs # 虚幻引擎集成示例代码 +``` + +## 相关文档 + +- **威胁源库文档**:[../../README.md](../../README.md) - 库的基本使用说明 +- **API文档**:[../../api/](../../api/) - 详细的API参考文档 +- **变更日志**:[../../CHANGELOG.md](../../CHANGELOG.md) - 版本更新记录 diff --git a/docs/examples/Integration/SimulinkExample.cs b/docs/examples/Integration/SimulinkExample.cs new file mode 100644 index 0000000..0134da2 --- /dev/null +++ b/docs/examples/Integration/SimulinkExample.cs @@ -0,0 +1,599 @@ +#if NEVER // 使用编译指令确保此文件永远不会被编译 + +// Matlab/Simulink集成示例代码 - .NET Assembly直接调用方式 +// +// 【适用场景】 +// - Matlab R2019b或更高版本 +// - 需要在Simulink模型中集成威胁源仿真 +// - 实时仿真数据交换和时间同步 +// +// 【前置条件】 +// 1. 将 ThreatSource.dll 放入 Matlab 路径或指定目录 +// 2. 将 data/ 目录复制到 Matlab 工作目录下 +// 3. Matlab版本支持 .NET 8.0 +// +// 展示如何将Matlab/Simulink与ThreatSource仿真系统集成 +// 需要实现的核心功能: .NET Assembly加载、数据交换、时间同步 + +using ThreatSource.Simulation; +using ThreatSource.Data; +using ThreatSource.Missile; +using ThreatSource.Equipment; +using ThreatSource.Utils; +using System; +using System.Collections.Generic; + +/// +/// Matlab/Simulink适配器类,演示如何将威胁源库集成到Matlab/Simulink中 +/// +/// +/// 该类提供以下功能: +/// - .NET Assembly方式的Matlab集成 +/// - 简化的API接口,便于Matlab调用 +/// - 实时数据交换和状态同步 +/// - 事件处理和回调机制 +/// - 与Simulink时间步长的协调 +/// 本示例代码作为集成参考,可根据具体需求进行修改 +/// +public class MatlabSimulinkAdapter +{ + #region 私有字段 + /// + /// 仿真管理器实例 + /// + private ISimulationManager _simulationManager; + + /// + /// 数据管理器实例 + /// + private ThreatSourceDataManager _dataManager; + + /// + /// Matlab创建的实体映射 + /// + private Dictionary _matlabEntities = new Dictionary(); + + /// + /// 当前仿真时间 + /// + private double _currentTime = 0.0; + + /// + /// 仿真时间步长 + /// + private double _timeStep = 0.01; + + /// + /// 是否已初始化 + /// + private bool _isInitialized = false; + #endregion + + #region 构造函数 + /// + /// 初始化Matlab/Simulink适配器的新实例 + /// + public MatlabSimulinkAdapter() + { + InitializeSimulation(); + } + + /// + /// 初始化仿真系统 + /// + private void InitializeSimulation() + { + try + { + // 创建仿真管理器 + _simulationManager = new SimulationManager(); + + // 创建数据管理器 + _dataManager = new ThreatSourceDataManager(); + + Console.WriteLine("[MatlabAdapter] 威胁源仿真系统初始化完成"); + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 初始化失败: {ex.Message}"); + throw; + } + } + #endregion + + #region Matlab公共接口 + /// + /// 启动仿真系统 + /// + /// 仿真时间步长(秒) + /// 启动是否成功 + public bool StartSimulation(double timeStep = 0.01) + { + try + { + if (!_isInitialized) + { + _timeStep = timeStep; + _simulationManager.StartSimulation(timeStep); + _isInitialized = true; + Console.WriteLine($"[MatlabAdapter] 仿真已启动,时间步长: {timeStep}s"); + } + return true; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 启动仿真失败: {ex.Message}"); + return false; + } + } + + /// + /// 更新仿真状态(在Simulink中每个时间步调用) + /// + /// 时间步长 + /// 更新是否成功 + public bool UpdateSimulation(double deltaTime) + { + try + { + if (!_isInitialized) return false; + + _simulationManager.Update(deltaTime); + _currentTime += deltaTime; + return true; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 仿真更新失败: {ex.Message}"); + return false; + } + } + + /// + /// 创建目标实体(供Matlab调用) + /// + /// 实体ID + /// X坐标 + /// Y坐标 + /// Z坐标 + /// X方向速度 + /// Y方向速度 + /// Z方向速度 + /// 创建是否成功 + public bool CreateTarget(string entityId, double posX, double posY, double posZ, + double velX, double velY, double velZ) + { + try + { + var targetPos = new Vector3D(posX, posY, posZ); + var targetVel = new Vector3D(velX, velY, velZ); + + var tankInitialMotion = new KinematicState + { + Position = targetPos, + Orientation = new Orientation(0, 0, Math.Atan2(velY, velX)), + Speed = targetVel.Magnitude() + }; + + var tankProperties = new EquipmentProperties + { + InfraredRadiationIntensity = 10.0, + UltravioletRadiationIntensity = 10.0, + MillimeterWaveRadiationIntensity = 10.0 + }; + + var tank = new Tank(entityId, tankProperties, tankInitialMotion, _simulationManager); + _simulationManager.RegisterEntity(entityId, tank); + _matlabEntities[entityId] = tank; + + Console.WriteLine($"[MatlabAdapter] 成功创建目标: {entityId}"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 创建目标失败: {ex.Message}"); + return false; + } + } + + /// + /// 创建红外成像制导导弹 + /// + /// 导弹ID + /// 发射位置X + /// 发射位置Y + /// 发射位置Z + /// 目标ID + /// 创建是否成功 + public bool CreateIRMissile(string entityId, double posX, double posY, double posZ, string targetId) + { + try + { + var launchPos = new Vector3D(posX, posY, posZ); + + var missileInitialMotion = new KinematicState + { + Position = launchPos, + Orientation = new Orientation(0, 0, 0), + Speed = 100 + }; + + var properties = new MissileProperties + { + MaxSpeed = 1000, + MaxFlightTime = 100, + MaxFlightDistance = 10000, + MaxAcceleration = 50, + ProportionalNavigationCoefficient = 3, + Mass = 100, + ExplosionRadius = 10, + HitProbability = 0.9, + Type = MissileType.InfraredImagingTerminalGuidance + }; + + var guidanceConfig = new InfraredImagingGuidanceConfig + { + JammingResistanceThreshold = 1e-3 + }; + + var missile = new InfraredImagingTerminalGuidanceMissile( + entityId, properties, missileInitialMotion, guidanceConfig, _simulationManager); + + if (!string.IsNullOrEmpty(targetId)) + { + missile.SetTarget(targetId); + } + + _simulationManager.RegisterEntity(entityId, missile); + _matlabEntities[entityId] = missile; + + Console.WriteLine($"[MatlabAdapter] 成功创建红外导弹: {entityId}"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 创建红外导弹失败: {ex.Message}"); + return false; + } + } + + /// + /// 创建毫米波制导导弹 + /// + /// 导弹ID + /// 发射位置X + /// 发射位置Y + /// 发射位置Z + /// 目标ID + /// 创建是否成功 + public bool CreateMMWMissile(string entityId, double posX, double posY, double posZ, string targetId) + { + try + { + var launchPos = new Vector3D(posX, posY, posZ); + + var missileInitialMotion = new KinematicState + { + Position = launchPos, + Orientation = new Orientation(0, 0, 0), + Speed = 100 + }; + + var properties = new MissileProperties + { + MaxSpeed = 1000, + MaxFlightTime = 100, + MaxFlightDistance = 10000, + MaxAcceleration = 50, + ProportionalNavigationCoefficient = 3, + Mass = 100, + ExplosionRadius = 10, + HitProbability = 0.9, + Type = MissileType.MillimeterWaveTerminalGuidance + }; + + var guidanceConfig = new MillimeterWaveGuidanceConfig + { + FieldOfViewAngle = 30, + TransmitPower = 0.5, + AntennaGainDB = 25, + WaveFrequency = 94e9 + }; + + var missile = new MillimeterWaveTerminalGuidedMissile( + entityId, properties, missileInitialMotion, guidanceConfig, _simulationManager); + + if (!string.IsNullOrEmpty(targetId)) + { + missile.SetTarget(targetId); + } + + _simulationManager.RegisterEntity(entityId, missile); + _matlabEntities[entityId] = missile; + + Console.WriteLine($"[MatlabAdapter] 成功创建毫米波导弹: {entityId}"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 创建毫米波导弹失败: {ex.Message}"); + return false; + } + } + + /// + /// 获取实体状态(供Matlab调用) + /// + /// 实体ID + /// 状态数组 [x, y, z, vx, vy, vz, roll, pitch, yaw, isActive] + public double[] GetEntityState(string entityId) + { + try + { + var entity = _simulationManager.GetEntityById(entityId); + if (entity is ISimulationElement simElement) + { + return ConvertToMatlabStateArray(simElement); + } + return new double[10]; // 返回零数组 + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 获取实体状态失败: {ex.Message}"); + return new double[10]; + } + } + + /// + /// 设置实体位置(供Matlab调用) + /// + /// 实体ID + /// X坐标 + /// Y坐标 + /// Z坐标 + /// 设置是否成功 + public bool SetEntityPosition(string entityId, double posX, double posY, double posZ) + { + try + { + var entity = _simulationManager.GetEntityById(entityId); + if (entity is ISimulationElement simElement) + { + simElement.KState.Position = new Vector3D(posX, posY, posZ); + return true; + } + return false; + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 设置实体位置失败: {ex.Message}"); + return false; + } + } + + /// + /// 获取所有实体ID列表(供Matlab调用) + /// + /// 实体ID字符串数组 + public string[] GetAllEntityIds() + { + try + { + var allEntities = _simulationManager.GetAllEntities(); + var entityIds = new List(); + + foreach (var entity in allEntities) + { + if (entity is ISimulationElement simElement) + { + entityIds.Add(simElement.Id); + } + } + + return entityIds.ToArray(); + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 获取实体列表失败: {ex.Message}"); + return new string[0]; + } + } + + /// + /// 停止仿真 + /// + public void StopSimulation() + { + try + { + _simulationManager.StopSimulation(); + _isInitialized = false; + _matlabEntities.Clear(); + _currentTime = 0.0; + Console.WriteLine("[MatlabAdapter] 仿真已停止"); + } + catch (Exception ex) + { + Console.WriteLine($"[MatlabAdapter] 停止仿真失败: {ex.Message}"); + } + } + + /// + /// 获取当前仿真时间 + /// + /// 当前仿真时间(秒) + public double GetCurrentTime() + { + return _currentTime; + } + + /// + /// 检查实体是否存在 + /// + /// 实体ID + /// 实体是否存在 + public bool EntityExists(string entityId) + { + var entity = _simulationManager.GetEntityById(entityId); + return entity != null; + } + #endregion + + #region 私有辅助方法 + /// + /// 将仿真元素转换为Matlab状态数组 + /// + /// 仿真元素 + /// 状态数组 [x, y, z, vx, vy, vz, roll, pitch, yaw, isActive] + private double[] ConvertToMatlabStateArray(ISimulationElement element) + { + var pos = element.KState.Position; + var ori = element.KState.Orientation; + var speed = element.KState.Speed; + + // 计算速度分量 + var vx = speed * Math.Cos(ori.Yaw) * Math.Cos(ori.Pitch); + var vy = speed * Math.Sin(ori.Yaw) * Math.Cos(ori.Pitch); + var vz = speed * Math.Sin(ori.Pitch); + + return new double[] + { + pos.X, pos.Y, pos.Z, // 位置 [0-2] + vx, vy, vz, // 速度 [3-5] + ori.Roll, ori.Pitch, ori.Yaw, // 姿态 [6-8] + element.IsActive ? 1.0 : 0.0 // 活动状态 [9] + }; + } + #endregion +} + +/// +/// Matlab/Simulink仿真示例类 +/// +/// +/// 该类演示了: +/// - Matlab/Simulink仿真系统的初始化 +/// - 适配器的配置和使用 +/// - 典型的导弹-目标仿真场景 +/// 用于指导实际项目中的集成实现 +/// +public class MatlabSimulinkExample +{ + private MatlabSimulinkAdapter _adapter; + + /// + /// 初始化示例 + /// + public void Initialize() + { + _adapter = new MatlabSimulinkAdapter(); + Console.WriteLine("Matlab/Simulink ThreatSource集成示例初始化完成"); + } + + /// + /// 运行基本仿真示例 + /// + public void RunBasicSimulationExample() + { + try + { + // 启动仿真系统 + if (!_adapter.StartSimulation(0.01)) + { + Console.WriteLine("仿真启动失败"); + return; + } + + // 创建目标 + bool targetCreated = _adapter.CreateTarget( + "target_001", + 5000, 0, 1000, // 位置: 5km距离,1km高度 + -50, 0, 0 // 速度: 50m/s向西移动 + ); + + if (!targetCreated) + { + Console.WriteLine("目标创建失败"); + return; + } + + // 创建红外制导导弹 + bool missileCreated = _adapter.CreateIRMissile( + "missile_001", + 0, 0, 100, // 发射位置: 起始位置,100m高度 + "target_001" // 目标ID + ); + + if (missileCreated) + { + Console.WriteLine("基本仿真示例场景创建成功"); + + // 运行仿真步骤示例 + for (int i = 0; i < 10; i++) + { + _adapter.UpdateSimulation(0.01); + + // 获取导弹状态 + var missileState = _adapter.GetEntityState("missile_001"); + Console.WriteLine($"时间: {_adapter.GetCurrentTime():F2}s, 导弹位置: [{missileState[0]:F1}, {missileState[1]:F1}, {missileState[2]:F1}]"); + + // 在实际Simulink中,这里会是Simulink的时间步进 + System.Threading.Thread.Sleep(10); + } + } + else + { + Console.WriteLine("导弹创建失败"); + } + } + catch (Exception ex) + { + Console.WriteLine($"运行仿真示例失败: {ex.Message}"); + } + } + + /// + /// 运行多导弹仿真示例 + /// + public void RunMultiMissileExample() + { + try + { + // 启动仿真 + _adapter.StartSimulation(0.01); + + // 创建多个目标 + _adapter.CreateTarget("target_001", 3000, 1000, 800, -30, -10, 0); + _adapter.CreateTarget("target_002", 4000, -500, 1200, -40, 20, 0); + + // 创建不同类型的导弹 + _adapter.CreateIRMissile("ir_missile_001", 0, 0, 100, "target_001"); + _adapter.CreateMMWMissile("mmw_missile_001", 100, 0, 100, "target_002"); + + Console.WriteLine("多导弹仿真示例场景创建成功"); + + // 显示所有实体 + var entityIds = _adapter.GetAllEntityIds(); + Console.WriteLine($"仿真中共有 {entityIds.Length} 个实体:"); + foreach (var id in entityIds) + { + Console.WriteLine($" - {id}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"运行多导弹示例失败: {ex.Message}"); + } + } + + /// + /// 清理资源 + /// + public void Cleanup() + { + _adapter?.StopSimulation(); + Console.WriteLine("Matlab/Simulink ThreatSource集成示例已清理"); + } +} + +#endif // 结束编译指令块 \ No newline at end of file diff --git a/docs/examples/Integration/matlab_example.m b/docs/examples/Integration/matlab_example.m new file mode 100644 index 0000000..c693142 --- /dev/null +++ b/docs/examples/Integration/matlab_example.m @@ -0,0 +1,277 @@ +%% 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 \ No newline at end of file