diff --git a/ThreatSource.Tests/src/Missile/TerminalSensitiveSubmunitionTests.cs b/ThreatSource.Tests/src/Missile/TerminalSensitiveSubmunitionTests.cs
index 40668dd..ed76345 100644
--- a/ThreatSource.Tests/src/Missile/TerminalSensitiveSubmunitionTests.cs
+++ b/ThreatSource.Tests/src/Missile/TerminalSensitiveSubmunitionTests.cs
@@ -236,5 +236,146 @@ namespace ThreatSource.Tests.Missile
_output.WriteLine($"修正后的水平方向: {horizontalCorrectedDirection}");
_output.WriteLine($"修正后的水平夹角: {correctedHorizontalAngle:F2}°");
}
+
+ [Theory]
+ [InlineData(0, 0, 0, 44, 76.5, 0)] // 原点场景
+ [InlineData(100, 0, 0, 144, 76.5, 0)] // X轴平移
+ [InlineData(0, 0, 100, 44, 76.5, 100)] // Z轴平移
+ [InlineData(100, 0, 100, 144, 76.5, 100)] // XZ平面平移
+ public void TestTargetDetectionAtDifferentPositions(
+ double targetX, double targetY, double targetZ,
+ double submunitionX, double submunitionY, double submunitionZ)
+ {
+ try
+ {
+ // 设置目标位置
+ var targetPosition = new Vector3D(targetX, targetY, targetZ);
+ _tank.Position = targetPosition;
+
+ // 设置子弹位置
+ var submunitionPosition = new Vector3D(submunitionX, submunitionY, submunitionZ);
+ _submunition.Position = submunitionPosition;
+
+ // 计算从子弹到目标的向量
+ var toTarget = (targetPosition - submunitionPosition).Normalize();
+
+ // 设置子弹的扫描方向直接指向目标
+ var scanDirection = toTarget;
+ var field = typeof(TerminalSensitiveSubmunition)
+ .GetField("scanDirection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+
+ if (field == null)
+ {
+ _output.WriteLine("无法找到scanDirection字段");
+ Assert.Fail("无法找到scanDirection字段");
+ return;
+ }
+
+ field.SetValue(_submunition, scanDirection);
+
+ // 执行目标检测
+ var detectionResult = _submunition.DetectTarget(30); // 30度视场角
+
+ // 输出测试信息
+ _output.WriteLine($"\n=== 测试场景 ===");
+ _output.WriteLine($"目标位置: ({targetX}, {targetY}, {targetZ})");
+ _output.WriteLine($"子弹位置: ({submunitionX}, {submunitionY}, {submunitionZ})");
+ _output.WriteLine($"相对位置向量: {toTarget}");
+ _output.WriteLine($"扫描方向: {scanDirection}");
+ _output.WriteLine($"检测结果: {(detectionResult.Target != null ? "已检测到目标" : "未检测到目标")}");
+
+ if (detectionResult.Target != null)
+ {
+ _output.WriteLine($"目标方位角: {detectionResult.Angle * 180 / Math.PI:F2}度");
+ }
+ else
+ {
+ _output.WriteLine("警告:未检测到目标!");
+ }
+
+ // 验证检测结果
+ Assert.True(detectionResult.Target != null, $"在位置({targetX}, {targetY}, {targetZ})处未能检测到目标");
+ Assert.True(detectionResult.Angle.HasValue, "检测结果中没有方位角信息");
+ }
+ catch (Exception ex)
+ {
+ _output.WriteLine($"\n发生异常: {ex.Message}");
+ _output.WriteLine($"堆栈跟踪: {ex.StackTrace}");
+ throw;
+ }
+ }
+
+ [Theory]
+ [InlineData(0, 0, 0)] // 原点场景
+ [InlineData(100, 0, 0)] // X轴平移
+ [InlineData(0, 0, 100)] // Z轴平移
+ [InlineData(100, 0, 100)] // XZ平面平移
+ public void TestScanningAtFixedHeight(double targetX, double targetY, double targetZ)
+ {
+ try
+ {
+ // 设置目标位置
+ var targetPosition = new Vector3D(targetX, targetY, targetZ);
+ _tank.Position = targetPosition;
+
+ // 设置子弹位置和速度(只有垂直下降速度-10m/s)
+ _submunition.Position = new Vector3D(targetX + 44, 210, targetZ);
+ _submunition.Velocity = new Vector3D(0, -10, 0); // 设置速度为(0,-10,0)
+
+ // 记录初始状态
+ _output.WriteLine($"\n=== 初始状态 ===");
+ _output.WriteLine($"目标位置: {targetPosition}");
+ _output.WriteLine($"子弹位置: {_submunition.Position}");
+ _output.WriteLine($"相对位置: {(targetPosition - _submunition.Position)}");
+ _output.WriteLine($"子弹速度: {_submunition.Velocity}");
+
+ // 激活子弹
+ _submunition.Activate();
+
+ // 运行1000步扫描,每步0.002秒
+ const double deltaTime = 0.002;
+ const int totalSteps = 1000;
+ bool targetDetected = false;
+ int firstDetectionStep = -1;
+
+ for (int i = 0; i < totalSteps; i++)
+ {
+ _submunition.Update(deltaTime);
+
+ // 检查是否进入制导
+ if (_submunition.IsGuidance && !targetDetected)
+ {
+ targetDetected = true;
+ firstDetectionStep = i;
+ _output.WriteLine($"\n=== 首次检测到目标!===");
+ _output.WriteLine($"检测步数: {i} (时间: {i * deltaTime:F3}秒)");
+ _output.WriteLine($"当前子弹位置: {_submunition.Position}");
+ _output.WriteLine($"当前子弹速度: {_submunition.Velocity}");
+ }
+
+ if (i % 500 == 0) // 每1秒(500步)输出一次状态
+ {
+ _output.WriteLine($"\n=== 第{i}步扫描 (时间: {i * deltaTime:F3}秒) ===");
+ _output.WriteLine(_submunition.GetStatus());
+ }
+ }
+
+ // 验证是否检测到目标
+ Assert.True(targetDetected, $"在位置({targetX}, {targetY}, {targetZ})处未能检测到目标");
+
+ // 输出扫描统计信息
+ _output.WriteLine($"\n=== 扫描统计 ===");
+ _output.WriteLine($"总扫描步数: {totalSteps}");
+ _output.WriteLine($"总扫描时间: {totalSteps * deltaTime:F3}秒");
+ _output.WriteLine($"首次检测步数: {firstDetectionStep}");
+ _output.WriteLine($"首次检测时间: {firstDetectionStep * deltaTime:F3}秒");
+ }
+ catch (Exception ex)
+ {
+ _output.WriteLine($"\n发生异常: {ex.Message}");
+ _output.WriteLine($"堆栈跟踪: {ex.StackTrace}");
+ throw;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/ThreatSource/src/MIssile/TerminalSensitiveMissile.cs b/ThreatSource/src/MIssile/TerminalSensitiveMissile.cs
index 4543908..c36deb7 100644
--- a/ThreatSource/src/MIssile/TerminalSensitiveMissile.cs
+++ b/ThreatSource/src/MIssile/TerminalSensitiveMissile.cs
@@ -43,6 +43,16 @@ namespace ThreatSource.Missile
///
private const double SeparationDistance = 1000;
+ ///
+ /// 子弹分离角度(与地面的夹角)
+ ///
+ ///
+ /// 单位:度
+ /// 子弹从母弹分离时与地面的夹角
+ /// 默认设置为60度
+ ///
+ private const double SubmunitionSeparationAngle = 45;
+
///
/// 触发分离的距离阈值
///
@@ -225,19 +235,32 @@ namespace ThreatSource.Missile
Console.WriteLine($"开始分离,当前位置:{Position},分离点:{separationPoint}");
Debug.WriteLine($"开始分离,当前位置:{Position},分离点:{separationPoint}");
- // 获取目标位置
- SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
- Vector3D targetPosition = target.Position;
- Console.WriteLine($"目标位置:{targetPosition}");
- Debug.WriteLine($"目标位置:{targetPosition}");
+ // 获取母弹当前的方向向量
+ Vector3D currentDirection = Orientation.ToVector();
- // 计算子弹朝向目标的方向
- Vector3D directionToTarget = (targetPosition - this.Position).Normalize();
- Orientation orientationToTarget = Orientation.FromVector(directionToTarget);
- Console.WriteLine($"子弹朝向:{directionToTarget}");
- Debug.WriteLine($"子弹朝向:{directionToTarget}");
+ // 计算水平方向(保持母弹的水平方向分量)
+ Vector3D horizontalDirection = new Vector3D(currentDirection.X, 0, currentDirection.Z).Normalize();
- // 创建并释子弹
+ // 计算分离角度(弧度)
+ double separationAngleRad = SubmunitionSeparationAngle * Math.PI / 180.0;
+
+ // 计算子弹的初始方向(保持水平方向不变,设置垂直角度为-60度)
+ Vector3D initialDirection = new Vector3D(
+ horizontalDirection.X,
+ -Math.Tan(separationAngleRad), // 负号表示向下的60度角
+ horizontalDirection.Z
+ ).Normalize();
+
+ // 根据新方向创建朝向
+ Orientation separationOrientation = Orientation.FromVector(initialDirection);
+ Console.WriteLine($"母弹当前方向:{currentDirection}");
+ Console.WriteLine($"子弹分离角度:{SubmunitionSeparationAngle}度(向下)");
+ Console.WriteLine($"子弹初始方向:{initialDirection}");
+ Debug.WriteLine($"母弹当前方向:{currentDirection}");
+ Debug.WriteLine($"子弹分离角度:{SubmunitionSeparationAngle}度(向下)");
+ Debug.WriteLine($"子弹初始方向:{initialDirection}");
+
+ // 创建并释放子弹
for (int i = 0; i < SubmunitionCount; i++)
{
Console.WriteLine($"创建子弹 {i}");
@@ -248,7 +271,7 @@ namespace ThreatSource.Missile
{
Id = $"{Id}_Sub_{i}",
InitialPosition = Position,
- InitialOrientation = Orientation, // 子弹初始方向等于母弹方向
+ InitialOrientation = separationOrientation, // 使用新计算的分离方向
InitialSpeed = Velocity.Magnitude(), // 子弹初始速度等于母弹速度
MaxSpeed = 2000,
MaxFlightTime = 100,
diff --git a/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs b/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs
index 76a7c0d..5ac1f4f 100644
--- a/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs
+++ b/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs
@@ -75,13 +75,13 @@ namespace ThreatSource.Missile
private SubmunitionStage currentStage;
///
- /// 螺旋扫描旋转速度,单位:弧度/秒
+ /// 减速加速度,单位:米/秒²
///
///
- /// 定义了螺旋扫描时的旋转角速度
- /// 4转/秒 = 8π弧度/秒
+ /// 减速阶段的减速度大小
+ /// 影响速度调整的快慢
///
- private const double SpiralRotationSpeed = 8 * Math.PI;
+ private const double DecelerationAcceleration = 250;
///
/// 减速阶段末速,单位:米/秒
@@ -89,15 +89,32 @@ namespace ThreatSource.Missile
///
/// 定义了减速阶段的垂直下降速度
///
- private const double DecelerationEndSpeed = 40;
+ private const double DecelerationEndSpeed = 50;
+ ///
+ /// 开伞高度,单位:米
+ ///
+ ///
+ /// 打开降落伞的高度阈值
+ /// 影响降落伞打开阶段的触发时机
+ ///
+ private const double ParachuteDeploymentHeight = 400;
///
/// 降落伞减速加速度,单位:米/秒²
///
///
/// 定义了降落伞减速加速度
///
- private const double ParachuteDeceleration = 50;
+ private const double ParachuteDeceleration = 140;
+
+ ///
+ /// 稳定扫描高度,单位:米
+ ///
+ ///
+ /// 开始螺旋扫描的高度阈值
+ /// 影响扫描阶段的触发时机
+ ///
+ private const double StableScanHeight = 200;
///
/// 垂直下降速度,单位:米/秒
@@ -107,6 +124,15 @@ namespace ThreatSource.Missile
///
private const double VerticalDeclineSpeed = 10;
+ ///
+ /// 螺旋扫描旋转速度,单位:弧度/秒
+ ///
+ ///
+ /// 定义了螺旋扫描时的旋转角速度
+ /// 4转/秒 = 8π弧度/秒
+ ///
+ private const double SpiralRotationSpeed = 8 * Math.PI;
+
///
/// 扫描角度,单位:弧度
///
@@ -116,33 +142,6 @@ namespace ThreatSource.Missile
///
public const double ScanAngle = 30 * Math.PI / 180;
- ///
- /// 开伞高度,单位:米
- ///
- ///
- /// 打开降落伞的高度阈值
- /// 影响降落伞打开阶段的触发时机
- ///
- private const double ParachuteDeploymentHeight = 400;
-
- ///
- /// 减速加速度,单位:米/秒²
- ///
- ///
- /// 减速阶段的减速度大小
- /// 影响速度调整的快慢
- ///
- private const double DecelerationAcceleration = 50;
-
- ///
- /// 稳定扫描高度,单位:米
- ///
- ///
- /// 开始螺旋扫描的高度阈值
- /// 影响扫描阶段的触发时机
- ///
- private const double StableScanHeight = 200;
-
///
/// 目标探测距离,单位:米
///
@@ -386,7 +385,8 @@ namespace ThreatSource.Missile
if (Velocity.Magnitude() <= DecelerationEndSpeed)
{
- Velocity = new Vector3D(0, -DecelerationEndSpeed, 0);
+ //垂直速度设为减速阶段末速
+ Velocity = new Vector3D(Velocity.X, -DecelerationEndSpeed, Velocity.Z);
GuidanceAcceleration = Vector3D.Zero;
}
@@ -402,6 +402,10 @@ namespace ThreatSource.Missile
{
// 如果是,则进入降落伞打开阶段
currentStage = SubmunitionStage.ParachuteDeployment;
+
+ //垂直速度设为减速阶段末速
+ Velocity = new Vector3D(Velocity.X, -DecelerationEndSpeed, Velocity.Z);
+ GuidanceAcceleration = Vector3D.Zero;
}
}
@@ -850,6 +854,7 @@ namespace ThreatSource.Missile
$"运行状态: {currentStage}\n" +
$"扫描角度: {spiralAngle * 180 / Math.PI:F2}°, 弧度值: {spiralAngle:F6}\n" +
$"目标检测: {lastDetectionTime != null}\n" +
+ $"目标位置: {target.Position}\n" +
$"目标距离: {distanceToTarget:F2}米\n" +
$"传感器状态: {(IsSensorsJammed() ? "传感器受到干扰" : "正常工作")}";
diff --git a/tools/ComprehensiveMissileSimulator.cs b/tools/ComprehensiveMissileSimulator.cs
new file mode 100644
index 0000000..d4e8c57
--- /dev/null
+++ b/tools/ComprehensiveMissileSimulator.cs
@@ -0,0 +1,546 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Linq;
+using ThreatSource.Missile;
+using ThreatSource.Simulation;
+using ThreatSource.Utils;
+using ThreatSource.Jamming;
+using ThreatSource.Sensor;
+using ThreatSource.Target;
+using ThreatSource.Guidance;
+using ThreatSource.Indicator;
+
+namespace ThreatSource.Tools.MissileSimulation
+{
+ ///
+ /// 综合导弹模拟器 - 支持6种不同类型的导弹模拟
+ ///
+ public class ComprehensiveMissileSimulator
+ {
+ // 定义仿真结束事件
+ public event EventHandler? SimulationEnded;
+
+ private readonly ISimulationManager simulationManager;
+ private readonly Dictionary missiles;
+ private readonly Dictionary targets;
+ private readonly Dictionary sensors;
+ private Dictionary missileActiveStatus;
+ private bool isRunning;
+ private readonly double timeStep = 0.002; // 时间步长,单位:秒
+
+ ///
+ /// 初始化综合导弹模拟器
+ ///
+ public ComprehensiveMissileSimulator()
+ {
+ simulationManager = new SimulationManager();
+ missiles = new Dictionary();
+ targets = new Dictionary();
+ sensors = new Dictionary();
+ missileActiveStatus = new Dictionary();
+ isRunning = false;
+ InitializeSimulation();
+ }
+
+ ///
+ /// 初始化仿真环境
+ ///
+ private void InitializeSimulation()
+ {
+ // 添加目标(坦克)
+ AddTarget("Tank_1", new Vector3D(0, 0, 0));
+
+ // 添加各种类型的导弹
+ AddLaserSemiActiveMissile();
+ AddLaserBeamRiderMissile();
+ AddTerminalSensitiveMissile();
+ AddInfraredCommandMissile();
+ AddInfraredImagingMissile();
+ AddMillimeterWaveMissile();
+
+ // 添加各种传感器和指示器
+ AddSensorsAndDesignators();
+
+ // 初始化所有导弹的激活状态为false
+ foreach (var missile in missiles.Keys)
+ {
+ missileActiveStatus[missile] = false;
+ missiles[missile].Activate(); // 激活导弹,但不会更新状态
+ }
+ }
+
+ ///
+ /// 添加目标
+ ///
+ private void AddTarget(string targetId, Vector3D position)
+ {
+ var target = new Tank(targetId, position, 0, simulationManager)
+ {
+ Position = position
+ };
+ targets[targetId] = target;
+ simulationManager.RegisterEntity(targetId, target);
+ Console.WriteLine($"添加目标 {targetId},位置:{position}");
+ }
+
+ ///
+ /// 添加激光半主动制导导弹
+ ///
+ private void AddLaserSemiActiveMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "LSGM_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 800,
+ MaxFlightTime = 10,
+ MaxFlightDistance = 5000,
+ MaxAcceleration = 400,
+ InitialPosition = new Vector3D(2000, 100, 100),
+ InitialSpeed = 700,
+ InitialOrientation = new Orientation(Math.PI, -0.1, 0),
+ Type = MissileType.LaserSemiActiveGuidance
+ };
+
+ var missile = new LaserSemiActiveGuidedMissile(properties, simulationManager);
+ missiles["LSGM_1"] = missile;
+ }
+
+ ///
+ /// 添加激光驾束制导导弹
+ ///
+ private void AddLaserBeamRiderMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "LBRM_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 400,
+ MaxFlightTime = 10,
+ MaxFlightDistance = 3000,
+ MaxAcceleration = 400,
+ InitialPosition = new Vector3D(2000, 10, 100),
+ InitialSpeed = 300,
+ InitialOrientation = new Orientation(Math.PI, 0.0, 0.0),
+ Type = MissileType.LaserBeamRiderGuidance
+ };
+
+ var missile = new LaserBeamRiderMissile(properties, simulationManager);
+ missiles["LBRM_1"] = missile;
+ }
+
+ ///
+ /// 添加末敏弹
+ ///
+ private void AddTerminalSensitiveMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "TSM_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 1000,
+ MaxFlightTime = 100,
+ MaxFlightDistance = 5000,
+ MaxAcceleration = 200,
+ InitialPosition = new Vector3D(3000, 0, 0),
+ InitialSpeed = 800,
+ InitialOrientation = new Orientation(Math.PI, 0, 0),
+ Type = MissileType.TerminalSensitiveMissile
+ };
+
+ var missile = new TerminalSensitiveMissile("Tank_1", properties, simulationManager);
+ missiles["TSM_1"] = missile;
+ }
+
+ ///
+ /// 添加红外指令制导导弹
+ ///
+ private void AddInfraredCommandMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "ICGM_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 400,
+ MaxFlightTime = 60,
+ MaxFlightDistance = 5000,
+ MaxAcceleration = 100,
+ InitialPosition = new Vector3D(2000, 10, 100),
+ InitialSpeed = 300,
+ InitialOrientation = new Orientation(Math.PI, 0.0, 0),
+ Type = MissileType.InfraredCommandGuidance
+ };
+
+ var missile = new InfraredCommandGuidedMissile(properties, simulationManager);
+ missiles["ICGM_1"] = missile;
+ }
+
+ ///
+ /// 添加红外成像末制导导弹
+ ///
+ private void AddInfraredImagingMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "ITGM_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 400,
+ MaxFlightTime = 60,
+ MaxFlightDistance = 5000,
+ MaxAcceleration = 50,
+ InitialPosition = new Vector3D(2000, 20, 100),
+ InitialSpeed = 300,
+ InitialOrientation = new Orientation(Math.PI, 0.0, 0),
+ Type = MissileType.InfraredImagingTerminalGuidance
+ };
+
+ var missile = new InfraredImagingTerminalGuidedMissile(properties, simulationManager);
+ missiles["ITGM_1"] = missile;
+ }
+
+ ///
+ /// 添加毫米波末制导导弹
+ ///
+ private void AddMillimeterWaveMissile()
+ {
+ var properties = new MissileProperties
+ {
+ Id = "MMWG_1",
+ Mass = 50,
+ ExplosionRadius = 5,
+ MaxSpeed = 400,
+ MaxFlightTime = 60,
+ MaxFlightDistance = 5000,
+ MaxAcceleration = 50,
+ InitialPosition = new Vector3D(2000, 200, 100),
+ InitialSpeed = 300,
+ InitialOrientation = new Orientation(Math.PI, 0.0, 0),
+ Type = MissileType.MillimeterWaveTerminalGuidance
+ };
+
+ var missile = new MillimeterWaveTerminalGuidedMissile(properties, simulationManager);
+ missiles["MMWG_1"] = missile;
+ }
+
+ ///
+ /// 添加传感器和指示器
+ ///
+ private void AddSensorsAndDesignators()
+ {
+ // 添加激光目标指示器
+ var laserDesignator = new LaserDesignator(
+ "LD_1",
+ "Tank_1",
+ "LSGM_1",
+ 0,
+ new LaserDesignatorConfig
+ {
+ Id = "LD_1",
+ InitialPosition = new Vector3D(2000, 150, 100),
+ LaserPower = 1e6,
+ LaserDivergenceAngle = 0.01
+ },
+ simulationManager
+ );
+ sensors["LD_1"] = laserDesignator;
+
+ // 添加激光驾束仪
+ var laserBeamRider = new LaserBeamRider(
+ "LBR_1",
+ "LBRM_1",
+ "Tank_1",
+ 0,
+ new LaserBeamRiderConfig
+ {
+ Id = "LBR_1",
+ InitialPosition = new Vector3D(2000, 10, 100),
+ LaserPower = 1000,
+ ControlFieldDiameter = 6
+ },
+ simulationManager
+ );
+ sensors["LBR_1"] = laserBeamRider;
+
+ // 添加红外测角仪
+ var infraredTracker = new InfraredTracker(
+ "IT_1",
+ "Tank_1",
+ new InfraredTrackerConfig
+ {
+ Id = "IT_1",
+ InitialPosition = new Vector3D(2000, 0, 100),
+ InitialOrientation = new Orientation(Math.PI, 0, 0),
+ MaxTrackingRange = 10000,
+ FieldOfView = Math.PI / 4,
+ AngleMeasurementAccuracy = 0.0005,
+ UpdateFrequency = 100
+ },
+ simulationManager
+ );
+ sensors["IT_1"] = infraredTracker;
+ }
+
+ ///
+ /// 选择要激活的导弹
+ ///
+ public void SelectMissile(string missileId)
+ {
+ if (!missiles.ContainsKey(missileId))
+ {
+ Console.WriteLine($"错误:找不到导弹 {missileId}");
+ return;
+ }
+
+ // 重置所有导弹的激活状态
+ foreach (var id in missiles.Keys)
+ {
+ missileActiveStatus[id] = false;
+ }
+
+ // 激活选中的导弹
+ missileActiveStatus[missileId] = true;
+ Console.WriteLine($"已选择导弹:{missileId}");
+
+ // 激活相关的传感器和指示器
+ ActivateRelatedSensors(missileId);
+ }
+
+ ///
+ /// 激活与导弹相关的传感器和指示器
+ ///
+ private void ActivateRelatedSensors(string missileId)
+ {
+ // 停用所有传感器
+ foreach (var sensor in sensors.Values)
+ {
+ sensor.Deactivate();
+ }
+
+ // 根据导弹类型激活相应的传感器
+ switch (missileId)
+ {
+ case "LSGM_1": // 激光半主动制导导弹
+ if (sensors.ContainsKey("LD_1"))
+ {
+ sensors["LD_1"].Activate();
+ }
+ break;
+ case "LBRM_1": // 激光驾束制导导弹
+ if (sensors.ContainsKey("LBR_1"))
+ {
+ sensors["LBR_1"].Activate();
+ }
+ break;
+ case "ICGM_1": // 红外指令制导导弹
+ case "ITGM_1": // 红外成像末制导导弹
+ if (sensors.ContainsKey("IT_1"))
+ {
+ sensors["IT_1"].Activate();
+ }
+ break;
+ case "TSM_1": // 末敏弹
+ case "MMWG_1": // 毫米波末制导导弹
+ // 这些导弹使用自身的传感器系统
+ break;
+ }
+ }
+
+ ///
+ /// 应用干扰
+ ///
+ public void ApplyJamming(JammingType type, double power, double duration, Vector3D position)
+ {
+ var jammingParams = new JammingParameters
+ {
+ Type = type,
+ Power = power,
+ Duration = duration,
+ Direction = new Vector3D(1, 0, 0)
+ };
+
+ foreach (var missile in missiles.Values)
+ {
+ if (missile is BaseMissile actualMissile)
+ {
+ // 获取导弹内部的传感器
+ var infraredDetector = actualMissile.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as InfraredDetector;
+ var radiometer = actualMissile.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as MillimeterWaveRadiometer;
+ var rangefinder = actualMissile.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as LaserRangefinder;
+ var altimeter = actualMissile.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as MillimeterWaveAltimeter;
+
+ switch (type)
+ {
+ case JammingType.Infrared:
+ infraredDetector?.ApplyJamming(jammingParams);
+ break;
+ case JammingType.MillimeterWave:
+ radiometer?.ApplyJamming(jammingParams);
+ altimeter?.ApplyJamming(jammingParams);
+ break;
+ case JammingType.Laser:
+ rangefinder?.ApplyJamming(jammingParams);
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 清除干扰
+ ///
+ public void ClearJamming(JammingType type)
+ {
+ var jammingParams = new JammingParameters
+ {
+ Type = type,
+ Power = 0,
+ Duration = 0,
+ Direction = new Vector3D(1, 0, 0)
+ };
+
+ foreach (var missile in missiles.Values)
+ {
+ if (missile is BaseMissile actualMissile)
+ {
+ // 获取导弹内部的传感器
+ var infraredDetector = actualMissile.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as InfraredDetector;
+ var radiometer = actualMissile.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as MillimeterWaveRadiometer;
+ var rangefinder = actualMissile.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as LaserRangefinder;
+ var altimeter = actualMissile.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(actualMissile) as MillimeterWaveAltimeter;
+
+ switch (type)
+ {
+ case JammingType.Infrared:
+ infraredDetector?.ClearJamming(type);
+ break;
+ case JammingType.MillimeterWave:
+ radiometer?.ClearJamming(type);
+ altimeter?.ClearJamming(type);
+ break;
+ case JammingType.Laser:
+ rangefinder?.ClearJamming(type);
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 开始模拟
+ ///
+ public void Start()
+ {
+ isRunning = true;
+ bool hasActiveEntities = true;
+ Console.WriteLine("开始综合导弹模拟...");
+
+ while (isRunning)
+ {
+ hasActiveEntities = false;
+ // 更新所有导弹
+ foreach (var missile in missiles.Values)
+ {
+ if (missile.IsActive && missileActiveStatus[missile.Id])
+ {
+ hasActiveEntities = true;
+ missile.Update(timeStep);
+ Console.WriteLine($"\n导弹状态:\n{missile.GetStatus()}");
+ }
+ }
+
+ // 获取并更新所有子弹
+ var allEntities = simulationManager.GetAllEntities();
+ foreach (var entity in allEntities)
+ {
+ if (entity is TerminalSensitiveSubmunition submunition && submunition.IsActive)
+ {
+ hasActiveEntities = true;
+ submunition.Update(timeStep);
+ Console.WriteLine($"\n子弹状态:\n{submunition.GetStatus()}");
+ }
+ }
+
+ // 如果没有活动的导弹和子弹,退出模拟
+ if (!hasActiveEntities)
+ {
+ isRunning = false;
+ // 触发仿真结束事件
+ SimulationEnded?.Invoke(this, EventArgs.Empty);
+ break;
+ }
+
+ foreach (var target in targets.Values)
+ {
+ target.Update(timeStep);
+ }
+
+ foreach (var sensor in sensors.Values)
+ {
+ if (sensor.IsActive)
+ {
+ sensor.Update(timeStep);
+ }
+ }
+
+ Thread.Sleep((int)(timeStep * 1000));
+ }
+ }
+
+ ///
+ /// 停止模拟
+ ///
+ public void Stop()
+ {
+ isRunning = false;
+ Console.WriteLine("模拟结束");
+ }
+
+ ///
+ /// 获取当前活动的传感器列表
+ ///
+ public (string Id, string Name, bool IsActive)[] GetActiveSensors()
+ {
+ return sensors.Select(s => (
+ s.Value.Id,
+ GetSensorDisplayName(s.Value),
+ s.Value.IsActive
+ )).ToArray();
+ }
+
+ ///
+ /// 获取传感器的显示名称
+ ///
+ private string GetSensorDisplayName(SimulationElement sensor)
+ {
+ return sensor switch
+ {
+ LaserDesignator _ => "激光目标指示器",
+ LaserBeamRider _ => "激光驾束仪",
+ InfraredTracker _ => "红外测角仪",
+ _ => sensor.Id
+ };
+ }
+
+ ///
+ /// 切换传感器的激活状态
+ ///
+ public void ToggleSensor(string sensorId)
+ {
+ if (sensors.TryGetValue(sensorId, out var sensor))
+ {
+ if (sensor.IsActive)
+ sensor.Deactivate();
+ else
+ sensor.Activate();
+
+ Console.WriteLine($"传感器 {GetSensorDisplayName(sensor)} 已{(sensor.IsActive ? "激活" : "停用")}");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/MissileSimulator.cs b/tools/MissileSimulator.cs
deleted file mode 100644
index 51b605f..0000000
--- a/tools/MissileSimulator.cs
+++ /dev/null
@@ -1,217 +0,0 @@
-using ThreatSource.Missile;
-using ThreatSource.Simulation;
-using ThreatSource.Utils;
-using ThreatSource.Jamming;
-using ThreatSource.Sensor;
-using ThreatSource.Target;
-namespace ThreatSource.Tools
-{
- ///
- /// 导弹模拟程序
- ///
- public class MissileSimulator
- {
- private readonly ISimulationManager simulationManager;
- private readonly List missiles;
- private readonly List targets;
- private bool isRunning;
- private readonly double timeStep = 0.0025; // 时间步长,单位:秒
-
- ///
- /// 初始化导弹模拟器
- ///
- public MissileSimulator()
- {
- simulationManager = new SimulationManager();
- missiles = new List();
- targets = new List();
- isRunning = false;
- }
-
- ///
- /// 添加目标
- ///
- /// 目标位置
- /// 目标ID
- public string AddTarget(Vector3D position)
- {
- string targetId = $"target_{targets.Count + 1}";
- var target = new MockTarget(targetId, simulationManager)
- {
- Position = position
- };
- targets.Add(target);
- simulationManager.RegisterEntity(targetId, target);
- Console.WriteLine($"添加目标 {targetId},位置:{position}");
- return targetId;
- }
-
- ///
- /// 发射导弹
- ///
- /// 目标ID
- /// 发射位置
- public void LaunchMissile(string targetId, Vector3D position)
- {
- var properties = new MissileProperties
- {
- Mass = 10,
- ExplosionRadius = 0.1,
- MaxSpeed = 2000,
- MaxFlightTime = 100,
- MaxFlightDistance = 5000,
- MaxAcceleration = 200,
- InitialPosition = position,
- InitialSpeed = 80,
- InitialOrientation = new Orientation(0, -Math.PI/2, 0) // 垂直向下
- };
-
- var missile = new TerminalSensitiveSubmunition(targetId, properties, simulationManager);
- missile.Activate();
- missiles.Add(missile);
- Console.WriteLine($"发射导弹,目标:{targetId},位置:{position}");
- }
-
- ///
- /// 应用干扰
- ///
- /// 干扰类型
- /// 干扰功率
- /// 持续时间
- /// 干扰源位置
- public void ApplyJamming(JammingType type, double power, double duration, Vector3D position)
- {
- var jammingParams = new JammingParameters
- {
- Type = type,
- Power = power,
- Duration = duration,
- Direction = new Vector3D(1, 0, 0)
- };
-
- foreach (var missile in missiles)
- {
- // 获取导弹内部的传感器
- var infraredDetector = missile.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as InfraredDetector;
- var radiometer = missile.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as MillimeterWaveRadiometer;
- var rangefinder = missile.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as LaserRangefinder;
- var altimeter = missile.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as MillimeterWaveAltimeter;
-
- switch (type)
- {
- case JammingType.Infrared:
- infraredDetector?.ApplyJamming(jammingParams);
- break;
- case JammingType.MillimeterWave:
- radiometer?.ApplyJamming(jammingParams);
- altimeter?.ApplyJamming(jammingParams);
- break;
- case JammingType.Laser:
- rangefinder?.ApplyJamming(jammingParams);
- break;
- }
- }
-
- Console.WriteLine($"应用{type}干扰,功率:{power}瓦特,持续时间:{duration}秒,位置:{position}");
- }
-
- ///
- /// 清除干扰
- ///
- /// 干扰类型
- public void ClearJamming(JammingType type)
- {
- foreach (var missile in missiles)
- {
- // 获取导弹内部的传感器
- var infraredDetector = missile.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as InfraredDetector;
- var radiometer = missile.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as MillimeterWaveRadiometer;
- var rangefinder = missile.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as LaserRangefinder;
- var altimeter = missile.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(missile) as MillimeterWaveAltimeter;
-
- switch (type)
- {
- case JammingType.Infrared:
- infraredDetector?.ClearJamming(type);
- break;
- case JammingType.MillimeterWave:
- radiometer?.ClearJamming(type);
- altimeter?.ClearJamming(type);
- break;
- case JammingType.Laser:
- rangefinder?.ClearJamming(type);
- break;
- }
- }
-
- Console.WriteLine($"清除{type}干扰");
- }
-
- ///
- /// 开始模拟
- ///
- public void Start()
- {
- isRunning = true;
- Console.WriteLine("开始模拟...");
-
- while (isRunning)
- {
- // 更新所有实体
- foreach (var missile in missiles.ToList())
- {
- missile.Update(timeStep);
- Console.WriteLine($"\n导弹状态:\n{missile.GetStatus()}");
- }
-
- foreach (var target in targets)
- {
- target.Update(timeStep);
- }
-
- // 移除已经爆炸或自毁的导弹
- missiles.RemoveAll(m => m.GetType().GetField("currentStage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(m)?.ToString() is "Explode" or "SelfDestruct");
-
- // 如果所有导弹都已经结束,停止模拟
- if (!missiles.Any())
- {
- Stop();
- }
-
- Thread.Sleep((int)(timeStep * 1000)); // 按照时间步长暂停
- }
- }
-
- ///
- /// 停止模拟
- ///
- public void Stop()
- {
- isRunning = false;
- Console.WriteLine("模拟结束");
- }
- }
-
- ///
- /// 模拟目标类
- ///
- public class MockTarget : SimulationElement, ITarget
- {
- public MockTarget(string id, ISimulationManager simulationManager) : base(id, new Vector3D(0, 0, 0), new Orientation(), 1000, simulationManager) { }
-
- public override void Update(double deltaTime) { }
-
- public string Type => "Tank";
-
- // 设置目标的物理尺寸
- public double Length => 6.0; // 长度 6 米
- public double Width => 3.0; // 宽度 3 米
- public double Height => 2.5; // 高度 2.5 米
-
- // 设置目标的特征参数
- public double RadarCrossSection => 10.0; // 雷达散射截面积(示例值)
- public double InfraredRadiationIntensity => 500.0; // 红外辐射强度(示例值)
- public double MillimeterWaveRadiationTemperature => 90.0; // 毫米波辐射温度(示例值)
- public double LaserReflectivity => 0.3; // 激光反射率(示例值)
- }
-}
\ No newline at end of file
diff --git a/tools/Program.cs b/tools/Program.cs
index d31bdd8..21b34c6 100644
--- a/tools/Program.cs
+++ b/tools/Program.cs
@@ -1,75 +1,206 @@
using ThreatSource.Utils;
using ThreatSource.Jamming;
+using System;
+using System.Threading;
-namespace ThreatSource.Tools
+namespace ThreatSource.Tools.MissileSimulation
{
class Program
{
static void Main(string[] args)
{
- Console.WriteLine("末敏子弹模拟程序启动...");
- var simulator = new MissileSimulator();
-
- // 添加目标
- var targetId = simulator.AddTarget(new Vector3D(0, 0, 0));
-
- // 发射导弹
- simulator.LaunchMissile(targetId, new Vector3D(40, 450, 40));
-
- // 启动模拟线程
- var simulationThread = new Thread(simulator.Start);
- simulationThread.Start();
-
- // 等待用户输入命令
+ Console.WriteLine("综合导弹模拟程序启动...");
+ var simulator = new ComprehensiveMissileSimulator();
+
+ // 标记是否收到仿真结束事件
+ var simulationEndedEvent = new ManualResetEvent(false);
+
+ // 订阅仿真结束事件
+ simulator.SimulationEnded += (sender, e) => {
+ simulationEndedEvent.Set();
+ };
+
while (true)
{
- Console.WriteLine("\n请输入命令(help查看帮助):");
- var command = Console.ReadLine()?.ToLower();
-
- switch (command)
+ // 显示主菜单,如果返回false则退出程序
+ if (!ShowMainMenu(simulator))
{
- case "help":
- ShowHelp();
- break;
- case "ir":
- simulator.ApplyJamming(JammingType.Infrared, 100, 5, new Vector3D(0, 0, 0));
- break;
- case "mw":
- simulator.ApplyJamming(JammingType.MillimeterWave, 200, 5, new Vector3D(0, 0, 0));
- break;
- case "laser":
- simulator.ApplyJamming(JammingType.Laser, 150, 5, new Vector3D(0, 0, 0));
- break;
- case "clear ir":
- simulator.ClearJamming(JammingType.Infrared);
- break;
- case "clear mw":
- simulator.ClearJamming(JammingType.MillimeterWave);
- break;
- case "clear laser":
- simulator.ClearJamming(JammingType.Laser);
- break;
- case "exit":
- simulator.Stop();
- return;
- default:
- Console.WriteLine("未知命令,请输入help查看帮助");
- break;
+ break;
}
+
+ // 重置事件状态
+ simulationEndedEvent.Reset();
+
+ // 开始仿真
+ var simulationThread = new Thread(simulator.Start);
+ simulationThread.Start();
+
+ // 等待退出命令
+ Console.WriteLine("\n仿真已开始运行。输入 'exit' 退出程序。");
+ bool exitProgram = false;
+ while (true)
+ {
+ if (Console.KeyAvailable)
+ {
+ var input = Console.ReadLine()?.ToLower();
+ if (input == "exit")
+ {
+ simulator.Stop();
+ exitProgram = true;
+ break;
+ }
+ }
+
+ // 检查仿真是否结束
+ if (simulationEndedEvent.WaitOne(100)) // 等待100ms
+ {
+ break;
+ }
+ }
+
+ if (exitProgram)
+ {
+ break;
+ }
+
+ // 等待仿真线程完全结束
+ simulationThread.Join();
+
+ // 显示分隔线和新的仿真选项
+ Console.WriteLine("\n" + new string('=', 50));
+ Console.WriteLine("当前导弹仿真结束,准备开始新的仿真...");
+ Console.WriteLine(new string('=', 50) + "\n");
+ }
+
+ Console.WriteLine("\n程序已退出。");
+ }
+
+ static bool ShowMainMenu(ComprehensiveMissileSimulator simulator)
+ {
+ Console.WriteLine("=== 导弹仿真系统主菜单 ===\n");
+
+ // 第一步:选择导弹
+ if (!SelectMissile(simulator))
+ return false;
+
+ // 第二步:配置传感器
+ if (!ConfigureSensors(simulator))
+ return false;
+
+ // 第三步:配置干扰
+ if (!ConfigureJamming(simulator))
+ return false;
+
+ return true;
+ }
+
+ static bool SelectMissile(ComprehensiveMissileSimulator simulator)
+ {
+ var missiles = new[]
+ {
+ ("LSGM_1", "激光半主动制导导弹"),
+ ("LBRM_1", "激光驾束制导导弹"),
+ ("TSM_1", "末敏弹"),
+ ("ICGM_1", "红外指令制导导弹"),
+ ("ITGM_1", "红外成像末制导导弹"),
+ ("MMWG_1", "毫米波末制导导弹")
+ };
+
+ while (true)
+ {
+ Console.WriteLine("\n第一步:请选择导弹类型:");
+ for (int i = 0; i < missiles.Length; i++)
+ {
+ Console.WriteLine($" {i + 1}. {missiles[i].Item2}");
+ }
+ Console.WriteLine(" exit. 退出程序");
+
+ var input = Console.ReadLine()?.ToLower();
+ if (input == "exit")
+ return false;
+
+ if (int.TryParse(input, out int choice) &&
+ choice >= 1 && choice <= missiles.Length)
+ {
+ simulator.SelectMissile(missiles[choice - 1].Item1);
+ return true;
+ }
+ Console.WriteLine("无效选择,请重试");
}
}
-
- static void ShowHelp()
+
+ static bool ConfigureSensors(ComprehensiveMissileSimulator simulator)
{
- Console.WriteLine("可用命令:");
- Console.WriteLine(" help - 显示帮助信息");
- Console.WriteLine(" ir - 应用红外干扰");
- Console.WriteLine(" mw - 应用毫米波干扰");
- Console.WriteLine(" laser - 应用激光干扰");
- Console.WriteLine(" clear ir - 清除红外干扰");
- Console.WriteLine(" clear mw - 清除毫米波干扰");
- Console.WriteLine(" clear laser - 清除激光干扰");
- Console.WriteLine(" exit - 退出程序");
+ while (true)
+ {
+ Console.WriteLine("\n第二步:配置传感器和指示器");
+ Console.WriteLine("当前传感器状态:");
+ var sensors = simulator.GetActiveSensors();
+ for (int i = 0; i < sensors.Length; i++)
+ {
+ Console.WriteLine($" {i + 1}. {sensors[i].Name} [{(sensors[i].IsActive ? "激活" : "未激活")}]");
+ }
+ Console.WriteLine(" 0. 继续下一步");
+ Console.WriteLine(" exit. 退出程序");
+
+ var input = Console.ReadLine()?.ToLower();
+ if (input == "exit")
+ return false;
+
+ if (int.TryParse(input, out int choice))
+ {
+ if (choice == 0) return true;
+ if (choice >= 1 && choice <= sensors.Length)
+ {
+ simulator.ToggleSensor(sensors[choice - 1].Id);
+ continue;
+ }
+ }
+ Console.WriteLine("无效选择,请重试");
+ }
+ }
+
+ static bool ConfigureJamming(ComprehensiveMissileSimulator simulator)
+ {
+ var jammingTypes = new[]
+ {
+ (JammingType.Infrared, "红外干扰"),
+ (JammingType.MillimeterWave, "毫米波干扰"),
+ (JammingType.Laser, "激光干扰")
+ };
+
+ var jammingStatus = new bool[jammingTypes.Length];
+
+ while (true)
+ {
+ Console.WriteLine("\n第三步:配置干扰方式");
+ Console.WriteLine("当前干扰状态:");
+ for (int i = 0; i < jammingTypes.Length; i++)
+ {
+ Console.WriteLine($" {i + 1}. {jammingTypes[i].Item2} [{(jammingStatus[i] ? "激活" : "未激活")}]");
+ }
+ Console.WriteLine(" 0. 开始仿真");
+ Console.WriteLine(" exit. 退出程序");
+
+ var input = Console.ReadLine()?.ToLower();
+ if (input == "exit")
+ return false;
+
+ if (int.TryParse(input, out int choice))
+ {
+ if (choice == 0) return true;
+ if (choice >= 1 && choice <= jammingTypes.Length)
+ {
+ jammingStatus[choice - 1] = !jammingStatus[choice - 1];
+ if (jammingStatus[choice - 1])
+ simulator.ApplyJamming(jammingTypes[choice - 1].Item1, 100, 5, new Vector3D(0, 0, 0));
+ else
+ simulator.ClearJamming(jammingTypes[choice - 1].Item1);
+ continue;
+ }
+ }
+ Console.WriteLine("无效选择,请重试");
+ }
}
}
}
\ No newline at end of file