增加了 Matlab/Simulink 集成示例代码和说明

This commit is contained in:
Tian jianyong 2025-06-05 18:12:14 +08:00
parent 131ba3997c
commit 1017af871e
5 changed files with 1090 additions and 73 deletions

View File

@ -8,10 +8,6 @@
## [未发布]
### 计划功能
- Matlab/Simulink 仿真环境适配器
- 支持与 Simulink 模型的数据交互
- 实现实时仿真数据同步
- 处理不同时间步长的协调
- dll 库的接口有效性验证
- 所有威胁源的参数规范化,增加默认参数配置
- 规范第三方仿真环境使用 dll 库的场景和事件类型
@ -26,7 +22,8 @@
- 增加了命中概率的计算和实现
- 增加了导弹运动状态的随机噪声,并根据飞行阶段设置不同的噪声系数
- 同步 dll 库的文档api 文档、使用说明、工作原理
- 增加了性能测试,优化了仿真管理器和红外成像制导的性能,并做了记录
- 增加了性能测试,优化了仿真管理器、红外成像制导、毫米波制导的性能,并做了记录
- 增加了 Matlab/Simulink集成示例代码和说明
## [1.1.21] - 2025-05-24
- 增加了升力加速度的计算

View File

@ -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 <stdio.h>
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)
## 故障排除

View File

@ -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;
/// <summary>
/// Matlab/Simulink适配器类演示如何将威胁源库集成到Matlab/Simulink中
/// </summary>
public class MatlabSimulinkAdapter
{
private ISimulationManager _simulationManager;
private ThreatSourceDataManager _dataManager;
private Dictionary<string, object> _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.0R2019b或更高版本
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) - 版本更新记录

View File

