修改了detectionAngle的 bug

This commit is contained in:
Tian jianyong 2025-01-07 02:58:28 +08:00
parent ee2128b36e
commit a97cb6a909
10 changed files with 614 additions and 51 deletions

View File

@ -126,18 +126,24 @@ namespace ThreatSource.Tests.Jamming
var mockTarget = new MockTarget("target1") { Position = new Vector3D(100, 0, 100) };
mockManager.RegisterEntity("target1", mockTarget);
// 初始化子弹设置初始位置在目标正上方120米处刚好进入探测距离
// 初始化子弹
var properties = new MissileProperties
{
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 2000
MaxSpeed = 500,
MaxFlightTime = 100 // 设置最大飞行时间为100秒
};
var submunition = new TerminalSensitiveSubmunition("target1", properties, mockManager)
{
Position = new Vector3D(100, 120, 100), // 设置在目标正上方120米处
Position = new Vector3D(0, 200, 0), // 设置在目标正上方200米处(稳定扫描高度)
Velocity = new Vector3D(0, -10, 0) // 设置垂直下降速度为10米/秒
};
// 重置飞行时间
var flightTimeField = submunition.GetType().GetField("flightTime", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
flightTimeField?.SetValue(submunition, 0.0);
submunition.Activate();
// 获取子弹内部的传感器实例
@ -150,15 +156,7 @@ namespace ThreatSource.Tests.Jamming
radiometer?.Activate();
rangefinder?.Activate();
// 更新子弹状态让它进入Detection阶段
for (int i = 0; i < 3; i++)
{
submunition.Update(0.1);
var currentStatus = submunition.GetStatus();
Console.WriteLine($"更新 {i + 1} 后的状态:{currentStatus}"); // 添加状态输出,帮助调试
}
// 手动设置子弹阶段为Detection
// 手动设置到探测阶段
var stageField = submunition.GetType().GetField("currentStage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var stageEnum = submunition.GetType().GetNestedType("SubmunitionStage", System.Reflection.BindingFlags.NonPublic);
var detectionStage = Enum.Parse(stageEnum!, "Detection");
@ -204,6 +202,126 @@ namespace ThreatSource.Tests.Jamming
Assert.IsFalse(infraredDetector?.IsActive == false || radiometer?.IsActive == false, "传感器应该恢复正常工作状态");
Assert.IsFalse(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
}
[TestMethod]
public void TestSubmunitionHitDetection()
{
// 初始化仿真管理器
var mockManager = new MockSimulationManager();
var mockTarget = new MockTarget("target1") { Position = new Vector3D(0, 0, 0) };
mockManager.RegisterEntity("target1", mockTarget);
// 初始化子弹设置初始位置在目标正上方6米处
var properties = new MissileProperties
{
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500 // 设置最大速度为500米/秒,确保大于攻击速度
};
var submunition = new TerminalSensitiveSubmunition("target1", properties, mockManager)
{
Position = new Vector3D(0, 6, 0), // 设置在目标正上方6米处
Velocity = new Vector3D(0, -1, 0) // 设置垂直下降速度为1米/秒
};
submunition.Activate();
// 手动设置子弹阶段为Attack
var stageField = submunition.GetType().GetField("currentStage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var stageEnum = submunition.GetType().GetNestedType("SubmunitionStage", System.Reflection.BindingFlags.NonPublic);
var attackStage = Enum.Parse(stageEnum!, "Attack");
stageField?.SetValue(submunition, attackStage);
// 设置攻击方向和速度
var scanDirectionField = submunition.GetType().GetField("scanDirection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
scanDirectionField?.SetValue(submunition, new Vector3D(0, -1, 0)); // 设置向下的攻击方向
var attackSpeedField = submunition.GetType().GetField("AttackSpeed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
attackSpeedField?.SetValue(submunition, 10.0); // 设置攻击速度为10米/秒
// 更新子弹状态每次更新0.1秒
for (int i = 0; i < 10; i++)
{
var beforePosition = submunition.Position;
submunition.Update(0.1);
var afterPosition = submunition.Position;
var status = submunition.GetStatus();
Console.WriteLine($"更新 {i + 1}:");
Console.WriteLine($"位置: 从 {beforePosition} 到 {afterPosition}");
Console.WriteLine($"状态: {status}");
if (status.Contains("Explode"))
{
Console.WriteLine("子弹已爆炸!");
return;
}
}
Assert.Fail("子弹应该在接近目标时爆炸");
}
[TestMethod]
public void TestSubmunitionScanAndAttack()
{
// 初始化仿真管理器
var mockManager = new MockSimulationManager();
// 设置目标在子弹下方25度角的位置小于扫描角度30度
var mockTarget = new MockTarget("target1") { Position = new Vector3D(5, -10, 0) }; // 目标在 (5,-10,0)约25度
mockManager.RegisterEntity("target1", mockTarget);
// 初始化子弹
var properties = new MissileProperties
{
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500
};
var submunition = new TerminalSensitiveSubmunition("target1", properties, mockManager)
{
Position = new Vector3D(0, 0, 0), // 子弹在原点
};
submunition.Activate();
// 手动设置到探测阶段
var stageField = submunition.GetType().GetField("currentStage", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var stageEnum = submunition.GetType().GetNestedType("SubmunitionStage", System.Reflection.BindingFlags.NonPublic);
var detectionStage = Enum.Parse(stageEnum!, "Detection");
stageField?.SetValue(submunition, detectionStage);
// 模拟探测过程
for (int i = 0; i < 100; i++)
{
var beforePosition = submunition.Position;
var beforeStage = stageField?.GetValue(submunition)?.ToString();
submunition.Update(0.02); // 20ms的更新间隔
var afterPosition = submunition.Position;
var afterStage = stageField?.GetValue(submunition)?.ToString();
Console.WriteLine($"更新 {i + 1}:");
Console.WriteLine($"阶段: 从 {beforeStage} 到 {afterStage}");
Console.WriteLine($"位置: 从 {beforePosition} 到 {afterPosition}");
// 如果进入攻击阶段,检查攻击方向
if (afterStage == "Attack")
{
var scanDirectionField = submunition.GetType().GetField("scanDirection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var scanDirectionValue = scanDirectionField?.GetValue(submunition) ?? throw new Exception("扫描方向不能为空");
var scanDirection = (Vector3D)scanDirectionValue;
Console.WriteLine($"攻击方向: {scanDirection}");
// 计算理论上的正确方向(从子弹指向目标)
var expectedDirection = (mockTarget.Position - submunition.Position).Normalize();
Console.WriteLine($"期望方向: {expectedDirection}");
// 检查方向误差是否在可接受范围内30度
var angle = Math.Acos(Vector3D.DotProduct(scanDirection.Normalize(), expectedDirection));
Assert.IsTrue(angle <= Math.PI / 6, $"攻击方向误差过大: {angle * 180 / Math.PI:F2}度");
return;
}
}
Assert.Fail("100次更新后仍未进入攻击阶段");
}
}
// 模拟仿真管理器
@ -256,9 +374,8 @@ namespace ThreatSource.Tests.Jamming
}
// 模拟目标
public class MockTarget : SimulationElement
public class MockTarget(string id) : SimulationElement(id, new Vector3D(100, 50, 100), new Orientation(), 1000, new MockSimulationManager())
{
public MockTarget(string id) : base(id, new Vector3D(100, 50, 100), new Orientation(), 1000, null) { }
public override void Update(double deltaTime) { }
}
}

View File

@ -248,12 +248,12 @@ namespace ThreatSource.Missile
{
Id = $"{Id}_Sub_{i}",
InitialPosition = Position,
InitialOrientation = orientationToTarget,
InitialSpeed = 200, // 子弹初始速度
InitialOrientation = Orientation, // 子弹初始方向等于母弹方向
InitialSpeed = Velocity.Magnitude(), // 子弹初始速度等于母弹速度
MaxSpeed = 2000,
MaxFlightTime = 50,
MaxFlightDistance = 1000,
MaxAcceleration = 50,
MaxFlightTime = 100,
MaxFlightDistance = 2000,
MaxAcceleration = 1000,
ProportionalNavigationCoefficient = 3,
Mass = 10,
ExplosionRadius = MissileProperties.ExplosionRadius,

View File

@ -138,7 +138,7 @@ namespace ThreatSource.Missile
/// 攻击阶段的期望速度
/// 影响末端制导的精度
/// </remarks>
private const double AttackSpeed = 500;
private double AttackSpeed = 200;
/// <summary>
/// 获取或设置最后一次检测到目标的时间
@ -416,16 +416,6 @@ namespace ThreatSource.Missile
/// </remarks>
private void UpdateStableScanStage(double deltaTime)
{
if(!radiometer.IsActive)
{
// 激活毫米波辐射计
radiometer.Activate();
}
if(!infraredDetector.IsActive)
{
// 激活红外探测器
infraredDetector.Activate();
}
if(!rangefinder.IsActive)
{
// 激活激光测距仪
@ -439,6 +429,29 @@ namespace ThreatSource.Missile
return;
}
// 更新螺旋角度
double oldSpiralAngle = spiralAngle;
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime) % (2 * Math.PI);
Console.WriteLine($"[ANGLE] 螺旋角更新: {oldSpiralAngle * 180 / Math.PI:F2}°({oldSpiralAngle:F6}) -> {spiralAngle * 180 / Math.PI:F2}°({spiralAngle:F6})");
// 计算水平速度分量
double horizontalSpeed = VerticalDeclineSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度,执行螺旋运动
Velocity = new(horizontalVelocity.X, -VerticalDeclineSpeed, horizontalVelocity.Z);
// 更新扫描方向(虽然这时候不开启探测器,但保持方向更新)
scanDirection = new(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
// 如果距离小于等于目标探测距离,则进入目标探测阶段
if (((RangefinderSensorData)rangefinder.GetSensorData()).Distance <= TargetDetectionDistance)
{
@ -459,6 +472,17 @@ namespace ThreatSource.Missile
/// </remarks>
private void UpdateDetectionStage(double deltaTime)
{
// 激活毫米波辐射计
if(!radiometer.IsActive)
{
radiometer.Activate();
}
// 激活红外探测器
if(!infraredDetector.IsActive)
{
infraredDetector.Activate();
}
// 检查传感器干扰状态
if (IsSensorsJammed())
{
@ -467,7 +491,12 @@ namespace ThreatSource.Missile
}
// 更新螺旋角度
double oldSpiralAngle = spiralAngle;
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime) % (2 * Math.PI);
if (lastDetectionTime != null)
{
Console.WriteLine($"[DEBUG] 螺旋角更新: {oldSpiralAngle * 180 / Math.PI:F2}° -> {spiralAngle * 180 / Math.PI:F2}°");
}
// 计算水平速度分量
double horizontalSpeed = VerticalDeclineSpeed * Math.Tan(ScanAngle);
@ -492,15 +521,15 @@ namespace ThreatSource.Missile
if (isRadiationDetected || isInfraredDetected)
{
double currentTime = DateTime.Now.Ticks;
double currentTime = FlightTime;
if (lastDetectionTime == null)
{
lastDetectionTime = currentTime;
Console.WriteLine($"[DEBUG] 首次探测到目标:");
}
else
{
double timeSinceLastDetection = currentTime - lastDetectionTime.Value;
// 重新检测到目标的时间大于等于螺旋周期的90%,则二次确认目标
if (timeSinceLastDetection >= 0.9 * 2 * Math.PI / SpiralRotationSpeed)
{
Console.WriteLine($"目标确认,进入攻击阶段。距离上次检测时间:{timeSinceLastDetection:F2}秒");
@ -524,25 +553,38 @@ namespace ThreatSource.Missile
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 攻击阶段处理:
/// - 获取目标位置
/// - 计算攻击速度
/// - 使用当前的螺旋角和锥角计算攻击方向
/// - 使用扫描方向作为攻击方向,弹丸没有传感器,只进行弹道运动
/// - 更新速度和位置
/// - 检查命中条件
/// - 检查命中条件:使用纯几何计算
/// </remarks>
private void UpdateAttackStage(double deltaTime)
{
// 攻击逻辑
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
Vector3D targetPosition = target.Position;
// 使用当前的螺旋角和锥角计算攻击方向
scanDirection = new Vector3D(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
).Normalize();
// 计算攻击速度,攻击角度为最后的扫描方向
// 使用 AttackSpeed 设置攻击速度
Velocity = scanDirection * AttackSpeed;
Position += Velocity * deltaTime;
IsGuidance = false; // 明确声明这是无制导的直线运动
GuidanceAcceleration = Vector3D.Zero; // 清除任何可能的加速度
// 检查命中条件
if ((targetPosition - Position).Magnitude() <= MissileProperties.ExplosionRadius)
// 检查命中条件:使用纯几何计算
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
if ((target.Position - Position).Magnitude() <= MissileProperties.ExplosionRadius)
{
currentStage = SubmunitionStage.Explode;
return;
}
// 检查自毁条件
if (Position.Y <= 0)
{
currentStage = SubmunitionStage.SelfDestruct;
return;
}
}
@ -659,12 +701,14 @@ namespace ThreatSource.Missile
/// </remarks>
public override string GetStatus()
{
var status = $"{base.GetStatus()}\n运行状态: {currentStage}\n检测角度: {detectionAngle * 180 / Math.PI:F2}°\n螺旋角度: {spiralAngle * 180 / Math.PI:F2}°\n目标检测: {lastDetectionTime != null}";
var status = $"{base.GetStatus()}\n" +
$"运行状态: {currentStage}\n" +
$"扫描角度: {spiralAngle * 180 / Math.PI:F2}°, 弧度值: {spiralAngle:F6}\n" +
$"目标检测: {lastDetectionTime != null}";
// 使用IsSensorsJammed方法检查当前阶段所需传感器的状态
if (IsSensorsJammed())
{
status += "\n传感器受到干扰";
status += "\n传感器状态: 受到干扰";
}
return status;

View File

@ -95,6 +95,8 @@ namespace ThreatSource.Sensor
WaveLength = waveLength;
PulseRate = pulseRate;
Accuracy = accuracy;
// 初始化距离为最大量程
currentDistance = maxRange;
}
/// <summary>
@ -110,12 +112,22 @@ namespace ThreatSource.Sensor
/// </remarks>
public override void Update(double deltaTime)
{
// 激光测距仪的更新逻辑,考虑测量精度
if (IsActive)
{
// 计算斜向距离:高度/cos(扫描角度)
double slantRange = submunition.Position.Y / Math.Cos(TerminalSensitiveSubmunition.ScanAngle);
// 计算到地面的垂直距离和水平距离
double verticalDistance = submunition.Position.Y;
double horizontalDistance = Math.Sqrt(
submunition.Position.X * submunition.Position.X +
submunition.Position.Z * submunition.Position.Z);
// 计算实际的斜距
double slantRange = Math.Sqrt(verticalDistance * verticalDistance + horizontalDistance * horizontalDistance);
// 添加测量精度引入的随机误差
currentDistance = slantRange + (2 * new Random().NextDouble() - 1) * Accuracy;
// 调试输出
Console.WriteLine($"激光测距仪 - 垂直距离: {verticalDistance:F2}m, 水平距离: {horizontalDistance:F2}m, 斜距: {slantRange:F2}m, 测量距离: {currentDistance:F2}m");
}
}

View File

@ -9,9 +9,9 @@ namespace ThreatSource.Simulation.Testing
/// </summary>
public class TestSimulationAdapter : ISimulationAdapter
{
private readonly Dictionary<string, object> _testEntities = new();
private readonly List<object> _receivedEvents = new();
private readonly List<object> _publishedEvents = new();
private readonly Dictionary<string, object> _testEntities = [];
private readonly List<object> _receivedEvents = [];
private readonly List<object> _publishedEvents = [];
private ISimulationManager? _simulationManager;
/// <summary>

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Numerics;
public class MissileSimulator
{
private List<TerminalSensitiveSubmunition> missiles = new List<TerminalSensitiveSubmunition>();
private SimulationManager simulationManager;
private double InitialHeight;
public void LaunchMissile(Vector3 target)
{
var missile = new TerminalSensitiveSubmunition
{
Position = new Vector3(target.X, target.Y, InitialHeight),
Velocity = new Vector3(0, 0, 0),
Target = target
};
missiles.Add(missile);
simulationManager.AddElement(missile);
}
}

75
src/tools/Program.cs Normal file
View File

@ -0,0 +1,75 @@
using ThreatSource.Utils;
using ThreatSource.Jamming;
namespace ThreatSource.Tools
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("末敏子弹模拟程序启动...");
var simulator = new MissileSimulator();
// 添加目标
var targetId = simulator.AddTarget(new Vector3D(100, 0, 100));
// 发射导弹
simulator.LaunchMissile(targetId, new Vector3D(100, 400, 100));
// 启动模拟线程
var simulationThread = new Thread(simulator.Start);
simulationThread.Start();
// 等待用户输入命令
while (true)
{
Console.WriteLine("\n请输入命令help查看帮助");
var command = Console.ReadLine()?.ToLower();
switch (command)
{
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;
}
}
}
static void ShowHelp()
{
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 - 退出程序");
}
}
}

203
tools/MissileSimulator.cs Normal file
View File

@ -0,0 +1,203 @@
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using ThreatSource.Jamming;
using ThreatSource.Sensor;
namespace ThreatSource.Tools
{
/// <summary>
/// 导弹模拟程序
/// </summary>
public class MissileSimulator
{
private readonly ISimulationManager simulationManager;
private readonly List<TerminalSensitiveSubmunition> missiles;
private readonly List<SimulationElement> targets;
private bool isRunning;
private readonly double timeStep = 0.005; // 时间步长,单位:秒
/// <summary>
/// 初始化导弹模拟器
/// </summary>
public MissileSimulator()
{
simulationManager = new SimulationManager();
missiles = new List<TerminalSensitiveSubmunition>();
targets = new List<SimulationElement>();
isRunning = false;
}
/// <summary>
/// 添加目标
/// </summary>
/// <param name="position">目标位置</param>
/// <returns>目标ID</returns>
public string AddTarget(Vector3D position)
{
string targetId = $"target_{targets.Count + 1}";
var target = new MockTarget(targetId)
{
Position = position
};
targets.Add(target);
simulationManager.RegisterEntity(targetId, target);
Console.WriteLine($"添加目标 {targetId},位置:{position}");
return targetId;
}
/// <summary>
/// 发射导弹
/// </summary>
/// <param name="targetId">目标ID</param>
/// <param name="position">发射位置</param>
public void LaunchMissile(string targetId, Vector3D position)
{
var properties = new MissileProperties
{
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 2000
};
var missile = new TerminalSensitiveSubmunition(targetId, properties, simulationManager)
{
Position = position,
Velocity = new Vector3D(0, -10, 0) // 初始垂直下降速度
};
missile.Activate();
missiles.Add(missile);
Console.WriteLine($"发射导弹,目标:{targetId},位置:{position}");
}
/// <summary>
/// 应用干扰
/// </summary>
/// <param name="type">干扰类型</param>
/// <param name="power">干扰功率</param>
/// <param name="duration">持续时间</param>
/// <param name="position">干扰源位置</param>
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}");
}
/// <summary>
/// 清除干扰
/// </summary>
/// <param name="type">干扰类型</param>
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}干扰");
}
/// <summary>
/// 开始模拟
/// </summary>
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)); // 按照时间步长暂停
}
}
/// <summary>
/// 停止模拟
/// </summary>
public void Stop()
{
isRunning = false;
Console.WriteLine("模拟结束");
}
}
/// <summary>
/// 模拟目标类
/// </summary>
public class MockTarget : SimulationElement
{
public MockTarget(string id) : base(id, new Vector3D(0, 0, 0), new Orientation(), 1000, null) { }
public override void Update(double deltaTime) { }
}
}

75
tools/Program.cs Normal file
View File

@ -0,0 +1,75 @@
using ThreatSource.Utils;
using ThreatSource.Jamming;
namespace ThreatSource.Tools
{
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(50, 400, 50));
// 启动模拟线程
var simulationThread = new Thread(simulator.Start);
simulationThread.Start();
// 等待用户输入命令
while (true)
{
Console.WriteLine("\n请输入命令help查看帮助");
var command = Console.ReadLine()?.ToLower();
switch (command)
{
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;
}
}
}
static void ShowHelp()
{
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 - 退出程序");
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../ThreatSource/ThreatSource.csproj" />
</ItemGroup>
</Project>