修改了detectionAngle的 bug
This commit is contained in:
parent
ee2128b36e
commit
a97cb6a909
@ -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) { }
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
23
src/tools/MissileSimulator.cs
Normal file
23
src/tools/MissileSimulator.cs
Normal 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
75
src/tools/Program.cs
Normal 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
203
tools/MissileSimulator.cs
Normal 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
75
tools/Program.cs
Normal 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 - 退出程序");
|
||||
}
|
||||
}
|
||||
}
|
||||
14
tools/ThreatSource.Tools.csproj
Normal file
14
tools/ThreatSource.Tools.csproj
Normal 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>
|
||||
Loading…
Reference in New Issue
Block a user