@ -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;
/// <summary>
/// Matlab/Simulink适配器类演示如何将威胁源库集成到Matlab/Simulink中
/// </summary>
/// <remarks>
/// 该类提供以下功能:
/// - .NET Assembly方式的Matlab集成
/// - 简化的API接口便于Matlab调用
/// - 实时数据交换和状态同步
/// - 事件处理和回调机制
/// - 与Simulink时间步长的协调
/// 本示例代码作为集成参考,可根据具体需求进行修改
/// </remarks>
public class MatlabSimulinkAdapter
{
#region
/// <summary>
/// 仿真管理器实例
/// </summary>
private ISimulationManager _simulationManager;
/// <summary>
/// 数据管理器实例
/// </summary>
private ThreatSourceDataManager _dataManager;
/// <summary>
/// Matlab创建的实体映射
/// </summary>
private Dictionary<string, object> _matlabEntities = new Dictionary<string, object>();
/// <summary>
/// 当前仿真时间
/// </summary>
private double _currentTime = 0.0;
/// <summary>
/// 仿真时间步长
/// </summary>
private double _timeStep = 0.01;
/// <summary>
/// 是否已初始化
/// </summary>
private bool _isInitialized = false;
#endregion
#region
/// <summary>
/// 初始化Matlab/Simulink适配器的新实例
/// </summary>
public MatlabSimulinkAdapter()
{
InitializeSimulation();
}
/// <summary>
/// 初始化仿真系统
/// </summary>
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公共接口
/// <summary>
/// 启动仿真系统
/// </summary>
/// <param name="timeStep">仿真时间步长(秒)</param>
/// <returns>启动是否成功</returns>
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;
}
}
/// <summary>
/// 更新仿真状态在Simulink中每个时间步调用
/// </summary>
/// <param name="deltaTime">时间步长</param>
/// <returns>更新是否成功</returns>
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;
}
}
/// <summary>
/// 创建目标实体供Matlab调用
/// </summary>
/// <param name="entityId">实体ID</param>
/// <param name="posX">X坐标</param>
/// <param name="posY">Y坐标</param>
/// <param name="posZ">Z坐标</param>
/// <param name="velX">X方向速度</param>
/// <param name="velY">Y方向速度</param>
/// <param name="velZ">Z方向速度</param>
/// <returns>创建是否成功</returns>
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;
}
}
/// <summary>
/// 创建红外成像制导导弹
/// </summary>
/// <param name="entityId">导弹ID</param>
/// <param name="posX">发射位置X</param>
/// <param name="posY">发射位置Y</param>
/// <param name="posZ">发射位置Z</param>
/// <param name="targetId">目标ID</param>
/// <returns>创建是否成功</returns>
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;
}
}
/// <summary>
/// 创建毫米波制导导弹
/// </summary>
/// <param name="entityId">导弹ID</param>
/// <param name="posX">发射位置X</param>
/// <param name="posY">发射位置Y</param>
/// <param name="posZ">发射位置Z</param>
/// <param name="targetId">目标ID</param>
/// <returns>创建是否成功</returns>
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;
}
}
/// <summary>
/// 获取实体状态供Matlab调用
/// </summary>
/// <param name="entityId">实体ID</param>
/// <returns>状态数组 [x, y, z, vx, vy, vz, roll, pitch, yaw, isActive]</returns>
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];
}
}
/// <summary>
/// 设置实体位置供Matlab调用
/// </summary>
/// <param name="entityId">实体ID</param>
/// <param name="posX">X坐标</param>
/// <param name="posY">Y坐标</param>
/// <param name="posZ">Z坐标</param>
/// <returns>设置是否成功</returns>
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;
}
}
/// <summary>
/// 获取所有实体ID列表供Matlab调用
/// </summary>
/// <returns>实体ID字符串数组</returns>
public string[] GetAllEntityIds()
{
try
{
var allEntities = _simulationManager.GetAllEntities();
var entityIds = new List<string>();
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];
}
}
/// <summary>
/// 停止仿真
/// </summary>
public void StopSimulation()
{
try
{
_simulationManager.StopSimulation();
_isInitialized = false;
_matlabEntities.Clear();
_currentTime = 0.0;
Console.WriteLine("[MatlabAdapter] 仿真已停止");
}
catch (Exception ex)
{
Console.WriteLine($"[MatlabAdapter] 停止仿真失败: {ex.Message}");
}
}
/// <summary>
/// 获取当前仿真时间
/// </summary>
/// <returns>当前仿真时间(秒)</returns>
public double GetCurrentTime()
{
return _currentTime;
}
/// <summary>
/// 检查实体是否存在
/// </summary>
/// <param name="entityId">实体ID</param>
/// <returns>实体是否存在</returns>
public bool EntityExists(string entityId)
{
var entity = _simulationManager.GetEntityById(entityId);
return entity != null;
}
#endregion
#region
/// <summary>
/// 将仿真元素转换为Matlab状态数组
/// </summary>
/// <param name="element">仿真元素</param>
/// <returns>状态数组 [x, y, z, vx, vy, vz, roll, pitch, yaw, isActive]</returns>
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
}
/// <summary>
/// Matlab/Simulink仿真示例类
/// </summary>
/// <remarks>
/// 该类演示了:
/// - Matlab/Simulink仿真系统的初始化
/// - 适配器的配置和使用
/// - 典型的导弹-目标仿真场景
/// 用于指导实际项目中的集成实现
/// </remarks>
public class MatlabSimulinkExample
{
private MatlabSimulinkAdapter _adapter;
/// <summary>
/// 初始化示例
/// </summary>
public void Initialize()
{
_adapter = new MatlabSimulinkAdapter();
Console.WriteLine("Matlab/Simulink ThreatSource集成示例初始化完成");
}
/// <summary>
/// 运行基本仿真示例
/// </summary>
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}");
}
}
/// <summary>
/// 运行多导弹仿真示例
/// </summary>
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}");
}
}
/// <summary>
/// 清理资源
/// </summary>
public void Cleanup()
{
_adapter?.StopSimulation();
Console.WriteLine("Matlab/Simulink ThreatSource集成示例已清理");
}
}
#endif // 结束编译指令块

View File

@ -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