修改了测试代码,完善了末敏弹的探测逻辑,完善了几个传感器的逻辑

This commit is contained in:
Tian jianyong 2025-02-17 18:19:13 +08:00
parent 9ce5ec248e
commit bb7e66673a
17 changed files with 740 additions and 407 deletions

View File

@ -3,52 +3,67 @@ using ThreatSource.Jamming;
using ThreatSource.Sensor;
using ThreatSource.Missile;
using ThreatSource.Simulation;
using ThreatSource.Simulation.Testing;
using ThreatSource.Target;
using ThreatSource.Utils;
using System.Linq;
namespace ThreatSource.Tests.Jamming
{
[TestClass]
public class JammingTests
{
private InfraredDetector infraredDetector = null!;
private MillimeterWaveRadiometer radiometer = null!;
private LaserRangefinder rangefinder = null!;
private MillimeterWaveAltimeter altimeter = null!;
private TerminalSensitiveSubmunition submunition = null!;
private MockSimulationManager simulationManager = null!;
private SimulationManager _simulationManager = null!;
private TestSimulationAdapter _testAdapter = null!;
private Tank _tank = null!;
private TerminalSensitiveSubmunition _submunition = null!;
private InfraredDetector _infraredDetector = null!;
private MillimeterWaveRadiometer _radiometer = null!;
private LaserRangefinder _rangefinder = null!;
private MillimeterWaveAltimeter _altimeter = null!;
[TestInitialize]
public void Setup()
{
simulationManager = new MockSimulationManager();
_simulationManager = new SimulationManager();
_testAdapter = new TestSimulationAdapter(_simulationManager);
_simulationManager.SetSimulationAdapter(_testAdapter);
// 创建目标
_tank = new Tank("tank1", new Vector3D(100, 0, 100), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank1", _tank);
_tank.Activate();
// 创建子弹
var properties = new MissileProperties
{
Id = "submunition1",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 2000
MaxSpeed = 2000,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(20, 150, 0),
InitialSpeed = 20,
InitialOrientation = new Orientation(0, -Math.PI/4, 0)
};
submunition = new TerminalSensitiveSubmunition("target1", properties, simulationManager);
_submunition = new TerminalSensitiveSubmunition("tank1", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition1", _submunition);
// 初始化传感器
infraredDetector = new InfraredDetector(submunition, 500, InfraredBand.Short, 10);
radiometer = new MillimeterWaveRadiometer(submunition, 500, MillimeterWaveBand.Band3, 11);
altimeter = new MillimeterWaveAltimeter(submunition, 1000, MillimeterWaveBand.Band8, 0.5, 25);
rangefinder = new LaserRangefinder(submunition, 500, 1.06, 100, 0.5);
// 设置子弹到Detection阶段
for (int i = 0; i < 5; i++)
{
submunition.Update(0.1);
}
_infraredDetector = new InfraredDetector(_submunition, 500, InfraredBand.Short, 10);
_radiometer = new MillimeterWaveRadiometer(_submunition, 500, MillimeterWaveBand.Band3, 11);
_altimeter = new MillimeterWaveAltimeter(_submunition, 1000, MillimeterWaveBand.Band8, 0.5, 25);
_rangefinder = new LaserRangefinder(_submunition, 500, 1.06, 100, 0.5);
}
[TestMethod]
public void TestInfraredJamming()
{
// 激活红外探测器
infraredDetector.Activate();
Assert.IsTrue(infraredDetector.IsActive);
_infraredDetector.Activate();
Assert.IsTrue(_infraredDetector.IsActive);
// 应用红外干扰
var jammingParams = new JammingParameters
@ -60,20 +75,20 @@ namespace ThreatSource.Tests.Jamming
Direction = new Vector3D(1, 0, 0)
};
infraredDetector.ApplyJamming(jammingParams);
Assert.IsFalse(infraredDetector.IsActive, "红外探测器应该在干扰下失效");
_infraredDetector.ApplyJamming(jammingParams);
Assert.IsFalse(_infraredDetector.IsActive, "红外探测器应该在干扰下失效");
// 清除干扰
infraredDetector.ClearJamming(JammingType.Infrared);
Assert.IsTrue(infraredDetector.IsActive, "红外探测器应该在干扰清除后恢复工作");
_infraredDetector.ClearJamming(JammingType.Infrared);
Assert.IsTrue(_infraredDetector.IsActive, "红外探测器应该在干扰清除后恢复工作");
}
[TestMethod]
public void TestMillimeterWaveJamming()
{
// 激活毫米波辐射计
radiometer.Activate();
Assert.IsTrue(radiometer.IsActive);
_radiometer.Activate();
Assert.IsTrue(_radiometer.IsActive);
// 应用毫米波干扰
var jammingParams = new JammingParameters
@ -85,20 +100,20 @@ namespace ThreatSource.Tests.Jamming
Direction = new Vector3D(1, 0, 0)
};
radiometer.ApplyJamming(jammingParams);
Assert.IsFalse(radiometer.IsActive, "毫米波辐射计应该在干扰下失效");
_radiometer.ApplyJamming(jammingParams);
Assert.IsFalse(_radiometer.IsActive, "毫米波辐射计应该在干扰下失效");
// 清除干扰
radiometer.ClearJamming(JammingType.MillimeterWave);
Assert.IsTrue(radiometer.IsActive, "毫米波辐射计应该在干扰清除后恢复工作");
_radiometer.ClearJamming(JammingType.MillimeterWave);
Assert.IsTrue(_radiometer.IsActive, "毫米波辐射计应该在干扰清除后恢复工作");
}
[TestMethod]
public void TestLaserJamming()
{
// 激活激光测距仪
rangefinder.Activate();
Assert.IsTrue(rangefinder.IsActive);
_rangefinder.Activate();
Assert.IsTrue(_rangefinder.IsActive);
// 应用激光干扰
var jammingParams = new JammingParameters
@ -110,272 +125,522 @@ namespace ThreatSource.Tests.Jamming
Direction = new Vector3D(1, 0, 0)
};
rangefinder.ApplyJamming(jammingParams);
Assert.IsFalse(rangefinder.IsActive, "激光测距仪应该在干扰下失效");
_rangefinder.ApplyJamming(jammingParams);
Assert.IsFalse(_rangefinder.IsActive, "激光测距仪应该在干扰下失效");
// 清除干扰
rangefinder.ClearJamming(JammingType.Laser);
Assert.IsTrue(rangefinder.IsActive, "激光测距仪应该在干扰清除后恢复工作");
}
[TestMethod]
public void TestSubmunitionJammingResponse()
{
// 初始化仿真管理器
var mockManager = new MockSimulationManager();
var mockTarget = new MockTarget("target1") { Position = new Vector3D(100, 0, 100) };
mockManager.RegisterEntity("target1", mockTarget);
// 初始化子弹
var properties = new MissileProperties
{
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500,
MaxFlightTime = 100 // 设置最大飞行时间为100秒
};
var submunition = new TerminalSensitiveSubmunition("target1", properties, mockManager)
{
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();
// 获取子弹内部的传感器实例
var infraredDetector = submunition.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as InfraredDetector;
var radiometer = submunition.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as MillimeterWaveRadiometer;
var rangefinder = submunition.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as LaserRangefinder;
// 激活传感器
infraredDetector?.Activate();
radiometer?.Activate();
rangefinder?.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);
// 创建干扰参数
var infraredJamming = new JammingParameters
{
Type = JammingType.Infrared,
Power = 100,
Duration = 5,
Direction = new Vector3D(1, 0, 0)
};
var millimeterWaveJamming = new JammingParameters
{
Type = JammingType.MillimeterWave,
Power = 200,
Duration = 5,
Direction = new Vector3D(1, 0, 0)
};
// 应用干扰
infraredDetector?.ApplyJamming(infraredJamming);
radiometer?.ApplyJamming(millimeterWaveJamming);
// 更新子弹状态
submunition.Update(0.1);
// 验证子弹响应
var status = submunition.GetStatus();
Console.WriteLine($"应用干扰后的状态:{status}"); // 添加状态输出,帮助调试
Assert.IsTrue(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器受到干扰");
// 清除干扰
infraredDetector?.ClearJamming(JammingType.Infrared);
radiometer?.ClearJamming(JammingType.MillimeterWave);
// 再次更新子弹状态
submunition.Update(0.1);
status = submunition.GetStatus();
Console.WriteLine($"清除干扰后的状态:{status}"); // 添加状态输出,帮助调试
Assert.IsFalse(infraredDetector?.IsActive == false || radiometer?.IsActive == false, "传感器应该恢复正常工作状态");
Assert.IsFalse(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
_rangefinder.ClearJamming(JammingType.Laser);
Assert.IsTrue(_rangefinder.IsActive, "激光测距仪应该在干扰清除后恢复工作");
}
[TestMethod]
public void TestSubmunitionHitDetection()
{
// 初始化仿真管理器
var mockManager = new MockSimulationManager();
var mockTarget = new MockTarget("target1") { Position = new Vector3D(0, 0, 0) };
mockManager.RegisterEntity("target1", mockTarget);
// 创建目标
var tank = new Tank("tank3", new Vector3D(0, 0, 0), 0, _simulationManager);
_simulationManager.RegisterEntity("tank3", tank);
tank.Activate();
// 初始化子弹设置初始位置在目标正上方6米处
// 创建子弹
var properties = new MissileProperties
{
Id = "submunition3",
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米/秒
MaxSpeed = 500,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(0, 6, 0),
InitialSpeed = 10,
InitialOrientation = new Orientation(0, -Math.PI/2, 0)
};
var submunition = new TerminalSensitiveSubmunition("tank3", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition3", submunition);
// 激活并发射子弹
submunition.Fire();
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米/秒
bool hasExploded = false;
// 更新子弹状态每次更新0.1秒
for (int i = 0; i < 10; i++)
for (int i = 0; i < 100 && !hasExploded; i++)
{
var beforePosition = submunition.Position;
submunition.Update(0.1);
var afterPosition = submunition.Position;
var status = submunition.GetStatus();
// 更新目标位置
tank.Update(0.02);
Console.WriteLine($"更新 {i + 1}:");
Console.WriteLine($"位置: 从 {beforePosition} 到 {afterPosition}");
Console.WriteLine($"状态: {status}");
// 计算目标方向
var direction = tank.Position - submunition.Position;
direction = direction.Normalize();
if (status.Contains("Explode"))
// 计算所需朝向
var targetOrientation = new Orientation(
Math.Atan2(direction.Y, direction.X),
Math.Atan2(-direction.Z, Math.Sqrt(direction.X * direction.X + direction.Y * direction.Y)),
0);
// 更新子弹朝向和速度
submunition.Orientation = targetOrientation;
submunition.Velocity = direction * submunition.Speed;
// 更新子弹位置
submunition.Update(0.02);
// 输出调试信息
Console.WriteLine($"更新 {i}:");
Console.WriteLine($"子弹位置: {submunition.Position}");
Console.WriteLine($"目标位置: {tank.Position}");
Console.WriteLine($"距离: {(tank.Position - submunition.Position).Magnitude()}");
if ((tank.Position - submunition.Position).Magnitude() < 5)
{
Console.WriteLine("子弹已爆炸!");
return;
hasExploded = true;
break;
}
}
Assert.Fail("子弹应该在接近目标时爆炸");
Assert.IsTrue(hasExploded, "子弹应该在接近目标时爆炸");
}
[TestMethod]
public void TestDecelerationStageJamming()
{
// 创建目标
var tank = new Tank("tank5", new Vector3D(100, 0, 100), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank5", tank);
tank.Activate();
// 创建子弹初始高度设置为400米
var properties = new MissileProperties
{
Id = "submunition5",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(0, 400, 0),
InitialSpeed = 100,
InitialOrientation = new Orientation(0, -Math.PI/4, 0)
};
var submunition = new TerminalSensitiveSubmunition("tank5", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition5", submunition);
// 激活并发射子弹
submunition.Fire();
submunition.Activate();
// 获取子弹内部的毫米波测高仪实例
var altimeter = submunition.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as MillimeterWaveAltimeter;
Assert.IsNotNull(altimeter, "无法获取测高仪实例");
// 创建毫米波干扰参数
var millimeterWaveJamming = new JammingParameters
{
Type = JammingType.MillimeterWave,
Power = 200,
AngleRange = 45,
Duration = 3,
Direction = new Vector3D(1, 0, 0)
};
// 记录初始高度
double? initialAltitude = ((AltimeterSensorData)altimeter.GetSensorData()).Altitude;
Assert.IsTrue(initialAltitude.HasValue, "无法获取初始高度");
// 应用干扰
altimeter.ApplyJamming(millimeterWaveJamming);
// 更新子弹状态
submunition.Update(0.1);
// 验证干扰效果
Assert.IsTrue(altimeter.IsJammed, "测高仪应该处于被干扰状态");
var status = submunition.GetStatus();
Assert.IsTrue(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器受到干扰");
// 清除干扰
altimeter.ClearJamming(JammingType.MillimeterWave);
submunition.Update(0.1);
// 验证恢复效果
Assert.IsFalse(altimeter.IsJammed, "测高仪应该恢复正常工作");
status = submunition.GetStatus();
Assert.IsFalse(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
// 验证高度测量恢复
double? recoveredAltitude = ((AltimeterSensorData)altimeter.GetSensorData()).Altitude;
Assert.IsTrue(recoveredAltitude.HasValue, "恢复后应该能获取高度数据");
Assert.AreNotEqual(initialAltitude, recoveredAltitude, "高度应该有变化");
}
[TestMethod]
public void TestSubmunitionScanAndAttack()
public void TestParachuteDeploymentStageJamming()
{
// 初始化仿真管理器
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 tank = new Tank("tank6", new Vector3D(100, 0, 100), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank6", tank);
tank.Activate();
// 初始化子弹
// 创建子弹初始高度设置为300米接近开伞高度
var properties = new MissileProperties
{
Id = "submunition6",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500
};
var submunition = new TerminalSensitiveSubmunition("target1", properties, mockManager)
{
Position = new Vector3D(0, 0, 0), // 子弹在原点
MaxSpeed = 500,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(0, 300, 0),
InitialSpeed = 40, // 设置为减速阶段末速度
InitialOrientation = new Orientation(0, -Math.PI/2, 0) // 垂直向下
};
var submunition = new TerminalSensitiveSubmunition("tank6", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition6", submunition);
// 激活并发射子弹
submunition.Fire();
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);
// 获取子弹内部的毫米波测高仪实例
var altimeter = submunition.GetType().GetField("altimeter", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as MillimeterWaveAltimeter;
Assert.IsNotNull(altimeter, "无法获取测高仪实例");
// 模拟探测过程
for (int i = 0; i < 100; i++)
// 创建毫米波干扰参数
var millimeterWaveJamming = new JammingParameters
{
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;
}
Type = JammingType.MillimeterWave,
Power = 200,
AngleRange = 45,
Duration = 3,
Direction = new Vector3D(1, 0, 0)
};
// 记录初始状态
double? initialAltitude = ((AltimeterSensorData)altimeter.GetSensorData()).Altitude;
Assert.IsTrue(initialAltitude.HasValue, "无法获取初始高度");
var initialStatus = submunition.GetStatus();
Console.WriteLine($"初始状态:{initialStatus}");
// 更新几次状态,使子弹进入开伞阶段
for (int i = 0; i < 10; i++)
{
submunition.Update(0.1);
}
// 应用干扰
altimeter.ApplyJamming(millimeterWaveJamming);
Assert.Fail("100次更新后仍未进入攻击阶段");
// 更新子弹状态
submunition.Update(0.1);
// 验证干扰效果
Assert.IsTrue(altimeter.IsJammed, "测高仪应该处于被干扰状态");
var status = submunition.GetStatus();
Console.WriteLine($"干扰后状态:{status}");
Assert.IsTrue(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器受到干扰");
// 记录干扰时的位置
var jammedPosition = submunition.Position;
// 继续更新一段时间
for (int i = 0; i < 10; i++)
{
submunition.Update(0.1);
}
// 验证在干扰期间的行为
var currentPosition = submunition.Position;
Console.WriteLine($"干扰期间位置变化:从 {jammedPosition} 到 {currentPosition}");
// 清除干扰
altimeter.ClearJamming(JammingType.MillimeterWave);
submunition.Update(0.1);
// 验证恢复效果
Assert.IsFalse(altimeter.IsJammed, "测高仪应该恢复正常工作");
status = submunition.GetStatus();
Console.WriteLine($"恢复后状态:{status}");
Assert.IsFalse(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
// 验证高度测量恢复
double? recoveredAltitude = ((AltimeterSensorData)altimeter.GetSensorData()).Altitude;
Assert.IsTrue(recoveredAltitude.HasValue, "恢复后应该能获取高度数据");
Assert.AreNotEqual(initialAltitude, recoveredAltitude, "高度应该有变化");
// 验证速度变化
Assert.IsTrue(submunition.Speed <= 40, "速度应该保持在开伞阶段的限制范围内");
}
}
// 模拟仿真管理器
public class MockSimulationManager : ISimulationManager
{
private readonly Dictionary<string, object> entities = new();
private ISimulationAdapter? adapter;
void ISimulationManager.PublishEvent<T>(T evt) { }
void ISimulationManager.SubscribeToEvent<T>(Action<T> handler) { }
void ISimulationManager.UnsubscribeFromEvent<T>(Action<T> handler) { }
public bool RegisterEntity(string id, object entity)
[TestMethod]
public void TestStableScanStageJamming()
{
entities[id] = entity;
return true;
// 创建目标
var tank = new Tank("tank7", new Vector3D(100, 0, 100), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank7", tank);
tank.Activate();
// 创建子弹初始高度设置为200米稳定扫描高度
var properties = new MissileProperties
{
Id = "submunition7",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 500,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(0, 250, 0),
InitialSpeed = 10, // 设置为垂直下降速度
InitialOrientation = new Orientation(0, -Math.PI/2, 0) // 垂直向下
};
var submunition = new TerminalSensitiveSubmunition("tank7", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition7", submunition);
// 激活并发射子弹
submunition.Fire();
submunition.Activate();
// 获取子弹内部的激光测距仪实例
var rangefinder = submunition.GetType().GetField("rangefinder", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as LaserRangefinder;
Assert.IsNotNull(rangefinder, "无法获取激光测距仪实例");
// 激活激光测距仪
rangefinder.Activate();
// 更新几次状态,确保进入稳定扫描阶段
for (int i = 0; i < 20; i++)
{
submunition.Update(0.1);
}
// 记录扫描开始时的状态
var scanStartStatus = submunition.GetStatus();
Console.WriteLine($"扫描开始状态:{scanStartStatus}");
var scanStartPosition = submunition.Position;
var scanStartDirection = submunition.ScanDirection;
// 记录干扰前的距离数据
var initialRangefinderData = rangefinder.GetSensorData() as RangefinderSensorData;
Assert.IsNotNull(initialRangefinderData, "应该能获取初始测距仪数据");
Assert.IsTrue(initialRangefinderData.IsValid, "初始数据应该有效");
var initialDistance = initialRangefinderData.Distance;
// 创建激光干扰参数
var laserJamming = new JammingParameters
{
Type = JammingType.Laser,
Power = 150,
AngleRange = 30,
Duration = 3,
Direction = new Vector3D(1, 0, 0)
};
// 应用干扰
rangefinder.ApplyJamming(laserJamming);
// 更新子弹状态
submunition.Update(0.1);
// 验证干扰效果
Assert.IsTrue(rangefinder.IsJammed, "激光测距仪应该处于被干扰状态");
var status = submunition.GetStatus();
Console.WriteLine($"干扰后状态:{status}");
// 验证距离测量受到影响
var jammedRangefinderData = rangefinder.GetSensorData() as RangefinderSensorData;
Assert.IsNotNull(jammedRangefinderData, "应该能获取干扰后的测距仪数据");
Assert.IsFalse(jammedRangefinderData.IsValid, "干扰状态下数据应该无效");
Assert.AreEqual(0, jammedRangefinderData.Distance, "干扰状态下距离应该为0");
Console.WriteLine($"干扰前距离: {initialDistance}米");
Console.WriteLine($"干扰后距离: {jammedRangefinderData.Distance}米");
// 记录干扰时的位置和扫描方向
var jammedPosition = submunition.Position;
var jammedDirection = submunition.ScanDirection;
// 继续更新一段时间
for (int i = 0; i < 10; i++)
{
submunition.Update(0.1);
Console.WriteLine($"干扰期间第{i+1}次更新:");
Console.WriteLine($"位置: {submunition.Position}");
Console.WriteLine($"扫描方向: {submunition.ScanDirection}");
}
// 验证在干扰期间的行为
var currentPosition = submunition.Position;
var currentDirection = submunition.ScanDirection;
Console.WriteLine($"干扰期间位置变化:从 {jammedPosition} 到 {currentPosition}");
Console.WriteLine($"干扰期间扫描方向变化:从 {jammedDirection} 到 {currentDirection}");
// 清除干扰
rangefinder.ClearJamming(JammingType.Laser);
submunition.Update(0.1);
// 验证恢复效果
Assert.IsFalse(rangefinder.IsJammed, "激光测距仪应该恢复正常工作");
status = submunition.GetStatus();
Console.WriteLine($"恢复后状态:{status}");
Assert.IsFalse(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
// 验证扫描行为的恢复
var recoveredDirection = submunition.ScanDirection;
Console.WriteLine($"恢复后的扫描方向:{recoveredDirection}");
// 验证速度保持在合理范围
Assert.IsTrue(submunition.Speed <= 10, "速度应该保持在稳定扫描阶段的限制范围内");
}
public bool UnregisterEntity(string id)
[TestMethod]
public void TestDetectionStageJamming()
{
return entities.Remove(id);
// 创建目标
var tank = new Tank("tank8", new Vector3D( 30, 0, 30), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank8", tank);
tank.Activate();
// 创建子弹,初始位置设置在探测阶段范围内
var properties = new MissileProperties
{
Id = "submunition8",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 10,
MaxFlightTime = 100,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(0, 140, 0),
InitialSpeed = 10,
InitialOrientation = new Orientation(0, -Math.PI/2, 0)
};
var submunition = new TerminalSensitiveSubmunition("tank8", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition8", submunition);
// 激活并发射子弹
submunition.Fire();
submunition.Activate();
// 获取子弹内部的传感器实例
var infraredDetector = submunition.GetType().GetField("infraredDetector", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as InfraredDetector;
var radiometer = submunition.GetType().GetField("radiometer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(submunition) as MillimeterWaveRadiometer;
Assert.IsNotNull(infraredDetector, "无法获取红外探测器实例");
Assert.IsNotNull(radiometer, "无法获取毫米波辐射计实例");
// 激活传感器
infraredDetector.Activate();
radiometer.Activate();
// 更新几次状态,确保进入探测阶段
for (double time = 0; time < 5.0; time += 0.1)
{
// 更新子弹状态
submunition.Update(0.1);
}
// Assert
Assert.IsTrue(submunition.IsGuidance);
}
public object GetEntityById(string id)
[TestMethod]
public void TestAttackStageJamming()
{
return entities.TryGetValue(id, out var entity) ? entity : new MockTarget("mock_target") { Position = new Vector3D(100, 50, 100) };
}
// 创建目标
var tank = new Tank("tank_attack", new Vector3D(300, 0, 100), Math.PI/4, _simulationManager);
_simulationManager.RegisterEntity("tank_attack", tank);
tank.Activate();
public IReadOnlyList<T> GetEntitiesByType<T>() where T : class
{
return entities.Values.OfType<T>().ToList();
}
// 创建子弹,初始位置设置在传感器探测范围内
var properties = new MissileProperties
{
Id = "submunition_attack",
Mass = 10,
ExplosionRadius = 5,
MaxSpeed = 2000,
MaxFlightTime = 50,
MaxFlightDistance = 1000,
InitialPosition = new Vector3D(400, 200, 100), // 距离目标100米高度200米
InitialSpeed = 10,
InitialOrientation = new Orientation(0, -Math.PI/6, 0) // 向下30度
};
var submunition = new TerminalSensitiveSubmunition("tank_attack", properties, _simulationManager);
_simulationManager.RegisterEntity("submunition_attack", submunition);
// 激活并发射子弹
submunition.Fire();
submunition.Activate();
public IReadOnlyList<object> GetAllEntities()
{
return entities.Values.ToList();
}
// 获取子弹内部的传感器实例
var rangefinder = submunition.GetType().GetField("rangefinder",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
?.GetValue(submunition) as LaserRangefinder;
public void SetSimulationAdapter(ISimulationAdapter adapter)
{
this.adapter = adapter;
}
Assert.IsNotNull(rangefinder, "无法获取激光测距仪实例");
public ISimulationAdapter? GetSimulationAdapter()
{
return adapter;
}
}
// 激活传感器
rangefinder.Activate();
// 模拟目标
public class MockTarget(string id) : SimulationElement(id, new Vector3D(100, 50, 100), new Orientation(), 1000, new MockSimulationManager())
{
public override void Update(double deltaTime) { }
// 验证传感器初始状态
Assert.IsTrue(rangefinder.IsActive, "激光测距仪应该处于激活状态");
Assert.IsFalse(rangefinder.IsJammed, "激光测距仪不应该处于干扰状态");
// 更新几次状态,确保传感器工作正常
for (int i = 0; i < 5; i++)
{
submunition.Update(0.1);
var status = submunition.GetStatus();
Console.WriteLine($"干扰前状态 {i+1}{status}");
}
// 创建干扰参数
var laserJamming = new JammingParameters
{
Type = JammingType.Laser,
Power = 150,
AngleRange = 30,
Duration = 3,
Direction = new Vector3D(1, 0, 0)
};
// 应用干扰
Console.WriteLine("应用干扰...");
rangefinder.ApplyJamming(laserJamming);
// 验证干扰效果
Assert.IsFalse(rangefinder.IsActive, "激光测距仪应该在干扰下失效");
Assert.IsTrue(rangefinder.IsJammed, "激光测距仪应该处于干扰状态");
// 更新并验证干扰期间的行为
for (int i = 0; i < 5; i++)
{
submunition.Update(0.1);
var status = submunition.GetStatus();
Console.WriteLine($"干扰期间状态 {i+1}{status}");
Assert.IsTrue(status.Contains("传感器受到干扰"), "子弹状态应该反映传感器受到干扰");
// 验证传感器数据无效
var rangefinderData = rangefinder.GetSensorData() as RangefinderSensorData;
Assert.IsFalse(rangefinderData?.IsValid ?? true, "干扰期间距离数据应该无效");
}
// 清除干扰
Console.WriteLine("清除干扰...");
rangefinder.ClearJamming(JammingType.Laser);
// 验证恢复效果
Assert.IsTrue(rangefinder.IsActive, "激光测距仪应该恢复正常工作");
Assert.IsFalse(rangefinder.IsJammed, "激光测距仪应该解除干扰状态");
// 验证恢复后的状态
submunition.Update(0.1);
var finalStatus = submunition.GetStatus();
Console.WriteLine($"恢复后状态:{finalStatus}");
Assert.IsFalse(finalStatus.Contains("传感器受到干扰"), "子弹状态应该反映传感器恢复正常");
}
}
}

View File

@ -80,17 +80,6 @@ namespace ThreatSource.Tests.Missile
// 末制导阶段
for (double time = 0; time < 3.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "target1",
InfraredRadiationIntensity = 100.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 0.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
tank.Update(0.1);
_missile.Update(0.1);
}

View File

@ -80,17 +80,6 @@ namespace ThreatSource.Tests.Missile
// 末制导阶段
for (double time = 0; time < 3.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "target1",
InfraredRadiationIntensity = 0.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 1.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
tank.Update(0.1);
_missile.Update(0.1);
}

View File

@ -112,17 +112,6 @@ namespace ThreatSource.Tests.Missile
// Act - 等待进入螺旋扫描阶段并发送目标辐射
for (double time = 0; time < 5.0; time += 0.1)
{
// 发布坦克辐射事件
_simulationManager.PublishEvent(new TankRadiationEvent
{
SenderId = "tank1",
InfraredRadiationIntensity = 100.0,
LaserReflectionIntensity = 0.0,
MillimeterWaveReflectionIntensity = 1.0,
MillimeterWaveRadiationTemperature = 300.0,
Timestamp = DateTime.UtcNow.Ticks
});
_tank.Update(0.1);
_submunition.Update(0.1);
}

View File

@ -151,6 +151,12 @@ namespace ThreatSource.Missile
{
// 更新导弹运动状态
UpdateMotionState(deltaTime);
// 检查是否应该自毁
if (ShouldSelfDestruct())
{
SelfDestruct();
}
}
}

View File

@ -5,6 +5,27 @@ using ThreatSource.Target;
namespace ThreatSource.Missile
{
/// <summary>
/// 目标探测结果结构
/// </summary>
/// <remarks>
/// 包含目标探测的完整信息:
/// - 目标角度
/// - 目标对象引用
/// </remarks>
public struct DetectionResult
{
/// <summary>
/// 目标角度(弧度)
/// </summary>
public double? Angle { get; set; }
/// <summary>
/// 目标对象
/// </summary>
public ITarget? Target { get; set; }
}
/// <summary>
/// 末敏子弹类,实现了多传感器融合的末端制导功能
/// </summary>
@ -70,6 +91,14 @@ namespace ThreatSource.Missile
/// </remarks>
private const double DecelerationEndSpeed = 40;
/// <summary>
/// 降落伞减速加速度,单位:米/秒²
/// </summary>
/// <remarks>
/// 定义了降落伞减速加速度
/// </remarks>
private const double ParachuteDeceleration = 50;
/// <summary>
/// 垂直下降速度,单位:米/秒
/// </summary>
@ -391,11 +420,30 @@ namespace ThreatSource.Missile
/// </remarks>
private void UpdateParachuteDeploymentStage(double deltaTime)
{
if (Velocity.Magnitude() <= VerticalDeclineSpeed)
// 计算当前速度与目标速度的差值
double currentSpeed = Velocity.Magnitude();
if (currentSpeed > VerticalDeclineSpeed)
{
Velocity = new Vector3D(0, -VerticalDeclineSpeed, 0);
GuidanceAcceleration = Vector3D.Zero;
// 开伞,用较大的减速度快速降低速度
Vector3D deceleration = -Velocity.Normalize() * ParachuteDeceleration;
// 更新速度
Velocity += deceleration * deltaTime;
// 如果速度低于稳定扫描下降速度,直接设置为稳定扫描下降速度
if (Velocity.Magnitude() <= VerticalDeclineSpeed)
{
Velocity = new Vector3D(0, -VerticalDeclineSpeed, 0);
}
}
else
{
// 维持稳定的垂直下降速度
Velocity = new Vector3D(0, -VerticalDeclineSpeed, 0);
}
// 清除制导加速度
GuidanceAcceleration = Vector3D.Zero;
if(IsSensorsJammed())
{
@ -470,38 +518,37 @@ namespace ThreatSource.Missile
/// </remarks>
private void UpdateDetectionStage(double deltaTime)
{
// 激活毫米波辐射计
// 激活传感器
if(!radiometer.IsActive)
{
radiometer.Activate();
}
// 激活红外探测器
if(!infraredDetector.IsActive)
{
infraredDetector.Activate();
}
// 检查传感器干扰状态
if (IsSensorsJammed())
{
Console.WriteLine("探测阶段:传感器受到干扰,无法进行目标探测");
return;
}
// 更新螺旋角度(顺时针旋转)
// 更新扫描角度(顺时针旋转)
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime); // 顺时针角度增加
while (spiralAngle >= 2 * Math.PI)
{
spiralAngle -= 2 * Math.PI;
}
// 计算扫描方向
// 更新扫描方向
scanDirection = new Vector3D(
Math.Sin(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Cos(spiralAngle) * Math.Sin(ScanAngle)
).Normalize();
// 检查传感器干扰状态
if (IsSensorsJammed())
{
Console.WriteLine("探测阶段:传感器受到干扰,无法进行目标探测");
return; // 此时返回不会影响扫描角度的更新
}
// 获取传感器数据
RadiometerSensorData? radiometerData = null;
InfraredSensorData? infraredData = null;
@ -518,7 +565,7 @@ namespace ThreatSource.Missile
bool isRadiationDetected = radiometerData?.IsTargetDetected ?? false;
bool isInfraredDetected = infraredData?.IsTargetDetected ?? false;
// 如果还未探测到目标,进行首次探测
// 目标探测逻辑
if (!isTargetDetected)
{
if (isRadiationDetected || isInfraredDetected)
@ -584,12 +631,11 @@ namespace ThreatSource.Missile
}
// 检查自毁条件
if (rangefinder.GetSensorData() is RangefinderSensorData rangefinderData &&
rangefinderData.Distance <= SelfDestructHeight)
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= SelfDestructHeight)
{
currentStage = SubmunitionStage.SelfDestruct;
}
}
}
}
/// <summary>
/// 更新攻击阶段状态
@ -674,21 +720,25 @@ namespace ThreatSource.Missile
/// 检测目标是否在视场内
/// </summary>
/// <param name="fieldOfView">视场角,单位:度</param>
/// <returns>返回目标方位角。如果目标在视场内返回方位角否则返回null</returns>
/// <returns>返回探测结果。如果目标在视场内返回角度和目标引用否则返回null</returns>
/// <remarks>
/// 检测过程:
/// - 获取目标位置
/// - 计算目标方向
/// - 判断是否在视场内
/// </remarks>
public double? DetectTarget(double fieldOfView)
public DetectionResult DetectTarget(double fieldOfView)
{
// 获取目标对象
SimulationElement target = SimulationManager.GetEntityById(TargetId) as SimulationElement ?? throw new Exception("目标不存在");
var target = SimulationManager.GetEntityById(TargetId) as SimulationElement;
if (target == null) return new DetectionResult();
// 获取目标的尺寸属性
double targetLength = (target as ITarget)?.Length ?? 0; // 目标长度
double targetWidth = (target as ITarget)?.Width ?? 0; // 目标宽度
var targetInterface = target as ITarget;
if (targetInterface == null) return new DetectionResult();
double targetLength = targetInterface.Length; // 目标长度
double targetWidth = targetInterface.Width; // 目标宽度
// 获取目标的朝向向量
Vector3D targetForward = target.Orientation.ToVector();
@ -719,13 +769,16 @@ namespace ThreatSource.Missile
Vector3D toVertex = (vertex - Position).Normalize();
if(Vector3D.DotProduct(scanDirection, toVertex) > cosFieldOfView)
{
// 如果目标的任何一个顶点在视场角内,返回目标方位角
return targetAzimuth;
// 如果目标的任何一个顶点在视场角内,返回目标方位角和目标引用
return new DetectionResult {
Angle = targetAzimuth,
Target = targetInterface
};
}
}
// 如果目标不在视场角内,返回null
return null;
// 如果目标不在视场角内,返回空结果
return new DetectionResult();
}
/// <summary>
@ -734,13 +787,10 @@ namespace ThreatSource.Missile
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅目标辐射事件
/// - 准备传感器系统
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<TankRadiationEvent>(OnTankRadiationEvent);
}
/// <summary>
@ -761,24 +811,6 @@ namespace ThreatSource.Missile
rangefinder.Deactivate();
}
/// <summary>
/// 处理坦克辐射事件
/// </summary>
/// <param name="evt">坦克辐射事件数据</param>
/// <remarks>
/// 处理过程:
/// - 验证目标ID
/// - 记录辐射信息
/// - 更新目标状态
/// </remarks>
private void OnTankRadiationEvent(TankRadiationEvent evt)
{
if (evt.SenderId == TargetId)
{
Console.WriteLine("检测到目标辐射");
}
}
/// <summary>
/// 获取子弹状态信息
/// </summary>
@ -800,7 +832,8 @@ namespace ThreatSource.Missile
$"运行状态: {currentStage}\n" +
$"扫描角度: {spiralAngle * 180 / Math.PI:F2}°, 弧度值: {spiralAngle:F6}\n" +
$"目标检测: {lastDetectionTime != null}\n" +
$"目标距离: {distanceToTarget:F2}米";
$"目标距离: {distanceToTarget:F2}米\n" +
$"传感器状态: {(IsSensorsJammed() ? "" : "")}";
return status;
}

View File

@ -2,6 +2,7 @@ using ThreatSource.Utils;
using ThreatSource.Jamming;
using ThreatSource.Simulation;
using ThreatSource.Missile;
using ThreatSource.Target;
namespace ThreatSource.Sensor
{
@ -137,11 +138,11 @@ namespace ThreatSource.Sensor
private double GetCurrentDirectionRadiationIntensity()
{
// 获取当前方向上的辐射强度如果检测到目标则返回目标的辐射强度否则返回0
var angle = submunition.DetectTarget(FieldOfView);
if (angle != null)
var result = submunition.DetectTarget(FieldOfView);
if (result.Angle != null && result.Target != null)
{
sensorData.TargetAngle = angle;
return 100;
sensorData.TargetAngle = result.Angle;
return result.Target.InfraredRadiationIntensity;
}
sensorData.TargetAngle = null;
return 0;

View File

@ -112,7 +112,7 @@ namespace ThreatSource.Sensor
/// </remarks>
public override void Update(double deltaTime)
{
if (IsActive)
if (IsActive && !IsJammed)
{
// 计算到地面的垂直距离和水平距离
double verticalDistance = submunition.Position.Y;
@ -129,6 +129,11 @@ namespace ThreatSource.Sensor
// 调试输出
//Console.WriteLine($"激光测距仪 - 垂直距离: {verticalDistance:F2}m, 水平距离: {horizontalDistance:F2}m, 斜距: {slantRange:F2}m, 测量距离: {currentDistance:F2}m");
}
else if (IsJammed)
{
// 在干扰状态下,将距离设置为无效值
currentDistance = 0;
}
}
/// <summary>
@ -141,12 +146,11 @@ namespace ThreatSource.Sensor
/// </remarks>
public override SensorData GetSensorData()
{
// 返回激光测距仪的数据
RangefinderSensorData rangefinderSensorData = new()
return new RangefinderSensorData
{
Distance = currentDistance
Distance = IsJammed ? 0 : currentDistance,
IsValid = !IsJammed && IsActive
};
return rangefinderSensorData;
}
/// <summary>

View File

@ -88,7 +88,7 @@ namespace ThreatSource.Sensor
Accuracy = accuracy;
Band = band;
FieldOfView = fieldOfView;
currentAltitude = 0;
currentAltitude = submunition.Position.Y;
this.submunition = submunition;
}
@ -108,6 +108,7 @@ namespace ThreatSource.Sensor
if (IsActive)
{
currentAltitude = submunition.Position.Y + (2 * new Random().NextDouble() - 1) * Accuracy;
Console.WriteLine($"测高仪Update - 实际高度: {submunition.Position.Y:F2}米, 测量高度: {currentAltitude:F2}米");
}
}
@ -159,6 +160,7 @@ namespace ThreatSource.Sensor
{
Altitude = currentAltitude
};
Console.WriteLine($"测高仪GetSensorData - 返回高度: {currentAltitude:F2}米");
return altimeterSensorData;
}

View File

@ -163,15 +163,15 @@ namespace ThreatSource.Sensor
/// </remarks>
private double GetCurrentDirectionRadiationTemperature()
{
// 获取当前方向上的辐射温度,如果检测到目标,则返回天空背景辐射的反射温度否则返回300K
var angle = submunition.DetectTarget(FieldOfView);
if (angle != null)
// 获取当前方向上的辐射温度,如果检测到目标,则返回目标的辐射温度,否则返回地面温度
var result = submunition.DetectTarget(FieldOfView);
if (result.Angle != null && result.Target != null)
{
sensorData.TargetAngle = angle;
return 90;
sensorData.TargetAngle = result.Angle;
return result.Target.MillimeterWaveRadiationTemperature;
}
sensorData.TargetAngle = null;
return 300;
return 300; // 地面温度
}
/// <summary>

View File

@ -142,5 +142,10 @@ namespace ThreatSource.Sensor
/// 用于目标定位和制导控制
/// </remarks>
public double Distance { get; set; }
/// <summary>
/// 获取或设置数据是否有效
/// </summary>
public bool IsValid { get; set; }
}
}

View File

@ -378,52 +378,6 @@ namespace ThreatSource.Simulation
public double JammingPower { get; set; }
}
/// <summary>
/// 坦克辐射事件,表示坦克的多波段辐射特性
/// </summary>
/// <remarks>
/// 用于模拟坦克在不同波段的辐射特征
/// 包含激光、毫米波和红外波段的信息
/// </remarks>
public class TankRadiationEvent : SimulationEvent
{
/// <summary>
/// 获取或设置激光漫反射强度
/// </summary>
/// <remarks>
/// 单位:相对单位
/// 表示坦克表面对激光的反射能力
/// </remarks>
public double LaserReflectionIntensity { get; set; }
/// <summary>
/// 获取或设置毫米波反射强度
/// </summary>
/// <remarks>
/// 单位:相对单位
/// 表示坦克对毫米波雷达的反射特性
/// </remarks>
public double MillimeterWaveReflectionIntensity { get; set; }
/// <summary>
/// 获取或设置毫米波辐射温度
/// </summary>
/// <remarks>
/// 单位:开尔文
/// 表示坦克在毫米波波段的辐射温度
/// </remarks>
public double MillimeterWaveRadiationTemperature { get; set; }
/// <summary>
/// 获取或设置红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 表示坦克的红外辐射强度
/// </remarks>
public double InfraredRadiationIntensity { get; set; }
}
/// <summary>
/// 目标被击中事件
/// </summary>

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ThreatSource.Simulation;
using ThreatSource.Utils;
namespace ThreatSource.Simulation.Testing
{
@ -13,6 +14,12 @@ namespace ThreatSource.Simulation.Testing
private readonly List<object> _receivedEvents = [];
private readonly List<object> _publishedEvents = [];
private ISimulationManager? _simulationManager;
// 存储实体状态的字典
private Dictionary<string, SimulationElement> entityStates = new();
// 存储环境数据的字典
private Dictionary<string, SimulationEnvironmentData> environmentData = new();
// 当前仿真时间
private double currentTime = 0;
/// <summary>
/// 构造函数,初始化测试适配器
@ -100,5 +107,49 @@ namespace ThreatSource.Simulation.Testing
_publishedEvents.Clear();
_receivedEvents.Clear();
}
/// <summary>
/// 获取实体状态
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
public SimulationElement GetEntityState(string entityId)
{
return entityStates.TryGetValue(entityId, out var state) ? state : new MockSimulationElement(entityId);
}
/// <summary>
/// 设置实体环境数据
/// </summary>
/// <param name="entityId"></param>
/// <param name="data"></param>
public void SetEntityEnvironment(string entityId, SimulationEnvironmentData data)
{
environmentData[entityId] = data;
}
/// <summary>
/// 同步仿真时间
/// </summary>
/// <param name="time"></param>
public void SynchronizeTime(double time)
{
currentTime = time;
}
}
/// <summary>
/// 用于测试的模拟仿真元素
/// </summary>
internal class MockSimulationElement : SimulationElement
{
public MockSimulationElement(string id)
: base(id, new Vector3D(0, 0, 0), new Orientation(), 0, null!)
{
}
public override void Update(double deltaTime)
{
}
}
}

View File

@ -38,12 +38,34 @@ namespace ThreatSource.Target
/// 获取目标的红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 单位:瓦特/球面度
/// 表示目标的热辐射特征
/// 影响红外制导系统的探测和跟踪能力
/// 典型值200-500 W/sr
/// </remarks>
double InfraredRadiationIntensity { get; }
/// <summary>
/// 获取目标的毫米波辐射温度
/// </summary>
/// <remarks>
/// 单位:开尔文
/// 表示目标的毫米波辐射特征
/// 影响毫米波制导系统的探测和跟踪能力
/// 典型值350-450K
/// </remarks>
double MillimeterWaveRadiationTemperature { get; }
/// <summary>
/// 获取目标的激光反射率
/// </summary>
/// <remarks>
/// 无量纲取值范围0-1
/// 表示目标表面对激光的反射特性
/// 影响激光测距和制导系统的效果
/// </remarks>
double LaserReflectivity { get; }
/// <summary>
/// 获取目标的长度
/// </summary>

View File

@ -36,10 +36,30 @@ namespace ThreatSource.Target
/// 获取坦克的红外辐射强度
/// </summary>
/// <remarks>
/// 单位:瓦特/平方米
/// 固定值100.0,表示坦克发动机和装甲的热辐射特性
/// 单位:瓦特/球面度
/// 固定值500.0,表示坦克发动机和装甲的热辐射特性
/// 典型值200-500 W/sr
/// </remarks>
public double InfraredRadiationIntensity => 100.0;
public double InfraredRadiationIntensity => 500.0;
/// <summary>
/// 获取坦克的毫米波辐射温度
/// </summary>
/// <remarks>
/// 单位:开尔文
/// 固定值400.0,表示坦克的毫米波辐射特征
/// 典型值350-450K
/// </remarks>
public double MillimeterWaveRadiationTemperature => 400.0;
/// <summary>
/// 获取坦克的激光反射率
/// </summary>
/// <remarks>
/// 无量纲取值范围0-1
/// 固定值0.3,表示坦克表面对激光的反射特性
/// </remarks>
public double LaserReflectivity => 0.3;
/// <summary>
/// 获取或设置坦克的当前生命值

View File

@ -36,7 +36,7 @@ namespace ThreatSource.Tools
public string AddTarget(Vector3D position)
{
string targetId = $"target_{targets.Count + 1}";
var target = new MockTarget(targetId)
var target = new MockTarget(targetId, simulationManager)
{
Position = position
};
@ -57,15 +57,16 @@ namespace ThreatSource.Tools
{
Mass = 10,
ExplosionRadius = 0.1,
MaxSpeed = 2000
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)
{
Position = position,
Velocity = new Vector3D(0, -10, 0) // 初始垂直下降速度
};
var missile = new TerminalSensitiveSubmunition(targetId, properties, simulationManager);
missile.Activate();
missiles.Add(missile);
Console.WriteLine($"发射导弹,目标:{targetId},位置:{position}");
@ -196,7 +197,7 @@ namespace ThreatSource.Tools
/// </summary>
public class MockTarget : SimulationElement, ITarget
{
public MockTarget(string id) : base(id, new Vector3D(0, 0, 0), new Orientation(), 1000, null) { }
public MockTarget(string id, ISimulationManager simulationManager) : base(id, new Vector3D(0, 0, 0), new Orientation(), 1000, simulationManager) { }
public override void Update(double deltaTime) { }
@ -210,5 +211,7 @@ namespace ThreatSource.Tools
// 设置目标的特征参数
public double RadarCrossSection => 10.0; // 雷达散射截面积(示例值)
public double InfraredRadiationIntensity => 500.0; // 红外辐射强度(示例值)
public double MillimeterWaveRadiationTemperature => 90.0; // 毫米波辐射温度(示例值)
public double LaserReflectivity => 0.3; // 激光反射率(示例值)
}
}

View File

@ -14,7 +14,7 @@ namespace ThreatSource.Tools
var targetId = simulator.AddTarget(new Vector3D(0, 0, 0));
// 发射导弹
simulator.LaunchMissile(targetId, new Vector3D(40, 400, 40));
simulator.LaunchMissile(targetId, new Vector3D(40, 450, 40));
// 启动模拟线程
var simulationThread = new Thread(simulator.Start);