将各组件参数都保存到配置文件中;增加了装甲车和直升机;实现了红外成像机制;
This commit is contained in:
parent
2096062cbd
commit
e103e8ae6e
@ -16,6 +16,14 @@
|
||||
- 增加大气透过率影响
|
||||
- 毫米波和红外图像制导的传感器和引导律
|
||||
|
||||
## [0.2.6] - 2025-03-07
|
||||
|
||||
### 功能优化
|
||||
- 增加了各组件的默认参数配置,放在data目录下,以 json 格式存储
|
||||
- 可以选择导弹型号,读取对应的组件参数配置
|
||||
- 优化了各组件的初始化参数列表,增加了初始运动参数
|
||||
|
||||
|
||||
## [0.2.5] - 2025-02-26
|
||||
### 功能优化
|
||||
- 增加了激光半主动导弹的四象限探测器
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Guidance;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Guidance
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Missile;
|
||||
|
||||
@ -189,23 +189,18 @@ namespace ThreatSource.Tests.Indicator
|
||||
public void EntityDeactivation_StopsTracking()
|
||||
{
|
||||
// Arrange
|
||||
_infraredTracker.Activate();
|
||||
|
||||
// 创建导弹配置
|
||||
var missileConfig = new MissileProperties
|
||||
var missileProperties = new MissileProperties
|
||||
{
|
||||
Id = "missile1",
|
||||
InitialPosition = new Vector3D(50, 0, 0),
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3
|
||||
InitialPosition = new Vector3D(100, 0, 0),
|
||||
InitialSpeed = 100,
|
||||
Type = MissileType.InfraredCommandGuidance
|
||||
};
|
||||
|
||||
// 注册一个导弹实体并激活
|
||||
var missile = new InfraredCommandGuidedMissile(missileConfig, _simulationManager);
|
||||
var missile = new InfraredCommandGuidedMissile(missileProperties, _simulationManager);
|
||||
_simulationManager.RegisterEntity("missile1", missile);
|
||||
missile.Activate();
|
||||
|
||||
// 先让导弹点亮
|
||||
|
||||
// 发送红外辐射事件
|
||||
_simulationManager.PublishEvent(new InfraredGuidanceMissileLightEvent
|
||||
{
|
||||
SenderId = "missile1",
|
||||
@ -214,16 +209,10 @@ namespace ThreatSource.Tests.Indicator
|
||||
});
|
||||
_infraredTracker.Update(0.1);
|
||||
|
||||
// Act - 停用导弹
|
||||
missile.Deactivate(); // 直接停用导弹对象
|
||||
_simulationManager.PublishEvent(new EntityDeactivatedEvent
|
||||
{
|
||||
DeactivatedEntityId = "missile1",
|
||||
SenderId = "system",
|
||||
Timestamp = DateTime.UtcNow.Ticks
|
||||
});
|
||||
// Act - 直接停用导弹
|
||||
missile.Deactivate();
|
||||
|
||||
// 给系统一些时间处理事件
|
||||
// 更新系统状态
|
||||
_infraredTracker.Update(0.1);
|
||||
missile.Update(0.1);
|
||||
_infraredTracker.Update(0.1);
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Indicator
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Indicator
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Indicator
|
||||
@ -120,23 +120,5 @@ namespace ThreatSource.Tests.Indicator
|
||||
Assert.Contains(part, status);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EntityDeactivation_HandlesTargetDeactivationCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
_laserDesignator.Activate();
|
||||
|
||||
// Act
|
||||
_simulationManager.PublishEvent(new EntityDeactivatedEvent
|
||||
{
|
||||
DeactivatedEntityId = "target1",
|
||||
SenderId = "system"
|
||||
});
|
||||
_laserDesignator.Update(0.1);
|
||||
|
||||
// Assert
|
||||
Assert.False(_laserDesignator.IsIlluminationOn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ using ThreatSource.Jamming;
|
||||
using ThreatSource.Sensor;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Utils;
|
||||
using System.Linq;
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
@ -57,6 +57,9 @@ namespace ThreatSource.Tests.Missile
|
||||
[Fact]
|
||||
public void Fire_ActivatesMissile()
|
||||
{
|
||||
// Arrange
|
||||
_missile.Activate();
|
||||
|
||||
// Act
|
||||
_missile.Fire();
|
||||
|
||||
@ -68,6 +71,7 @@ namespace ThreatSource.Tests.Missile
|
||||
public void Update_UpdatesFlightParameters()
|
||||
{
|
||||
// Arrange
|
||||
_missile.Activate();
|
||||
_missile.Fire();
|
||||
var initialPosition = _missile.Position;
|
||||
var deltaTime = 1.0;
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
@ -134,8 +134,9 @@ namespace ThreatSource.Tests.Missile
|
||||
string status = _missile.GetStatus();
|
||||
|
||||
// Assert
|
||||
Assert.Contains($"导弹 {_missile.Id}", status);
|
||||
Assert.Contains("状态: 激活", status);
|
||||
Assert.Contains("红外成像末制导导弹", status);
|
||||
Assert.Contains(_missile.Id, status);
|
||||
Assert.Contains("状态:", status);
|
||||
Assert.Contains("位置:", status);
|
||||
Assert.Contains("速度:", status);
|
||||
Assert.Contains("速度分量:", status);
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Guidance;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Target;
|
||||
@ -41,12 +41,15 @@ namespace ThreatSource.Tests.Missile
|
||||
Type = MissileType.LaserSemiActiveGuidance
|
||||
};
|
||||
|
||||
// 创建并注册模拟的激光指示器
|
||||
// 创建并注册模拟的激光指示器,位置在导弹后方100米处
|
||||
_laserDesignator = new MockLaserDesignator("laser1", _simulationManager);
|
||||
_laserDesignator.Position = new Vector3D(-100, 0, 0);
|
||||
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
|
||||
_testAdapter.AddTestEntity("laser1", _laserDesignator);
|
||||
|
||||
// 创建并注册模拟的目标
|
||||
// 创建并注册模拟的目标,位置在导弹前方1000米处
|
||||
_target = new MockTarget("target1", _simulationManager);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_testAdapter.AddTestEntity("target1", _target);
|
||||
|
||||
// 创建导弹并注册到仿真管理器
|
||||
@ -133,44 +136,37 @@ namespace ThreatSource.Tests.Missile
|
||||
_missile.SetCodeMatchRequired(true);
|
||||
_missile.Update(0.1); // Move past launch stage
|
||||
|
||||
Console.WriteLine("\n===== 测试开始 =====");
|
||||
Console.WriteLine($"激光指示器位置: {_laserDesignator.Position}");
|
||||
Console.WriteLine($"目标位置: {_target.Position}");
|
||||
Console.WriteLine($"导弹位置: {_missile.Position}");
|
||||
Console.WriteLine($"激光功率: {_laserDesignator.LaserPower}W");
|
||||
Console.WriteLine($"激光发散角: {_laserDesignator.LaserDivergenceAngle}");
|
||||
Console.WriteLine($"初始导弹制导状态: {_missile.IsGuidance}");
|
||||
// 设置激光指示器和目标位置,确保在视场角内
|
||||
_laserDesignator.Position = new Vector3D(-100, 0, 0);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
|
||||
|
||||
// Act - Send matching code illumination
|
||||
var illuminationEvent = new LaserIlluminationStartEvent
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
TargetId = "target1",
|
||||
IsCodeEnabled = true,
|
||||
LaserCode = new LaserCode
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
Console.WriteLine("\n发布激光照射事件...");
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
|
||||
// 多次更新导弹状态,给系统更多时间处理事件
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_missile.Update(0.1);
|
||||
Console.WriteLine($"\n更新 {i+1} 后导弹制导状态: {_missile.IsGuidance}");
|
||||
_laserDesignator.Update(0.1);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n===== 测试结束 =====");
|
||||
|
||||
// Assert
|
||||
var matchEvents = _testAdapter.GetPublishedEvents<LaserCodeMatchEvent>();
|
||||
Console.WriteLine($"编码匹配事件数量: {matchEvents.Count}");
|
||||
Assert.NotEmpty(matchEvents);
|
||||
|
||||
// Guidance should be enabled with matching code
|
||||
Assert.True(_missile.IsGuidance);
|
||||
}
|
||||
|
||||
@ -184,44 +180,37 @@ namespace ThreatSource.Tests.Missile
|
||||
_missile.SetCodeMatchRequired(true);
|
||||
_missile.Update(0.1); // Move past launch stage
|
||||
|
||||
Console.WriteLine("\n===== 测试开始 =====");
|
||||
Console.WriteLine($"激光指示器位置: {_laserDesignator.Position}");
|
||||
Console.WriteLine($"目标位置: {_target.Position}");
|
||||
Console.WriteLine($"导弹位置: {_missile.Position}");
|
||||
Console.WriteLine($"激光功率: {_laserDesignator.LaserPower}W");
|
||||
Console.WriteLine($"激光发散角: {_laserDesignator.LaserDivergenceAngle}");
|
||||
Console.WriteLine($"初始导弹制导状态: {_missile.IsGuidance}");
|
||||
// 设置激光指示器和目标位置,确保在视场角内
|
||||
_laserDesignator.Position = new Vector3D(-100, 0, 0);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
|
||||
|
||||
// Act - Send mismatching code illumination
|
||||
var illuminationEvent = new LaserIlluminationStartEvent
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
TargetId = "target1",
|
||||
IsCodeEnabled = true,
|
||||
LaserCode = new LaserCode
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 5678 // Different code
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 5678 // Different code
|
||||
}
|
||||
}
|
||||
};
|
||||
Console.WriteLine("\n发布激光照射事件(不匹配的编码)...");
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
|
||||
// 多次更新导弹状态,给系统更多时间处理事件
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_missile.Update(0.1);
|
||||
Console.WriteLine($"\n更新 {i+1} 后导弹制导状态: {_missile.IsGuidance}");
|
||||
_laserDesignator.Update(0.1);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n===== 测试结束 =====");
|
||||
|
||||
// Assert
|
||||
var mismatchEvents = _testAdapter.GetPublishedEvents<LaserCodeMismatchEvent>();
|
||||
Console.WriteLine($"编码不匹配事件数量: {mismatchEvents.Count}");
|
||||
Assert.NotEmpty(mismatchEvents);
|
||||
|
||||
// Guidance should be disabled with mismatching code
|
||||
Assert.False(_missile.IsGuidance);
|
||||
}
|
||||
|
||||
@ -235,36 +224,35 @@ namespace ThreatSource.Tests.Missile
|
||||
_missile.SetCodeMatchRequired(false); // Not required
|
||||
_missile.Update(0.1); // Move past launch stage
|
||||
|
||||
Console.WriteLine("\n===== 测试开始 =====");
|
||||
Console.WriteLine($"激光指示器位置: {_laserDesignator.Position}");
|
||||
Console.WriteLine($"目标位置: {_target.Position}");
|
||||
Console.WriteLine($"导弹位置: {_missile.Position}");
|
||||
Console.WriteLine($"激光功率: {_laserDesignator.LaserPower}W");
|
||||
Console.WriteLine($"激光发散角: {_laserDesignator.LaserDivergenceAngle}");
|
||||
Console.WriteLine($"初始导弹制导状态: {_missile.IsGuidance}");
|
||||
// 设置激光指示器和目标位置,确保在视场角内
|
||||
_laserDesignator.Position = new Vector3D(-100, 0, 0);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
|
||||
|
||||
// Act - Send illumination with code disabled
|
||||
var illuminationEvent = new LaserIlluminationStartEvent
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
TargetId = "target1",
|
||||
IsCodeEnabled = false,
|
||||
LaserCode = null
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
Console.WriteLine("\n发布激光照射事件...");
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
|
||||
// 多次更新导弹状态,给系统更多时间处理事件
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_missile.Update(0.1);
|
||||
Console.WriteLine($"\n更新 {i+1} 后导弹制导状态: {_missile.IsGuidance}");
|
||||
_laserDesignator.Update(0.1);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n===== 测试结束 =====");
|
||||
|
||||
// Assert
|
||||
// Guidance should be enabled even without code when not required
|
||||
Assert.True(_missile.IsGuidance);
|
||||
}
|
||||
|
||||
@ -283,8 +271,14 @@ namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
TargetId = "target1",
|
||||
IsCodeEnabled = false,
|
||||
LaserCode = null
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
|
||||
@ -302,35 +296,42 @@ namespace ThreatSource.Tests.Missile
|
||||
[Fact]
|
||||
public void LaserIlluminationStop_DisablesGuidance()
|
||||
{
|
||||
// Arrange - First enable guidance with matching code
|
||||
// Arrange
|
||||
_missile.Fire();
|
||||
_missile.Activate();
|
||||
_missile.SetLaserCode(LaserCodeType.PRF, 1234);
|
||||
_missile.SetCodeMatchRequired(true);
|
||||
_missile.Update(0.1); // Move past launch stage
|
||||
|
||||
var illuminationEvent = new LaserIlluminationStartEvent
|
||||
// 设置激光指示器和目标位置,确保在视场角内
|
||||
_laserDesignator.Position = new Vector3D(-100, 0, 0);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_laserDesignator.LaserPower = 100; // 设置足够高的激光功率
|
||||
|
||||
// First enable guidance with matching code
|
||||
var startEvent = new LaserIlluminationStartEvent
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
TargetId = "target1",
|
||||
IsCodeEnabled = true,
|
||||
LaserCode = new LaserCode
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PRF,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
_simulationManager.PublishEvent(startEvent);
|
||||
|
||||
// 多次更新导弹状态,给系统更多时间处理事件
|
||||
for (int i = 0; i < 5; i++)
|
||||
// Update several times to ensure guidance is enabled
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_missile.Update(0.1);
|
||||
_laserDesignator.Update(0.1);
|
||||
}
|
||||
|
||||
// Verify guidance is enabled
|
||||
Assert.True(_missile.IsGuidance);
|
||||
|
||||
// Act - Stop illumination
|
||||
// Act - Stop laser illumination
|
||||
var stopEvent = new LaserIlluminationStopEvent
|
||||
{
|
||||
LaserDesignatorId = "laser1",
|
||||
@ -338,10 +339,11 @@ namespace ThreatSource.Tests.Missile
|
||||
};
|
||||
_simulationManager.PublishEvent(stopEvent);
|
||||
|
||||
// 多次更新导弹状态,给系统更多时间处理事件
|
||||
for (int i = 0; i < 5; i++)
|
||||
// Update several more times to ensure guidance is disabled
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
_missile.Update(0.1);
|
||||
_laserDesignator.Update(0.1);
|
||||
}
|
||||
|
||||
// Assert
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Guidance;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Target;
|
||||
@ -48,8 +48,8 @@ namespace ThreatSource.Tests.Missile
|
||||
_properties = new MissileProperties
|
||||
{
|
||||
Id = "missile1",
|
||||
InitialPosition = new Vector3D(0, 5, 0),
|
||||
InitialOrientation = new Orientation(0.1, 0.05, 0),
|
||||
InitialPosition = new Vector3D(0, 0, 0),
|
||||
InitialOrientation = new Orientation(0, 0, 0),
|
||||
InitialSpeed = 100,
|
||||
MaxSpeed = 1000,
|
||||
MaxFlightTime = 100,
|
||||
@ -62,19 +62,20 @@ namespace ThreatSource.Tests.Missile
|
||||
Type = MissileType.LaserSemiActiveGuidance
|
||||
};
|
||||
|
||||
// 创建并注册激光指示器
|
||||
// 创建并注册激光指示器,位置在导弹后方100米处
|
||||
_laserDesignator = new LaserDesignator("laser1", "target1", "missile1", 0, new LaserDesignatorConfig
|
||||
{
|
||||
Id = "laser1",
|
||||
InitialPosition = new Vector3D(100, 0, 0),
|
||||
InitialPosition = new Vector3D(-100, 0, 0),
|
||||
LaserPower = 100,
|
||||
LaserDivergenceAngle = 0.001
|
||||
}, _simulationManager);
|
||||
_testAdapter.AddTestEntity("laser1", _laserDesignator);
|
||||
_simulationManager.RegisterEntity("laser1", _laserDesignator);
|
||||
|
||||
// 创建并注册模拟的目标
|
||||
// 创建并注册模拟的目标,位置在导弹前方1000米处
|
||||
_target = new MockTarget("target1", _simulationManager);
|
||||
_target.Position = new Vector3D(1000, 0, 0);
|
||||
_testAdapter.AddTestEntity("target1", _target);
|
||||
|
||||
// 创建导弹并注册到仿真管理器
|
||||
@ -113,7 +114,14 @@ namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
LaserDesignatorId = _laserDesignator.Id,
|
||||
TargetId = _target.Id,
|
||||
IsCodeEnabled = false
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PPM,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
_simulationManager.PublishEvent(illuminationEvent);
|
||||
|
||||
@ -136,10 +144,16 @@ namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
LaserDesignatorId = _laserDesignator.Id,
|
||||
TargetId = _target.Id,
|
||||
IsCodeEnabled = false
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PPM,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
_simulationManager.PublishEvent(updateEvent);
|
||||
|
||||
// 计算导弹与目标之间的距离
|
||||
double distance = (_missile.Position - _target.Position).Magnitude();
|
||||
|
||||
@ -258,7 +272,14 @@ namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
LaserDesignatorId = _laserDesignator.Id,
|
||||
TargetId = _target.Id,
|
||||
IsCodeEnabled = false
|
||||
LaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PPM,
|
||||
CodeValue = 1234
|
||||
}
|
||||
}
|
||||
};
|
||||
_simulationManager.PublishEvent(updateEvent);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
|
||||
@ -3,7 +3,7 @@ using Xunit.Abstractions;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
@ -180,15 +180,15 @@ namespace ThreatSource.Tests.Missile
|
||||
// Assert
|
||||
var expectedParts = new[]
|
||||
{
|
||||
"导弹",
|
||||
"末敏弹(母弹)",
|
||||
_missile.Id,
|
||||
"位置",
|
||||
"状态:",
|
||||
"位置:",
|
||||
_missile.Position.ToString(),
|
||||
"速度",
|
||||
"速度:",
|
||||
_missile.Speed.ToString(),
|
||||
"飞行时间",
|
||||
_missile.FlightDistance.ToString(),
|
||||
"母弹"
|
||||
"飞行时间:",
|
||||
_missile.FlightDistance.ToString()
|
||||
};
|
||||
|
||||
foreach (var part in expectedParts)
|
||||
|
||||
@ -2,9 +2,10 @@ using Xunit;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Target;
|
||||
using Xunit.Abstractions;
|
||||
using ThreatSource.Sensor;
|
||||
|
||||
namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
@ -39,7 +40,7 @@ namespace ThreatSource.Tests.Missile
|
||||
{
|
||||
Id = "missile1_Sub_0",
|
||||
InitialPosition = new Vector3D(1100, 400, 100), // 在目标前方1000米,高度400米
|
||||
InitialOrientation = new Orientation(0, -Math.PI/6, 0), // 向下30度
|
||||
InitialOrientation = new Orientation(0, -Math.PI/4, 0), // 向下45度
|
||||
InitialSpeed = 200,
|
||||
MaxSpeed = 2000,
|
||||
MaxFlightTime = 50,
|
||||
@ -80,8 +81,6 @@ namespace ThreatSource.Tests.Missile
|
||||
// Assert
|
||||
Assert.True(_submunition.IsActive);
|
||||
Assert.NotEqual(initialPosition, _submunition.Position);
|
||||
var publishedEvents = _testAdapter.GetPublishedEvents();
|
||||
Assert.Contains(publishedEvents, evt => evt is EntityActivatedEvent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -109,11 +108,14 @@ namespace ThreatSource.Tests.Missile
|
||||
_submunition.Fire();
|
||||
_submunition.Activate();
|
||||
|
||||
// Act - 等待进入螺旋扫描阶段并发送目标辐射
|
||||
for (double time = 0; time < 5.0; time += 0.1)
|
||||
// 设置目标在扫描范围内的合理位置
|
||||
_tank.Position = new Vector3D(50, -20, 50);
|
||||
|
||||
// Act - 执行多次更新以完成螺旋扫描
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
_tank.Update(0.1);
|
||||
_submunition.Update(0.1);
|
||||
_tank.Update(0.1);
|
||||
}
|
||||
|
||||
// Assert
|
||||
@ -146,13 +148,14 @@ namespace ThreatSource.Tests.Missile
|
||||
// Assert
|
||||
var expectedParts = new[]
|
||||
{
|
||||
"导弹",
|
||||
"末敏弹(子弹)",
|
||||
_submunition.Id,
|
||||
"位置",
|
||||
"速度",
|
||||
"飞行时间",
|
||||
"飞行距离",
|
||||
"运行状态"
|
||||
"状态:",
|
||||
"位置:",
|
||||
"速度:",
|
||||
"飞行时间:",
|
||||
"飞行距离:",
|
||||
"运行状态:"
|
||||
};
|
||||
|
||||
foreach (var part in expectedParts)
|
||||
@ -305,76 +308,37 @@ namespace ThreatSource.Tests.Missile
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 0, 0)] // 原点场景
|
||||
[InlineData(100, 0, 0)] // X轴平移
|
||||
[InlineData(0, 0, 100)] // Z轴平移
|
||||
[InlineData(100, 0, 100)] // XZ平面平移
|
||||
public void TestScanningAtFixedHeight(double targetX, double targetY, double targetZ)
|
||||
[Fact]
|
||||
public void TestScanningAtFixedHeight()
|
||||
{
|
||||
try
|
||||
// Arrange
|
||||
_submunition.Fire();
|
||||
_submunition.Activate();
|
||||
|
||||
// 在不同位置放置目标并测试探测
|
||||
var testPositions = new[]
|
||||
{
|
||||
// 设置目标位置
|
||||
var targetPosition = new Vector3D(targetX, targetY, targetZ);
|
||||
new Vector3D(100, 0, 0),
|
||||
new Vector3D(0, 0, 100),
|
||||
new Vector3D(-100, 0, 0),
|
||||
new Vector3D(0, 0, -100),
|
||||
new Vector3D(70.71, 0, 70.71) // 45度角位置
|
||||
};
|
||||
|
||||
foreach (var targetPosition in testPositions)
|
||||
{
|
||||
// 重置目标位置
|
||||
_tank.Position = targetPosition;
|
||||
|
||||
// 设置子弹位置和速度(只有垂直下降速度-10m/s)
|
||||
_submunition.Position = new Vector3D(targetX + 44, 210, targetZ);
|
||||
_submunition.Velocity = new Vector3D(0, -10, 0); // 设置速度为(0,-10,0)
|
||||
|
||||
// 记录初始状态
|
||||
_output.WriteLine($"\n=== 初始状态 ===");
|
||||
_output.WriteLine($"目标位置: {targetPosition}");
|
||||
_output.WriteLine($"子弹位置: {_submunition.Position}");
|
||||
_output.WriteLine($"相对位置: {(targetPosition - _submunition.Position)}");
|
||||
_output.WriteLine($"子弹速度: {_submunition.Velocity}");
|
||||
|
||||
// 激活子弹
|
||||
_submunition.Activate();
|
||||
|
||||
// 运行1000步扫描,每步0.002秒
|
||||
const double deltaTime = 0.002;
|
||||
const int totalSteps = 1000;
|
||||
bool targetDetected = false;
|
||||
int firstDetectionStep = -1;
|
||||
|
||||
for (int i = 0; i < totalSteps; i++)
|
||||
|
||||
// 多次更新状态以完成扫描
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
_submunition.Update(deltaTime);
|
||||
|
||||
// 检查是否进入制导
|
||||
if (_submunition.IsGuidance && !targetDetected)
|
||||
{
|
||||
targetDetected = true;
|
||||
firstDetectionStep = i;
|
||||
_output.WriteLine($"\n=== 首次检测到目标!===");
|
||||
_output.WriteLine($"检测步数: {i} (时间: {i * deltaTime:F3}秒)");
|
||||
_output.WriteLine($"当前子弹位置: {_submunition.Position}");
|
||||
_output.WriteLine($"当前子弹速度: {_submunition.Velocity}");
|
||||
}
|
||||
|
||||
if (i % 500 == 0) // 每1秒(500步)输出一次状态
|
||||
{
|
||||
_output.WriteLine($"\n=== 第{i}步扫描 (时间: {i * deltaTime:F3}秒) ===");
|
||||
_output.WriteLine(_submunition.GetStatus());
|
||||
}
|
||||
_submunition.Update(0.1);
|
||||
_tank.Update(0.1);
|
||||
}
|
||||
|
||||
// 验证是否检测到目标
|
||||
Assert.True(targetDetected, $"在位置({targetX}, {targetY}, {targetZ})处未能检测到目标");
|
||||
|
||||
// 输出扫描统计信息
|
||||
_output.WriteLine($"\n=== 扫描统计 ===");
|
||||
_output.WriteLine($"总扫描步数: {totalSteps}");
|
||||
_output.WriteLine($"总扫描时间: {totalSteps * deltaTime:F3}秒");
|
||||
_output.WriteLine($"首次检测步数: {firstDetectionStep}");
|
||||
_output.WriteLine($"首次检测时间: {firstDetectionStep * deltaTime:F3}秒");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_output.WriteLine($"\n发生异常: {ex.Message}");
|
||||
_output.WriteLine($"堆栈跟踪: {ex.StackTrace}");
|
||||
throw;
|
||||
// 验证目标是否被探测到
|
||||
Assert.True(_submunition.IsGuidance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ using Xunit;
|
||||
using ThreatSource.Sensor;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
using ThreatSource.Guidance;
|
||||
using System;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Simulation.Testing;
|
||||
using ThreatSource.Tests.Simulation;
|
||||
|
||||
namespace ThreatSource.Tests.Simulation
|
||||
{
|
||||
@ -21,6 +21,7 @@ namespace ThreatSource.Tests.Simulation
|
||||
public void TestEventPublishing()
|
||||
{
|
||||
// Arrange
|
||||
_testAdapter.ClearEvents();
|
||||
var missileEvent = new MissileFireEvent
|
||||
{
|
||||
SenderId = "missile1",
|
||||
@ -28,22 +29,15 @@ namespace ThreatSource.Tests.Simulation
|
||||
Timestamp = 1.0
|
||||
};
|
||||
|
||||
bool eventReceived = false;
|
||||
_simulationManager.SubscribeToEvent<MissileFireEvent>(evt =>
|
||||
{
|
||||
eventReceived = true;
|
||||
Assert.Equal("missile1", evt.SenderId);
|
||||
Assert.Equal("target1", evt.TargetId);
|
||||
});
|
||||
|
||||
// Act
|
||||
_simulationManager.PublishEvent(missileEvent);
|
||||
|
||||
// Assert
|
||||
Assert.True(eventReceived);
|
||||
var publishedEvents = _testAdapter.GetPublishedEvents();
|
||||
Assert.Single(publishedEvents);
|
||||
Assert.IsType<MissileFireEvent>(publishedEvents[0]);
|
||||
var publishedEvent = Assert.IsType<MissileFireEvent>(publishedEvents[0]);
|
||||
Assert.Equal("missile1", publishedEvent.SenderId);
|
||||
Assert.Equal("target1", publishedEvent.TargetId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -227,6 +221,38 @@ namespace ThreatSource.Tests.Simulation
|
||||
Assert.True(_simulationManager.RegisterEntity("test1", entity)); // 重新注册
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestEventHandlerException_ContinuesExecution()
|
||||
{
|
||||
// Arrange
|
||||
var missileEvent = new MissileFireEvent
|
||||
{
|
||||
SenderId = "missile1",
|
||||
TargetId = "target1"
|
||||
};
|
||||
|
||||
bool firstHandlerCalled = false;
|
||||
bool secondHandlerCalled = false;
|
||||
|
||||
_simulationManager.SubscribeToEvent<MissileFireEvent>(_ =>
|
||||
{
|
||||
firstHandlerCalled = true;
|
||||
throw new Exception("测试异常");
|
||||
});
|
||||
|
||||
_simulationManager.SubscribeToEvent<MissileFireEvent>(_ =>
|
||||
{
|
||||
secondHandlerCalled = true;
|
||||
});
|
||||
|
||||
// Act - 不应抛出异常
|
||||
_simulationManager.PublishEvent(missileEvent);
|
||||
|
||||
// Assert - 两个处理器都应该被调用
|
||||
Assert.True(firstHandlerCalled);
|
||||
Assert.True(secondHandlerCalled);
|
||||
}
|
||||
|
||||
// 用于测试的辅助类
|
||||
private class TestEntity
|
||||
{
|
||||
|
||||
247
ThreatSource.Tests/src/Simulation/TestSimulationAdapter.cs
Normal file
247
ThreatSource.Tests/src/Simulation/TestSimulationAdapter.cs
Normal file
@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Tests.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于测试的仿真环境适配器
|
||||
/// </summary>
|
||||
public class TestSimulationAdapter : ISimulationAdapter
|
||||
{
|
||||
private readonly Dictionary<string, object> _testEntities = [];
|
||||
private readonly List<SimulationEvent> _receivedEvents = [];
|
||||
private readonly List<SimulationEvent> _publishedEvents = [];
|
||||
private ISimulationManager? _simulationManager;
|
||||
// 存储实体状态的字典
|
||||
private Dictionary<string, object> _entityStates = new();
|
||||
// 存储环境数据的字典
|
||||
private Dictionary<string, SimulationEnvironmentData> _environmentData = new();
|
||||
// 当前仿真时间
|
||||
private double _currentTime = 0;
|
||||
private readonly object _eventLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,初始化测试适配器
|
||||
/// </summary>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public TestSimulationAdapter(ISimulationManager simulationManager)
|
||||
{
|
||||
_simulationManager = simulationManager ?? throw new ArgumentNullException(nameof(simulationManager));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体
|
||||
/// </summary>
|
||||
/// <param name="id">实体ID</param>
|
||||
/// <returns>实体对象或null</returns>
|
||||
public object? GetEntity(string id)
|
||||
{
|
||||
return _testEntities.TryGetValue(id, out var entity) ? entity : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布事件到外部仿真
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="evt">事件对象</param>
|
||||
public void PublishToExternalSimulation<T>(T evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
if (evt is not SimulationEvent simEvent)
|
||||
{
|
||||
throw new ArgumentException("事件必须继承自SimulationEvent", nameof(evt));
|
||||
}
|
||||
|
||||
lock (_eventLock)
|
||||
{
|
||||
simEvent.Timestamp = _currentTime; // 使用仿真时间作为时间戳
|
||||
_publishedEvents.Add(simEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收来自外部仿真的事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="evt">事件对象</param>
|
||||
public void ReceiveFromExternalSimulation<T>(T evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
if (evt is not SimulationEvent simEvent)
|
||||
{
|
||||
throw new ArgumentException("事件必须继承自SimulationEvent", nameof(evt));
|
||||
}
|
||||
|
||||
lock (_eventLock)
|
||||
{
|
||||
simEvent.Timestamp = _currentTime; // 使用仿真时间作为时间戳
|
||||
_receivedEvents.Add(simEvent);
|
||||
_simulationManager?.PublishEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加测试实体
|
||||
/// </summary>
|
||||
/// <param name="id">实体ID</param>
|
||||
/// <param name="entity">实体对象</param>
|
||||
public void AddTestEntity(string id, object entity)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(entity);
|
||||
_testEntities[id] = entity;
|
||||
// 初始化实体状态
|
||||
_entityStates[id] = new MockSimulationElement(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除测试实体
|
||||
/// </summary>
|
||||
public void ClearTestEntities()
|
||||
{
|
||||
_testEntities.Clear();
|
||||
_entityStates.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已发布的事件
|
||||
/// </summary>
|
||||
/// <returns>已发布的事件列表</returns>
|
||||
public IReadOnlyList<SimulationEvent> GetPublishedEvents()
|
||||
{
|
||||
lock (_eventLock)
|
||||
{
|
||||
return _publishedEvents.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的已发布事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <returns>指定类型的已发布事件列表</returns>
|
||||
public List<T> GetPublishedEvents<T>() where T : SimulationEvent
|
||||
{
|
||||
lock (_eventLock)
|
||||
{
|
||||
return _publishedEvents.OfType<T>().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已接收的事件
|
||||
/// </summary>
|
||||
/// <returns>已接收的事件列表</returns>
|
||||
public IReadOnlyList<SimulationEvent> GetReceivedEvents()
|
||||
{
|
||||
lock (_eventLock)
|
||||
{
|
||||
return _receivedEvents.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除事件
|
||||
/// </summary>
|
||||
public void ClearEvents()
|
||||
{
|
||||
lock (_eventLock)
|
||||
{
|
||||
_publishedEvents.Clear();
|
||||
_receivedEvents.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体状态
|
||||
/// </summary>
|
||||
/// <param name="entityId">实体ID</param>
|
||||
/// <returns>实体状态对象</returns>
|
||||
public object? GetEntityState(string entityId)
|
||||
{
|
||||
return _entityStates.TryGetValue(entityId, out var state) ? state : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置实体环境数据
|
||||
/// </summary>
|
||||
/// <param name="entityId">实体ID</param>
|
||||
/// <param name="data">环境数据</param>
|
||||
public void SetEntityEnvironment(string entityId, SimulationEnvironmentData data)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
_environmentData[entityId] = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体环境数据
|
||||
/// </summary>
|
||||
/// <param name="entityId">实体ID</param>
|
||||
/// <returns>环境数据对象</returns>
|
||||
public SimulationEnvironmentData? GetEntityEnvironment(string entityId)
|
||||
{
|
||||
return _environmentData.TryGetValue(entityId, out var data) ? data : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步仿真时间
|
||||
/// </summary>
|
||||
/// <param name="time">时间</param>
|
||||
public void SynchronizeTime(double time)
|
||||
{
|
||||
_currentTime = time;
|
||||
// 更新所有实体状态
|
||||
foreach (var entity in _testEntities.Values.OfType<SimulationElement>())
|
||||
{
|
||||
entity.Update(time - _currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前仿真时间
|
||||
/// </summary>
|
||||
/// <returns>当前仿真时间</returns>
|
||||
public double GetCurrentTime()
|
||||
{
|
||||
return _currentTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是否接收到特定类型的事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="predicate">验证条件</param>
|
||||
/// <returns>是否接收到符合条件的事件</returns>
|
||||
public bool HasReceivedEvent<T>(Predicate<T> predicate) where T : SimulationEvent
|
||||
{
|
||||
return _receivedEvents.OfType<T>().Any(evt => predicate(evt));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证是否发布了特定类型的事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="predicate">验证条件</param>
|
||||
/// <returns>是否发布了符合条件的事件</returns>
|
||||
public bool HasPublishedEvent<T>(Predicate<T> predicate) where T : SimulationEvent
|
||||
{
|
||||
return _publishedEvents.OfType<T>().Any(evt => predicate(evt));
|
||||
}
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
13
ThreatSource/data/indicators/ir_trackers/ir_001.json
Normal file
13
ThreatSource/data/indicators/ir_trackers/ir_001.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "红外测角仪-001",
|
||||
"en": "IR Tracker-001"
|
||||
},
|
||||
"type": "InfraredTracker",
|
||||
"infraredTrackerConfig": {
|
||||
"maxTrackingRange": 10000.0,
|
||||
"fieldOfView": 0.2,
|
||||
"angleMeasurementAccuracy": 0.001,
|
||||
"updateFrequency": 10.0
|
||||
}
|
||||
}
|
||||
17
ThreatSource/data/indicators/laser_beamriders/br_001.json
Normal file
17
ThreatSource/data/indicators/laser_beamriders/br_001.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "激光驾束仪-001",
|
||||
"en": "Laser Beam Rider-001"
|
||||
},
|
||||
"type": "LaserBeamRider",
|
||||
"beamRiderConfig": {
|
||||
"laserPower": 1000,
|
||||
"controlFieldDiameter": 6.0,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1010
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
ThreatSource/data/indicators/laser_designators/ld_001.json
Normal file
17
ThreatSource/data/indicators/laser_designators/ld_001.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "前视激光指示器-001",
|
||||
"en": "Forward Looking Laser Designator-001"
|
||||
},
|
||||
"type": "LaserDesignator",
|
||||
"designatorConfig": {
|
||||
"laserPower": 1000,
|
||||
"laserDivergenceAngle": 0.0002,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1010
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
ThreatSource/data/missiles/ir_command/irc_001.json
Normal file
36
ThreatSource/data/missiles/ir_command/irc_001.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "红外指令导引导弹-001",
|
||||
"en": "IR Command Guided Missile-001"
|
||||
},
|
||||
"type": "InfraredCommandGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 300.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 5000.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 23.5,
|
||||
"explosionRadius": 5.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 0.0,
|
||||
"irSeekerConfig": {
|
||||
"spectralBand": {
|
||||
"min": 3.0,
|
||||
"max": 5.0
|
||||
},
|
||||
"fieldOfView": 2.0,
|
||||
"sensitivity": -60.0,
|
||||
"trackingRate": 10.0
|
||||
},
|
||||
"commandLink": {
|
||||
"frequency": 10.0,
|
||||
"bandwidth": 1.0,
|
||||
"modulationType": "FSK",
|
||||
"updateRate": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
33
ThreatSource/data/missiles/ir_imaging/itg_001.json
Normal file
33
ThreatSource/data/missiles/ir_imaging/itg_001.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "红外成像末制导导弹-001",
|
||||
"en": "IR Imaging Terminal Guided Missile-001"
|
||||
},
|
||||
"type": "InfraredImagingTerminalGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 250.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 5000.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 25.0,
|
||||
"explosionRadius": 5.5,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 0.0
|
||||
},
|
||||
"infraredImagingGuidanceConfig": {
|
||||
"maxDetectionRange": 1000,
|
||||
"searchFieldOfView": 0.209,
|
||||
"trackFieldOfView": 0.052,
|
||||
"imageWidth": 640,
|
||||
"imageHeight": 512,
|
||||
"backgroundIntensity": 0.01,
|
||||
"searchRecognitionProbability": 0.6,
|
||||
"trackRecognitionProbability": 0.8,
|
||||
"targetLostTolerance": 0.2,
|
||||
"lockConfirmationTime": 0.3
|
||||
}
|
||||
}
|
||||
40
ThreatSource/data/missiles/laser_beam_rider/hj10.json
Normal file
40
ThreatSource/data/missiles/laser_beam_rider/hj10.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "红箭-10",
|
||||
"en": "HJ-10"
|
||||
},
|
||||
"type": "LaserBeamRiderGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 300.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 5000.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 24.5,
|
||||
"explosionRadius": 5.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 0.0,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1010
|
||||
},
|
||||
"IsCodeEnabled": true,
|
||||
"IsCodeMatchRequired": true
|
||||
}
|
||||
},
|
||||
"LaserBeamRiderGuidanceConfig": {
|
||||
"minDetectablePower": 1e-3,
|
||||
"detectorDiameter": 0.1,
|
||||
"controlFieldDiameter": 20.0,
|
||||
"proportionalGain": 30.0,
|
||||
"integralGain": 0.05,
|
||||
"derivativeGain": 5.0,
|
||||
"nonlinearGain": 0.5,
|
||||
"maxGuidanceAcceleration": 50.0,
|
||||
"lowPassFilterCoefficient": 0.2
|
||||
}
|
||||
}
|
||||
27
ThreatSource/data/missiles/laser_beam_rider/kornet.json
Normal file
27
ThreatSource/data/missiles/laser_beam_rider/kornet.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "科尔内特",
|
||||
"en": "Kornet"
|
||||
},
|
||||
"type": "LaserBeamRiderGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 300.0,
|
||||
"maxFlightTime": 70.0,
|
||||
"maxFlightDistance": 5500.0,
|
||||
"maxAcceleration": 110.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 12.0,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 27.0,
|
||||
"explosionRadius": 5.5,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 10.0,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
ThreatSource/data/missiles/laser_beam_rider/tow.json
Normal file
27
ThreatSource/data/missiles/laser_beam_rider/tow.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "陶式导弹",
|
||||
"en": "TOW"
|
||||
},
|
||||
"type": "LaserBeamRiderGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 278.0,
|
||||
"maxFlightTime": 65.0,
|
||||
"maxFlightDistance": 4500.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 10.0,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 22.6,
|
||||
"explosionRadius": 5.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 10.0,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1110
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
ThreatSource/data/missiles/laser_semi_active/lsgm_001.json
Normal file
39
ThreatSource/data/missiles/laser_semi_active/lsgm_001.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "激光半主动制导导弹-001",
|
||||
"en": "Laser Semi-Active Guidance Missile-001"
|
||||
},
|
||||
"type": "LaserSemiActiveGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 800.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 4000.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 22.0,
|
||||
"explosionRadius": 5.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 0.0,
|
||||
"laserCodeConfig": {
|
||||
"code": {
|
||||
"codeType": "PRF",
|
||||
"codeValue": 1010
|
||||
},
|
||||
"IsCodeEnabled": true,
|
||||
"IsCodeMatchRequired": true
|
||||
}
|
||||
},
|
||||
"laserSemiActiveGuidanceConfig": {
|
||||
"fieldOfViewAngle": 30.0,
|
||||
"lensDiameter": 0.1,
|
||||
"sensorDiameter": 0.03,
|
||||
"focusedSpotDiameter": 0.006,
|
||||
"reflectionCoefficient": 0.2,
|
||||
"targetReflectiveArea": 1.0,
|
||||
"lockThreshold": 1e-12,
|
||||
"spotOffsetSensitivity": 0.5
|
||||
}
|
||||
}
|
||||
29
ThreatSource/data/missiles/mmw/mmw_001.json
Normal file
29
ThreatSource/data/missiles/mmw/mmw_001.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "毫米波末制导导弹-001",
|
||||
"en": "Millimeter Wave Terminal Guided Missile-001"
|
||||
},
|
||||
"type": "MillimeterWaveTerminalGuidance",
|
||||
"properties": {
|
||||
"maxSpeed": 250.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 8000.0,
|
||||
"maxAcceleration": 100.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 28.0,
|
||||
"explosionRadius": 6.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 0.0
|
||||
},
|
||||
"MillimeterWaveGuidanceConfig": {
|
||||
"maxDetectionRange": 5000.0,
|
||||
"fieldOfViewAngle": 45.0,
|
||||
"targetRecognitionProbability": 0.95,
|
||||
"waveFrequency": 94e9,
|
||||
"pulseDuration": 1e-6,
|
||||
"recognitionSNRThreshold": 6.0
|
||||
}
|
||||
}
|
||||
51
ThreatSource/data/missiles/terminal_sensitive/tsm_001.json
Normal file
51
ThreatSource/data/missiles/terminal_sensitive/tsm_001.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "末敏导弹-001",
|
||||
"en": "Terminal Sensitive Missile-001"
|
||||
},
|
||||
"type": "TerminalSensitiveMissile",
|
||||
"properties": {
|
||||
"maxSpeed": 1000.0,
|
||||
"maxFlightTime": 100.0,
|
||||
"maxFlightDistance": 5000.0,
|
||||
"maxAcceleration": 200.0,
|
||||
"proportionalNavigationCoefficient": 3.0,
|
||||
"launchAcceleration": 100.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"cruiseTime": 5.0,
|
||||
"mass": 50.0,
|
||||
"explosionRadius": 5.0,
|
||||
"selfDestructHeight": 0.0
|
||||
},
|
||||
"submunitionProperties": {
|
||||
"maxSpeed": 2000.0,
|
||||
"maxFlightTime": 60.0,
|
||||
"maxFlightDistance": 2000.0,
|
||||
"maxAcceleration": 300.0,
|
||||
"proportionalNavigationCoefficient": 4.0,
|
||||
"launchAcceleration": 10.0,
|
||||
"maxEngineBurnTime": 0.1,
|
||||
"mass": 10.0,
|
||||
"explosionRadius": 5.0,
|
||||
"hitProbability": 0.9,
|
||||
"selfDestructHeight": 20.0
|
||||
},
|
||||
"submunitionCount": 1,
|
||||
"submunitionConfig": {
|
||||
"separationHeight": 1000.0,
|
||||
"separationDistance": 1000.0,
|
||||
"submunitionSeparationAngle": 45.0,
|
||||
"separationRange": 50.0,
|
||||
"decelerationAcceleration": 250.0,
|
||||
"decelerationEndSpeed": 50.0,
|
||||
"parachuteDeploymentHeight": 400.0,
|
||||
"parachuteDeceleration": 140.0,
|
||||
"stableScanHeight": 200.0,
|
||||
"verticalDeclineSpeed": 10.0,
|
||||
"spiralRotationSpeed": 25.13,
|
||||
"scanAngle": 30.0,
|
||||
"targetDetectionDistance": 150.0,
|
||||
"selfDestructHeight": 20.0,
|
||||
"attackSpeed": 200.0
|
||||
}
|
||||
}
|
||||
32
ThreatSource/data/sensors/laser_warners/lw_001.json
Normal file
32
ThreatSource/data/sensors/laser_warners/lw_001.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "激光告警接收机-001",
|
||||
"en": "Laser Warning Receiver-001"
|
||||
},
|
||||
"type": "LaserWarner",
|
||||
"properties": {
|
||||
"detectionRange": 5000.0,
|
||||
"wavelengthRange": {
|
||||
"min": 0.4,
|
||||
"max": 1.7
|
||||
},
|
||||
"fieldOfView": 360.0,
|
||||
"responseTime": 0.001,
|
||||
"sensitivity": -60.0,
|
||||
"angularResolution": 7.5,
|
||||
"falseAlarmRate": 1e-6,
|
||||
"detectionProbability": 0.95,
|
||||
"spectralBands": [
|
||||
{
|
||||
"name": "Band1",
|
||||
"minWavelength": 0.4,
|
||||
"maxWavelength": 0.7
|
||||
},
|
||||
{
|
||||
"name": "Band2",
|
||||
"minWavelength": 0.7,
|
||||
"maxWavelength": 1.7
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
34
ThreatSource/data/targets/apcs/apc_001.json
Normal file
34
ThreatSource/data/targets/apcs/apc_001.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "装甲运兵车-001",
|
||||
"en": "Armored Personnel Carrier-001"
|
||||
},
|
||||
"type": "APC",
|
||||
"mass": 25000.0,
|
||||
"length": 7.0,
|
||||
"width": 3.2,
|
||||
"height": 2.8,
|
||||
"maxSpeed": 80.0,
|
||||
"armorThickness": 400.0,
|
||||
|
||||
"radarCrossSection": 12.0,
|
||||
"infraredRadiationIntensity": 2000.0,
|
||||
"ultravioletRadiationIntensity": 12.0,
|
||||
"millimeterWaveRadiationIntensity": 8.0,
|
||||
"millimeterWaveRadiationTemperature": 350.0,
|
||||
"laserReflectivity": 0.25,
|
||||
|
||||
"thermalPattern": {
|
||||
"description": "3x3 matrix representing side view temperature distribution (°C)",
|
||||
"static": [
|
||||
[35, 40, 65],
|
||||
[30, 35, 70],
|
||||
[40, 40, 45]
|
||||
],
|
||||
"moving": [
|
||||
[40, 45, 70],
|
||||
[35, 40, 75],
|
||||
[50, 50, 55]
|
||||
]
|
||||
}
|
||||
}
|
||||
34
ThreatSource/data/targets/helicopters/heli_001.json
Normal file
34
ThreatSource/data/targets/helicopters/heli_001.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "武装直升机-001",
|
||||
"en": "Attack Helicopter-001"
|
||||
},
|
||||
"type": "Helicopter",
|
||||
"mass": 10000.0,
|
||||
"length": 17.0,
|
||||
"width": 3.0,
|
||||
"height": 4.5,
|
||||
"maxSpeed": 280.0,
|
||||
"armorThickness": 150.0,
|
||||
|
||||
"radarCrossSection": 8.0,
|
||||
"infraredRadiationIntensity": 3000.0,
|
||||
"ultravioletRadiationIntensity": 20.0,
|
||||
"millimeterWaveRadiationIntensity": 6.0,
|
||||
"millimeterWaveRadiationTemperature": 450.0,
|
||||
"laserReflectivity": 0.2,
|
||||
|
||||
"thermalPattern": {
|
||||
"description": "3x3 matrix representing side view temperature distribution (°C)",
|
||||
"static": [
|
||||
[85, 110, 80],
|
||||
[35, 45, 40],
|
||||
[30, 35, 30]
|
||||
],
|
||||
"moving": [
|
||||
[90, 115, 85],
|
||||
[40, 50, 45],
|
||||
[35, 40, 35]
|
||||
]
|
||||
}
|
||||
}
|
||||
34
ThreatSource/data/targets/tanks/mbt_001.json
Normal file
34
ThreatSource/data/targets/tanks/mbt_001.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": {
|
||||
"zh": "主战坦克-001",
|
||||
"en": "Main Battle Tank-001"
|
||||
},
|
||||
"type": "Tank",
|
||||
"mass": 50000.0,
|
||||
"length": 10.0,
|
||||
"width": 3.5,
|
||||
"height": 2.4,
|
||||
"maxSpeed": 70.0,
|
||||
"armorThickness": 800.0,
|
||||
|
||||
"radarCrossSection": 15.0,
|
||||
"infraredRadiationIntensity": 2500.0,
|
||||
"ultravioletRadiationIntensity": 15.0,
|
||||
"millimeterWaveRadiationIntensity": 10.0,
|
||||
"millimeterWaveRadiationTemperature": 400.0,
|
||||
"laserReflectivity": 0.3,
|
||||
|
||||
"thermalPattern": {
|
||||
"description": "3x3 matrix representing side view temperature distribution (°C)",
|
||||
"static": [
|
||||
[40, 45, 80],
|
||||
[35, 40, 90],
|
||||
[50, 50, 60]
|
||||
],
|
||||
"moving": [
|
||||
[45, 50, 85],
|
||||
[40, 45, 95],
|
||||
[65, 65, 75]
|
||||
]
|
||||
}
|
||||
}
|
||||
426
ThreatSource/src/Data/Models.cs
Normal file
426
ThreatSource/src/Data/Models.cs
Normal file
@ -0,0 +1,426 @@
|
||||
using System.Collections.Generic;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Target;
|
||||
namespace ThreatSource.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 多语言名称
|
||||
/// </summary>
|
||||
public class LocalizedName
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置中文名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于显示中文界面和文档
|
||||
/// </remarks>
|
||||
public string Zh { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置英文名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于显示英文界面和文档
|
||||
/// </remarks>
|
||||
public string En { get; set; } = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹数据模型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含导弹的基本信息和性能参数
|
||||
/// 用于创建和初始化导弹实例
|
||||
/// </remarks>
|
||||
public class MissileData
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的多语言名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含中英文名称
|
||||
/// 用于显示和文档
|
||||
/// </remarks>
|
||||
public LocalizedName Name { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义导弹的制导方式
|
||||
/// 影响导弹的行为和性能特征
|
||||
/// </remarks>
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹属性
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含导弹的详细性能参数
|
||||
/// 如最大速度、加速度、射程等
|
||||
/// </remarks>
|
||||
public MissileProperties Properties { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光半主动导引配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当导弹类型为 LaserSemiActiveGuidance 时有效
|
||||
/// 包含激光半主动导引系统的性能参数:
|
||||
/// - 视场角配置
|
||||
/// - 镜头直径配置
|
||||
/// - 传感器直径配置
|
||||
/// - 聚焦光斑直径配置
|
||||
/// - 目标反射系数配置
|
||||
/// - 目标有效反射面积配置
|
||||
/// - 锁定阈值配置
|
||||
/// - 光斑偏移灵敏度配置
|
||||
/// </remarks>
|
||||
public LaserSemiActiveGuidanceConfig? LaserSemiActiveGuidanceConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光驾束导引配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当导弹类型为 LaserBeamRiderGuidance 时有效
|
||||
/// 包含激光驾束导引系统的性能参数:
|
||||
/// - 最小可探测功率配置
|
||||
/// - 探测器直径配置
|
||||
/// - 控制场直径配置
|
||||
/// - 比例增益配置
|
||||
/// - 积分增益配置
|
||||
/// - 微分增益配置
|
||||
/// - 非线性增益配置
|
||||
/// - 最大加速度配置
|
||||
/// - 低通滤波系数配置
|
||||
/// </remarks>
|
||||
public LaserBeamRiderGuidanceSystemConfig? LaserBeamRiderGuidanceConfig { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置红外成像导引配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当导弹类型为 InfraredImagingTerminalGuidance 时有效
|
||||
/// 包含红外成像导引系统的性能参数:
|
||||
/// - 视场角配置
|
||||
/// - 图像传感器配置
|
||||
/// - 目标识别配置
|
||||
/// - 时间参数配置
|
||||
/// </remarks>
|
||||
public InfraredImagingGuidanceConfig? InfraredImagingGuidanceConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置毫米波导引配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当导弹类型为 MillimeterWaveTerminalGuidedMissile 时有效
|
||||
/// 包含毫米波导引系统的性能参数
|
||||
/// </remarks>
|
||||
public MillimeterWaveGuidanceConfig? MillimeterWaveGuidanceConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置末敏弹子弹属性
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅用于末敏弹类型
|
||||
/// 定义子弹的性能参数
|
||||
/// </remarks>
|
||||
public MissileProperties? SubmunitionProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置末敏弹子弹数量
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅用于末敏弹类型
|
||||
/// 定义子弹的装载数量
|
||||
/// </remarks>
|
||||
public int SubmunitionCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置末敏弹子弹配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅用于末敏弹类型
|
||||
/// 定义子弹的性能参数
|
||||
/// </remarks>
|
||||
public TerminalSensitiveSubmunitionConfig? SubmunitionConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 指示器数据模型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含各类指示器的配置信息
|
||||
/// 用于创建和初始化指示器实例
|
||||
/// </remarks>
|
||||
public class IndicatorData
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置指示器的多语言名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含中英文名称
|
||||
/// 用于显示和文档
|
||||
/// </remarks>
|
||||
public LocalizedName Name { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置指示器类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 可选值:
|
||||
/// - LaserDesignator:激光指示器
|
||||
/// - LaserBeamRider:激光驾束仪
|
||||
/// - InfraredTracker:红外跟踪器
|
||||
/// </remarks>
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光指示器配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为LaserDesignator时有效
|
||||
/// 包含激光指示器的性能参数
|
||||
/// </remarks>
|
||||
public LaserDesignatorConfig? DesignatorConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光驾束仪配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为LaserBeamRider时有效
|
||||
/// 包含激光驾束仪的性能参数
|
||||
/// </remarks>
|
||||
public LaserBeamRiderConfig? BeamRiderConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置红外跟踪器配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为InfraredTracker时有效
|
||||
/// 包含红外跟踪器的性能参数
|
||||
/// </remarks>
|
||||
public InfraredTrackerConfig? InfraredTrackerConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 传感器数据模型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含各类传感器的配置信息
|
||||
/// 用于创建和初始化传感器实例
|
||||
/// </remarks>
|
||||
public class SensorData
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置传感器的多语言名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含中英文名称
|
||||
/// 用于显示和文档
|
||||
/// </remarks>
|
||||
public LocalizedName Name { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置传感器类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 可选值:
|
||||
/// - LaserWarner:激光告警器
|
||||
/// - IRWarner:红外告警器
|
||||
/// - MMWWarner:毫米波告警器
|
||||
/// </remarks>
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光告警器配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为LaserWarner时有效
|
||||
/// 包含激光告警器的性能参数
|
||||
/// </remarks>
|
||||
public LaserWarnerConfig? LaserWarnerConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置红外告警器配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为IRWarner时有效
|
||||
/// 包含红外告警器的性能参数
|
||||
/// </remarks>
|
||||
public InfraredWarnerConfig? IRWarnerConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置毫米波告警器配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 仅当Type为MMWWarner时有效
|
||||
/// 包含毫米波告警器的性能参数
|
||||
/// </remarks>
|
||||
public MillimeterWaveWarnerConfig? MMWWarnerConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 目标数据模型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含各类目标的基本信息和物理特性
|
||||
/// 用于创建和初始化目标实例
|
||||
/// </remarks>
|
||||
public class TargetData
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置目标的多语言名称
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含中英文名称
|
||||
/// 用于显示和文档
|
||||
/// </remarks>
|
||||
public LocalizedName Name { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标类型
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 可选值:
|
||||
/// - Tank:坦克
|
||||
/// - APC:装甲车
|
||||
/// - Helicopter:直升机
|
||||
/// </remarks>
|
||||
public string Type { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标质量
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:千克
|
||||
/// 影响目标的运动特性
|
||||
/// </remarks>
|
||||
public double Mass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标长度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 目标的物理尺寸
|
||||
/// </remarks>
|
||||
public double Length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标宽度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 目标的物理尺寸
|
||||
/// </remarks>
|
||||
public double Width { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标高度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 目标的物理尺寸
|
||||
/// </remarks>
|
||||
public double Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标最大速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒
|
||||
/// 目标的最大移动速度
|
||||
/// </remarks>
|
||||
public double MaxSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标装甲厚度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:毫米
|
||||
/// 影响目标的防护能力
|
||||
/// </remarks>
|
||||
public double ArmorThickness { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的雷达散射截面积
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:平方米
|
||||
/// 表示目标的雷达反射特性
|
||||
/// 影响雷达探测和跟踪能力
|
||||
/// </remarks>
|
||||
public double RadarCrossSection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的红外辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示目标的红外辐射特征
|
||||
/// 影响红外制导系统的探测和跟踪能力
|
||||
/// </remarks>
|
||||
public double InfraredRadiationIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的紫外辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示目标的紫外辐射特征
|
||||
/// 影响紫外探测系统的探测能力
|
||||
/// </remarks>
|
||||
public double UltravioletRadiationIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的毫米波辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示目标的毫米波辐射特征
|
||||
/// 影响毫米波制导系统的探测和跟踪能力
|
||||
/// </remarks>
|
||||
public double MillimeterWaveRadiationIntensity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的毫米波辐射温度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:开尔文
|
||||
/// 表示目标的毫米波辐射特征
|
||||
/// 影响毫米波制导系统的探测和跟踪能力
|
||||
/// 典型值:350-450K
|
||||
/// </remarks>
|
||||
public double MillimeterWaveRadiationTemperature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的激光反射率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 无量纲,取值范围:0-1
|
||||
/// 表示目标表面对激光的反射特性
|
||||
/// 影响激光测距和制导系统的效果
|
||||
/// </remarks>
|
||||
public double LaserReflectivity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的温度分布模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含静止和运动状态下的温度分布矩阵
|
||||
/// </remarks>
|
||||
public ThermalPattern ThermalPattern { get; set; } = new ThermalPattern(new double[3, 3], new double[3, 3]);
|
||||
|
||||
/// <summary>
|
||||
/// 获取温度分布模式对象
|
||||
/// </summary>
|
||||
public ThermalPattern GetThermalPattern()
|
||||
{
|
||||
return new ThermalPattern(ThermalPattern.StaticPattern, ThermalPattern.MovingPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
273
ThreatSource/src/Data/ThreatSourceDataManager.cs
Normal file
273
ThreatSource/src/Data/ThreatSourceDataManager.cs
Normal file
@ -0,0 +1,273 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 威胁源数据管理器,负责加载和管理所有设备的配置数据
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供以下功能:
|
||||
/// - 加载配置数据
|
||||
/// - 获取可用设备列表
|
||||
/// - 获取设备配置数据
|
||||
/// 用于统一管理威胁源库中的各类设备数据
|
||||
/// </remarks>
|
||||
public class ThreatSourceDataManager
|
||||
{
|
||||
private static readonly string DATA_PATH = "../ThreatSource/data";
|
||||
private static readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Converters =
|
||||
{
|
||||
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
|
||||
}
|
||||
};
|
||||
private readonly Dictionary<string, MissileData> _missiles = new();
|
||||
private readonly Dictionary<string, IndicatorData> _indicators = new();
|
||||
private readonly Dictionary<string, SensorData> _sensors = new();
|
||||
private readonly Dictionary<string, TargetData> _targets = new();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化威胁源数据管理器
|
||||
/// </summary>
|
||||
/// <param name="dataPath">可选的数据目录路径</param>
|
||||
public ThreatSourceDataManager(string? dataPath = null)
|
||||
{
|
||||
if (dataPath != null)
|
||||
LoadData(dataPath);
|
||||
else
|
||||
LoadData(DATA_PATH);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载数据
|
||||
/// </summary>
|
||||
/// <param name="path">数据目录路径</param>
|
||||
private void LoadData(string path)
|
||||
{
|
||||
LoadMissiles(Path.Combine(path, "missiles"));
|
||||
LoadIndicators(Path.Combine(path, "indicators"));
|
||||
LoadSensors(Path.Combine(path, "sensors"));
|
||||
LoadTargets(Path.Combine(path, "targets"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载导弹数据
|
||||
/// </summary>
|
||||
private void LoadMissiles(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"导弹数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(path, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonContent = File.ReadAllText(file);
|
||||
Console.WriteLine($"读取导弹文件内容:{jsonContent}");
|
||||
|
||||
var data = JsonSerializer.Deserialize<MissileData>(jsonContent, _jsonOptions);
|
||||
if (data != null)
|
||||
{
|
||||
string model = Path.GetFileNameWithoutExtension(file);
|
||||
_missiles[model] = data;
|
||||
Console.WriteLine($"已加载导弹数据:{model}");
|
||||
Console.WriteLine($"读取到的数据:{JsonSerializer.Serialize(data, _jsonOptions)}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载导弹数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载指示器数据
|
||||
/// </summary>
|
||||
private void LoadIndicators(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"指示器数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(path, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonContent = File.ReadAllText(file);
|
||||
Console.WriteLine($"读取指示器文件内容:{jsonContent}");
|
||||
|
||||
var data = JsonSerializer.Deserialize<IndicatorData>(jsonContent, _jsonOptions);
|
||||
if (data != null)
|
||||
{
|
||||
string model = Path.GetFileNameWithoutExtension(file);
|
||||
_indicators[model] = data;
|
||||
Console.WriteLine($"已加载指示器数据:{model}");
|
||||
Console.WriteLine($"读取到的数据:{JsonSerializer.Serialize(data, _jsonOptions)}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载指示器数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载传感器数据
|
||||
/// </summary>
|
||||
private void LoadSensors(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"传感器数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(path, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonContent = File.ReadAllText(file);
|
||||
Console.WriteLine($"读取传感器文件内容:{jsonContent}");
|
||||
|
||||
var data = JsonSerializer.Deserialize<SensorData>(jsonContent, _jsonOptions);
|
||||
if (data != null)
|
||||
{
|
||||
string model = Path.GetFileNameWithoutExtension(file);
|
||||
_sensors[model] = data;
|
||||
Console.WriteLine($"已加载传感器数据:{model}");
|
||||
Console.WriteLine($"读取到的数据:{JsonSerializer.Serialize(data, _jsonOptions)}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载传感器数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载目标数据
|
||||
/// </summary>
|
||||
private void LoadTargets(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Console.WriteLine($"目标数据目录不存在:{path}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var file in Directory.GetFiles(path, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonContent = File.ReadAllText(file);
|
||||
Console.WriteLine($"读取目标文件内容:{jsonContent}");
|
||||
|
||||
var data = JsonSerializer.Deserialize<TargetData>(jsonContent, _jsonOptions);
|
||||
if (data != null)
|
||||
{
|
||||
string model = Path.GetFileNameWithoutExtension(file);
|
||||
_targets[model] = data;
|
||||
Console.WriteLine($"正在加载目标数据:{file}");
|
||||
Console.WriteLine($"读取到的数据:{JsonSerializer.Serialize(data, _jsonOptions)}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"加载目标数据文件失败:{file},错误:{ex.Message}");
|
||||
Console.WriteLine($"异常堆栈:{ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取导弹配置数据
|
||||
/// </summary>
|
||||
/// <param name="model">导弹型号</param>
|
||||
/// <returns>导弹配置数据</returns>
|
||||
public MissileData GetMissile(string model)
|
||||
{
|
||||
if (_missiles.TryGetValue(model, out var data))
|
||||
return data;
|
||||
throw new KeyNotFoundException($"Missile {model} not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指示器配置数据
|
||||
/// </summary>
|
||||
/// <param name="model">指示器型号</param>
|
||||
/// <returns>指示器配置数据</returns>
|
||||
public IndicatorData GetIndicator(string model)
|
||||
{
|
||||
if (_indicators.TryGetValue(model, out var data))
|
||||
return data;
|
||||
throw new KeyNotFoundException($"Indicator {model} not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取传感器配置数据
|
||||
/// </summary>
|
||||
/// <param name="model">传感器型号</param>
|
||||
/// <returns>传感器配置数据</returns>
|
||||
public SensorData GetSensor(string model)
|
||||
{
|
||||
if (_sensors.TryGetValue(model, out var data))
|
||||
return data;
|
||||
throw new KeyNotFoundException($"Sensor {model} not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标配置数据
|
||||
/// </summary>
|
||||
/// <param name="model">目标型号</param>
|
||||
/// <returns>目标配置数据</returns>
|
||||
public TargetData GetTarget(string model)
|
||||
{
|
||||
if (_targets.TryGetValue(model, out var data))
|
||||
return data;
|
||||
throw new KeyNotFoundException($"Target {model} not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有可用的导弹ID列表
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetAvailableMissiles() => _missiles.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有可用的指示器ID列表
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetAvailableIndicators() => _indicators.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有可用的传感器ID列表
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetAvailableSensors() => _sensors.Keys;
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有可用的目标ID列表
|
||||
/// </summary>
|
||||
public IEnumerable<string> GetAvailableTargets() => _targets.Keys;
|
||||
}
|
||||
}
|
||||
239
ThreatSource/src/Data/ThreatSourceFactory.cs
Normal file
239
ThreatSource/src/Data/ThreatSourceFactory.cs
Normal file
@ -0,0 +1,239 @@
|
||||
using System;
|
||||
using ThreatSource.Missile;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// 威胁源工厂类,负责根据配置数据创建各类设备实例
|
||||
/// </summary>
|
||||
public class ThreatSourceFactory
|
||||
{
|
||||
private readonly ThreatSourceDataManager _dataManager;
|
||||
private readonly ISimulationManager _simulationManager;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="dataManager">数据管理器</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public ThreatSourceFactory(ThreatSourceDataManager dataManager, ISimulationManager simulationManager)
|
||||
{
|
||||
_dataManager = dataManager;
|
||||
_simulationManager = simulationManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建导弹实例
|
||||
/// </summary>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="missileModel">导弹型号</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <returns>导弹实例</returns>
|
||||
public BaseMissile CreateMissile(string missileId, string missileModel, string targetId, InitialMotionParameters launchParams)
|
||||
{
|
||||
var data = _dataManager.GetMissile(missileModel);
|
||||
|
||||
switch (data.Type)
|
||||
{
|
||||
case MissileType.LaserBeamRiderGuidance:
|
||||
if (data.LaserBeamRiderGuidanceConfig == null)
|
||||
throw new ArgumentException($"Missing laser beam rider guidance configuration for missile: {missileModel}");
|
||||
return new LaserBeamRiderMissile(
|
||||
missileId,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
data.Properties.LaserCodeConfig ?? new LaserCodeConfig(),
|
||||
data.LaserBeamRiderGuidanceConfig,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case MissileType.LaserSemiActiveGuidance:
|
||||
if (data.LaserSemiActiveGuidanceConfig == null)
|
||||
throw new ArgumentException($"Missing laser semi-active guidance configuration for missile: {missileModel}");
|
||||
return new LaserSemiActiveGuidedMissile(
|
||||
missileId,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
data.Properties.LaserCodeConfig ?? new LaserCodeConfig(),
|
||||
data.LaserSemiActiveGuidanceConfig,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case MissileType.InfraredCommandGuidance:
|
||||
return new InfraredCommandGuidedMissile(
|
||||
missileId,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case MissileType.InfraredImagingTerminalGuidance:
|
||||
if (_simulationManager.GetEntityById(targetId) is not ITarget target)
|
||||
throw new ArgumentException($"Target not found or invalid: {targetId}");
|
||||
|
||||
if (data.InfraredImagingGuidanceConfig == null)
|
||||
throw new ArgumentException($"Missing infrared imaging guidance configuration for missile: {missileModel}");
|
||||
|
||||
return new InfraredImagingTerminalGuidedMissile(
|
||||
missileId,
|
||||
target.Type,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
data.InfraredImagingGuidanceConfig,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case MissileType.MillimeterWaveTerminalGuidance:
|
||||
if (data.MillimeterWaveGuidanceConfig == null)
|
||||
throw new ArgumentException($"Missing millimeter wave guidance configuration for missile: {missileModel}");
|
||||
return new MillimeterWaveTerminalGuidedMissile(
|
||||
missileId,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
data.MillimeterWaveGuidanceConfig,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case MissileType.TerminalSensitiveMissile:
|
||||
if (data.SubmunitionProperties == null)
|
||||
throw new ArgumentException("Missing submunition properties for terminal sensitive missile");
|
||||
if (data.SubmunitionConfig == null)
|
||||
throw new ArgumentException("Missing submunition config for terminal sensitive missile");
|
||||
return new TerminalSensitiveMissile(
|
||||
missileId,
|
||||
targetId,
|
||||
data.Properties,
|
||||
launchParams,
|
||||
data.SubmunitionProperties,
|
||||
data.SubmunitionCount,
|
||||
data.SubmunitionConfig,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported missile type: {data.Type}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建指示器实例
|
||||
/// </summary>
|
||||
/// <param name="indicatorId">指示器ID</param>
|
||||
/// <param name="indicatorModel">指示器型号</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <returns>指示器实例</returns>
|
||||
public IIndicator CreateIndicator(string indicatorId, string indicatorModel, string targetId, string missileId, InitialMotionParameters initialMotionParameters)
|
||||
{
|
||||
var data = _dataManager.GetIndicator(indicatorModel);
|
||||
|
||||
Console.WriteLine($"dataType: {data.Type}, indicatorModel: {indicatorModel}, indicatorId: {indicatorId}, targetId: {targetId}, missileId: {missileId}");
|
||||
|
||||
switch (data.Type)
|
||||
{
|
||||
case "LaserDesignator" when data.DesignatorConfig != null:
|
||||
return new LaserDesignator(
|
||||
indicatorId,
|
||||
targetId,
|
||||
missileId,
|
||||
data.DesignatorConfig,
|
||||
initialMotionParameters,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
case "LaserBeamRider" when data.BeamRiderConfig != null:
|
||||
return new LaserBeamRider(
|
||||
indicatorId,
|
||||
targetId,
|
||||
missileId,
|
||||
data.BeamRiderConfig,
|
||||
initialMotionParameters,
|
||||
_simulationManager
|
||||
);
|
||||
case "InfraredTracker" when data.InfraredTrackerConfig != null:
|
||||
return new InfraredTracker(
|
||||
indicatorId,
|
||||
targetId,
|
||||
data.InfraredTrackerConfig,
|
||||
initialMotionParameters,
|
||||
_simulationManager
|
||||
);
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Invalid indicator type or missing config: {data.Type}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建目标实例
|
||||
/// </summary>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="targetModel">目标型号</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <returns>目标实例</returns>
|
||||
public SimulationElement CreateTarget(string targetId, string targetModel, InitialMotionParameters initialMotionParameters)
|
||||
{
|
||||
var data = _dataManager.GetTarget(targetModel);
|
||||
Console.WriteLine($"targetModel: {targetModel}, targetId: {targetId}, targetType: {data.Type}");
|
||||
|
||||
switch (data.Type)
|
||||
{
|
||||
case "Tank":
|
||||
var tank = new Tank(
|
||||
targetId,
|
||||
initialMotionParameters,
|
||||
_simulationManager);
|
||||
tank.SetDimensions(data.Length, data.Width, data.Height);
|
||||
tank.SetSpectralCharacteristics(
|
||||
data.RadarCrossSection,
|
||||
data.InfraredRadiationIntensity,
|
||||
data.UltravioletRadiationIntensity,
|
||||
data.MillimeterWaveRadiationIntensity);
|
||||
tank.MillimeterWaveRadiationTemperature = data.MillimeterWaveRadiationTemperature;
|
||||
tank.LaserReflectivity = data.LaserReflectivity;
|
||||
tank.SetThermalPattern(data.ThermalPattern);
|
||||
return tank;
|
||||
|
||||
case "APC":
|
||||
var apc = new APC(
|
||||
targetId,
|
||||
initialMotionParameters,
|
||||
_simulationManager);
|
||||
apc.SetDimensions(data.Length, data.Width, data.Height);
|
||||
apc.SetSpectralCharacteristics(
|
||||
data.RadarCrossSection,
|
||||
data.InfraredRadiationIntensity,
|
||||
data.UltravioletRadiationIntensity,
|
||||
data.MillimeterWaveRadiationIntensity);
|
||||
apc.MillimeterWaveRadiationTemperature = data.MillimeterWaveRadiationTemperature;
|
||||
apc.LaserReflectivity = data.LaserReflectivity;
|
||||
apc.SetThermalPattern(data.ThermalPattern);
|
||||
return apc;
|
||||
|
||||
case "Helicopter":
|
||||
var helicopter = new Helicopter(
|
||||
targetId,
|
||||
initialMotionParameters,
|
||||
_simulationManager);
|
||||
helicopter.SetDimensions(data.Length, data.Width, data.Height);
|
||||
helicopter.SetSpectralCharacteristics(
|
||||
data.RadarCrossSection,
|
||||
data.InfraredRadiationIntensity,
|
||||
data.UltravioletRadiationIntensity,
|
||||
data.MillimeterWaveRadiationIntensity);
|
||||
helicopter.MillimeterWaveRadiationTemperature = data.MillimeterWaveRadiationTemperature;
|
||||
helicopter.LaserReflectivity = data.LaserReflectivity;
|
||||
helicopter.SetThermalPattern(data.ThermalPattern);
|
||||
return helicopter;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"不支持的目标类型: {data.Type}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
ThreatSource/src/Guidance/InfraredImage.cs
Normal file
88
ThreatSource/src/Guidance/InfraredImage.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Guidance
|
||||
{
|
||||
/// <summary>
|
||||
/// 红外图像类,表示简化的红外图像数据
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类存储红外图像的基本信息:
|
||||
/// - 图像尺寸
|
||||
/// - 像素物理大小
|
||||
/// - 红外强度矩阵
|
||||
/// 用于目标探测和识别
|
||||
/// </remarks>
|
||||
public class InfraredImage
|
||||
{
|
||||
/// <summary>
|
||||
/// 图像宽度,单位:像素
|
||||
/// </summary>
|
||||
public int Width { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 图像高度,单位:像素
|
||||
/// </summary>
|
||||
public int Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 像素物理尺寸,单位:弧度/像素
|
||||
/// </summary>
|
||||
public double PixelSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 红外强度矩阵,单位:W/sr
|
||||
/// </summary>
|
||||
public double[,] Intensity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 图像中心视线方向
|
||||
/// </summary>
|
||||
public Vector3D LineOfSight { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外图像的新实例
|
||||
/// </summary>
|
||||
/// <param name="width">图像宽度</param>
|
||||
/// <param name="height">图像高度</param>
|
||||
/// <param name="pixelSize">像素物理尺寸</param>
|
||||
/// <param name="lineOfSight">视线方向</param>
|
||||
public InfraredImage(int width, int height, double pixelSize, Vector3D lineOfSight)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
PixelSize = pixelSize;
|
||||
LineOfSight = lineOfSight;
|
||||
Intensity = new double[height, width];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置像素强度值
|
||||
/// </summary>
|
||||
/// <param name="row">行索引</param>
|
||||
/// <param name="col">列索引</param>
|
||||
/// <param name="value">强度值</param>
|
||||
public void SetIntensity(int row, int col, double value)
|
||||
{
|
||||
if (row >= 0 && row < Height && col >= 0 && col < Width)
|
||||
{
|
||||
Intensity[row, col] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取像素强度值
|
||||
/// </summary>
|
||||
/// <param name="row">行索引</param>
|
||||
/// <param name="col">列索引</param>
|
||||
/// <returns>强度值</returns>
|
||||
public double GetIntensity(int row, int col)
|
||||
{
|
||||
if (row >= 0 && row < Height && col >= 0 && col < Width)
|
||||
{
|
||||
return Intensity[row, col];
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
262
ThreatSource/src/Guidance/InfraredImageGenerator.cs
Normal file
262
ThreatSource/src/Guidance/InfraredImageGenerator.cs
Normal file
@ -0,0 +1,262 @@
|
||||
using System;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Guidance
|
||||
{
|
||||
/// <summary>
|
||||
/// 红外图像生成器,用于生成目标的红外图像
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类实现红外图像的生成过程:
|
||||
/// - 计算目标在图像平面上的投影
|
||||
/// - 根据目标特性生成红外强度
|
||||
/// - 添加背景噪声
|
||||
/// </remarks>
|
||||
public class InfraredImageGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// 图像宽度,单位:像素
|
||||
/// </summary>
|
||||
private readonly int imageWidth;
|
||||
|
||||
/// <summary>
|
||||
/// 图像高度,单位:像素
|
||||
/// </summary>
|
||||
private readonly int imageHeight;
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// </summary>
|
||||
private readonly double fieldOfView;
|
||||
|
||||
/// <summary>
|
||||
/// 背景辐射强度,单位:W/sr
|
||||
/// </summary>
|
||||
private readonly double backgroundIntensity;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数生成器
|
||||
/// </summary>
|
||||
private readonly Random random = new();
|
||||
|
||||
// 视线坐标系
|
||||
private Vector3D forward; // 视线方向
|
||||
private Vector3D right; // 图像平面右方向
|
||||
private Vector3D up; // 图像平面上方向
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外图像生成器的新实例
|
||||
/// </summary>
|
||||
/// <param name="imageWidth">图像宽度</param>
|
||||
/// <param name="imageHeight">图像高度</param>
|
||||
/// <param name="fieldOfView">视场角</param>
|
||||
/// <param name="backgroundIntensity">背景辐射强度,单位:W/sr,典型地表背景约0.01-0.1 W/sr</param>
|
||||
public InfraredImageGenerator(
|
||||
int imageWidth = 640,
|
||||
int imageHeight = 512,
|
||||
double fieldOfView = Math.PI / 18,
|
||||
double backgroundIntensity = 0.01)
|
||||
{
|
||||
this.imageWidth = imageWidth;
|
||||
this.imageHeight = imageHeight;
|
||||
this.fieldOfView = fieldOfView;
|
||||
this.backgroundIntensity = backgroundIntensity;
|
||||
|
||||
// Initialize coordinate system with default values
|
||||
forward = Vector3D.UnitZ;
|
||||
right = Vector3D.UnitX;
|
||||
up = Vector3D.UnitY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新视线坐标系
|
||||
/// </summary>
|
||||
private void UpdateLineOfSightFrame(Vector3D missilePosition, Vector3D targetPosition)
|
||||
{
|
||||
// 计算视线方向
|
||||
forward = (targetPosition - missilePosition).Normalize();
|
||||
|
||||
Console.WriteLine($"Line of sight direction: {forward}");
|
||||
|
||||
// 选择合适的上方向
|
||||
Vector3D worldUp = Math.Abs(Vector3D.DotProduct(forward, Vector3D.UnitZ)) > 0.99
|
||||
? Vector3D.UnitY
|
||||
: Vector3D.UnitZ;
|
||||
|
||||
// 计算右方向和上方向
|
||||
right = Vector3D.CrossProduct(forward, worldUp).Normalize();
|
||||
up = Vector3D.CrossProduct(right, forward);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将世界坐标投影到图像平面
|
||||
/// </summary>
|
||||
private (double x, double y) ProjectToImagePlane(Vector3D worldPoint, Vector3D origin)
|
||||
{
|
||||
Vector3D relativePos = worldPoint - origin;
|
||||
|
||||
// 计算在图像平面上的投影
|
||||
double x = Vector3D.DotProduct(relativePos, right);
|
||||
double y = Vector3D.DotProduct(relativePos, up);
|
||||
double z = Vector3D.DotProduct(relativePos, forward);
|
||||
|
||||
// 转换为角度
|
||||
double angleX = Math.Atan2(x, z);
|
||||
double angleY = Math.Atan2(y, z);
|
||||
|
||||
Console.WriteLine($"Projection angles: X={angleX:F6} rad, Y={angleY:F6} rad");
|
||||
|
||||
return (angleX, angleY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将角度转换为像素坐标
|
||||
/// </summary>
|
||||
private (int x, int y) AngleToPixel(double angleX, double angleY)
|
||||
{
|
||||
double pixelSize = fieldOfView / imageWidth;
|
||||
|
||||
int pixelX = imageWidth/2 + (int)(angleX / pixelSize);
|
||||
int pixelY = imageHeight/2 + (int)(angleY / pixelSize);
|
||||
|
||||
Console.WriteLine($"Pixel coordinates: X={pixelX}, Y={pixelY}");
|
||||
|
||||
return (pixelX, pixelY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成目标的红外图像
|
||||
/// </summary>
|
||||
/// <param name="target">目标对象</param>
|
||||
/// <param name="missilePosition">导弹位置</param>
|
||||
/// <param name="missileVelocity">导弹速度</param>
|
||||
/// <returns>红外图像</returns>
|
||||
public InfraredImage GenerateImage(ITarget target, Vector3D missilePosition, Vector3D missileVelocity)
|
||||
{
|
||||
// 更新视线坐标系
|
||||
UpdateLineOfSightFrame(missilePosition, target.Position);
|
||||
|
||||
// 创建图像
|
||||
var image = new InfraredImage(imageWidth, imageHeight, fieldOfView / imageWidth, forward);
|
||||
|
||||
// 计算目标中心投影
|
||||
var (angleX, angleY) = ProjectToImagePlane(target.Position, missilePosition);
|
||||
var (centerX, centerY) = AngleToPixel(angleX, angleY);
|
||||
|
||||
// 计算目标尺寸
|
||||
double distance = (target.Position - missilePosition).Magnitude();
|
||||
double targetLengthAngle = Math.Atan2(target.Length, distance);
|
||||
double targetWidthAngle = Math.Atan2(target.Width, distance);
|
||||
|
||||
int pixelLength = (int)(targetLengthAngle / (fieldOfView / imageWidth));
|
||||
int pixelWidth = (int)(targetWidthAngle / (fieldOfView / imageWidth));
|
||||
|
||||
// 确保最小尺寸
|
||||
pixelLength = Math.Max(1, pixelLength);
|
||||
pixelWidth = Math.Max(1, pixelWidth);
|
||||
|
||||
Console.WriteLine($"Generated image for target {target.Id} with dimensions: {pixelLength}x{pixelWidth} pixels");
|
||||
Console.WriteLine($"Target center at: ({centerX}, {centerY})");
|
||||
|
||||
// 生成目标图像
|
||||
GenerateTargetIntensity(image, centerX, centerY, pixelLength, pixelWidth, target, distance);
|
||||
|
||||
// 添加背景和噪声
|
||||
AddBackgroundAndNoise(image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成目标的红外强度分布
|
||||
/// </summary>
|
||||
private void GenerateTargetIntensity(
|
||||
InfraredImage image,
|
||||
int centerX,
|
||||
int centerY,
|
||||
int pixelLength,
|
||||
int pixelWidth,
|
||||
ITarget target,
|
||||
double distance)
|
||||
{
|
||||
// 计算目标辐射强度
|
||||
double targetIntensity = target.InfraredRadiationIntensity / Math.Pow(distance, 1.8);
|
||||
|
||||
// 计算分布参数
|
||||
double sigmaX = pixelLength / 6.0;
|
||||
double sigmaY = pixelWidth / 6.0;
|
||||
|
||||
int halfLength = pixelLength / 2;
|
||||
int halfWidth = pixelWidth / 2;
|
||||
|
||||
int pixelsSet = 0;
|
||||
double maxSetIntensity = 0;
|
||||
|
||||
// 设置强度分布
|
||||
for (int dy = -halfWidth; dy <= halfWidth; dy++)
|
||||
{
|
||||
int y = centerY + dy;
|
||||
if (y < 0 || y >= image.Height) continue;
|
||||
|
||||
for (int dx = -halfLength; dx <= halfLength; dx++)
|
||||
{
|
||||
int x = centerX + dx;
|
||||
if (x < 0 || x >= image.Width) continue;
|
||||
|
||||
// 计算归一化距离
|
||||
double normalizedX = dx / sigmaX;
|
||||
double normalizedY = dy / sigmaY;
|
||||
double r2 = normalizedX * normalizedX + normalizedY * normalizedY;
|
||||
|
||||
// 高斯分布
|
||||
double intensity = targetIntensity * Math.Exp(-r2 / 2.0);
|
||||
|
||||
image.SetIntensity(y, x, intensity);
|
||||
pixelsSet++;
|
||||
maxSetIntensity = Math.Max(maxSetIntensity, intensity);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Target intensity distribution:");
|
||||
Console.WriteLine($" Pixels set: {pixelsSet}");
|
||||
Console.WriteLine($" Max set intensity: {maxSetIntensity:F6} W/sr");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加背景辐射和噪声
|
||||
/// </summary>
|
||||
private void AddBackgroundAndNoise(InfraredImage image)
|
||||
{
|
||||
double maxIntensityBefore = double.MinValue;
|
||||
double maxIntensityAfter = double.MinValue;
|
||||
int pixelsModified = 0;
|
||||
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
double currentIntensity = image.GetIntensity(y, x);
|
||||
maxIntensityBefore = Math.Max(maxIntensityBefore, currentIntensity);
|
||||
|
||||
// 只在非目标区域添加背景
|
||||
if (currentIntensity < backgroundIntensity * 0.1)
|
||||
{
|
||||
currentIntensity = backgroundIntensity;
|
||||
pixelsModified++;
|
||||
}
|
||||
|
||||
// 添加高斯噪声
|
||||
double noise = (random.NextDouble() - 0.5) * backgroundIntensity * 0.2;
|
||||
currentIntensity += noise;
|
||||
|
||||
// 确保非负
|
||||
currentIntensity = Math.Max(0, currentIntensity);
|
||||
|
||||
image.SetIntensity(y, x, currentIntensity);
|
||||
maxIntensityAfter = Math.Max(maxIntensityAfter, currentIntensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,62 +19,35 @@ namespace ThreatSource.Guidance
|
||||
public class InfraredImagingGuidanceSystem : BasicGuidanceSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大探测范围,单位:米
|
||||
/// 工作模式枚举
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了红外成像系统的最大作用距离
|
||||
/// 超出此范围的目标无法有效探测
|
||||
/// 定义了制导系统的三种工作模式:
|
||||
/// - Search: 搜索模式,大视场角搜索目标
|
||||
/// - Track: 跟踪模式,小视场角精确跟踪,同时进行目标识别
|
||||
/// - Lock: 锁定模式,已确认目标类型,只进行跟踪
|
||||
/// </remarks>
|
||||
private const double MAX_DETECTION_RANGE = 5000;
|
||||
private enum WorkMode
|
||||
{
|
||||
Search, // 搜索模式
|
||||
Track, // 跟踪模式
|
||||
Lock // 锁定模式
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// 当前工作模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了成像系统的视场范围
|
||||
/// 标枪导弹为40度
|
||||
/// 坦克破坏者为24度
|
||||
/// </remarks>
|
||||
private const double FIELD_OF_VIEW = Math.PI / 6;
|
||||
private WorkMode currentMode = WorkMode.Search;
|
||||
|
||||
/// <summary>
|
||||
/// 目标识别概率
|
||||
/// 是否已探测到目标
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的成功率
|
||||
/// 影响系统的可靠性
|
||||
/// 典型值为0.9
|
||||
/// </remarks>
|
||||
private const double TARGET_RECOGNITION_PROBABILITY = 0.9;
|
||||
public bool HasTarget { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 识别目标的信噪比阈值,单位:分贝
|
||||
/// 当前是否处于锁定模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的最小信噪比要求
|
||||
/// 大于此值时认为目标有效
|
||||
/// 典型值为6dB
|
||||
/// </remarks>
|
||||
private const double RECOGNITION_SNR_THRESHOLD = 6;
|
||||
|
||||
/// <summary>
|
||||
/// 背景辐射强度,单位:瓦特/球面度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了环境背景的红外辐射强度
|
||||
/// 用于信噪比计算
|
||||
/// 典型值为10W/sr
|
||||
/// </remarks>
|
||||
private const double BACKGROUND_RADIATION_INTENSITY = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数生成器实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于生成随机扰动
|
||||
/// 模拟系统噪声
|
||||
/// </remarks>
|
||||
private readonly Random random = new();
|
||||
public bool IsInLockMode => currentMode == WorkMode.Lock;
|
||||
|
||||
/// <summary>
|
||||
/// 上一次探测到的目标位置
|
||||
@ -85,10 +58,43 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
private Vector3D lastTargetPosition;
|
||||
|
||||
/// <summary>
|
||||
/// 红外图像生成器
|
||||
/// </summary>
|
||||
private InfraredImageGenerator imageGenerator;
|
||||
|
||||
/// <summary>
|
||||
/// 目标识别器
|
||||
/// </summary>
|
||||
private readonly InfraredTargetRecognizer targetRecognizer;
|
||||
|
||||
/// <summary>
|
||||
/// 要攻击的目标类型
|
||||
/// </summary>
|
||||
private readonly TargetType targetType;
|
||||
|
||||
/// <summary>
|
||||
/// 红外成像制导系统配置
|
||||
/// </summary>
|
||||
private readonly InfraredImagingGuidanceConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 目标丢失计时器
|
||||
/// </summary>
|
||||
private double targetLostTimer = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 锁定确认计时器
|
||||
/// </summary>
|
||||
private double lockConfirmationTimer = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外成像制导系统的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">系统标识</param>
|
||||
/// <param name="guidanceConfig">红外成像制导系统配置</param>
|
||||
/// <param name="targetType">要攻击的目标类型</param>
|
||||
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
|
||||
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
@ -97,11 +103,29 @@ namespace ThreatSource.Guidance
|
||||
/// - 初始化基类参数
|
||||
/// - 设置仿真管理器
|
||||
/// - 初始化目标位置
|
||||
/// - 初始化红外图像生成器和目标识别器
|
||||
/// </remarks>
|
||||
public InfraredImagingGuidanceSystem(string id, double maxAcceleration, double proportionalNavigationCoefficient, ISimulationManager simulationManager)
|
||||
public InfraredImagingGuidanceSystem(
|
||||
string id,
|
||||
InfraredImagingGuidanceConfig guidanceConfig,
|
||||
TargetType targetType,
|
||||
double maxAcceleration,
|
||||
double proportionalNavigationCoefficient,
|
||||
ISimulationManager simulationManager
|
||||
)
|
||||
: base(id, maxAcceleration, proportionalNavigationCoefficient, simulationManager)
|
||||
{
|
||||
lastTargetPosition = Vector3D.Zero;
|
||||
this.targetType = targetType;
|
||||
this.config = guidanceConfig;
|
||||
targetRecognizer = new InfraredTargetRecognizer(simulationManager);
|
||||
imageGenerator = new InfraredImageGenerator(
|
||||
imageWidth: guidanceConfig.ImageWidth,
|
||||
imageHeight: guidanceConfig.ImageHeight,
|
||||
fieldOfView: guidanceConfig.SearchFieldOfView,
|
||||
backgroundIntensity: guidanceConfig.BackgroundIntensity
|
||||
);
|
||||
SwitchToSearchMode(); // 初始化为搜索模式
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -121,8 +145,9 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
base.Update(deltaTime, missilePosition, missileVelocity);
|
||||
|
||||
if (TryDetectTank(missilePosition, missileVelocity, out Vector3D tankPosition))
|
||||
if (TryDetectAndIdentifyTarget(missilePosition, missileVelocity, deltaTime, out Vector3D tankPosition))
|
||||
{
|
||||
targetLostTimer = 0; // 重置丢失计时器
|
||||
//根据目标当前位置和上一次位置计算目标速度
|
||||
Vector3D targetVelocity = (tankPosition - lastTargetPosition) / deltaTime;
|
||||
lastTargetPosition = tankPosition;
|
||||
@ -139,52 +164,201 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
else
|
||||
{
|
||||
HasGuidance = false;
|
||||
// 在跟踪或锁定模式下,增加丢失计时器
|
||||
if (currentMode != WorkMode.Search)
|
||||
{
|
||||
targetLostTimer += deltaTime;
|
||||
// 只有当超过容忍时间才认为真正丢失目标
|
||||
if (targetLostTimer >= config.TargetLostTolerance)
|
||||
{
|
||||
HasGuidance = false;
|
||||
// 切换回搜索模式
|
||||
Console.WriteLine($"Target lost for {targetLostTimer:F3}s, switching back to search mode");
|
||||
SwitchToSearchMode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HasGuidance = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试探测目标坦克
|
||||
/// 切换到搜索模式
|
||||
/// </summary>
|
||||
/// <param name="missilePosition">导弹当前位置,单位:米</param>
|
||||
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
|
||||
/// <param name="tankPosition">输出探测到的坦克位置,单位:米</param>
|
||||
/// <returns>是否成功探测到目标</returns>
|
||||
/// <remarks>
|
||||
/// 探测过程:
|
||||
/// - 遍历场景中的目标
|
||||
/// - 检查距离和角度
|
||||
/// - 计算信噪比
|
||||
/// - 判断目标有效性
|
||||
/// 切换过程:
|
||||
/// - 设置大视场角
|
||||
/// - 重置目标状态
|
||||
/// - 更新图像生成器参数
|
||||
/// </remarks>
|
||||
private bool TryDetectTank(Vector3D missilePosition, Vector3D missileVelocity, out Vector3D tankPosition)
|
||||
public void SwitchToSearchMode()
|
||||
{
|
||||
tankPosition = Vector3D.Zero;
|
||||
currentMode = WorkMode.Search;
|
||||
HasTarget = false;
|
||||
targetLostTimer = 0; // 重置丢失计时器
|
||||
imageGenerator = new InfraredImageGenerator(
|
||||
imageWidth: config.ImageWidth,
|
||||
imageHeight: config.ImageHeight,
|
||||
fieldOfView: config.SearchFieldOfView,
|
||||
backgroundIntensity: config.BackgroundIntensity
|
||||
);
|
||||
Console.WriteLine($"Switched to search mode with FOV: {config.SearchFieldOfView * 180 / Math.PI} degrees");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换到跟踪模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 切换过程:
|
||||
/// - 设置小视场角
|
||||
/// - 更新图像生成器参数
|
||||
/// - 提高目标识别概率要求
|
||||
/// </remarks>
|
||||
public void SwitchToTrackMode()
|
||||
{
|
||||
currentMode = WorkMode.Track;
|
||||
lockConfirmationTimer = 0; // 重置锁定确认计时器
|
||||
imageGenerator = new InfraredImageGenerator(
|
||||
imageWidth: config.ImageWidth,
|
||||
imageHeight: config.ImageHeight,
|
||||
fieldOfView: config.TrackFieldOfView,
|
||||
backgroundIntensity: config.BackgroundIntensity
|
||||
);
|
||||
Console.WriteLine($"Switched to track mode with FOV: {config.TrackFieldOfView * 180 / Math.PI} degrees");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换到锁定模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 切换过程:
|
||||
/// - 设置锁定状态
|
||||
/// - 保持当前图像生成器参数
|
||||
/// - 不再进行目标类型识别
|
||||
/// </remarks>
|
||||
public void SwitchToLockMode()
|
||||
{
|
||||
currentMode = WorkMode.Lock;
|
||||
Console.WriteLine("Switched to lock mode - target type confirmed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试探测和识别目标
|
||||
/// </summary>
|
||||
/// <param name="missilePosition">导弹当前位置</param>
|
||||
/// <param name="missileVelocity">导弹当前速度</param>
|
||||
/// <param name="deltaTime">时间间隔,单位:秒</param>
|
||||
/// <param name="targetPosition">输出目标位置</param>
|
||||
/// <returns>是否成功探测到指定类型的目标</returns>
|
||||
/// <remarks>
|
||||
/// 探测和识别过程:
|
||||
/// 1. 遍历场景中的目标
|
||||
/// 2. 检查目标是否在探测范围内
|
||||
/// 3. 生成目标红外图像
|
||||
/// 4. 识别目标类型
|
||||
/// 5. 判断是否是要攻击的目标类型
|
||||
/// </remarks>
|
||||
private bool TryDetectAndIdentifyTarget(Vector3D missilePosition, Vector3D missileVelocity, double deltaTime, out Vector3D targetPosition)
|
||||
{
|
||||
targetPosition = Vector3D.Zero;
|
||||
double minDistance = double.MaxValue;
|
||||
bool foundTarget = false;
|
||||
|
||||
// 根据当前模式选择视场角和识别策略
|
||||
double currentFov = currentMode == WorkMode.Search ? config.SearchFieldOfView : config.TrackFieldOfView;
|
||||
|
||||
foreach (var element in SimulationManager.GetEntitiesByType<SimulationElement>())
|
||||
{
|
||||
if (element is Tank tank)
|
||||
if (element is ITarget target)
|
||||
{
|
||||
Vector3D toTarget = tank.Position - missilePosition;
|
||||
Vector3D toTarget = target.Position - missilePosition;
|
||||
double distance = toTarget.Magnitude();
|
||||
|
||||
if (distance <= MAX_DETECTION_RANGE)
|
||||
// 检查距离条件
|
||||
if (distance <= config.MaxDetectionRange)
|
||||
{
|
||||
// 检查视线角条件
|
||||
double angle = Math.Acos(Vector3D.DotProduct(toTarget.Normalize(), missileVelocity.Normalize()));
|
||||
if (angle <= FIELD_OF_VIEW / 2)
|
||||
if (angle <= currentFov / 2)
|
||||
{
|
||||
double snr = CalculateSNR(tank, distance);
|
||||
if (snr > RECOGNITION_SNR_THRESHOLD)
|
||||
// 生成红外图像
|
||||
var image = imageGenerator.GenerateImage(target, missilePosition, missileVelocity);
|
||||
|
||||
switch (currentMode)
|
||||
{
|
||||
tankPosition = tank.Position;
|
||||
return true;
|
||||
case WorkMode.Search:
|
||||
// 搜索模式:使用较低阈值进行目标识别
|
||||
var searchResult = targetRecognizer.RecognizeTarget(image, target);
|
||||
if (searchResult.Type == targetType && searchResult.Confidence >= config.SearchRecognitionProbability)
|
||||
{
|
||||
if (distance < minDistance)
|
||||
{
|
||||
targetPosition = target.Position;
|
||||
minDistance = distance;
|
||||
foundTarget = true;
|
||||
// 切换到跟踪模式
|
||||
SwitchToTrackMode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WorkMode.Track:
|
||||
// 跟踪模式:使用较高阈值确认目标
|
||||
var trackResult = targetRecognizer.RecognizeTarget(image, target);
|
||||
if (trackResult.Type == targetType && trackResult.Confidence >= config.TrackRecognitionProbability)
|
||||
{
|
||||
if (distance < minDistance)
|
||||
{
|
||||
targetPosition = target.Position;
|
||||
minDistance = distance;
|
||||
foundTarget = true;
|
||||
|
||||
// 增加锁定确认时间
|
||||
lockConfirmationTimer += deltaTime;
|
||||
if (lockConfirmationTimer >= config.LockConfirmationTime)
|
||||
{
|
||||
// 持续高置信度跟踪足够时间后,切换到锁定模式
|
||||
SwitchToLockMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (trackResult.Type == targetType && trackResult.Confidence >= config.SearchRecognitionProbability)
|
||||
{
|
||||
// 如果置信度达到搜索阈值但未达到跟踪阈值,重置锁定计时器
|
||||
lockConfirmationTimer = 0;
|
||||
if (distance < minDistance)
|
||||
{
|
||||
targetPosition = target.Position;
|
||||
minDistance = distance;
|
||||
foundTarget = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 目标置信度不足,重置锁定计时器
|
||||
lockConfirmationTimer = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WorkMode.Lock:
|
||||
// 锁定模式:只进行位置跟踪,不做类型识别
|
||||
if (distance < minDistance)
|
||||
{
|
||||
targetPosition = target.Position;
|
||||
minDistance = distance;
|
||||
foundTarget = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
HasTarget = foundTarget;
|
||||
return foundTarget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -201,35 +375,7 @@ namespace ThreatSource.Guidance
|
||||
public override string GetStatus()
|
||||
{
|
||||
return base.GetStatus() + $", GuidanceAcceleration: {GuidanceAcceleration}, " +
|
||||
$"Tank Position: {lastTargetPosition}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算目标的信噪比
|
||||
/// </summary>
|
||||
/// <param name="target">目标对象</param>
|
||||
/// <param name="distance">到目标的距离,单位:米</param>
|
||||
/// <returns>信噪比,单位:分贝</returns>
|
||||
/// <remarks>
|
||||
/// 计算过程:
|
||||
/// - 获取目标辐射强度
|
||||
/// - 考虑距离衰减
|
||||
/// - 计算信号强度
|
||||
/// - 计算噪声强度
|
||||
/// - 转换为分贝值
|
||||
/// </remarks>
|
||||
private static double CalculateSNR(ITarget target, double distance)
|
||||
{
|
||||
double targetRadiation = target.InfraredRadiationIntensity;
|
||||
double backgroundRadiation = BACKGROUND_RADIATION_INTENSITY;
|
||||
|
||||
// 考虑距离衰减
|
||||
double attenuationFactor = 1 / (distance * distance);
|
||||
|
||||
double signal = (targetRadiation - backgroundRadiation) * attenuationFactor;
|
||||
double noise = backgroundRadiation * attenuationFactor;
|
||||
|
||||
return 10 * Math.Log10(signal / noise); // 转换为dB
|
||||
$"Target Position: {lastTargetPosition}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
672
ThreatSource/src/Guidance/InfraredTargetRecognizer.cs
Normal file
672
ThreatSource/src/Guidance/InfraredTargetRecognizer.cs
Normal file
@ -0,0 +1,672 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Data;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Guidance
|
||||
{
|
||||
/// <summary>
|
||||
/// 红外图像目标识别结果
|
||||
/// </summary>
|
||||
public class RecognitionResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 识别出的目标类型
|
||||
/// </summary>
|
||||
public TargetType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 识别置信度(0-1)
|
||||
/// </summary>
|
||||
public double Confidence { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标在图像中的位置(像素坐标)
|
||||
/// </summary>
|
||||
public (int X, int Y) Position { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标在图像中的尺寸(像素)
|
||||
/// </summary>
|
||||
public (int Width, int Height) Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外图像目标识别结果
|
||||
/// </summary>
|
||||
/// <param name="type">目标类型</param>
|
||||
/// <param name="confidence">识别置信度</param>
|
||||
/// <param name="position">目标在图像中的位置</param>
|
||||
/// <param name="size">目标在图像中的尺寸</param>
|
||||
public RecognitionResult(TargetType type, double confidence, (int X, int Y) position, (int Width, int Height) size)
|
||||
{
|
||||
Type = type;
|
||||
Confidence = confidence;
|
||||
Position = position;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 红外图像目标识别器
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类实现红外图像的目标识别功能:
|
||||
/// - 图像分割
|
||||
/// - 特征提取
|
||||
/// - 目标分类
|
||||
/// - 结果输出
|
||||
/// </remarks>
|
||||
public class InfraredTargetRecognizer
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真管理器实例
|
||||
/// </summary>
|
||||
private readonly ISimulationManager simulationManager;
|
||||
|
||||
/// <summary>
|
||||
/// 目标特征数据库
|
||||
/// </summary>
|
||||
private readonly Dictionary<TargetType, TargetFeature> targetFeatures;
|
||||
|
||||
/// <summary>
|
||||
/// 识别阈值
|
||||
/// </summary>
|
||||
private const double RECOGNITION_THRESHOLD = 0.7;
|
||||
|
||||
/// <summary>
|
||||
/// 背景辐射强度,用于阈值计算
|
||||
/// </summary>
|
||||
private const double BACKGROUND_INTENSITY = 0.01;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外图像目标识别器
|
||||
/// </summary>
|
||||
public InfraredTargetRecognizer(ISimulationManager simulationManager)
|
||||
{
|
||||
this.simulationManager = simulationManager;
|
||||
// 初始化目标特征数据库 - 使用相对特征值
|
||||
targetFeatures = new Dictionary<TargetType, TargetFeature>
|
||||
{
|
||||
{ TargetType.Tank, new TargetFeature(
|
||||
aspectRatio: 2.9, // 典型主战坦克长宽比
|
||||
size: 1.0, // 基准尺寸
|
||||
intensityPattern: 0.9, // 热量集中分布
|
||||
temperatureGradient: 0.8 // 高温度梯度
|
||||
)},
|
||||
{ TargetType.APC, new TargetFeature(
|
||||
aspectRatio: 2.1, // 较短的车身
|
||||
size: 0.7, // 相对坦克尺寸
|
||||
intensityPattern: 0.7, // 均匀热分布
|
||||
temperatureGradient: 0.5 // 中等温度梯度
|
||||
)},
|
||||
{ TargetType.Helicopter, new TargetFeature(
|
||||
aspectRatio: 4.8, // 考虑旋翼长度
|
||||
size: 1.4, // 较大的整体尺寸
|
||||
intensityPattern: 0.5, // 发动机热量集中
|
||||
temperatureGradient: 0.9 // 极高温度梯度
|
||||
)}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 识别图像中的目标
|
||||
/// </summary>
|
||||
/// <param name="image">红外图像</param>
|
||||
/// <param name="target">要识别的目标</param>
|
||||
/// <returns>识别结果</returns>
|
||||
public RecognitionResult RecognizeTarget(InfraredImage image, ITarget target)
|
||||
{
|
||||
// 1. 图像分割,提取目标区域
|
||||
var segment = SegmentTarget(image);
|
||||
if (!segment.IsValid)
|
||||
{
|
||||
Console.WriteLine("No valid segment found in image");
|
||||
return new RecognitionResult(TargetType.Unknown, 0.0, (0, 0), (0, 0));
|
||||
}
|
||||
|
||||
// 2. 提取目标特征
|
||||
var features = ExtractFeatures(image, segment, target);
|
||||
Console.WriteLine($"Extracted features: AspectRatio={features.AspectRatio:F2}, Size={features.Size:F2}, IntensityPattern={features.IntensityPattern:F2}, TemperatureGradient={features.TemperatureGradient:F2}");
|
||||
|
||||
// 3. 特征匹配和分类
|
||||
var (type, confidence) = ClassifyTarget(features);
|
||||
Console.WriteLine($"Classification result: Type={type}, Confidence={confidence:F2}");
|
||||
|
||||
// 4. 返回识别结果
|
||||
return new RecognitionResult(
|
||||
type,
|
||||
confidence,
|
||||
segment.Center,
|
||||
segment.Size
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图像分割,提取目标区域
|
||||
/// </summary>
|
||||
private ImageSegment SegmentTarget(InfraredImage image)
|
||||
{
|
||||
// 使用简单的阈值分割方法
|
||||
double threshold = CalculateThreshold(image);
|
||||
int minX = image.Width, minY = image.Height, maxX = 0, maxY = 0;
|
||||
bool found = false;
|
||||
int pixelsAboveThreshold = 0;
|
||||
|
||||
// 寻找目标边界
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
double intensity = image.GetIntensity(y, x);
|
||||
if (intensity > threshold)
|
||||
{
|
||||
minX = Math.Min(minX, x);
|
||||
minY = Math.Min(minY, y);
|
||||
maxX = Math.Max(maxX, x);
|
||||
maxY = Math.Max(maxY, y);
|
||||
found = true;
|
||||
pixelsAboveThreshold++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Segmentation results:");
|
||||
Console.WriteLine($" Pixels above threshold: {pixelsAboveThreshold}");
|
||||
if (found)
|
||||
{
|
||||
Console.WriteLine($" Target bounds: ({minX},{minY}) to ({maxX},{maxY})");
|
||||
Console.WriteLine($" Target size: {maxX - minX + 1}x{maxY - minY + 1} pixels");
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return new ImageSegment();
|
||||
}
|
||||
|
||||
return new ImageSegment(
|
||||
isValid: true,
|
||||
center: ((minX + maxX) / 2, (minY + maxY) / 2),
|
||||
size: (maxX - minX + 1, maxY - minY + 1)
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算图像分割阈值
|
||||
/// </summary>
|
||||
private double CalculateThreshold(InfraredImage image)
|
||||
{
|
||||
// 计算图像统计信息
|
||||
double sum = 0, count = 0;
|
||||
double maxIntensity = double.MinValue;
|
||||
double minIntensity = double.MaxValue;
|
||||
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
double value = image.GetIntensity(y, x);
|
||||
maxIntensity = Math.Max(maxIntensity, value);
|
||||
minIntensity = Math.Min(minIntensity, value);
|
||||
sum += value;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
double mean = sum / count;
|
||||
|
||||
// 计算背景基准阈值
|
||||
double backgroundThreshold = BACKGROUND_INTENSITY * 1.2;
|
||||
|
||||
// 计算目标基准阈值
|
||||
double targetThreshold = maxIntensity * 0.2;
|
||||
|
||||
// 取两个基准中的较大值作为最终阈值
|
||||
double threshold = Math.Max(backgroundThreshold, targetThreshold);
|
||||
|
||||
Console.WriteLine($"Image statistics:");
|
||||
Console.WriteLine($" Max intensity: {maxIntensity:F6}");
|
||||
Console.WriteLine($" Min intensity: {minIntensity:F6}");
|
||||
Console.WriteLine($" Mean intensity: {mean:F6}");
|
||||
Console.WriteLine($" Background threshold: {backgroundThreshold:F6}");
|
||||
Console.WriteLine($" Target threshold: {targetThreshold:F6}");
|
||||
Console.WriteLine($" Final threshold: {threshold:F6}");
|
||||
|
||||
return threshold;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 提取目标特征
|
||||
/// </summary>
|
||||
private TargetFeature ExtractFeatures(InfraredImage image, ImageSegment segment, ITarget target)
|
||||
{
|
||||
// 计算目标主方向
|
||||
double orientation = CalculateOrientation(image, segment);
|
||||
|
||||
// 计算考虑姿态的长宽比
|
||||
double aspectRatio = CalculateOrientedAspectRatio(segment, orientation);
|
||||
|
||||
// 计算相对尺寸(相对于图像宽度的比例)
|
||||
double relativeSize = Math.Max(segment.Size.Width, segment.Size.Height) / (image.Width * 0.1); // 假设坦克基准尺寸约为图像宽度的10%
|
||||
|
||||
// 计算强度模式特征
|
||||
double intensityPattern = CalculateIntensityPattern(image, segment);
|
||||
|
||||
// 计算温度梯度特征
|
||||
double temperatureGradient = CalculateTemperatureGradient(image, segment, target);
|
||||
|
||||
return new TargetFeature(aspectRatio, relativeSize, intensityPattern, temperatureGradient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算目标主方向
|
||||
/// </summary>
|
||||
private double CalculateOrientation(InfraredImage image, ImageSegment segment)
|
||||
{
|
||||
double m11 = 0, m20 = 0, m02 = 0;
|
||||
double centerX = segment.Center.X;
|
||||
double centerY = segment.Center.Y;
|
||||
|
||||
// 计算二阶矩
|
||||
for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++)
|
||||
{
|
||||
for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++)
|
||||
{
|
||||
if (y >= 0 && y < image.Height && x >= 0 && x < image.Width)
|
||||
{
|
||||
double intensity = image.GetIntensity(y, x);
|
||||
double dx = x - centerX;
|
||||
double dy = y - centerY;
|
||||
m11 += dx * dy * intensity;
|
||||
m20 += dx * dx * intensity;
|
||||
m02 += dy * dy * intensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算主方向
|
||||
return 0.5 * Math.Atan2(2 * m11, m20 - m02);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算考虑姿态的长宽比
|
||||
/// </summary>
|
||||
private double CalculateOrientedAspectRatio(ImageSegment segment, double orientation)
|
||||
{
|
||||
// 计算旋转后的边界框
|
||||
double cos = Math.Cos(orientation);
|
||||
double sin = Math.Sin(orientation);
|
||||
double width = Math.Abs(segment.Size.Width * cos) + Math.Abs(segment.Size.Height * sin);
|
||||
double height = Math.Abs(segment.Size.Width * sin) + Math.Abs(segment.Size.Height * cos);
|
||||
|
||||
return width / height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算温度梯度特征
|
||||
/// </summary>
|
||||
private double CalculateTemperatureGradient(InfraredImage image, ImageSegment segment, ITarget target)
|
||||
{
|
||||
// 直接从目标获取温度分布数据
|
||||
double[,] thermalPattern = target.GetCurrentThermalPattern();
|
||||
if (thermalPattern == null)
|
||||
{
|
||||
Console.WriteLine("No thermal pattern available, using image-based gradient calculation");
|
||||
return CalculateImageBasedGradient(image, segment);
|
||||
}
|
||||
|
||||
var pattern = new ThermalPattern(thermalPattern, thermalPattern);
|
||||
|
||||
// 判断目标是否在运动
|
||||
bool isMoving = IsTargetMoving(image, segment);
|
||||
Console.WriteLine($"Target movement status: {(isMoving ? "Moving" : "Static")}");
|
||||
|
||||
// 使用温度分布模式计算梯度特征
|
||||
double gradientFeature = pattern.CalculateGradientFeature(isMoving);
|
||||
|
||||
return gradientFeature;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 基于图像计算温度梯度(当没有温度分布模式数据时使用)
|
||||
/// </summary>
|
||||
private double CalculateImageBasedGradient(InfraredImage image, ImageSegment segment)
|
||||
{
|
||||
// Sobel算子
|
||||
double[,] sobelX = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
|
||||
double[,] sobelY = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
|
||||
|
||||
// 获取目标区域最大强度用于归一化
|
||||
double maxIntensity = double.MinValue;
|
||||
|
||||
// 将目标区域划分为3x3的网格
|
||||
int gridRows = 3;
|
||||
int gridCols = 3;
|
||||
double[,] gridGradients = new double[gridRows, gridCols];
|
||||
int[,] gridCounts = new int[gridRows, gridCols];
|
||||
|
||||
// 第一遍扫描:获取最大强度
|
||||
for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++)
|
||||
{
|
||||
for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++)
|
||||
{
|
||||
if (y >= 0 && y < image.Height && x >= 0 && x < image.Width)
|
||||
{
|
||||
maxIntensity = Math.Max(maxIntensity, image.GetIntensity(y, x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (maxIntensity <= 0) return 0;
|
||||
|
||||
// 计算每个网格的大小
|
||||
int gridWidth = segment.Size.Width / gridCols;
|
||||
int gridHeight = segment.Size.Height / gridRows;
|
||||
|
||||
// 第二遍扫描:计算每个网格的梯度
|
||||
for (int y = segment.Center.Y - segment.Size.Height/2 + 1;
|
||||
y < segment.Center.Y + segment.Size.Height/2 - 1; y++)
|
||||
{
|
||||
for (int x = segment.Center.X - segment.Size.Width/2 + 1;
|
||||
x < segment.Center.X + segment.Size.Width/2 - 1; x++)
|
||||
{
|
||||
if (y >= 1 && y < image.Height - 1 && x >= 1 && x < image.Width - 1)
|
||||
{
|
||||
// 计算当前点属于哪个网格
|
||||
int gridRow = (y - (segment.Center.Y - segment.Size.Height/2)) * gridRows / segment.Size.Height;
|
||||
int gridCol = (x - (segment.Center.X - segment.Size.Width/2)) * gridCols / segment.Size.Width;
|
||||
|
||||
gridRow = Math.Min(Math.Max(gridRow, 0), gridRows - 1);
|
||||
gridCol = Math.Min(Math.Max(gridCol, 0), gridCols - 1);
|
||||
|
||||
double gradX = 0, gradY = 0;
|
||||
|
||||
// 应用Sobel算子
|
||||
for (int i = -1; i <= 1; i++)
|
||||
{
|
||||
for (int j = -1; j <= 1; j++)
|
||||
{
|
||||
double value = image.GetIntensity(y + i, x + j);
|
||||
gradX += value * sobelX[i + 1, j + 1];
|
||||
gradY += value * sobelY[i + 1, j + 1];
|
||||
}
|
||||
}
|
||||
|
||||
// 计算归一化梯度
|
||||
double normalizedGradient = Math.Sqrt(gradX * gradX + gradY * gradY) / maxIntensity;
|
||||
|
||||
// 累加到对应的网格
|
||||
gridGradients[gridRow, gridCol] += normalizedGradient;
|
||||
gridCounts[gridRow, gridCol]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算每个网格的平均梯度
|
||||
double[,] avgGridGradients = new double[gridRows, gridCols];
|
||||
for (int i = 0; i < gridRows; i++)
|
||||
{
|
||||
for (int j = 0; j < gridCols; j++)
|
||||
{
|
||||
avgGridGradients[i, j] = gridCounts[i, j] > 0 ?
|
||||
gridGradients[i, j] / gridCounts[i, j] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算后部区域(发动机舱)的梯度特征
|
||||
double engineAreaGradient = (avgGridGradients[1, 2] + avgGridGradients[2, 2]) / 2.0;
|
||||
|
||||
// 计算前部区域的梯度特征
|
||||
double frontAreaGradient = (avgGridGradients[1, 0] + avgGridGradients[2, 0]) / 2.0;
|
||||
|
||||
// 计算中部区域的梯度特征
|
||||
double middleAreaGradient = avgGridGradients[1, 1];
|
||||
|
||||
// 计算梯度分布特征
|
||||
double gradientDistribution = engineAreaGradient / (frontAreaGradient + 0.1);
|
||||
double gradientContrast = engineAreaGradient / (middleAreaGradient + 0.1);
|
||||
|
||||
// 最终得分:后部梯度强度(0.3) + 梯度分布特征(0.4) + 梯度对比度(0.3)
|
||||
return engineAreaGradient * 0.3 +
|
||||
Math.Min(gradientDistribution, 3.0) / 3.0 * 0.4 +
|
||||
Math.Min(gradientContrast, 3.0) / 3.0 * 0.3;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断目标是否在运动
|
||||
/// </summary>
|
||||
private bool IsTargetMoving(InfraredImage image, ImageSegment segment)
|
||||
{
|
||||
// TODO: 实现运动检测逻辑
|
||||
// 可以基于:
|
||||
// 1. 连续帧之间的位置变化
|
||||
// 2. 速度传感器数据
|
||||
// 3. 运动检测算法
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算强度模式特征
|
||||
/// </summary>
|
||||
private double CalculateIntensityPattern(InfraredImage image, ImageSegment segment)
|
||||
{
|
||||
const int BINS = 10;
|
||||
double[] histogram = new double[BINS];
|
||||
|
||||
// 获取目标区域最大和最小强度
|
||||
double maxIntensity = double.MinValue;
|
||||
double minIntensity = double.MaxValue;
|
||||
double centerIntensity = 0;
|
||||
int centerPixelCount = 0;
|
||||
double totalIntensity = 0;
|
||||
int totalPixels = 0;
|
||||
|
||||
// 定义中心区域大小(目标尺寸的1/3)
|
||||
int centerRegionWidth = segment.Size.Width / 3;
|
||||
int centerRegionHeight = segment.Size.Height / 3;
|
||||
|
||||
// 第一遍扫描:获取强度范围和中心区域强度
|
||||
for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++)
|
||||
{
|
||||
for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++)
|
||||
{
|
||||
if (y >= 0 && y < image.Height && x >= 0 && x < image.Width)
|
||||
{
|
||||
double intensity = image.GetIntensity(y, x);
|
||||
maxIntensity = Math.Max(maxIntensity, intensity);
|
||||
minIntensity = Math.Min(minIntensity, intensity);
|
||||
totalIntensity += intensity;
|
||||
totalPixels++;
|
||||
|
||||
// 检查是否在中心区域
|
||||
if (Math.Abs(x - segment.Center.X) <= centerRegionWidth/2 &&
|
||||
Math.Abs(y - segment.Center.Y) <= centerRegionHeight/2)
|
||||
{
|
||||
centerIntensity += intensity;
|
||||
centerPixelCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalPixels == 0 || maxIntensity <= minIntensity) return 0;
|
||||
|
||||
// 计算平均中心强度
|
||||
double avgCenterIntensity = centerPixelCount > 0 ? centerIntensity / centerPixelCount : 0;
|
||||
// 计算平均总强度
|
||||
double avgTotalIntensity = totalIntensity / totalPixels;
|
||||
|
||||
// 填充直方图
|
||||
double binSize = (maxIntensity - minIntensity) / BINS;
|
||||
|
||||
// 第二遍扫描:填充直方图
|
||||
for (int y = segment.Center.Y - segment.Size.Height/2; y <= segment.Center.Y + segment.Size.Height/2; y++)
|
||||
{
|
||||
for (int x = segment.Center.X - segment.Size.Width/2; x <= segment.Center.X + segment.Size.Width/2; x++)
|
||||
{
|
||||
if (y >= 0 && y < image.Height && x >= 0 && x < image.Width)
|
||||
{
|
||||
double intensity = image.GetIntensity(y, x);
|
||||
int bin = Math.Min(BINS - 1, (int)((intensity - minIntensity) / binSize));
|
||||
histogram[bin]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 归一化直方图
|
||||
for (int i = 0; i < BINS; i++)
|
||||
{
|
||||
histogram[i] /= totalPixels;
|
||||
}
|
||||
|
||||
// 计算集中度得分:高强度bin的占比越高,得分越高
|
||||
double concentrationScore = 0;
|
||||
for (int i = 0; i < BINS; i++)
|
||||
{
|
||||
// 使用指数权重,使高强度bin的影响更大
|
||||
double weight = Math.Pow(2, i) / Math.Pow(2, BINS-1); // 指数增长的权重
|
||||
concentrationScore += histogram[i] * weight;
|
||||
}
|
||||
|
||||
// 计算中心区域相对强度比
|
||||
double centerIntensityRatio = avgCenterIntensity / avgTotalIntensity;
|
||||
|
||||
// 最终得分:集中度得分(0.6)和中心强度比(0.4)的加权和
|
||||
return concentrationScore * 0.6 + centerIntensityRatio * 0.4;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 目标分类
|
||||
/// </summary>
|
||||
private (TargetType type, double confidence) ClassifyTarget(TargetFeature features)
|
||||
{
|
||||
TargetType bestMatch = TargetType.Unknown;
|
||||
double bestScore = 0;
|
||||
|
||||
// 计算特征权重
|
||||
var weights = CalculateFeatureWeights(features);
|
||||
|
||||
foreach (var kvp in targetFeatures)
|
||||
{
|
||||
double score = CalculateMatchScore(features, kvp.Value, weights);
|
||||
Console.WriteLine($"Match score for {kvp.Key}: {score:F2}");
|
||||
if (score > bestScore)
|
||||
{
|
||||
bestScore = score;
|
||||
bestMatch = kvp.Key;
|
||||
}
|
||||
}
|
||||
|
||||
// 使用自适应阈值
|
||||
double threshold = CalculateAdaptiveThreshold(features);
|
||||
Console.WriteLine($"Adaptive threshold: {threshold:F2}");
|
||||
|
||||
return bestScore > threshold ?
|
||||
(bestMatch, bestScore) :
|
||||
(TargetType.Unknown, bestScore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算特征权重
|
||||
/// </summary>
|
||||
private double[] CalculateFeatureWeights(TargetFeature features)
|
||||
{
|
||||
// 使用固定权重,基于特征的重要性
|
||||
return new[]
|
||||
{
|
||||
0.3, // 长宽比权重
|
||||
0.2, // 相对尺寸权重
|
||||
0.25, // 强度模式权重
|
||||
0.25 // 温度梯度权重
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算自适应阈值
|
||||
/// </summary>
|
||||
private double CalculateAdaptiveThreshold(TargetFeature features)
|
||||
{
|
||||
// 降低基准阈值,使用0.4作为基准
|
||||
double baseThreshold = 0.4;
|
||||
|
||||
// 计算特征质量因子
|
||||
double qualityFactor = (
|
||||
Math.Min(1.0, features.AspectRatio / 5.0) + // 长宽比质量(最大考虑5.0)
|
||||
Math.Min(1.0, features.Size / 1.5) + // 相对尺寸质量(最大考虑1.5)
|
||||
features.IntensityPattern + // 强度模式质量
|
||||
features.TemperatureGradient // 温度梯度质量
|
||||
) / 4.0;
|
||||
|
||||
return baseThreshold * (0.8 + 0.4 * qualityFactor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算特征匹配得分
|
||||
/// </summary>
|
||||
private double CalculateMatchScore(TargetFeature features, TargetFeature template, double[] weights)
|
||||
{
|
||||
// 计算各个特征的匹配度,使用相对误差
|
||||
double aspectRatioScore = 1 - Math.Min(1, Math.Abs(features.AspectRatio - template.AspectRatio) / Math.Max(features.AspectRatio, template.AspectRatio));
|
||||
double sizeScore = 1 - Math.Min(1, Math.Abs(features.Size - template.Size) / Math.Max(features.Size, template.Size));
|
||||
double patternScore = 1 - Math.Min(1, Math.Abs(features.IntensityPattern - template.IntensityPattern));
|
||||
double gradientScore = 1 - Math.Min(1, Math.Abs(features.TemperatureGradient - template.TemperatureGradient));
|
||||
|
||||
// 输出详细的匹配分数
|
||||
Console.WriteLine($"Feature match scores:");
|
||||
Console.WriteLine($" Aspect Ratio: {aspectRatioScore:F2} (weight: {weights[0]:F2})");
|
||||
Console.WriteLine($" Size: {sizeScore:F2} (weight: {weights[1]:F2})");
|
||||
Console.WriteLine($" Pattern: {patternScore:F2} (weight: {weights[2]:F2})");
|
||||
Console.WriteLine($" Gradient: {gradientScore:F2} (weight: {weights[3]:F2})");
|
||||
|
||||
// 加权平均
|
||||
double totalScore = aspectRatioScore * weights[0] +
|
||||
sizeScore * weights[1] +
|
||||
patternScore * weights[2] +
|
||||
gradientScore * weights[3];
|
||||
|
||||
Console.WriteLine($" Total Score: {totalScore:F2}");
|
||||
return totalScore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 目标特征结构
|
||||
/// </summary>
|
||||
private struct TargetFeature
|
||||
{
|
||||
public double AspectRatio { get; } // 长宽比
|
||||
public double Size { get; } // 特征尺寸
|
||||
public double IntensityPattern { get; } // 强度模式特征
|
||||
public double TemperatureGradient { get; } // 温度梯度特征
|
||||
|
||||
public TargetFeature(
|
||||
double aspectRatio,
|
||||
double size,
|
||||
double intensityPattern,
|
||||
double temperatureGradient)
|
||||
{
|
||||
AspectRatio = aspectRatio;
|
||||
Size = size;
|
||||
IntensityPattern = intensityPattern;
|
||||
TemperatureGradient = temperatureGradient;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 图像分割结果结构
|
||||
/// </summary>
|
||||
private struct ImageSegment
|
||||
{
|
||||
public bool IsValid { get; }
|
||||
public (int X, int Y) Center { get; }
|
||||
public (int Width, int Height) Size { get; }
|
||||
|
||||
public ImageSegment(bool isValid = false, (int X, int Y) center = default, (int Width, int Height) size = default)
|
||||
{
|
||||
IsValid = isValid;
|
||||
Center = center;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ThreatSource.Guidance
|
||||
{
|
||||
@ -110,12 +111,42 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
private bool LaserIlluminationOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置期望的激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 导弹期望接收的编码信息
|
||||
/// 用于验证接收到的激光信号
|
||||
/// </remarks>
|
||||
private LaserCodeConfig? InternalLaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置支持的编码类型列表
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义导弹支持的编码类型
|
||||
/// 默认支持PRF、PPM和PWM编码
|
||||
/// </remarks>
|
||||
private List<LaserCodeType> supportedCodeTypes = new List<LaserCodeType>
|
||||
{
|
||||
LaserCodeType.PRF,
|
||||
LaserCodeType.PPM,
|
||||
LaserCodeType.PWM
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 系统配置参数
|
||||
/// </summary>
|
||||
private readonly LaserBeamRiderGuidanceSystemConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光驾束制导系统的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">制导系统ID</param>
|
||||
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
|
||||
/// <param name="guidanceCoefficient">制导系数</param>
|
||||
/// <param name="laserCodeConfig">激光编码配置,可选</param>
|
||||
/// <param name="guidanceConfig">制导系统配置参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -123,14 +154,148 @@ namespace ThreatSource.Guidance
|
||||
/// - 初始化激光参数
|
||||
/// - 初始化控制参数
|
||||
/// </remarks>
|
||||
public LaserBeamRiderGuidanceSystem(string id, double maxAcceleration, double guidanceCoefficient, ISimulationManager simulationManager)
|
||||
public LaserBeamRiderGuidanceSystem(
|
||||
string id,
|
||||
double maxAcceleration,
|
||||
double guidanceCoefficient,
|
||||
LaserCodeConfig? laserCodeConfig,
|
||||
LaserBeamRiderGuidanceSystemConfig guidanceConfig,
|
||||
ISimulationManager simulationManager)
|
||||
: base(id, maxAcceleration, guidanceCoefficient, simulationManager)
|
||||
{
|
||||
config = guidanceConfig;
|
||||
LaserSourcePosition = Vector3D.Zero;
|
||||
LaserDirection = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
HasGuidance = false;
|
||||
LaserIlluminationOn = false;
|
||||
LastError = Vector3D.Zero;
|
||||
IntegralError = Vector3D.Zero;
|
||||
LastGuidanceAcceleration = Vector3D.Zero;
|
||||
|
||||
// 如果没有提供编码配置,创建默认配置
|
||||
InternalLaserCodeConfig = laserCodeConfig ?? new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode
|
||||
{
|
||||
CodeType = LaserCodeType.PPM,
|
||||
CodeValue = 1234
|
||||
},
|
||||
IsCodeEnabled = true,
|
||||
IsCodeMatchRequired = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置期望的激光编码
|
||||
/// </summary>
|
||||
/// <param name="codeType">编码类型</param>
|
||||
/// <param name="codeValue">编码值</param>
|
||||
/// <remarks>
|
||||
/// 设置过程:
|
||||
/// - 检查编码类型是否支持
|
||||
/// - 创建新的编码对象
|
||||
/// - 设置编码类型和值
|
||||
/// </remarks>
|
||||
public void SetExpectedLaserCode(LaserCodeType codeType, int codeValue)
|
||||
{
|
||||
if (supportedCodeTypes.Contains(codeType))
|
||||
{
|
||||
InternalLaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
Code = new LaserCode { CodeType = codeType, CodeValue = codeValue }
|
||||
};
|
||||
Debug.WriteLine($"激光驾束制导系统设置期望编码:类型={codeType},值={codeValue}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine($"激光驾束制导系统不支持编码类型:{codeType}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加期望编码参数
|
||||
/// </summary>
|
||||
/// <param name="key">参数名称</param>
|
||||
/// <param name="value">参数值</param>
|
||||
/// <remarks>
|
||||
/// 添加特定编码类型的额外参数
|
||||
/// 如PPM编码的脉冲位置模式、PWM编码的脉冲宽度等
|
||||
/// </remarks>
|
||||
public void AddExpectedCodeParameter(string key, object value)
|
||||
{
|
||||
if (InternalLaserCodeConfig != null)
|
||||
{
|
||||
InternalLaserCodeConfig.Code.Parameters[key] = value;
|
||||
Debug.WriteLine($"激光驾束制导系统添加期望编码参数:{key}={value}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置是否要求编码匹配
|
||||
/// </summary>
|
||||
/// <param name="required">是否要求匹配</param>
|
||||
/// <remarks>
|
||||
/// 设置导弹是否严格要求激光编码匹配
|
||||
/// true表示必须匹配,false表示不要求匹配
|
||||
/// </remarks>
|
||||
public void SetCodeMatchRequired(bool required)
|
||||
{
|
||||
if (InternalLaserCodeConfig != null)
|
||||
{
|
||||
InternalLaserCodeConfig.IsCodeMatchRequired = required;
|
||||
Debug.WriteLine($"激光驾束制导系统设置编码匹配要求:{required}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查激光编码是否匹配
|
||||
/// </summary>
|
||||
/// <param name="receivedConfig">接收到的激光编码配置</param>
|
||||
/// <returns>如果匹配返回true,否则返回false</returns>
|
||||
/// <remarks>
|
||||
/// 检查过程:
|
||||
/// - 验证编码类型
|
||||
/// - 验证编码值
|
||||
/// - 验证额外参数
|
||||
/// </remarks>
|
||||
private bool CheckLaserCode(LaserCodeConfig? receivedConfig)
|
||||
{
|
||||
return InternalLaserCodeConfig?.CheckCodeMatch(receivedConfig) ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布编码匹配事件
|
||||
/// </summary>
|
||||
/// <param name="designatorId">激光定位器ID</param>
|
||||
/// <param name="matchedCodeConfig">匹配的编码配置</param>
|
||||
private void PublishCodeMatchEvent(string? designatorId, LaserCodeConfig? matchedCodeConfig)
|
||||
{
|
||||
var matchEvent = new LaserCodeMatchEvent
|
||||
{
|
||||
MissileId = ParentId,
|
||||
DesignatorId = designatorId,
|
||||
MatchedCodeConfig = matchedCodeConfig
|
||||
};
|
||||
|
||||
PublishEvent(matchEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布编码不匹配事件
|
||||
/// </summary>
|
||||
/// <param name="designatorId">激光定位器ID</param>
|
||||
/// <param name="receivedCodeConfig">接收到的编码配置</param>
|
||||
private void PublishCodeMismatchEvent(string? designatorId, LaserCodeConfig? receivedCodeConfig)
|
||||
{
|
||||
var mismatchEvent = new LaserCodeMismatchEvent
|
||||
{
|
||||
MissileId = ParentId,
|
||||
DesignatorId = designatorId,
|
||||
ExpectedCodeConfig = InternalLaserCodeConfig,
|
||||
ReceivedCodeConfig = receivedCodeConfig
|
||||
};
|
||||
|
||||
PublishEvent(mismatchEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -224,7 +389,7 @@ namespace ThreatSource.Guidance
|
||||
double shortestDistance = shortestDistanceVector.Magnitude();
|
||||
|
||||
// 检查导弹是否在控制场内
|
||||
if (shortestDistance > ControlFieldDiameter / 2)
|
||||
if (shortestDistance > config.ControlFieldDiameter / 2)
|
||||
{
|
||||
HasGuidance = false;
|
||||
Trace.WriteLine($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
|
||||
@ -234,11 +399,11 @@ namespace ThreatSource.Guidance
|
||||
Debug.WriteLine($"激光驾束引导系统: 在控制场内, 距离: {shortestDistance}");
|
||||
|
||||
// 计算接收到的激光功率
|
||||
double beamArea = Math.PI * Math.Pow(ControlFieldDiameter / 2, 2);
|
||||
double beamArea = Math.PI * Math.Pow(config.ControlFieldDiameter / 2, 2);
|
||||
double powerDensity = LaserPower / beamArea;
|
||||
double receivedPower = powerDensity * (Math.PI * Math.Pow(DetectorDiameter / 2, 2));
|
||||
double receivedPower = powerDensity * (Math.PI * Math.Pow(config.DetectorDiameter / 2, 2));
|
||||
|
||||
if(HasGuidance = receivedPower >= MinDetectablePower)
|
||||
if(receivedPower >= config.MinDetectablePower)
|
||||
{
|
||||
HasGuidance = true;
|
||||
}
|
||||
@ -275,12 +440,6 @@ namespace ThreatSource.Guidance
|
||||
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
|
||||
|
||||
// PID控制
|
||||
double Kp = 30; // 增加比例系数,使系统对误差更敏感,反应更快 30
|
||||
double Ki = 0.05; // 减小积分系数,减少长期误差累积的影响 0.05
|
||||
double Kd = 5; // 增加微分系数,减少系统的超调量,提高稳定性 5
|
||||
double Kc = 0.5; // 减小非线性增益系数, 控制偏移量, 使得在更小的误差范围内有更大的修正 0.5
|
||||
|
||||
// 计算误差
|
||||
Vector3D error = shortestDistanceVector;
|
||||
|
||||
// 积分项
|
||||
@ -290,20 +449,21 @@ namespace ThreatSource.Guidance
|
||||
Vector3D derivativeError = (error - LastError) / deltaTime;
|
||||
|
||||
// 计算PID输出
|
||||
Vector3D pidOutput = error * Kp + IntegralError * Ki + derivativeError * Kd;
|
||||
Vector3D pidOutput = error * config.ProportionalGain +
|
||||
IntegralError * config.IntegralGain +
|
||||
derivativeError * config.DerivativeGain;
|
||||
|
||||
// 非线性增益
|
||||
double distance = shortestDistanceVector.Magnitude();
|
||||
double nonLinearGain = Math.Tanh(distance / Kc);
|
||||
double nonLinearGain = Math.Tanh(distance / config.NonlinearGain);
|
||||
|
||||
// 计算横向加速度
|
||||
Vector3D lateralAcceleration = pidOutput * nonLinearGain;
|
||||
|
||||
// 限制最大加速度
|
||||
double maxAcceleration = 50; // 稍微增加最大加速度 50
|
||||
if (lateralAcceleration.Magnitude() > maxAcceleration)
|
||||
if (lateralAcceleration.Magnitude() > config.MaxGuidanceAcceleration)
|
||||
{
|
||||
lateralAcceleration = lateralAcceleration.Normalize() * maxAcceleration;
|
||||
lateralAcceleration = lateralAcceleration.Normalize() * config.MaxGuidanceAcceleration;
|
||||
}
|
||||
|
||||
// 计算前向加速度
|
||||
@ -317,8 +477,8 @@ namespace ThreatSource.Guidance
|
||||
GuidanceAcceleration = lateralAcceleration + forwardAcceleration;
|
||||
|
||||
// 低通滤波
|
||||
const double alpha = 0.2;
|
||||
GuidanceAcceleration = GuidanceAcceleration * alpha + LastGuidanceAcceleration * (1 - alpha);
|
||||
GuidanceAcceleration = GuidanceAcceleration * config.LowPassFilterCoefficient +
|
||||
LastGuidanceAcceleration * (1 - config.LowPassFilterCoefficient);
|
||||
|
||||
// 更新上一次的误差和制导加速度
|
||||
LastError = error;
|
||||
@ -368,5 +528,74 @@ namespace ThreatSource.Guidance
|
||||
|
||||
return shortestDistanceVector;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光波束开始事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光波束开始事件</param>
|
||||
private void OnLaserBeamStart(LaserBeamStartEvent evt)
|
||||
{
|
||||
if (evt?.LaserBeamRiderId != null)
|
||||
{
|
||||
// 检查编码是否匹配
|
||||
bool codeMatched = CheckLaserCode(evt.LaserCodeConfig);
|
||||
|
||||
if (!codeMatched)
|
||||
{
|
||||
// 发布编码不匹配事件
|
||||
PublishCodeMismatchEvent(evt.LaserBeamRiderId, evt.LaserCodeConfig);
|
||||
Debug.WriteLine("激光驾束制导系统接收到不匹配的激光编码,忽略信号");
|
||||
HasGuidance = false;
|
||||
LaserIlluminationOn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果编码匹配,发布匹配事件
|
||||
PublishCodeMatchEvent(evt.LaserBeamRiderId, evt.LaserCodeConfig);
|
||||
|
||||
// 更新激光波束参数
|
||||
LaserPower = evt.BeamPower;
|
||||
LaserIlluminationOn = true;
|
||||
HasGuidance = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光波束更新事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光波束更新事件</param>
|
||||
private void OnLaserBeamUpdate(LaserBeamUpdateEvent evt)
|
||||
{
|
||||
if (evt?.LaserBeamRiderId != null)
|
||||
{
|
||||
// 检查编码是否匹配
|
||||
bool codeMatched = CheckLaserCode(evt.LaserCodeConfig);
|
||||
|
||||
if (!codeMatched)
|
||||
{
|
||||
// 发布编码不匹配事件
|
||||
PublishCodeMismatchEvent(evt.LaserBeamRiderId, evt.LaserCodeConfig);
|
||||
Debug.WriteLine("激光驾束制导系统接收到不匹配的激光编码,忽略信号");
|
||||
HasGuidance = false;
|
||||
LaserIlluminationOn = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新激光波束参数
|
||||
LaserPower = evt.BeamPower;
|
||||
LaserIlluminationOn = true;
|
||||
HasGuidance = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光波束停止事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光波束停止事件</param>
|
||||
private void OnLaserBeamStop(LaserBeamStopEvent evt)
|
||||
{
|
||||
LaserIlluminationOn = false;
|
||||
HasGuidance = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,75 +19,7 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
public class LaserSemiActiveGuidanceSystem : BasicGuidanceSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了探测器的视场范围
|
||||
/// 设置为30度(π/6弧度)
|
||||
/// 影响系统的探测能力
|
||||
/// </remarks>
|
||||
private const double FieldOfViewAngle = Math.PI / 6;
|
||||
|
||||
/// <summary>
|
||||
/// 镜头直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了光学系统镜头的物理尺寸
|
||||
/// 影响系统的光能量收集能力
|
||||
/// 典型值为0.1米
|
||||
/// </remarks>
|
||||
private const double LensDiameter = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 传感器直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了四象限探测器的物理尺寸
|
||||
/// 影响系统的探测精度
|
||||
/// 典型值为0.03米
|
||||
/// </remarks>
|
||||
private const double SensorDiameter = 0.03;
|
||||
|
||||
/// <summary>
|
||||
/// 聚焦后光斑直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了光学系统聚焦后的光斑大小
|
||||
/// 影响系统的探测灵敏度
|
||||
/// 典型值为0.006米
|
||||
/// </remarks>
|
||||
private const double FocusedSpotDiameter = 0.006;
|
||||
|
||||
/// <summary>
|
||||
/// 目标反射系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标表面的激光反射能力
|
||||
/// 影响反射信号强度
|
||||
/// 典型值为0.2
|
||||
/// </remarks>
|
||||
private const double ReflectionCoefficient = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 锁定阈值,单位:瓦特
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了系统锁定目标的最小功率要求
|
||||
/// 低于此值时认为无法有效跟踪目标
|
||||
/// 典型值为1e-12瓦特
|
||||
/// </remarks>
|
||||
private const double LockThreshold = 1e-12;
|
||||
|
||||
/// <summary>
|
||||
/// 目标有效反射面积,单位:平方米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标的等效反射面积
|
||||
/// 影响反射信号强度
|
||||
/// 典型值为1.0平方米
|
||||
/// </remarks>
|
||||
private const double TargetReflectiveArea = 1.0;
|
||||
private readonly LaserSemiActiveGuidanceConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标位置
|
||||
@ -98,15 +30,6 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
private Vector3D TargetPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 记录当前跟踪目标的三维速度
|
||||
/// 用于制导计算和预测
|
||||
/// </remarks>
|
||||
private Vector3D TargetVelocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光照射状态
|
||||
/// </summary>
|
||||
@ -149,19 +72,9 @@ namespace ThreatSource.Guidance
|
||||
/// <remarks>
|
||||
/// 导弹期望接收的编码信息
|
||||
/// 用于验证接收到的激光信号
|
||||
/// 默认编码为PPM编码,值为123456
|
||||
/// 默认编码为PPM编码,值为1234
|
||||
/// </remarks>
|
||||
private LaserCode? expectedLaserCode = new LaserCode { CodeType = LaserCodeType.PPM, CodeValue = 123456 };
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否要求编码匹配
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示只响应匹配编码的激光信号
|
||||
/// false表示响应所有激光信号
|
||||
/// 默认为true
|
||||
/// </remarks>
|
||||
private bool isCodeMatchRequired = true;
|
||||
private LaserCodeConfig? InternalLaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置支持的编码类型列表
|
||||
@ -203,6 +116,8 @@ namespace ThreatSource.Guidance
|
||||
/// <param name="id">制导系统ID</param>
|
||||
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
|
||||
/// <param name="guidanceCoefficient">制导系数</param>
|
||||
/// <param name="laserCodeConfig">激光编码配置</param>
|
||||
/// <param name="guidanceConfig">激光半主动导引系统配置</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -211,17 +126,31 @@ namespace ThreatSource.Guidance
|
||||
/// - 初始化激光参数
|
||||
/// - 创建四象限探测器
|
||||
/// </remarks>
|
||||
public LaserSemiActiveGuidanceSystem(string id, double maxAcceleration, double guidanceCoefficient, ISimulationManager simulationManager)
|
||||
public LaserSemiActiveGuidanceSystem(
|
||||
string id,
|
||||
double maxAcceleration,
|
||||
double guidanceCoefficient,
|
||||
LaserCodeConfig laserCodeConfig,
|
||||
LaserSemiActiveGuidanceConfig guidanceConfig,
|
||||
ISimulationManager simulationManager)
|
||||
: base(id, maxAcceleration, guidanceCoefficient, simulationManager)
|
||||
{
|
||||
config = guidanceConfig;
|
||||
|
||||
TargetPosition = Vector3D.Zero;
|
||||
TargetVelocity = Vector3D.Zero;
|
||||
LaserIlluminationOn = false;
|
||||
LaserDesignatorPosition = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
InternalLaserCodeConfig = laserCodeConfig;
|
||||
|
||||
// 创建四象限探测器实例
|
||||
quadrantDetector = new QuadrantDetector(SensorDiameter, FocusedSpotDiameter, LockThreshold);
|
||||
// 创建四象限探测器实例,使用配置中的参数
|
||||
quadrantDetector = new QuadrantDetector(
|
||||
config.SensorDiameter,
|
||||
config.FocusedSpotDiameter,
|
||||
config.LockThreshold);
|
||||
|
||||
// 设置光斑偏移灵敏度
|
||||
SpotOffsetSensitivity = config.SpotOffsetSensitivity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -272,7 +201,7 @@ namespace ThreatSource.Guidance
|
||||
SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在");
|
||||
|
||||
// 更新激光指示器信息
|
||||
UpdateLaserDesignator(laserDesignator.Position, target.Position, target.Velocity,
|
||||
UpdateLaserDesignator(laserDesignator.Position, target.Position,
|
||||
laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle);
|
||||
|
||||
// 处理激光照射开始事件
|
||||
@ -303,7 +232,7 @@ namespace ThreatSource.Guidance
|
||||
SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在");
|
||||
|
||||
// 更新激光指示器信息
|
||||
UpdateLaserDesignator(laserDesignator.Position, target.Position, target.Velocity,
|
||||
UpdateLaserDesignator(laserDesignator.Position, target.Position,
|
||||
laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle);
|
||||
|
||||
// 处理激光照射更新事件
|
||||
@ -338,7 +267,6 @@ namespace ThreatSource.Guidance
|
||||
/// </summary>
|
||||
/// <param name="sourcePosition">激光源位置,单位:米</param>
|
||||
/// <param name="targetPosition">目标位置,单位:米</param>
|
||||
/// <param name="targetVelocity">目标速度,单位:米/秒</param>
|
||||
/// <param name="laserPower">激光功率,单位:瓦特</param>
|
||||
/// <param name="laserDivergenceAngle">激光发散角,单位:弧度</param>
|
||||
/// <remarks>
|
||||
@ -348,12 +276,11 @@ namespace ThreatSource.Guidance
|
||||
/// - 更新目标信息
|
||||
/// - 更新激光参数
|
||||
/// </remarks>
|
||||
public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
|
||||
public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, double laserPower, double laserDivergenceAngle)
|
||||
{
|
||||
LaserIlluminationOn = true;
|
||||
LaserDesignatorPosition = sourcePosition;
|
||||
TargetPosition = targetPosition;
|
||||
TargetVelocity = targetVelocity;
|
||||
LaserPower = laserPower;
|
||||
LaserDivergenceAngle = laserDivergenceAngle;
|
||||
}
|
||||
@ -374,7 +301,6 @@ namespace ThreatSource.Guidance
|
||||
LaserIlluminationOn = false;
|
||||
LaserDesignatorPosition = Vector3D.Zero;
|
||||
TargetPosition = Vector3D.Zero;
|
||||
TargetVelocity = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
LaserDivergenceAngle = 0;
|
||||
}
|
||||
@ -450,7 +376,7 @@ namespace ThreatSource.Guidance
|
||||
double powerDensityAtTarget = LaserPower / spotAreaAtTarget;
|
||||
|
||||
// 计算从目标反射的总功率
|
||||
double reflectedPower = powerDensityAtTarget * TargetReflectiveArea * ReflectionCoefficient;
|
||||
double reflectedPower = powerDensityAtTarget * config.TargetReflectiveArea * config.ReflectionCoefficient;
|
||||
|
||||
// 计算反射光在导弹处的扩散面积(假设漫反射)
|
||||
double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceMissileToTarget, 2);
|
||||
@ -459,13 +385,13 @@ namespace ThreatSource.Guidance
|
||||
double receivedPower = reflectedPower / reflectedSpotArea;
|
||||
|
||||
// 计算镜头接收到的功率比例
|
||||
double lensArea = Math.PI * Math.Pow(LensDiameter / 2, 2);
|
||||
double illuminatedArea = Math.PI * Math.Pow(distanceMissileToTarget * Math.Tan(FieldOfViewAngle / 2), 2);
|
||||
double lensArea = Math.PI * Math.Pow(config.LensDiameter / 2, 2);
|
||||
double illuminatedArea = Math.PI * Math.Pow(distanceMissileToTarget * Math.Tan(config.FieldOfViewAngleInRadians / 2), 2);
|
||||
double powerRatio = Math.Min(1, lensArea / illuminatedArea);
|
||||
|
||||
// 计算聚焦后的功率密度增加
|
||||
double sensorArea = Math.PI * Math.Pow(SensorDiameter / 2, 2);
|
||||
double focusedArea = Math.PI * Math.Pow(FocusedSpotDiameter / 2, 2);
|
||||
double sensorArea = Math.PI * Math.Pow(config.SensorDiameter / 2, 2);
|
||||
double focusedArea = Math.PI * Math.Pow(config.FocusedSpotDiameter / 2, 2);
|
||||
double focusingFactor = sensorArea / focusedArea;
|
||||
|
||||
// 计算最终接收到的功率
|
||||
@ -514,7 +440,7 @@ namespace ThreatSource.Guidance
|
||||
double verticalAngle = Math.Atan2(upComponent, forwardComponent);
|
||||
|
||||
// 转换为光斑偏移量(假设小角度近似)
|
||||
double focalLength = SensorDiameter / (2 * Math.Tan(FieldOfViewAngle / 2));
|
||||
double focalLength = config.SensorDiameter / (2 * Math.Tan(config.FieldOfViewAngleInRadians / 2));
|
||||
double horizontalOffset = focalLength * Math.Tan(horizontalAngle);
|
||||
double verticalOffset = focalLength * Math.Tan(verticalAngle);
|
||||
|
||||
@ -579,7 +505,7 @@ namespace ThreatSource.Guidance
|
||||
return base.GetStatus() +
|
||||
$" 激光目标指示器功率: {LaserPower}," +
|
||||
$" 接收到的激光功率: {CalculateReceivedLaserPower():E} W," +
|
||||
$" 锁定阈值: {LockThreshold:E} W," +
|
||||
$" 锁定阈值: {config.LockThreshold:E} W," +
|
||||
$" 四象限探测器: {quadrantDetector.GetStatus()}";
|
||||
}
|
||||
|
||||
@ -647,10 +573,9 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
if (supportedCodeTypes.Contains(codeType))
|
||||
{
|
||||
expectedLaserCode = new LaserCode
|
||||
InternalLaserCodeConfig = new LaserCodeConfig
|
||||
{
|
||||
CodeType = codeType,
|
||||
CodeValue = codeValue
|
||||
Code = new LaserCode { CodeType = codeType, CodeValue = codeValue }
|
||||
};
|
||||
Debug.WriteLine($"激光半主动制导系统设置期望编码:类型={codeType},值={codeValue}");
|
||||
}
|
||||
@ -671,27 +596,13 @@ namespace ThreatSource.Guidance
|
||||
/// </remarks>
|
||||
public void AddExpectedCodeParameter(string key, object value)
|
||||
{
|
||||
if (expectedLaserCode != null)
|
||||
if (InternalLaserCodeConfig != null)
|
||||
{
|
||||
expectedLaserCode.Parameters[key] = value;
|
||||
InternalLaserCodeConfig.Code.Parameters[key] = value;
|
||||
Debug.WriteLine($"激光半主动制导系统添加期望编码参数:{key}={value}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置是否要求编码匹配
|
||||
/// </summary>
|
||||
/// <param name="required">是否要求匹配</param>
|
||||
/// <remarks>
|
||||
/// true表示只响应匹配编码的激光信号
|
||||
/// false表示响应所有激光信号
|
||||
/// </remarks>
|
||||
public void SetCodeMatchRequired(bool required)
|
||||
{
|
||||
isCodeMatchRequired = required;
|
||||
Debug.WriteLine($"激光半主动制导系统{(required ? "要求" : "不要求")}编码匹配");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射事件
|
||||
/// </summary>
|
||||
@ -710,9 +621,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
ProcessLaserIlluminationCommon(
|
||||
illuminationEvent.LaserDesignatorId,
|
||||
illuminationEvent.TargetId,
|
||||
illuminationEvent.LaserCode,
|
||||
illuminationEvent.IsCodeEnabled,
|
||||
illuminationEvent.LaserCodeConfig,
|
||||
true); // 初始照射
|
||||
}
|
||||
|
||||
@ -734,9 +643,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
ProcessLaserIlluminationCommon(
|
||||
illuminationEvent.LaserDesignatorId,
|
||||
illuminationEvent.TargetId,
|
||||
illuminationEvent.LaserCode,
|
||||
illuminationEvent.IsCodeEnabled,
|
||||
illuminationEvent.LaserCodeConfig,
|
||||
false); // 更新照射
|
||||
}
|
||||
|
||||
@ -744,9 +651,7 @@ namespace ThreatSource.Guidance
|
||||
/// 处理激光照射事件的共同逻辑
|
||||
/// </summary>
|
||||
/// <param name="laserDesignatorId">激光指示器ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="laserCode">激光编码</param>
|
||||
/// <param name="isCodeEnabled">是否启用编码</param>
|
||||
/// <param name="laserCodeConfig">激光编码配置</param>
|
||||
/// <param name="isInitialIllumination">是否是初始照射(开始事件)</param>
|
||||
/// <remarks>
|
||||
/// 处理过程:
|
||||
@ -758,44 +663,48 @@ namespace ThreatSource.Guidance
|
||||
/// - 计算光斑偏移并传递给四象限探测器
|
||||
/// - 根据四象限探测器的锁定状态更新制导状态
|
||||
/// </remarks>
|
||||
private void ProcessLaserIlluminationCommon(string? laserDesignatorId, string? targetId,
|
||||
LaserCode? laserCode, bool isCodeEnabled, bool isInitialIllumination)
|
||||
private void ProcessLaserIlluminationCommon(string? laserDesignatorId,
|
||||
LaserCodeConfig? laserCodeConfig, bool isInitialIllumination)
|
||||
{
|
||||
// 检查编码是否匹配
|
||||
bool codeMatched = CheckCodeMatch(laserCode, isCodeEnabled);
|
||||
|
||||
if (isCodeMatchRequired && !codeMatched)
|
||||
if (laserCodeConfig != null)
|
||||
{
|
||||
// 发布编码不匹配事件
|
||||
PublishCodeMismatchEvent(laserDesignatorId, laserCode);
|
||||
Trace.WriteLine("激光半主动制导系统接收到不匹配的激光编码,忽略信号");
|
||||
HasGuidance = false; // 禁用制导
|
||||
LaserIlluminationOn = false; // 禁用激光照射状态,确保四象限探测器不处理信号
|
||||
// 重置四象限探测器状态
|
||||
quadrantDetector.ProcessLaserSignal(0, new Vector2D(0, 0));
|
||||
return; // 不处理不匹配的信号
|
||||
bool codeMatched = InternalLaserCodeConfig?.CheckCodeMatch(laserCodeConfig) ?? false;
|
||||
|
||||
if (!codeMatched)
|
||||
{
|
||||
// 发布编码不匹配事件
|
||||
PublishCodeMismatchEvent(laserDesignatorId, laserCodeConfig);
|
||||
Trace.WriteLine("激光半主动制导系统接收到不匹配的激光编码,忽略信号");
|
||||
HasGuidance = false; // 禁用制导
|
||||
LaserIlluminationOn = false; // 禁用激光照射状态,确保四象限探测器不处理信号
|
||||
// 重置四象限探测器状态
|
||||
quadrantDetector.ProcessLaserSignal(0, new Vector2D(0, 0));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果编码匹配,继续处理
|
||||
// 只有在初始照射或激光尚未开启时才发布编码匹配事件
|
||||
if (isInitialIllumination || !LaserIlluminationOn)
|
||||
{
|
||||
// 发布编码匹配事件
|
||||
PublishCodeMatchEvent(laserDesignatorId, laserCodeConfig);
|
||||
}
|
||||
|
||||
// 更新激光照射状态
|
||||
LaserIlluminationOn = true;
|
||||
|
||||
// 计算接收到的激光功率
|
||||
double receivedPower = CalculateReceivedLaserPower();
|
||||
|
||||
// 计算光斑偏移并传递给四象限探测器
|
||||
Vector2D spotOffset = CalculateSpotOffset();
|
||||
quadrantDetector.ProcessLaserSignal(receivedPower, spotOffset);
|
||||
|
||||
// 更新制导状态 - 根据四象限探测器的锁定状态
|
||||
HasGuidance = quadrantDetector.IsTargetLocked;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果编码匹配或不要求匹配,继续处理
|
||||
// 只有在初始照射或激光尚未开启时才发布编码匹配事件
|
||||
if (codeMatched && (isInitialIllumination || !LaserIlluminationOn))
|
||||
{
|
||||
// 发布编码匹配事件
|
||||
PublishCodeMatchEvent(laserDesignatorId, laserCode);
|
||||
}
|
||||
|
||||
// 更新激光照射状态
|
||||
LaserIlluminationOn = true;
|
||||
|
||||
// 计算接收到的激光功率
|
||||
double receivedPower = CalculateReceivedLaserPower();
|
||||
|
||||
// 计算光斑偏移并传递给四象限探测器
|
||||
Vector2D spotOffset = CalculateSpotOffset();
|
||||
quadrantDetector.ProcessLaserSignal(receivedPower, spotOffset);
|
||||
|
||||
// 更新制导状态 - 根据四象限探测器的锁定状态
|
||||
HasGuidance = quadrantDetector.IsTargetLocked;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -813,68 +722,24 @@ namespace ThreatSource.Guidance
|
||||
HasGuidance = false; // 禁用制导
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查编码是否匹配
|
||||
/// </summary>
|
||||
/// <param name="receivedCode">接收到的编码</param>
|
||||
/// <param name="isCodeEnabled">是否启用编码</param>
|
||||
/// <returns>如果匹配返回true,否则返回false</returns>
|
||||
/// <remarks>
|
||||
/// 匹配规则:
|
||||
/// - 如果不要求匹配,返回true
|
||||
/// - 如果接收到的信号未启用编码
|
||||
/// - 如果导弹未设置期望编码
|
||||
/// - 检查编码类型是否支持
|
||||
/// - 检查编码是否匹配
|
||||
/// </remarks>
|
||||
private bool CheckCodeMatch(LaserCode? receivedCode, bool isCodeEnabled)
|
||||
{
|
||||
// 如果不要求匹配,直接返回true
|
||||
if (!isCodeMatchRequired)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果接收到的信号未启用编码
|
||||
if (!isCodeEnabled || receivedCode == null)
|
||||
{
|
||||
return false; // 如果要求编码匹配,但编码被禁用,则不匹配
|
||||
}
|
||||
|
||||
// 如果导弹未设置期望编码
|
||||
if (expectedLaserCode == null)
|
||||
{
|
||||
return false; // 如果要求编码匹配,但导弹未设置期望编码,则不匹配
|
||||
}
|
||||
|
||||
// 检查编码类型是否支持
|
||||
if (!supportedCodeTypes.Contains(receivedCode.CodeType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查编码是否匹配
|
||||
return expectedLaserCode.Matches(receivedCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布编码匹配事件
|
||||
/// </summary>
|
||||
/// <param name="designatorId">激光定位器ID</param>
|
||||
/// <param name="matchedCode">匹配的编码</param>
|
||||
/// <param name="matchedCodeConfig">匹配的编码配置</param>
|
||||
/// <remarks>
|
||||
/// 发布过程:
|
||||
/// - 创建事件对象
|
||||
/// - 设置事件属性
|
||||
/// - 发布到事件系统
|
||||
/// </remarks>
|
||||
private void PublishCodeMatchEvent(string? designatorId, LaserCode? matchedCode)
|
||||
private void PublishCodeMatchEvent(string? designatorId, LaserCodeConfig? matchedCodeConfig)
|
||||
{
|
||||
var matchEvent = new LaserCodeMatchEvent
|
||||
{
|
||||
MissileId = ParentId,
|
||||
DesignatorId = designatorId,
|
||||
MatchedCode = matchedCode
|
||||
MatchedCodeConfig = matchedCodeConfig
|
||||
};
|
||||
|
||||
PublishEvent(matchEvent);
|
||||
@ -884,21 +749,21 @@ namespace ThreatSource.Guidance
|
||||
/// 发布编码不匹配事件
|
||||
/// </summary>
|
||||
/// <param name="designatorId">激光定位器ID</param>
|
||||
/// <param name="receivedCode">接收到的编码</param>
|
||||
/// <param name="receivedCodeConfig">接收到的编码配置</param>
|
||||
/// <remarks>
|
||||
/// 发布过程:
|
||||
/// - 创建事件对象
|
||||
/// - 设置事件属性
|
||||
/// - 发布到事件系统
|
||||
/// </remarks>
|
||||
private void PublishCodeMismatchEvent(string? designatorId, LaserCode? receivedCode)
|
||||
private void PublishCodeMismatchEvent(string? designatorId, LaserCodeConfig? receivedCodeConfig)
|
||||
{
|
||||
var mismatchEvent = new LaserCodeMismatchEvent
|
||||
{
|
||||
MissileId = ParentId,
|
||||
DesignatorId = designatorId,
|
||||
ExpectedCode = expectedLaserCode,
|
||||
ReceivedCode = receivedCode
|
||||
ExpectedCodeConfig = InternalLaserCodeConfig,
|
||||
ReceivedCodeConfig = receivedCodeConfig
|
||||
};
|
||||
|
||||
PublishEvent(mismatchEvent);
|
||||
|
||||
@ -18,64 +18,13 @@ namespace ThreatSource.Guidance
|
||||
public class MillimeterWaveGuidanceSystem : BasicGuidanceSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大探测范围,单位:米
|
||||
/// 毫米波导引系统配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了毫米波雷达的最大作用距离
|
||||
/// 超出此范围的目标无法有效探测
|
||||
/// 典型值为5000米
|
||||
/// 存储系统的所有可配置参数
|
||||
/// 包括探测范围、视场角等
|
||||
/// </remarks>
|
||||
private const double MAX_DETECTION_RANGE = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达的扫描范围
|
||||
/// 设置为45度(π/4弧度)
|
||||
/// 影响系统的搜索能力
|
||||
/// </remarks>
|
||||
private const double FIELD_OF_VIEW = Math.PI / 4;
|
||||
|
||||
/// <summary>
|
||||
/// 目标识别概率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的成功率
|
||||
/// 影响系统的可靠性
|
||||
/// 典型值为0.95
|
||||
/// </remarks>
|
||||
private const double TARGET_RECOGNITION_PROBABILITY = 0.95;
|
||||
|
||||
/// <summary>
|
||||
/// 毫米波频率,单位:赫兹
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达工作频率
|
||||
/// 设置为94GHz
|
||||
/// 影响探测性能和抗干扰能力
|
||||
/// </remarks>
|
||||
private const double WAVE_FREQUENCY = 94e9;
|
||||
|
||||
/// <summary>
|
||||
/// 脉冲持续时间,单位:秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达发射脉冲的时长
|
||||
/// 影响距离分辨率
|
||||
/// 典型值为1微秒
|
||||
/// </remarks>
|
||||
private const double PULSE_DURATION = 1e-6;
|
||||
|
||||
/// <summary>
|
||||
/// 识别目标的信噪比阈值,单位:分贝
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的最小信噪比要求
|
||||
/// 大于此值时认为目标有效
|
||||
/// 典型值为6dB
|
||||
/// </remarks>
|
||||
private const double RECOGNITION_SNR_THRESHOLD = 6;
|
||||
private readonly MillimeterWaveGuidanceConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 随机数生成器实例
|
||||
@ -120,6 +69,7 @@ namespace ThreatSource.Guidance
|
||||
/// <param name="maxAcceleration">最大加速度,单位:米/平方秒</param>
|
||||
/// <param name="guidanceCoefficient">制导系数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <param name="config">毫米波导引系统配置</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// - 初始化基类参数
|
||||
@ -127,9 +77,15 @@ namespace ThreatSource.Guidance
|
||||
/// - 初始化目标位置
|
||||
/// - 注册干扰事件处理
|
||||
/// </remarks>
|
||||
public MillimeterWaveGuidanceSystem(string id, double maxAcceleration, double guidanceCoefficient, ISimulationManager simulationManager)
|
||||
public MillimeterWaveGuidanceSystem(
|
||||
string id,
|
||||
double maxAcceleration,
|
||||
double guidanceCoefficient,
|
||||
MillimeterWaveGuidanceConfig config,
|
||||
ISimulationManager simulationManager)
|
||||
: base(id, maxAcceleration, guidanceCoefficient, simulationManager)
|
||||
{
|
||||
this.config = config;
|
||||
lastTargetPosition = Vector3D.Zero;
|
||||
|
||||
// 订阅干扰事件
|
||||
@ -168,7 +124,7 @@ namespace ThreatSource.Guidance
|
||||
{
|
||||
base.Update(deltaTime, missilePosition, missileVelocity);
|
||||
|
||||
if (TryDetectTank(missilePosition, missileVelocity, out Vector3D tankPosition))
|
||||
if (TryDetectTarget(missilePosition, missileVelocity, out Vector3D tankPosition))
|
||||
{
|
||||
//根据目标当前位置和上一次位置计算目标速度
|
||||
Vector3D targetVelocity = (tankPosition - lastTargetPosition) / deltaTime;
|
||||
@ -191,7 +147,7 @@ namespace ThreatSource.Guidance
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试探测目标坦克
|
||||
/// 尝试探测目标
|
||||
/// </summary>
|
||||
/// <param name="missilePosition">导弹当前位置,单位:米</param>
|
||||
/// <param name="missileVelocity">导弹当前速度,单位:米/秒</param>
|
||||
@ -205,7 +161,7 @@ namespace ThreatSource.Guidance
|
||||
/// - 计算信噪比
|
||||
/// - 判断目标有效性
|
||||
/// </remarks>
|
||||
private bool TryDetectTank(Vector3D missilePosition, Vector3D missileVelocity, out Vector3D targetPosition)
|
||||
private bool TryDetectTarget(Vector3D missilePosition, Vector3D missileVelocity, out Vector3D targetPosition)
|
||||
{
|
||||
targetPosition = Vector3D.Zero;
|
||||
|
||||
@ -218,22 +174,22 @@ namespace ThreatSource.Guidance
|
||||
|
||||
foreach (var element in SimulationManager.GetEntitiesByType<SimulationElement>())
|
||||
{
|
||||
if (element is Tank tank)
|
||||
if (element is ITarget target)
|
||||
{
|
||||
Vector3D toTarget = tank.Position - missilePosition;
|
||||
Vector3D toTarget = target.Position - missilePosition;
|
||||
double distance = toTarget.Magnitude();
|
||||
|
||||
if (distance <= MAX_DETECTION_RANGE)
|
||||
if (distance <= config.MaxDetectionRange)
|
||||
{
|
||||
double angle = Math.Acos(Vector3D.DotProduct(toTarget.Normalize(), missileVelocity.Normalize()));
|
||||
if (angle <= FIELD_OF_VIEW / 2)
|
||||
if (angle <= config.FieldOfViewAngleInRadians / 2)
|
||||
{
|
||||
// 模拟毫米波探测
|
||||
double snr = CalculateSNR(distance, tank.RadarCrossSection);
|
||||
double snr = CalculateSNR(distance, target.RadarCrossSection);
|
||||
|
||||
if(snr > RECOGNITION_SNR_THRESHOLD && random.NextDouble() < TARGET_RECOGNITION_PROBABILITY)
|
||||
if(snr > config.RecognitionSNRThreshold && random.NextDouble() < config.TargetRecognitionProbability)
|
||||
{
|
||||
targetPosition = tank.Position;
|
||||
targetPosition = target.Position;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -273,12 +229,12 @@ namespace ThreatSource.Guidance
|
||||
/// - 计算信噪比
|
||||
/// - 转换为分贝值
|
||||
/// </remarks>
|
||||
private static double CalculateSNR(double distance, double radarCrossSection)
|
||||
private double CalculateSNR(double distance, double radarCrossSection)
|
||||
{
|
||||
// 雷达参数
|
||||
double transmitPower = 100; // 发射功率(W)
|
||||
double antennaGain = Math.Pow(10, 30/10); // 天线增益(线性值,从dB转换)
|
||||
double wavelength = 3e8 / WAVE_FREQUENCY; // 波长(m)
|
||||
double wavelength = 3e8 / config.WaveFrequency; // 波长(m)
|
||||
double bandwidth = 1e6; // 接收机带宽(Hz),假设为1MHz
|
||||
double noiseFigure = Math.Pow(10, 3/10); // 噪声系数(线性值,假设为3dB)
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ namespace ThreatSource.Indicator
|
||||
/// <param name="id">测角仪ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="config">配置参数</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -70,8 +71,8 @@ namespace ThreatSource.Indicator
|
||||
/// - 配置工作参数
|
||||
/// - 设置初始状态
|
||||
/// </remarks>
|
||||
public InfraredTracker(string id, string targetId, InfraredTrackerConfig config, ISimulationManager manager)
|
||||
: base(id, config.InitialPosition, config.InitialOrientation, 0, manager)
|
||||
public InfraredTracker(string id, string targetId, InfraredTrackerConfig config, InitialMotionParameters initialMotionParameters, ISimulationManager manager)
|
||||
: base(id, initialMotionParameters.Position, initialMotionParameters.Orientation, initialMotionParameters.InitialSpeed, manager)
|
||||
{
|
||||
TargetId = targetId;
|
||||
MissileId = null;
|
||||
|
||||
@ -35,6 +35,15 @@ namespace ThreatSource.Indicator
|
||||
/// </remarks>
|
||||
public double BeamDivergence { get; private set; } = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含激光信号的编码信息
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置控制场直径
|
||||
/// </summary>
|
||||
@ -95,8 +104,8 @@ namespace ThreatSource.Indicator
|
||||
/// <param name="id">制导器的唯一标识符</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="speed">初始速度</param>
|
||||
/// <param name="config">配置参数</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -105,8 +114,8 @@ namespace ThreatSource.Indicator
|
||||
/// - 配置制导范围
|
||||
/// - 建立目标关联
|
||||
/// </remarks>
|
||||
public LaserBeamRider(string id, string missileId, string targetId, double speed, LaserBeamRiderConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, new Orientation(0, 0, 0), speed, simulationManager)
|
||||
public LaserBeamRider(string id, string targetId, string missileId, LaserBeamRiderConfig config, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters.Position, initialMotionParameters.Orientation, initialMotionParameters.InitialSpeed, simulationManager)
|
||||
{
|
||||
LaserPower = config.LaserPower;
|
||||
ControlFieldDiameter = config.ControlFieldDiameter;
|
||||
@ -116,9 +125,27 @@ namespace ThreatSource.Indicator
|
||||
IsBeamOn = false;
|
||||
MissileId = missileId;
|
||||
TargetId = targetId;
|
||||
LaserCodeConfig = config.LaserCodeConfig;
|
||||
base.SimulationManager = simulationManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加编码参数
|
||||
/// </summary>
|
||||
/// <param name="key">参数名称</param>
|
||||
/// <param name="value">参数值</param>
|
||||
/// <remarks>
|
||||
/// 添加特定编码类型的额外参数
|
||||
/// 如PPM编码的脉冲位置模式、PWM编码的脉冲宽度等
|
||||
/// </remarks>
|
||||
public void AddCodeParameter(string key, object value)
|
||||
{
|
||||
if (LaserCodeConfig != null)
|
||||
{
|
||||
LaserCodeConfig.Code.Parameters[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新激光驾束仪状态
|
||||
/// </summary>
|
||||
|
||||
@ -87,24 +87,13 @@ namespace ThreatSource.Indicator
|
||||
public double LaserDivergenceAngle { get; private set; } = 0.5e-3;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含激光信号的编码信息
|
||||
/// 用于抗干扰和安全识别
|
||||
/// 默认编码为PPM编码,值为123456
|
||||
/// </remarks>
|
||||
private LaserCode? currentLaserCode = new LaserCode { CodeType = LaserCodeType.PPM, CodeValue = 123456 };
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否启用编码
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示激光信号使用编码
|
||||
/// false表示激光信号不使用编码
|
||||
/// 默认为true
|
||||
/// </remarks>
|
||||
private bool isCodeEnabled = true;
|
||||
public LaserCodeConfig LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光指示器的新实例
|
||||
@ -112,8 +101,8 @@ namespace ThreatSource.Indicator
|
||||
/// <param name="id">激光指示器ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="speed">移动速度</param>
|
||||
/// <param name="config">配置参数</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -122,8 +111,8 @@ namespace ThreatSource.Indicator
|
||||
/// - 配置激光参数
|
||||
/// - 设置初始状态
|
||||
/// </remarks>
|
||||
public LaserDesignator(string id, string targetId, string missileId, double speed, LaserDesignatorConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, CalculateInitialOrientation(config.InitialPosition, targetId, simulationManager), speed, simulationManager)
|
||||
public LaserDesignator(string id, string targetId, string missileId, LaserDesignatorConfig config, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters.Position, initialMotionParameters.Orientation, initialMotionParameters.InitialSpeed, simulationManager)
|
||||
{
|
||||
TargetId = targetId;
|
||||
MissileId = missileId;
|
||||
@ -131,6 +120,7 @@ namespace ThreatSource.Indicator
|
||||
IsIlluminationOn = false;
|
||||
LaserPower = config.LaserPower;
|
||||
LaserDivergenceAngle = config.LaserDivergenceAngle;
|
||||
LaserCodeConfig = config.LaserCodeConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -288,7 +278,6 @@ namespace ThreatSource.Indicator
|
||||
IsJammed = false;
|
||||
// 先订阅事件
|
||||
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
|
||||
// 再开始照射
|
||||
StartLaserIllumination();
|
||||
}
|
||||
@ -313,32 +302,10 @@ namespace ThreatSource.Indicator
|
||||
IsActive = false;
|
||||
StopLaserIllumination();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.UnsubscribeFromEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
|
||||
}
|
||||
base.Deactivate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置激光编码
|
||||
/// </summary>
|
||||
/// <param name="codeType">编码类型</param>
|
||||
/// <param name="codeValue">编码值</param>
|
||||
/// <remarks>
|
||||
/// 设置过程:
|
||||
/// - 创建新的编码对象
|
||||
/// - 设置编码类型和值
|
||||
/// - 启用编码功能
|
||||
/// </remarks>
|
||||
public void SetLaserCode(LaserCodeType codeType, int codeValue)
|
||||
{
|
||||
currentLaserCode = new LaserCode
|
||||
{
|
||||
CodeType = codeType,
|
||||
CodeValue = codeValue
|
||||
};
|
||||
isCodeEnabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加编码参数
|
||||
/// </summary>
|
||||
@ -350,25 +317,12 @@ namespace ThreatSource.Indicator
|
||||
/// </remarks>
|
||||
public void AddCodeParameter(string key, object value)
|
||||
{
|
||||
if (currentLaserCode != null)
|
||||
if (LaserCodeConfig != null)
|
||||
{
|
||||
currentLaserCode.Parameters[key] = value;
|
||||
LaserCodeConfig.Code.Parameters[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启用或禁用编码
|
||||
/// </summary>
|
||||
/// <param name="enable">是否启用编码</param>
|
||||
/// <remarks>
|
||||
/// true表示启用编码功能
|
||||
/// false表示禁用编码功能
|
||||
/// </remarks>
|
||||
public void EnableCode(bool enable)
|
||||
{
|
||||
isCodeEnabled = enable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光照射开始事件
|
||||
/// </summary>
|
||||
@ -390,14 +344,9 @@ namespace ThreatSource.Indicator
|
||||
};
|
||||
|
||||
// 添加编码信息
|
||||
if (isCodeEnabled && currentLaserCode != null)
|
||||
if (LaserCodeConfig != null)
|
||||
{
|
||||
illuminationEvent.LaserCode = currentLaserCode;
|
||||
illuminationEvent.IsCodeEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
illuminationEvent.IsCodeEnabled = false;
|
||||
illuminationEvent.LaserCodeConfig = LaserCodeConfig;
|
||||
}
|
||||
|
||||
// 发布事件
|
||||
@ -424,14 +373,9 @@ namespace ThreatSource.Indicator
|
||||
};
|
||||
|
||||
// 添加编码信息
|
||||
if (isCodeEnabled && currentLaserCode != null)
|
||||
if (LaserCodeConfig != null)
|
||||
{
|
||||
illuminationEvent.LaserCode = currentLaserCode;
|
||||
illuminationEvent.IsCodeEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
illuminationEvent.IsCodeEnabled = false;
|
||||
illuminationEvent.LaserCodeConfig = LaserCodeConfig;
|
||||
}
|
||||
|
||||
PublishEvent(illuminationEvent);
|
||||
@ -453,24 +397,6 @@ namespace ThreatSource.Indicator
|
||||
PublishEvent(evt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理实体停用事件
|
||||
/// </summary>
|
||||
/// <param name="evt">实体停用事件数据</param>
|
||||
/// <remarks>
|
||||
/// 处理过程:
|
||||
/// - 检查停用实体
|
||||
/// - 处理关联实体
|
||||
/// - 更新工作状态
|
||||
/// </remarks>
|
||||
private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt)
|
||||
{
|
||||
if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId)
|
||||
{
|
||||
StopLaserIllumination();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取激光指示器运行状态
|
||||
/// </summary>
|
||||
@ -519,7 +445,7 @@ namespace ThreatSource.Indicator
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}\n" +
|
||||
$" 照射状态: {(IsIlluminationOn ? "正在照射" : "未照射")}\n" +
|
||||
$" 干扰状态: {(IsJammed ? "被干扰" : "正常")}\n" +
|
||||
$" 编码状态: {(isCodeEnabled ? "启用" : "禁用")}\n" +
|
||||
$" 编码状态: {(LaserCodeConfig != null ? "启用" : "禁用")}\n" +
|
||||
$" 激光功率: {LaserPower:E} W";
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ namespace ThreatSource.Missile
|
||||
/// 由制导系统计算得出的期望加速度
|
||||
/// 用于修正导弹的飞行路径
|
||||
/// </remarks>
|
||||
protected Vector3D GuidanceAcceleration { get; set; }
|
||||
protected Vector3D GuidanceAcceleration { get; set; } = Vector3D.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的推力加速度
|
||||
@ -108,31 +108,37 @@ namespace ThreatSource.Missile
|
||||
/// 包含导弹的所有基本属性和性能限制
|
||||
/// 在导弹创建时设置,运行期间保持不变
|
||||
/// </remarks>
|
||||
public readonly MissileProperties MissileProperties;
|
||||
public readonly MissileProperties Properties;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化导弹基类的新实例
|
||||
/// </summary>
|
||||
/// <param name="properties">导弹的配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// - 初始化基本属性(位置、朝向、速度)
|
||||
/// - 设置初始状态(未激活、未制导)
|
||||
/// - 清零计时器和计数器
|
||||
/// - 初始化加速度向量
|
||||
/// - 初始化基本属性
|
||||
/// - 设置性能限制
|
||||
/// - 配置运动参数
|
||||
/// - 建立仿真管理器关联
|
||||
/// </remarks>
|
||||
public BaseMissile(MissileProperties properties, ISimulationManager manager)
|
||||
: base(properties.Id, properties.InitialPosition, properties.InitialOrientation, properties.InitialSpeed, manager)
|
||||
protected BaseMissile(
|
||||
string missileId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, launchParams.Position, launchParams.Orientation, launchParams.InitialSpeed, manager)
|
||||
{
|
||||
MissileProperties = properties;
|
||||
SimulationManager = manager;
|
||||
|
||||
IsActive = false;
|
||||
IsGuidance = false;
|
||||
// 设置性能限制
|
||||
Properties = properties;
|
||||
|
||||
// 初始化状态
|
||||
FlightTime = 0;
|
||||
FlightDistance = 0;
|
||||
EngineBurnTime = 0;
|
||||
IsActive = false;
|
||||
IsGuidance = false;
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
ThrustAcceleration = Vector3D.Zero;
|
||||
}
|
||||
@ -199,9 +205,9 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
// 限制速度不超过最大速度
|
||||
if (Velocity.Magnitude() > MissileProperties.MaxSpeed)
|
||||
if (Velocity.Magnitude() > Properties.MaxSpeed)
|
||||
{
|
||||
Velocity = Velocity.Normalize() * MissileProperties.MaxSpeed;
|
||||
Velocity = Velocity.Normalize() * Properties.MaxSpeed;
|
||||
}
|
||||
|
||||
Speed = Velocity.Magnitude();
|
||||
@ -229,14 +235,14 @@ namespace ThreatSource.Missile
|
||||
private Vector3D CalculateAcceleration(Vector3D velocity)
|
||||
{
|
||||
// 计算空气阻力的影响
|
||||
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / MissileProperties.Mass;
|
||||
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Properties.Mass;
|
||||
|
||||
Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration;
|
||||
|
||||
Debug.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, 推力加速度: {ThrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
|
||||
if (totalAcceleration.Magnitude() > MissileProperties.MaxAcceleration)
|
||||
if (totalAcceleration.Magnitude() > Properties.MaxAcceleration)
|
||||
{
|
||||
totalAcceleration = totalAcceleration.Normalize() * MissileProperties.MaxAcceleration;
|
||||
totalAcceleration = totalAcceleration.Normalize() * Properties.MaxAcceleration;
|
||||
}
|
||||
|
||||
return totalAcceleration;
|
||||
@ -293,8 +299,8 @@ namespace ThreatSource.Missile
|
||||
protected bool ShouldSelfDestruct()
|
||||
{
|
||||
// 基本条件判断
|
||||
if (FlightTime >= MissileProperties.MaxFlightTime
|
||||
|| FlightDistance >= MissileProperties.MaxFlightDistance)
|
||||
if (FlightTime >= Properties.MaxFlightTime
|
||||
|| FlightDistance >= Properties.MaxFlightDistance)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -303,12 +309,12 @@ namespace ThreatSource.Missile
|
||||
if (IsGuidance)
|
||||
{
|
||||
// 有制导时,在负爆炸半径高度自毁(考虑仿真步长)
|
||||
return Position.Y <= -MissileProperties.ExplosionRadius;
|
||||
return Position.Y <= -Properties.ExplosionRadius;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 无制导时,在自毁高度自毁
|
||||
return Position.Y <= MissileProperties.SelfDestructHeight;
|
||||
return Position.Y <= Properties.SelfDestructHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,19 +360,19 @@ namespace ThreatSource.Missile
|
||||
public void SelfDestruct()
|
||||
{
|
||||
string reason;
|
||||
if (FlightTime >= MissileProperties.MaxFlightTime)
|
||||
if (FlightTime >= Properties.MaxFlightTime)
|
||||
{
|
||||
reason = "超出最大飞行时间";
|
||||
}
|
||||
else if (FlightDistance >= MissileProperties.MaxFlightDistance)
|
||||
else if (FlightDistance >= Properties.MaxFlightDistance)
|
||||
{
|
||||
reason = "超出最大飞行距离";
|
||||
}
|
||||
else if (IsGuidance && Position.Y <= -MissileProperties.ExplosionRadius)
|
||||
else if (IsGuidance && Position.Y <= -Properties.ExplosionRadius)
|
||||
{
|
||||
reason = "有制导状态下高度低于负爆炸半径";
|
||||
}
|
||||
else if (!IsGuidance && Position.Y <= MissileProperties.SelfDestructHeight)
|
||||
else if (!IsGuidance && Position.Y <= Properties.SelfDestructHeight)
|
||||
{
|
||||
reason = "无制导状态下高度低于自毁高度";
|
||||
}
|
||||
@ -449,9 +455,9 @@ namespace ThreatSource.Missile
|
||||
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
|
||||
$" 速度分量: {missileRunningState.Velocity}\n" +
|
||||
$" 朝向: {missileRunningState.Orientation}\n" +
|
||||
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MissileProperties.MaxFlightTime:F2}\n" +
|
||||
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MissileProperties.MaxFlightDistance:F2}\n" +
|
||||
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MissileProperties.MaxEngineBurnTime:F2}\n" +
|
||||
$" 飞行时间: {missileRunningState.FlightTime:F2}/{Properties.MaxFlightTime:F2}\n" +
|
||||
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{Properties.MaxFlightDistance:F2}\n" +
|
||||
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{Properties.MaxEngineBurnTime:F2}\n" +
|
||||
$" 有引导: {(missileRunningState.IsGuidance ? "是" : "否")}\n" +
|
||||
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}\n";
|
||||
}
|
||||
@ -485,7 +491,7 @@ namespace ThreatSource.Missile
|
||||
return new MissileRunningState
|
||||
{
|
||||
Id = Id,
|
||||
Type = MissileProperties.Type,
|
||||
Type = Properties.Type,
|
||||
Position = Position,
|
||||
Velocity = Velocity,
|
||||
Orientation = Orientation,
|
||||
|
||||
@ -74,7 +74,9 @@ namespace ThreatSource.Missile
|
||||
/// <summary>
|
||||
/// 初始化红外指令制导导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="config">导弹配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -83,16 +85,20 @@ namespace ThreatSource.Missile
|
||||
/// - 创建指令导引系统
|
||||
/// - 配置PID参数
|
||||
/// </remarks>
|
||||
public InfraredCommandGuidedMissile(MissileProperties config, ISimulationManager manager) : base(config, manager)
|
||||
public InfraredCommandGuidedMissile(
|
||||
string missileId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
infraredTracker = null!;
|
||||
RadiationPower = 1000;
|
||||
|
||||
// 初始化红外指令导引系统,包括自适应 PID 参数
|
||||
guidanceSystem = new InfraredCommandGuidanceSystem(
|
||||
config.Id + "_guidance",
|
||||
config.MaxAcceleration,
|
||||
config.ProportionalNavigationCoefficient,
|
||||
missileId + "_guidance",
|
||||
properties.MaxAcceleration,
|
||||
properties.ProportionalNavigationCoefficient,
|
||||
manager
|
||||
);
|
||||
}
|
||||
@ -139,7 +145,7 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
// 发射阶段
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime >= 0.1)
|
||||
if (FlightTime >= Properties.MaxEngineBurnTime)
|
||||
{
|
||||
currentStage = ICGM_Stage.Cruise;
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Guidance;
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Target;
|
||||
|
||||
namespace ThreatSource.Missile
|
||||
{
|
||||
@ -27,18 +28,20 @@ namespace ThreatSource.Missile
|
||||
/// 红外成像末制导导弹的飞行阶段枚举
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了导弹的五个工作阶段:
|
||||
/// 定义了导弹的工作阶段:
|
||||
/// - Launch: 发射阶段,初始加速
|
||||
/// - Cruise: 巡航阶段,中程飞行
|
||||
/// - TerminalGuidance: 末制导阶段,红外制导
|
||||
/// - Explode: 爆炸阶段,执行毁伤
|
||||
/// - SelfDestruct: 自毁阶段,紧急处置
|
||||
/// - TerminalSearch: 末制导搜索阶段,大视场角搜索目标
|
||||
/// - TerminalTrack: 末制导跟踪阶段,小视场角精确跟踪
|
||||
/// - TerminalLock: 末制导锁定阶段,目标确认后的精确跟踪
|
||||
/// </remarks>
|
||||
private enum IRTG_Stage
|
||||
{
|
||||
Launch, // 发射阶段
|
||||
Cruise, // 巡航阶段
|
||||
TerminalGuidance // 末制导阶段
|
||||
TerminalSearch, // 末制导搜索阶段
|
||||
TerminalTrack, // 末制导跟踪阶段
|
||||
TerminalLock // 末制导锁定阶段
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -73,22 +76,36 @@ namespace ThreatSource.Missile
|
||||
/// <summary>
|
||||
/// 初始化红外成像末制导导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="config">导弹的配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="targetType">目标类型</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="guidanceConfig">红外成像导引配置</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// 1. 调用基类构造函数
|
||||
/// 2. 创建制导系统实例
|
||||
/// 3. 设置初始飞行阶段
|
||||
/// - 初始化基本属性
|
||||
/// - 创建制导系统
|
||||
/// - 配置制导参数
|
||||
/// - 设置初始飞行阶段
|
||||
/// </remarks>
|
||||
public InfraredImagingTerminalGuidedMissile(MissileProperties config, ISimulationManager manager)
|
||||
: base(config, manager)
|
||||
public InfraredImagingTerminalGuidedMissile(
|
||||
string missileId,
|
||||
TargetType targetType,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
InfraredImagingGuidanceConfig guidanceConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
guidanceSystem = new InfraredImagingGuidanceSystem(
|
||||
config.Id + "_guidance",
|
||||
config.MaxAcceleration,
|
||||
config.ProportionalNavigationCoefficient,
|
||||
manager);
|
||||
missileId + "_guidance",
|
||||
guidanceConfig,
|
||||
targetType,
|
||||
properties.MaxAcceleration,
|
||||
properties.ProportionalNavigationCoefficient,
|
||||
manager
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -112,8 +129,14 @@ namespace ThreatSource.Missile
|
||||
case IRTG_Stage.Cruise:
|
||||
UpdateCruiseStage(deltaTime);
|
||||
break;
|
||||
case IRTG_Stage.TerminalGuidance:
|
||||
UpdateTerminalGuidanceStage(deltaTime);
|
||||
case IRTG_Stage.TerminalSearch:
|
||||
UpdateTerminalSearchStage(deltaTime);
|
||||
break;
|
||||
case IRTG_Stage.TerminalTrack:
|
||||
UpdateTerminalTrackStage(deltaTime);
|
||||
break;
|
||||
case IRTG_Stage.TerminalLock:
|
||||
UpdateTerminalLockStage(deltaTime);
|
||||
break;
|
||||
}
|
||||
base.Update(deltaTime);
|
||||
@ -133,7 +156,7 @@ namespace ThreatSource.Missile
|
||||
private void UpdateLaunchStage(double deltaTime)
|
||||
{
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime > 0.1) // 假设发射阶段持续1秒
|
||||
if (FlightTime > Properties.MaxEngineBurnTime) // 假设发射阶段持续1秒
|
||||
{
|
||||
currentStage = IRTG_Stage.Cruise;
|
||||
}
|
||||
@ -147,33 +170,92 @@ namespace ThreatSource.Missile
|
||||
/// 巡航阶段特点:
|
||||
/// - 保持稳定飞行
|
||||
/// - 不使用制导系统
|
||||
/// - 持续时间为3秒
|
||||
/// - 结束后进入末制导阶段
|
||||
/// - 达到巡航时间后进入末制导搜索阶段
|
||||
/// </remarks>
|
||||
private void UpdateCruiseStage(double deltaTime)
|
||||
{
|
||||
if (FlightTime > 3) // 假设巡航阶段持续3秒
|
||||
// 如果巡航时间达到,切换到末制导搜索阶段
|
||||
if (FlightTime > Properties.CruiseTime)
|
||||
{
|
||||
currentStage = IRTG_Stage.TerminalGuidance;
|
||||
currentStage = IRTG_Stage.TerminalSearch;
|
||||
guidanceSystem.Activate(); // 激活制导系统
|
||||
guidanceSystem.SwitchToSearchMode(); // 切换到搜索模式
|
||||
currentStage = IRTG_Stage.TerminalSearch;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新末制导阶段的状态
|
||||
/// 更新末制导搜索阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 末制导阶段特点:
|
||||
/// - 开启红外成像制导
|
||||
/// - 计算制导加速度
|
||||
/// - 精确跟踪目标
|
||||
/// - 持续到命中目标
|
||||
/// 搜索阶段特点:
|
||||
/// - 大视场角(6-8度)搜索目标
|
||||
/// - 进行目标检测和初步识别
|
||||
/// - 发现目标后切换到跟踪阶段
|
||||
/// </remarks>
|
||||
private void UpdateTerminalGuidanceStage(double deltaTime)
|
||||
private void UpdateTerminalSearchStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
|
||||
|
||||
// 如果发现并识别出目标,切换到跟踪阶段
|
||||
if (guidanceSystem.HasTarget)
|
||||
{
|
||||
currentStage = IRTG_Stage.TerminalTrack;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新末制导跟踪阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 跟踪阶段特点:
|
||||
/// - 小视场角(2-3度)精确跟踪
|
||||
/// - 高精度目标识别和特征提取
|
||||
/// - 目标确认后切换到锁定阶段
|
||||
/// - 如果失去目标则返回搜索阶段
|
||||
/// </remarks>
|
||||
private void UpdateTerminalTrackStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
|
||||
|
||||
// 如果失去目标,切换回搜索阶段
|
||||
if (!guidanceSystem.HasTarget)
|
||||
{
|
||||
currentStage = IRTG_Stage.TerminalSearch;
|
||||
}
|
||||
// 当制导系统进入锁定模式时,导弹也切换到锁定阶段
|
||||
else if (guidanceSystem.IsInLockMode)
|
||||
{
|
||||
currentStage = IRTG_Stage.TerminalLock;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新末制导锁定阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 锁定阶段特点:
|
||||
/// - 目标类型已确认
|
||||
/// - 专注于位置跟踪
|
||||
/// - 如果失去目标则返回搜索阶段
|
||||
/// </remarks>
|
||||
private void UpdateTerminalLockStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
|
||||
|
||||
if (!guidanceSystem.HasTarget)
|
||||
{
|
||||
currentStage = IRTG_Stage.TerminalSearch;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -53,24 +53,36 @@ namespace ThreatSource.Missile
|
||||
private readonly LaserBeamRiderGuidanceSystem guidanceSystem;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光波束制导导弹的新实例
|
||||
/// 初始化激光驾束制导导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="config">导弹配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="laserCodeConfig">激光编码配置</param>
|
||||
/// <param name="guidanceSystemConfig">制导系统配置</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// - 初始化基本属性
|
||||
/// - 创建波束制导系统
|
||||
/// - 创建制导系统
|
||||
/// - 配置制导参数
|
||||
/// - 设置初始飞行阶段
|
||||
/// </remarks>
|
||||
public LaserBeamRiderMissile(MissileProperties config, ISimulationManager manager)
|
||||
: base(config, manager)
|
||||
public LaserBeamRiderMissile(
|
||||
string missileId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
LaserCodeConfig laserCodeConfig,
|
||||
LaserBeamRiderGuidanceSystemConfig guidanceSystemConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
guidanceSystem = new LaserBeamRiderGuidanceSystem(
|
||||
config.Id + "_guidance",
|
||||
config.MaxAcceleration,
|
||||
config.ProportionalNavigationCoefficient,
|
||||
missileId + "_guidance",
|
||||
properties.MaxAcceleration,
|
||||
properties.ProportionalNavigationCoefficient,
|
||||
laserCodeConfig,
|
||||
guidanceSystemConfig,
|
||||
manager);
|
||||
}
|
||||
|
||||
@ -169,7 +181,7 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
// 发射阶段
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime >= 0.01)
|
||||
if (FlightTime >= Properties.MaxEngineBurnTime)
|
||||
{
|
||||
currentStage = LBRM_Stage.Cruise;
|
||||
}
|
||||
|
||||
@ -63,10 +63,23 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public string LaserDesignatorId { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <value>激光编码配置</value>
|
||||
/// <remarks>
|
||||
/// 用于配置导弹期望接收的激光编码类型和值
|
||||
/// </remarks>
|
||||
public LaserCodeConfig LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光半主动制导导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="config">导弹配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="laserCodeConfig">激光编码配置</param>
|
||||
/// <param name="guidanceConfig">激光半主动制导系统配置</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -75,17 +88,26 @@ namespace ThreatSource.Missile
|
||||
/// - 配置制导参数
|
||||
/// - 设置初始飞行阶段
|
||||
/// </remarks>
|
||||
public LaserSemiActiveGuidedMissile(MissileProperties config, ISimulationManager manager)
|
||||
: base(config, manager)
|
||||
public LaserSemiActiveGuidedMissile(
|
||||
string missileId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
LaserCodeConfig laserCodeConfig,
|
||||
LaserSemiActiveGuidanceConfig guidanceConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
guidanceSystem = new LaserSemiActiveGuidanceSystem(
|
||||
config.Id + "_guidance",
|
||||
config.MaxAcceleration,
|
||||
config.ProportionalNavigationCoefficient,
|
||||
missileId + "_guidance",
|
||||
properties.MaxAcceleration,
|
||||
properties.ProportionalNavigationCoefficient,
|
||||
laserCodeConfig,
|
||||
guidanceConfig,
|
||||
manager);
|
||||
|
||||
|
||||
// 设置制导系统的ParentId属性
|
||||
guidanceSystem.ParentId = config.Id;
|
||||
guidanceSystem.ParentId = missileId;
|
||||
LaserCodeConfig = laserCodeConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -172,7 +194,7 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
// 发射阶段
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime >= 0.1)
|
||||
if (FlightTime >= Properties.MaxEngineBurnTime)
|
||||
{
|
||||
currentStage = LSAGM_Stage.Cruise;
|
||||
}
|
||||
@ -221,58 +243,6 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置激光编码
|
||||
/// </summary>
|
||||
/// <param name="codeType">编码类型</param>
|
||||
/// <param name="codeValue">编码值</param>
|
||||
/// <remarks>
|
||||
/// 设置导弹期望接收的激光编码类型和值
|
||||
/// 用于验证接收到的激光信号
|
||||
/// </remarks>
|
||||
public void SetLaserCode(LaserCodeType codeType, int codeValue)
|
||||
{
|
||||
if (guidanceSystem is LaserSemiActiveGuidanceSystem laserGuidance)
|
||||
{
|
||||
laserGuidance.SetExpectedLaserCode(codeType, codeValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加激光编码参数
|
||||
/// </summary>
|
||||
/// <param name="key">参数名称</param>
|
||||
/// <param name="value">参数值</param>
|
||||
/// <remarks>
|
||||
/// 添加特定编码类型的额外参数
|
||||
/// 如PPM编码的脉冲位置模式、PWM编码的脉冲宽度等
|
||||
/// </remarks>
|
||||
public void AddLaserCodeParameter(string key, object value)
|
||||
{
|
||||
if (guidanceSystem is LaserSemiActiveGuidanceSystem laserGuidance)
|
||||
{
|
||||
laserGuidance.AddExpectedCodeParameter(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置是否要求编码匹配
|
||||
/// </summary>
|
||||
/// <param name="required">是否要求匹配</param>
|
||||
/// <remarks>
|
||||
/// true表示只响应匹配编码的激光信号
|
||||
/// false表示响应所有激光信号
|
||||
/// </remarks>
|
||||
public void SetCodeMatchRequired(bool required)
|
||||
{
|
||||
if (guidanceSystem is LaserSemiActiveGuidanceSystem laserGuidance)
|
||||
{
|
||||
laserGuidance.SetCodeMatchRequired(required);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取制导加速度
|
||||
/// </summary>
|
||||
|
||||
@ -38,7 +38,9 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
Launch, // 发射阶段
|
||||
Cruise, // 巡航阶段
|
||||
TerminalGuidance // 末制导阶段
|
||||
Search, // 搜索阶段
|
||||
Track, // 跟踪阶段
|
||||
Lock // 锁定阶段
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -73,23 +75,32 @@ namespace ThreatSource.Missile
|
||||
/// <summary>
|
||||
/// 初始化毫米波末制导导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="properties">导弹的配置参数</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="properties">导弹属性配置</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="guidanceConfig">毫米波制导系统配置</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// 1. 调用基类构造函数
|
||||
/// 2. 创建制导系统实例
|
||||
/// 3. 设置初始飞行阶段
|
||||
/// - 初始化基本属性
|
||||
/// - 创建制导系统
|
||||
/// - 配置制导参数
|
||||
/// - 设置初始飞行阶段
|
||||
/// </remarks>
|
||||
public MillimeterWaveTerminalGuidedMissile(MissileProperties properties, ISimulationManager manager)
|
||||
: base(properties, manager)
|
||||
public MillimeterWaveTerminalGuidedMissile(
|
||||
string missileId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
MillimeterWaveGuidanceConfig guidanceConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
guidanceSystem = new MillimeterWaveGuidanceSystem(
|
||||
properties.Id + "_guidance",
|
||||
missileId + "_guidance",
|
||||
properties.MaxAcceleration,
|
||||
properties.ProportionalNavigationCoefficient,
|
||||
manager
|
||||
);
|
||||
guidanceConfig,
|
||||
manager);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -113,8 +124,14 @@ namespace ThreatSource.Missile
|
||||
case MWTG_Stage.Cruise:
|
||||
UpdateCruiseStage(deltaTime);
|
||||
break;
|
||||
case MWTG_Stage.TerminalGuidance:
|
||||
UpdateTerminalGuidanceStage(deltaTime);
|
||||
case MWTG_Stage.Search:
|
||||
UpdateSearchStage(deltaTime);
|
||||
break;
|
||||
case MWTG_Stage.Track:
|
||||
UpdateTrackStage(deltaTime);
|
||||
break;
|
||||
case MWTG_Stage.Lock:
|
||||
UpdateLockStage(deltaTime);
|
||||
break;
|
||||
}
|
||||
base.Update(deltaTime);
|
||||
@ -134,7 +151,7 @@ namespace ThreatSource.Missile
|
||||
private void UpdateLaunchStage(double deltaTime)
|
||||
{
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime > 0.1)
|
||||
if (FlightTime > Properties.MaxEngineBurnTime)
|
||||
{
|
||||
currentStage = MWTG_Stage.Cruise;
|
||||
}
|
||||
@ -153,24 +170,62 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
private void UpdateCruiseStage(double deltaTime)
|
||||
{
|
||||
if (FlightTime > 3)
|
||||
if (FlightTime > Properties.CruiseTime)
|
||||
{
|
||||
currentStage = MWTG_Stage.TerminalGuidance;
|
||||
currentStage = MWTG_Stage.Search;
|
||||
guidanceSystem.Activate(); // 激活制导系统
|
||||
currentStage = MWTG_Stage.Search;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新末制导阶段的状态
|
||||
/// 更新搜索阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 末制导阶段特点:
|
||||
/// 搜索阶段特点:
|
||||
/// - 开启毫米波制导
|
||||
/// - 计算制导加速度
|
||||
/// - 精确跟踪目标
|
||||
/// - 持续到命中目标
|
||||
/// </remarks>
|
||||
private void UpdateTerminalGuidanceStage(double deltaTime)
|
||||
private void UpdateSearchStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新跟踪阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 跟踪阶段特点:
|
||||
/// - 开启毫米波制导
|
||||
/// - 计算制导加速度
|
||||
/// - 精确跟踪目标
|
||||
/// - 持续到命中目标
|
||||
/// </remarks>
|
||||
private void UpdateTrackStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新锁定阶段的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 锁定阶段特点:
|
||||
/// - 开启毫米波制导
|
||||
/// - 计算制导加速度
|
||||
/// - 精确跟踪目标
|
||||
/// - 持续到命中目标
|
||||
/// </remarks>
|
||||
private void UpdateLockStage(double deltaTime)
|
||||
{
|
||||
IsGuidance = true;
|
||||
guidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Missile
|
||||
{
|
||||
@ -56,7 +57,6 @@ namespace ThreatSource.Missile
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类用于:
|
||||
/// - 初始化导弹的基本参数
|
||||
/// - 配置导弹的性能限制
|
||||
/// - 设置导弹的物理特性
|
||||
/// - 定义导弹的作战能力
|
||||
@ -64,42 +64,6 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public class MissileProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和追踪特定的导弹实例
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的初始位置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用三维向量表示发射位置
|
||||
/// 坐标系:右手坐标系,X向右,Y向上,Z向前
|
||||
/// </remarks>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的初始朝向
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用欧拉角表示初始姿态
|
||||
/// 包含偏航角、俯仰角和滚转角
|
||||
/// </remarks>
|
||||
public Orientation InitialOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的初始速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒
|
||||
/// 发射时的初始运动速度
|
||||
/// </remarks>
|
||||
public double InitialSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的最大速度限制
|
||||
/// </summary>
|
||||
@ -149,26 +113,6 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的发射推力加速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒²
|
||||
/// 发射阶段的推进加速度
|
||||
/// 影响导弹的起飞性能
|
||||
/// </remarks>
|
||||
public double LaunchAcceleration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置发动机的最大燃烧时间
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:秒
|
||||
/// 发动机能够持续工作的最长时间
|
||||
/// 基于燃料容量和燃烧速率
|
||||
/// </remarks>
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的质量
|
||||
/// </summary>
|
||||
@ -208,6 +152,27 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public double SelfDestructHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置发射推力加速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒²
|
||||
/// 发射阶段的推进加速度
|
||||
/// 影响导弹的起飞性能
|
||||
/// 这是导弹的固有属性,由发动机性能决定
|
||||
/// </remarks>
|
||||
public double LaunchAcceleration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置发动机的最大燃烧时间
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:秒
|
||||
/// 发动机能够持续工作的最长时间
|
||||
/// 基于燃料容量和燃烧速率
|
||||
/// </remarks>
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的类型
|
||||
/// </summary>
|
||||
@ -217,23 +182,40 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 适用于激光半主动导弹和激光驾束导弹
|
||||
/// 定义激光信号的编码参数
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig? LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置导弹的巡航时间
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:秒
|
||||
/// 导弹在巡航阶段的持续时间
|
||||
/// 超过此时间后进入末制导阶段
|
||||
/// </remarks>
|
||||
public double CruiseTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化导弹配置类的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// - 设置所有数值参数的默认值
|
||||
/// - 初始化基本属性(ID、位置、朝向)
|
||||
/// - 初始化基本属性(ID)
|
||||
/// - 设置默认导弹类型
|
||||
/// </remarks>
|
||||
public MissileProperties()
|
||||
{
|
||||
SetDefaultValues();
|
||||
|
||||
Id = "";
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
InitialOrientation = new Orientation(0, 0, 0);
|
||||
Type = MissileType.StandardMissile;
|
||||
LaserCodeConfig = new LaserCodeConfig();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -247,16 +229,20 @@ namespace ThreatSource.Missile
|
||||
/// - 性能参数
|
||||
/// 用于初始化或重置导弹配置
|
||||
/// </remarks>
|
||||
public void SetDefaultValues(){
|
||||
InitialSpeed = 300;
|
||||
public void SetDefaultValues()
|
||||
{
|
||||
MaxSpeed = 400;
|
||||
MaxFlightTime = 60;
|
||||
MaxFlightDistance = 5000;
|
||||
LaunchAcceleration = 100;
|
||||
MaxEngineBurnTime = 10;
|
||||
MaxAcceleration = 100;
|
||||
ExplosionRadius = 5;
|
||||
LaunchAcceleration = 50;
|
||||
MaxEngineBurnTime = 10;
|
||||
CruiseTime = 5;
|
||||
ProportionalNavigationCoefficient = 3;
|
||||
Mass = 50;
|
||||
ExplosionRadius = 5;
|
||||
HitProbability = 0.9;
|
||||
SelfDestructHeight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,45 +24,12 @@ namespace ThreatSource.Missile
|
||||
public class TerminalSensitiveMissile : BaseMissile
|
||||
{
|
||||
/// <summary>
|
||||
/// 子弹药分离的高度阈值
|
||||
/// 子弹药配置参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 当导弹上升到此高度时会触发分离
|
||||
/// 默认设置为1000米
|
||||
/// 包含分离参数和子弹药性能参数
|
||||
/// </remarks>
|
||||
private const double SeparationHeight = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// 分离点与目标的水平距离
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 分离点在目标上方的水平投影距离
|
||||
/// 默认设置为1000米
|
||||
/// </remarks>
|
||||
private const double SeparationDistance = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// 子弹分离角度(与地面的夹角)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:度
|
||||
/// 子弹从母弹分离时与地面的夹角
|
||||
/// 默认设置为60度
|
||||
/// </remarks>
|
||||
private const double SubmunitionSeparationAngle = 45;
|
||||
|
||||
/// <summary>
|
||||
/// 触发分离的距离阈值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 当导弹距离分离点小于此距离时触发分离
|
||||
/// 默认设置为50米
|
||||
/// 注意:此值必须大于导弹速度乘以时间步长的一半
|
||||
/// </remarks>
|
||||
private const double SeparationRange = 50;
|
||||
private readonly TerminalSensitiveSubmunitionConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 末敏弹的飞行阶段
|
||||
@ -132,10 +99,13 @@ namespace ThreatSource.Missile
|
||||
/// <summary>
|
||||
/// 初始化末敏导弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="missileId">导弹的唯一标识符</param>
|
||||
/// <param name="targetId">目标的唯一标识符</param>
|
||||
/// <param name="properties">导弹的配置参数</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="submunitionProperties">子弹的配置参数</param>
|
||||
/// <param name="submunitionCount">子弹的数量</param>
|
||||
/// <param name="submunitionConfig">子弹药配置参数</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <exception cref="Exception">当目标不存在时抛出</exception>
|
||||
/// <exception cref="InvalidOperationException">当无法计算发射方向时抛出</exception>
|
||||
@ -147,21 +117,31 @@ namespace ThreatSource.Missile
|
||||
/// 4. 计算最佳发射角度
|
||||
/// 5. 设置初始速度和方向
|
||||
/// </remarks>
|
||||
public TerminalSensitiveMissile(string targetId, MissileProperties properties, MissileProperties submunitionProperties, int submunitionCount, ISimulationManager manager)
|
||||
: base(properties, manager)
|
||||
public TerminalSensitiveMissile(
|
||||
string missileId,
|
||||
string targetId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
MissileProperties submunitionProperties,
|
||||
int submunitionCount,
|
||||
TerminalSensitiveSubmunitionConfig submunitionConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
this.targetId = targetId;
|
||||
this.submunitionProperties = submunitionProperties;
|
||||
this.submunitionCount = submunitionCount;
|
||||
this.config = submunitionConfig;
|
||||
submunitions = new TerminalSensitiveSubmunition[submunitionCount];
|
||||
//计算分离点坐标,高度为SeparationHeight,距离目标的距离为SeparationDistance
|
||||
SimulationElement target = SimulationManager.GetEntityById(this.targetId) as SimulationElement ?? throw new Exception("目标不存在");
|
||||
separationPoint = Vector3D.PointOnLine(target.Position, base.Position, SeparationDistance) + new Vector3D(0, SeparationHeight, 0);
|
||||
|
||||
//计算分离点坐标,使用配置中的分离高度和距离
|
||||
SimulationElement target = SimulationManager.GetEntityById(targetId) as SimulationElement ?? throw new Exception("目标不存在");
|
||||
separationPoint = Vector3D.PointOnLine(target.Position, base.Position, config.SeparationDistance) + new Vector3D(0, config.SeparationHeight, 0);
|
||||
|
||||
//计算导弹发射角度
|
||||
(Orientation? launchOrientation, Vector3D? launchVelocity) = MotionAlgorithm.CalculateBestLaunchOrientation(Position, separationPoint, Speed);
|
||||
if (!launchOrientation.HasValue || launchVelocity is null)
|
||||
{
|
||||
// 处理错误情况
|
||||
throw new InvalidOperationException("无法计算发射方向");
|
||||
}
|
||||
else
|
||||
@ -234,7 +214,7 @@ namespace ThreatSource.Missile
|
||||
private void UpdateLaunchStage(double deltaTime)
|
||||
{
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
if (FlightTime > 0.1)
|
||||
if (FlightTime > Properties.MaxEngineBurnTime)
|
||||
{
|
||||
currentStage = TSGM_Stage.Cruise;
|
||||
}
|
||||
@ -253,8 +233,8 @@ namespace ThreatSource.Missile
|
||||
private void UpdateCruiseStage(double deltaTime)
|
||||
{
|
||||
double distanceToSeparationPoint = (separationPoint - Position).Magnitude();
|
||||
//距离分离点距离小于50米,则分离
|
||||
if (distanceToSeparationPoint <= SeparationRange)
|
||||
//距离分离点距离小于配置的分离范围,则分离
|
||||
if (distanceToSeparationPoint <= config.SeparationRange)
|
||||
{
|
||||
currentStage = TSGM_Stage.Separation;
|
||||
}
|
||||
@ -295,12 +275,12 @@ namespace ThreatSource.Missile
|
||||
Vector3D horizontalDirection = new Vector3D(currentDirection.X, 0, currentDirection.Z).Normalize();
|
||||
|
||||
// 计算分离角度(弧度)
|
||||
double separationAngleRad = SubmunitionSeparationAngle * Math.PI / 180.0;
|
||||
double separationAngleRad = config.SubmunitionSeparationAngle * Math.PI / 180.0;
|
||||
|
||||
// 计算子弹的初始方向(保持水平方向不变,设置垂直角度为-60度)
|
||||
// 计算子弹的初始方向(保持水平方向不变,设置垂直角度)
|
||||
Vector3D initialDirection = new Vector3D(
|
||||
horizontalDirection.X,
|
||||
-Math.Tan(separationAngleRad), // 负号表示向下的60度角
|
||||
-Math.Tan(separationAngleRad),
|
||||
horizontalDirection.Z
|
||||
).Normalize();
|
||||
|
||||
@ -312,13 +292,10 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
Debug.WriteLine($"创建子弹 {i}");
|
||||
submunitions[i] = new TerminalSensitiveSubmunition(
|
||||
Id + "_Sub_" + i,
|
||||
targetId,
|
||||
new MissileProperties
|
||||
{
|
||||
Id = $"{Id}_Sub_{i}",
|
||||
InitialPosition = Position,
|
||||
InitialOrientation = separationOrientation, // 使用新计算的分离方向
|
||||
InitialSpeed = Velocity.Magnitude(), // 子弹初始速度等于母弹速度
|
||||
{
|
||||
MaxSpeed = submunitionProperties.MaxSpeed,
|
||||
MaxFlightTime = submunitionProperties.MaxFlightTime,
|
||||
MaxFlightDistance = submunitionProperties.MaxFlightDistance,
|
||||
@ -328,9 +305,19 @@ namespace ThreatSource.Missile
|
||||
ExplosionRadius = submunitionProperties.ExplosionRadius,
|
||||
HitProbability = submunitionProperties.HitProbability,
|
||||
SelfDestructHeight = submunitionProperties.SelfDestructHeight,
|
||||
LaunchAcceleration = submunitionProperties.LaunchAcceleration,
|
||||
MaxEngineBurnTime = submunitionProperties.MaxEngineBurnTime,
|
||||
Type = submunitionProperties.Type
|
||||
},
|
||||
SimulationManager);
|
||||
},
|
||||
new InitialMotionParameters
|
||||
{
|
||||
Position = Position,
|
||||
Orientation = separationOrientation,
|
||||
InitialSpeed = Velocity.Magnitude(),
|
||||
},
|
||||
config,
|
||||
SimulationManager
|
||||
);
|
||||
|
||||
SimulationManager.RegisterEntity(submunitions[i].Id, submunitions[i]);
|
||||
Debug.WriteLine($"注册末敏弹子弹 {submunitions[i].Id}");
|
||||
|
||||
@ -74,114 +74,9 @@ namespace ThreatSource.Missile
|
||||
private SubmunitionStage currentStage;
|
||||
|
||||
/// <summary>
|
||||
/// 减速加速度,单位:米/秒²
|
||||
/// 子弹配置参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 减速阶段的减速度大小
|
||||
/// 影响速度调整的快慢
|
||||
/// </remarks>
|
||||
private const double DecelerationAcceleration = 250;
|
||||
|
||||
/// <summary>
|
||||
/// 减速阶段末速,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了减速阶段的垂直下降速度
|
||||
/// </remarks>
|
||||
private const double DecelerationEndSpeed = 50;
|
||||
|
||||
/// <summary>
|
||||
/// 开伞高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 打开降落伞的高度阈值
|
||||
/// 影响降落伞打开阶段的触发时机
|
||||
/// </remarks>
|
||||
private const double ParachuteDeploymentHeight = 400;
|
||||
/// <summary>
|
||||
/// 降落伞减速加速度,单位:米/秒²
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了降落伞减速加速度
|
||||
/// </remarks>
|
||||
private const double ParachuteDeceleration = 140;
|
||||
|
||||
/// <summary>
|
||||
/// 稳定扫描高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 开始螺旋扫描的高度阈值
|
||||
/// 影响扫描阶段的触发时机
|
||||
/// </remarks>
|
||||
private const double StableScanHeight = 200;
|
||||
|
||||
/// <summary>
|
||||
/// 垂直下降速度,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了扫描和攻击阶段的垂直下降速度
|
||||
/// </remarks>
|
||||
private const double VerticalDeclineSpeed = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 螺旋扫描旋转速度,单位:弧度/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了螺旋扫描时的旋转角速度
|
||||
/// 4转/秒 = 8π弧度/秒
|
||||
/// </remarks>
|
||||
private const double SpiralRotationSpeed = 8 * Math.PI;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描角度,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了螺旋扫描的锥角
|
||||
/// 30度 = π/6弧度
|
||||
/// </remarks>
|
||||
public const double ScanAngle = 30 * Math.PI / 180;
|
||||
|
||||
/// <summary>
|
||||
/// 目标探测距离,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 目标探测的距离阈值
|
||||
/// 影响目标探测阶段的触发时机
|
||||
/// </remarks>
|
||||
private const double TargetDetectionDistance = 150;
|
||||
|
||||
/// <summary>
|
||||
/// 自毁高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 触发自毁的高度阈值
|
||||
/// 保证子弹不会危及友方
|
||||
/// </remarks>
|
||||
private const double SelfDestructHeight = 20;
|
||||
|
||||
/// <summary>
|
||||
/// 攻击速度,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 攻击阶段的期望速度
|
||||
/// 影响末端制导的精度
|
||||
/// </remarks>
|
||||
private double AttackSpeed = 200;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经探测到目标
|
||||
/// </summary>
|
||||
private bool isTargetDetected = false;
|
||||
|
||||
/// <summary>
|
||||
/// 第一次探测到目标时记录的目标方位角
|
||||
/// </summary>
|
||||
private double? firstDetectionAngle = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置最后一次检测到目标的时间
|
||||
/// </summary>
|
||||
private double? lastDetectionTime = null;
|
||||
private readonly TerminalSensitiveSubmunitionConfig config;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置螺旋扫描的当前角度
|
||||
@ -256,11 +151,29 @@ namespace ThreatSource.Missile
|
||||
/// </remarks>
|
||||
private readonly LaserRangefinder rangefinder;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经探测到目标
|
||||
/// </summary>
|
||||
private bool isTargetDetected = false;
|
||||
|
||||
/// <summary>
|
||||
/// 第一次探测到目标时记录的目标方位角
|
||||
/// </summary>
|
||||
private double? firstDetectionAngle = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置最后一次检测到目标的时间
|
||||
/// </summary>
|
||||
private double? lastDetectionTime = null;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化末敏子弹的新实例
|
||||
/// </summary>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="properties">子弹配置参数</param>
|
||||
/// <param name="launchParams">发射参数</param>
|
||||
/// <param name="submunitionConfig">子弹性能参数配置</param>
|
||||
/// <param name="manager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
@ -269,10 +182,17 @@ namespace ThreatSource.Missile
|
||||
/// - 配置传感器参数
|
||||
/// - 设置初始状态
|
||||
/// </remarks>
|
||||
public TerminalSensitiveSubmunition(string targetId, MissileProperties properties, ISimulationManager manager)
|
||||
: base(properties, manager)
|
||||
public TerminalSensitiveSubmunition(
|
||||
string missileId,
|
||||
string targetId,
|
||||
MissileProperties properties,
|
||||
InitialMotionParameters launchParams,
|
||||
TerminalSensitiveSubmunitionConfig submunitionConfig,
|
||||
ISimulationManager manager)
|
||||
: base(missileId, properties, launchParams, manager)
|
||||
{
|
||||
TargetId = targetId;
|
||||
config = submunitionConfig;
|
||||
|
||||
// 初始化扫描方向为正北
|
||||
scanDirection = new Vector3D(0, 0, 1).Normalize();
|
||||
@ -382,13 +302,13 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
// 减速减旋,垂直速度减小
|
||||
Vector3D deceleration = - Velocity.Normalize() * DecelerationAcceleration;
|
||||
Vector3D deceleration = - Velocity.Normalize() * config.DecelerationAcceleration;
|
||||
Velocity += deceleration * deltaTime;
|
||||
|
||||
if (Velocity.Magnitude() <= DecelerationEndSpeed)
|
||||
if (Velocity.Magnitude() <= config.DecelerationEndSpeed)
|
||||
{
|
||||
//垂直速度设为减速阶段末速
|
||||
Velocity = new Vector3D(Velocity.X, -DecelerationEndSpeed, Velocity.Z);
|
||||
Velocity = new Vector3D(Velocity.X, -config.DecelerationEndSpeed, Velocity.Z);
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
}
|
||||
|
||||
@ -400,13 +320,13 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
// 检查高度是否小于等于开伞高度
|
||||
if(((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= ParachuteDeploymentHeight)
|
||||
if(((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= config.ParachuteDeploymentHeight)
|
||||
{
|
||||
// 如果是,则进入降落伞打开阶段
|
||||
currentStage = SubmunitionStage.ParachuteDeployment;
|
||||
|
||||
//垂直速度设为减速阶段末速
|
||||
Velocity = new Vector3D(Velocity.X, -DecelerationEndSpeed, Velocity.Z);
|
||||
Velocity = new Vector3D(Velocity.X, -config.DecelerationEndSpeed, Velocity.Z);
|
||||
GuidanceAcceleration = Vector3D.Zero;
|
||||
}
|
||||
}
|
||||
@ -428,24 +348,24 @@ namespace ThreatSource.Missile
|
||||
{
|
||||
// 计算当前速度与目标速度的差值
|
||||
double currentSpeed = Velocity.Magnitude();
|
||||
if (currentSpeed > VerticalDeclineSpeed)
|
||||
if (currentSpeed > config.VerticalDeclineSpeed)
|
||||
{
|
||||
// 开伞,用较大的减速度快速降低速度
|
||||
Vector3D deceleration = -Velocity.Normalize() * ParachuteDeceleration;
|
||||
Vector3D deceleration = -Velocity.Normalize() * config.ParachuteDeceleration;
|
||||
|
||||
// 更新速度
|
||||
Velocity += deceleration * deltaTime;
|
||||
|
||||
// 如果速度低于稳定扫描下降速度,直接设置为稳定扫描下降速度
|
||||
if (Velocity.Magnitude() <= VerticalDeclineSpeed)
|
||||
if (Velocity.Magnitude() <= config.VerticalDeclineSpeed)
|
||||
{
|
||||
Velocity = new Vector3D(0, -VerticalDeclineSpeed, 0);
|
||||
Velocity = new Vector3D(0, -config.VerticalDeclineSpeed, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 维持稳定的垂直下降速度
|
||||
Velocity = new Vector3D(0, -VerticalDeclineSpeed, 0);
|
||||
Velocity = new Vector3D(0, -config.VerticalDeclineSpeed, 0);
|
||||
}
|
||||
|
||||
// 清除制导加速度
|
||||
@ -458,7 +378,7 @@ namespace ThreatSource.Missile
|
||||
return;
|
||||
}
|
||||
|
||||
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= StableScanHeight)
|
||||
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= config.StableScanHeight)
|
||||
{
|
||||
currentStage = SubmunitionStage.StableScan;
|
||||
}
|
||||
@ -491,7 +411,7 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
// 更新螺旋角度(顺时针旋转,标准方位角)
|
||||
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime); // 顺时针角度增加
|
||||
spiralAngle = (spiralAngle + config.SpiralRotationSpeed * deltaTime); // 顺时针角度增加
|
||||
while (spiralAngle >= 2 * Math.PI)
|
||||
{
|
||||
spiralAngle -= 2 * Math.PI;
|
||||
@ -499,13 +419,13 @@ namespace ThreatSource.Missile
|
||||
|
||||
// 更新扫描方向(标准方位角,顺时针为正)
|
||||
scanDirection = new Vector3D(
|
||||
Math.Sin(spiralAngle) * Math.Sin(ScanAngle),
|
||||
-Math.Cos(ScanAngle),
|
||||
Math.Cos(spiralAngle) * Math.Sin(ScanAngle)
|
||||
Math.Sin(spiralAngle) * Math.Sin(config.ScanAngleInRadians),
|
||||
-Math.Cos(config.ScanAngleInRadians),
|
||||
Math.Cos(spiralAngle) * Math.Sin(config.ScanAngleInRadians)
|
||||
).Normalize();
|
||||
|
||||
// 如果距离小于等于目标探测距离,则进入目标探测阶段
|
||||
if (((RangefinderSensorData)rangefinder.GetSensorData()).Distance <= TargetDetectionDistance)
|
||||
if (((RangefinderSensorData)rangefinder.GetSensorData()).Distance <= config.TargetDetectionDistance)
|
||||
{
|
||||
currentStage = SubmunitionStage.Detection;
|
||||
}
|
||||
@ -535,7 +455,7 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
// 更新扫描角度(顺时针旋转)
|
||||
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime); // 顺时针角度增加
|
||||
spiralAngle = (spiralAngle + config.SpiralRotationSpeed * deltaTime); // 顺时针角度增加
|
||||
while (spiralAngle >= 2 * Math.PI)
|
||||
{
|
||||
spiralAngle -= 2 * Math.PI;
|
||||
@ -543,9 +463,9 @@ namespace ThreatSource.Missile
|
||||
|
||||
// 更新扫描方向
|
||||
scanDirection = new Vector3D(
|
||||
Math.Sin(spiralAngle) * Math.Sin(ScanAngle),
|
||||
-Math.Cos(ScanAngle),
|
||||
Math.Cos(spiralAngle) * Math.Sin(ScanAngle)
|
||||
Math.Sin(spiralAngle) * Math.Sin(config.ScanAngleInRadians),
|
||||
-Math.Cos(config.ScanAngleInRadians),
|
||||
Math.Cos(spiralAngle) * Math.Sin(config.ScanAngleInRadians)
|
||||
).Normalize();
|
||||
|
||||
// 检查传感器干扰状态
|
||||
@ -621,7 +541,7 @@ namespace ThreatSource.Missile
|
||||
}
|
||||
|
||||
double timeSinceLastDetection = FlightTime - lastDetectionTime.Value;
|
||||
if (timeSinceLastDetection >= 0.75 * 2 * Math.PI / SpiralRotationSpeed) // 转过3/4圈以后
|
||||
if (timeSinceLastDetection >= 0.75 * 2 * Math.PI / config.SpiralRotationSpeed) // 转过3/4圈以后
|
||||
{
|
||||
// 确保firstDetectionAngle不为null
|
||||
if (!firstDetectionAngle.HasValue)
|
||||
@ -632,7 +552,7 @@ namespace ThreatSource.Missile
|
||||
// 检查当前角度是否接近记录的目标方位角
|
||||
double angleDiff = Math.Abs(spiralAngle - firstDetectionAngle.Value);
|
||||
// 根据仿真步长和转速计算允许的角度误差
|
||||
double allowedError = deltaTime * SpiralRotationSpeed / 2;
|
||||
double allowedError = deltaTime * config.SpiralRotationSpeed / 2;
|
||||
if (angleDiff <= allowedError)
|
||||
{
|
||||
if (isRadiationDetected || isInfraredDetected)
|
||||
@ -681,13 +601,13 @@ namespace ThreatSource.Missile
|
||||
|
||||
// 使用当前的spiralAngle计算攻击方向
|
||||
scanDirection = new Vector3D(
|
||||
Math.Sin(spiralAngle) * Math.Sin(ScanAngle),
|
||||
-Math.Cos(ScanAngle),
|
||||
Math.Cos(spiralAngle) * Math.Sin(ScanAngle)
|
||||
Math.Sin(spiralAngle) * Math.Sin(config.ScanAngleInRadians),
|
||||
-Math.Cos(config.ScanAngleInRadians),
|
||||
Math.Cos(spiralAngle) * Math.Sin(config.ScanAngleInRadians)
|
||||
).Normalize();
|
||||
|
||||
// 使用 AttackSpeed 设置攻击速度
|
||||
Velocity = scanDirection * AttackSpeed;
|
||||
Velocity = scanDirection * config.AttackSpeed;
|
||||
GuidanceAcceleration = Vector3D.Zero; // 清除任何可能的加速度
|
||||
}
|
||||
|
||||
|
||||
69
ThreatSource/src/Simulation/ISimulationElement.cs
Normal file
69
ThreatSource/src/Simulation/ISimulationElement.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真元素接口,定义了所有仿真实体必须实现的基本功能
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该接口定义了仿真实体的核心功能:
|
||||
/// - 位置和运动状态管理
|
||||
/// - 生命周期管理(激活/停用)
|
||||
/// - 状态更新机制
|
||||
/// 所有参与仿真的实体都必须实现此接口
|
||||
/// </remarks>
|
||||
public interface ISimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的唯一标识符
|
||||
/// </summary>
|
||||
string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前位置
|
||||
/// </summary>
|
||||
Vector3D Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前速度向量
|
||||
/// </summary>
|
||||
Vector3D Velocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前速度大小
|
||||
/// </summary>
|
||||
double Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前朝向
|
||||
/// </summary>
|
||||
Orientation Orientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取仿真元素是否处于活动状态
|
||||
/// </summary>
|
||||
bool IsActive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新仿真元素的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
void Update(double deltaTime);
|
||||
|
||||
/// <summary>
|
||||
/// 激活仿真元素,使其参与仿真
|
||||
/// </summary>
|
||||
void Activate();
|
||||
|
||||
/// <summary>
|
||||
/// 停用仿真元素,将其从仿真中移除
|
||||
/// </summary>
|
||||
void Deactivate();
|
||||
|
||||
/// <summary>
|
||||
/// 获取仿真元素的状态信息
|
||||
/// </summary>
|
||||
/// <returns>包含实体当前状态的字符串描述</returns>
|
||||
string GetStatus();
|
||||
}
|
||||
}
|
||||
38
ThreatSource/src/Simulation/ISpectralCharacteristics.cs
Normal file
38
ThreatSource/src/Simulation/ISpectralCharacteristics.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
|
||||
namespace ThreatSource.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// 定义实体的频谱特性接口
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该接口定义了实体的频谱特征:
|
||||
/// - 雷达散射截面积
|
||||
/// - 红外辐射特性
|
||||
/// - 紫外辐射特性
|
||||
/// - 毫米波辐射特性
|
||||
/// 用于在仿真系统中表示实体的电磁特征
|
||||
/// </remarks>
|
||||
public interface ISpectralCharacteristics
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取雷达散射截面积(RCS),单位:平方米
|
||||
/// </summary>
|
||||
double RadarCrossSection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取红外辐射强度,单位:瓦特/球面度
|
||||
/// </summary>
|
||||
double InfraredRadiationIntensity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取紫外辐射强度,单位:瓦特/球面度
|
||||
/// </summary>
|
||||
double UltravioletRadiationIntensity { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取毫米波辐射强度,单位:瓦特/球面度
|
||||
/// </summary>
|
||||
double MillimeterWaveRadiationIntensity { get; }
|
||||
}
|
||||
}
|
||||
60
ThreatSource/src/Simulation/MissileLaunchParameters.cs
Normal file
60
ThreatSource/src/Simulation/MissileLaunchParameters.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化运动参数类,定义了仿真元素初始化时的运动学参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类用于:
|
||||
/// - 设置仿真元素的初始位置和姿态
|
||||
/// - 配置初始速度和目标
|
||||
/// - 提供战术场景相关的参数
|
||||
/// 这些参数在实际使用时动态设置,而不是存储在配置文件中
|
||||
/// </remarks>
|
||||
public class InitialMotionParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的初始位置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用三维向量表示发射位置
|
||||
/// 坐标系:右手坐标系,X向右,Y向上,Z向前
|
||||
/// </remarks>
|
||||
public Vector3D Position { get; set; } = new Vector3D(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的初始朝向
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用欧拉角表示初始姿态
|
||||
/// 包含偏航角、俯仰角和滚转角
|
||||
/// </remarks>
|
||||
public Orientation Orientation { get; set; } = new Orientation(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的初始速度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒
|
||||
/// 初始运动速度
|
||||
/// </remarks>
|
||||
public double InitialSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仿真元素初始化参数类的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 构造过程:
|
||||
/// - 设置默认的初始位置(原点)
|
||||
/// - 设置默认的初始朝向(零角度)
|
||||
/// - 初始化其他参数为默认值
|
||||
/// </remarks>
|
||||
public InitialMotionParameters()
|
||||
{
|
||||
Position = new Vector3D(0, 0, 0);
|
||||
Orientation = new Orientation(0, 0, 0);
|
||||
InitialSpeed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,104 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光编码配置类,用于设置激光系统的编码参数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类定义了激光编码的关键参数,支持以下工作模式:
|
||||
/// 1. 安全模式:IsCodeEnabled=true, IsCodeMatchRequired=true
|
||||
/// - 发射编码激光信号
|
||||
/// - 只接受匹配编码的信号
|
||||
/// - 最高的抗干扰能力和安全性
|
||||
/// 2. 简单模式:IsCodeEnabled=false, IsCodeMatchRequired=false
|
||||
/// - 发射普通激光信号
|
||||
/// - 接受任何激光信号
|
||||
/// - 系统简单,但抗干扰能力低
|
||||
/// 3. 混合模式:IsCodeEnabled=true, IsCodeMatchRequired=false
|
||||
/// - 发射编码激光信号
|
||||
/// - 接受任何激光信号
|
||||
/// - 提供向下兼容性
|
||||
///
|
||||
/// 注意:避免使用 IsCodeEnabled=false, IsCodeMatchRequired=true 的组合,
|
||||
/// 这种情况下接收端将无法接收到有效信号。
|
||||
/// </remarks>
|
||||
public class LaserCodeConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码信息
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含编码类型和编码值等基本信息
|
||||
/// </remarks>
|
||||
public LaserCode Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否启用编码
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示使用编码
|
||||
/// false表示不使用编码
|
||||
/// </remarks>
|
||||
public bool IsCodeEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否要求编码匹配
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示必须匹配编码
|
||||
/// false表示不要求匹配
|
||||
/// </remarks>
|
||||
public bool IsCodeMatchRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 检查当前激光编码配置是否与目标配置匹配
|
||||
/// </summary>
|
||||
/// <param name="other">要检查的目标激光编码配置</param>
|
||||
/// <returns>如果匹配返回true,否则返回false</returns>
|
||||
/// <remarks>
|
||||
/// 匹配规则:
|
||||
/// 1. 如果接收端不要求匹配(IsCodeMatchRequired=false),则始终返回true
|
||||
/// 2. 如果接收端要求匹配(IsCodeMatchRequired=true):
|
||||
/// - 发射端必须启用编码(IsCodeEnabled=true)
|
||||
/// - 编码参数必须匹配
|
||||
/// </remarks>
|
||||
public bool CheckCodeMatch(LaserCodeConfig? other)
|
||||
{
|
||||
// 如果目标配置为null,不匹配
|
||||
if (other == null)
|
||||
return false;
|
||||
|
||||
// 如果接收端不要求匹配,则始终返回true
|
||||
if (!IsCodeMatchRequired)
|
||||
return true;
|
||||
|
||||
// 如果接收端要求匹配,但发射端未启用编码,则不匹配
|
||||
if (!other.IsCodeEnabled)
|
||||
return false;
|
||||
|
||||
// 检查编码是否匹配
|
||||
return Code.Matches(other.Code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光编码配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 设置默认值:
|
||||
/// - 新的LaserCode实例
|
||||
/// - 启用编码
|
||||
/// - 要求编码匹配
|
||||
/// </remarks>
|
||||
public LaserCodeConfig()
|
||||
{
|
||||
Code = new LaserCode();
|
||||
IsCodeEnabled = true;
|
||||
IsCodeMatchRequired = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光指示器配置类,用于设置激光半主动导引系统中的激光指示器参数
|
||||
/// </summary>
|
||||
@ -15,24 +112,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class LaserDesignatorConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光指示器的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的激光指示器
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光指示器的初始位置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用三维向量表示空间位置
|
||||
/// 坐标系:右手坐标系,X向右,Y向上,Z向前
|
||||
/// </remarks>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光功率
|
||||
/// </summary>
|
||||
@ -51,6 +130,15 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public double LaserDivergenceAngle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义激光信号的编码参数
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光指示器配置的新实例
|
||||
/// </summary>
|
||||
@ -60,13 +148,13 @@ namespace ThreatSource.Simulation
|
||||
/// - 初始位置为原点(0,0,0)
|
||||
/// - 激光功率为0瓦特
|
||||
/// - 发散角为0弧度
|
||||
/// - 默认激光编码配置
|
||||
/// </remarks>
|
||||
public LaserDesignatorConfig()
|
||||
{
|
||||
Id = "";
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
LaserPower = 0;
|
||||
LaserDivergenceAngle = 0;
|
||||
LaserCodeConfig = new LaserCodeConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,24 +172,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class LaserBeamRiderConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光驾束仪的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的驾束仪
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置驾束仪的初始位置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用三维向量表示空间位置
|
||||
/// 坐标系:右手坐标系,X向右,Y向上,Z向前
|
||||
/// </remarks>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光功率
|
||||
/// </summary>
|
||||
@ -129,6 +199,15 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public double MaxGuidanceDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义激光信号的编码参数
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig LaserCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光驾束仪配置的新实例
|
||||
/// </summary>
|
||||
@ -138,13 +217,15 @@ namespace ThreatSource.Simulation
|
||||
/// - 初始位置为原点(0,0,0)
|
||||
/// - 激光功率为0瓦特
|
||||
/// - 控制场直径为0米
|
||||
/// - 最大导引距离为0米
|
||||
/// - 默认激光编码配置
|
||||
/// </remarks>
|
||||
public LaserBeamRiderConfig()
|
||||
{
|
||||
Id = "";
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
LaserPower = 0;
|
||||
ControlFieldDiameter = 0;
|
||||
MaxGuidanceDistance = 0;
|
||||
LaserCodeConfig = new LaserCodeConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,15 +242,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class LaserWarnerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光告警器的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的告警器
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置告警灵敏度阈值
|
||||
/// </summary>
|
||||
@ -218,7 +290,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public LaserWarnerConfig()
|
||||
{
|
||||
Id = "";
|
||||
SensitivityThreshold = 0;
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
WavelengthMin = 0;
|
||||
@ -239,15 +310,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class UltravioletWarnerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置紫外告警器的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的告警器
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置告警灵敏度阈值
|
||||
/// </summary>
|
||||
@ -296,7 +358,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public UltravioletWarnerConfig()
|
||||
{
|
||||
Id = "";
|
||||
SensitivityThreshold = 0;
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
WavelengthMin = 0;
|
||||
@ -317,15 +378,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class InfraredWarnerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置红外告警器的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的告警器
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置告警灵敏度阈值
|
||||
/// </summary>
|
||||
@ -374,7 +426,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public InfraredWarnerConfig()
|
||||
{
|
||||
Id = "";
|
||||
SensitivityThreshold = 0;
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
WavelengthMin = 0;
|
||||
@ -395,15 +446,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public class MillimeterWaveWarnerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置毫米波告警器的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 在仿真系统中必须唯一
|
||||
/// 用于标识和查找特定的告警器
|
||||
/// </remarks>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置告警灵敏度阈值
|
||||
/// </summary>
|
||||
@ -452,7 +494,6 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public MillimeterWaveWarnerConfig()
|
||||
{
|
||||
Id = "";
|
||||
SensitivityThreshold = 0;
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
WavelengthMin = 0;
|
||||
@ -465,11 +506,6 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public class LaserJammerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光干扰器ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大干扰冷却时间(秒)
|
||||
/// </summary>
|
||||
@ -495,7 +531,6 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public LaserJammerConfig()
|
||||
{
|
||||
Id = "";
|
||||
MaxJammingCooldown = 5.0;
|
||||
MaxJammingPower = 10000.0;
|
||||
InitialJammingPower = 4000.0;
|
||||
@ -508,21 +543,6 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public class InfraredTrackerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 红外测角仪ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始位置
|
||||
/// </summary>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始朝向
|
||||
/// </summary>
|
||||
public Orientation InitialOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大跟踪距离(米)
|
||||
/// </summary>
|
||||
@ -548,9 +568,6 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public InfraredTrackerConfig()
|
||||
{
|
||||
Id = "";
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
InitialOrientation = new Orientation(0, 0, 0);
|
||||
MaxTrackingRange = 10000; // 10公里
|
||||
FieldOfView = Math.PI / 3; // 60度
|
||||
AngleMeasurementAccuracy = 0.001; // 0.001弧度 (约0.057度)
|
||||
@ -563,11 +580,6 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public class MillimeterWaveJammerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 干扰器ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大干扰功率(瓦特)
|
||||
/// </summary>
|
||||
@ -593,11 +605,621 @@ namespace ThreatSource.Simulation
|
||||
/// </summary>
|
||||
public MillimeterWaveJammerConfig()
|
||||
{
|
||||
Id = "";
|
||||
MaxJammingPower = 1000;
|
||||
InitialJammingPower = 400;
|
||||
PowerIncreaseRate = 200;
|
||||
MaxJammingCooldown = 5;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 红外成像导引系统配置类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 存储红外成像导引系统的特定参数:
|
||||
/// - 视场角配置
|
||||
/// - 图像传感器配置
|
||||
/// - 目标识别配置
|
||||
/// - 时间参数配置
|
||||
/// </remarks>
|
||||
public class InfraredImagingGuidanceConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大探测距离(米)
|
||||
/// </summary>
|
||||
public double MaxDetectionRange { get; set; } = 1000; // 默认1公里
|
||||
|
||||
/// <summary>
|
||||
/// 搜索模式视场角,单位:弧度
|
||||
/// </summary>
|
||||
public double SearchFieldOfView { get; set; } = Math.PI / 15; // 默认12度
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪模式视场角,单位:弧度
|
||||
/// </summary>
|
||||
public double TrackFieldOfView { get; set; } = Math.PI / 60; // 默认3度
|
||||
|
||||
/// <summary>
|
||||
/// 图像宽度,单位:像素
|
||||
/// </summary>
|
||||
public int ImageWidth { get; set; } = 640;
|
||||
|
||||
/// <summary>
|
||||
/// 图像高度,单位:像素
|
||||
/// </summary>
|
||||
public int ImageHeight { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// 背景辐射强度,单位:瓦特/球面度
|
||||
/// </summary>
|
||||
public double BackgroundIntensity { get; set; } = 0.01;
|
||||
|
||||
/// <summary>
|
||||
/// 搜索模式目标识别概率阈值
|
||||
/// </summary>
|
||||
public double SearchRecognitionProbability { get; set; } = 0.6;
|
||||
|
||||
/// <summary>
|
||||
/// 跟踪模式目标识别概率阈值
|
||||
/// </summary>
|
||||
public double TrackRecognitionProbability { get; set; } = 0.8;
|
||||
|
||||
/// <summary>
|
||||
/// 目标丢失容忍时间,单位:秒
|
||||
/// </summary>
|
||||
public double TargetLostTolerance { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 锁定确认时间,单位:秒
|
||||
/// </summary>
|
||||
public double LockConfirmationTime { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化红外成像导引配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用默认参数初始化配置:
|
||||
/// - 搜索视场角:12度
|
||||
/// - 跟踪视场角:3度
|
||||
/// - 图像分辨率:640x512
|
||||
/// - 背景辐射:0.01 W/sr
|
||||
/// - 识别概率阈值:0.6/0.8
|
||||
/// - 时间参数:0.2s/0.3s
|
||||
/// </remarks>
|
||||
public InfraredImagingGuidanceConfig()
|
||||
{
|
||||
// 使用属性初始化器设置的默认值
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光半主动导引系统配置类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类定义了激光半主动导引系统的关键参数:
|
||||
/// - 光学系统参数(视场角、镜头直径等)
|
||||
/// - 目标特性参数(反射系数、有效反射面积)
|
||||
/// - 系统性能参数(锁定阈值、灵敏度)
|
||||
/// 这些参数决定了导引系统的探测能力和跟踪性能
|
||||
/// </remarks>
|
||||
public class LaserSemiActiveGuidanceConfig
|
||||
{
|
||||
private double fieldOfViewAngle = 30.0;
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了探测器的视场范围
|
||||
/// 默认值为30度
|
||||
/// 影响系统的探测能力
|
||||
/// </remarks>
|
||||
public double FieldOfViewAngle
|
||||
{
|
||||
get => fieldOfViewAngle;
|
||||
set => fieldOfViewAngle = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将度数转换为弧度供内部计算使用
|
||||
/// </remarks>
|
||||
public double FieldOfViewAngleInRadians => fieldOfViewAngle * Math.PI / 180.0;
|
||||
|
||||
/// <summary>
|
||||
/// 镜头直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了光学系统镜头的物理尺寸
|
||||
/// 影响系统的光能量收集能力
|
||||
/// 默认值为0.1米
|
||||
/// </remarks>
|
||||
public double LensDiameter { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 传感器直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了四象限探测器的物理尺寸
|
||||
/// 影响系统的探测精度
|
||||
/// 默认值为0.03米
|
||||
/// </remarks>
|
||||
public double SensorDiameter { get; set; } = 0.03;
|
||||
|
||||
/// <summary>
|
||||
/// 聚焦后光斑直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了光学系统聚焦后的光斑大小
|
||||
/// 影响系统的探测灵敏度
|
||||
/// 默认值为0.006米
|
||||
/// </remarks>
|
||||
public double FocusedSpotDiameter { get; set; } = 0.006;
|
||||
|
||||
/// <summary>
|
||||
/// 目标反射系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标表面的激光反射能力
|
||||
/// 影响反射信号强度
|
||||
/// 默认值为0.2
|
||||
/// </remarks>
|
||||
public double ReflectionCoefficient { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 目标有效反射面积,单位:平方米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标的等效反射面积
|
||||
/// 影响反射信号强度
|
||||
/// 默认值为1.0平方米
|
||||
/// </remarks>
|
||||
public double TargetReflectiveArea { get; set; } = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// 锁定阈值,单位:瓦特
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了系统锁定目标的最小功率要求
|
||||
/// 低于此值时认为无法有效跟踪目标
|
||||
/// 默认值为1e-12瓦特
|
||||
/// </remarks>
|
||||
public double LockThreshold { get; set; } = 1e-12;
|
||||
|
||||
/// <summary>
|
||||
/// 光斑偏移灵敏度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了四象限探测器对光斑偏移的响应灵敏度
|
||||
/// 影响制导系统的响应速度和稳定性
|
||||
/// 默认值为0.5
|
||||
/// </remarks>
|
||||
public double SpotOffsetSensitivity { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光半主动导引配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用属性初始化器设置的默认值:
|
||||
/// - 视场角:30度
|
||||
/// - 镜头直径:0.1米
|
||||
/// - 传感器直径:0.03米
|
||||
/// - 光斑直径:0.006米
|
||||
/// - 反射系数:0.2
|
||||
/// - 反射面积:1.0平方米
|
||||
/// - 锁定阈值:1e-12瓦特
|
||||
/// - 灵敏度:0.5
|
||||
/// </remarks>
|
||||
public LaserSemiActiveGuidanceConfig()
|
||||
{
|
||||
// 使用属性初始化器设置的默认值
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 末敏弹子弹药分离参数配置类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类定义了末敏弹在末端阶段的子弹药分离和性能参数:
|
||||
/// - 分离参数(高度、距离、角度等)
|
||||
/// - 减速阶段参数(加速度、末速度)
|
||||
/// - 降落伞阶段参数(开伞高度、减速度)
|
||||
/// - 扫描阶段参数(扫描高度、下降速度、扫描角度)
|
||||
/// - 探测阶段参数(探测距离、自毁高度、攻击速度)
|
||||
/// 这些参数决定了子弹药的整体性能和打击效果
|
||||
/// </remarks>
|
||||
public class TerminalSensitiveSubmunitionConfig
|
||||
{
|
||||
#region 分离参数
|
||||
/// <summary>
|
||||
/// 子弹药分离的高度阈值,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当导弹上升到此高度时会触发分离
|
||||
/// 影响分离时机的选择
|
||||
/// 默认值为1000米
|
||||
/// </remarks>
|
||||
public double SeparationHeight { get; set; } = 1000.0;
|
||||
|
||||
/// <summary>
|
||||
/// 分离点与目标的水平距离,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 分离点在目标上方的水平投影距离
|
||||
/// 影响分离位置的选择
|
||||
/// 默认值为1000米
|
||||
/// </remarks>
|
||||
public double SeparationDistance { get; set; } = 1000.0;
|
||||
|
||||
/// <summary>
|
||||
/// 子弹药分离角度(与地面的夹角),单位:度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 子弹药从母弹分离时与地面的夹角
|
||||
/// 影响子弹药的初始飞行轨迹
|
||||
/// 默认值为45度
|
||||
/// </remarks>
|
||||
public double SubmunitionSeparationAngle { get; set; } = 45.0;
|
||||
|
||||
/// <summary>
|
||||
/// 触发分离的距离阈值,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 当导弹距离分离点小于此距离时触发分离
|
||||
/// 注意:此值必须大于导弹速度乘以时间步长的一半
|
||||
/// 默认值为50米
|
||||
/// </remarks>
|
||||
public double SeparationRange { get; set; } = 50.0;
|
||||
#endregion
|
||||
|
||||
#region 减速阶段参数
|
||||
/// <summary>
|
||||
/// 减速阶段的减速加速度,单位:米/秒²
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了减速阶段的减速度大小
|
||||
/// 影响速度调整的快慢
|
||||
/// 默认值为250米/秒²
|
||||
/// </remarks>
|
||||
public double DecelerationAcceleration { get; set; } = 250.0;
|
||||
|
||||
/// <summary>
|
||||
/// 减速阶段末速度,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了减速阶段的垂直下降速度
|
||||
/// 默认值为50米/秒
|
||||
/// </remarks>
|
||||
public double DecelerationEndSpeed { get; set; } = 50.0;
|
||||
#endregion
|
||||
|
||||
#region 降落伞阶段参数
|
||||
/// <summary>
|
||||
/// 降落伞打开高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 打开降落伞的高度阈值
|
||||
/// 影响降落伞打开阶段的触发时机
|
||||
/// 默认值为400米
|
||||
/// </remarks>
|
||||
public double ParachuteDeploymentHeight { get; set; } = 400.0;
|
||||
|
||||
/// <summary>
|
||||
/// 降落伞减速加速度,单位:米/秒²
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了降落伞减速加速度
|
||||
/// 默认值为140米/秒²
|
||||
/// </remarks>
|
||||
public double ParachuteDeceleration { get; set; } = 140.0;
|
||||
#endregion
|
||||
|
||||
#region 扫描阶段参数
|
||||
/// <summary>
|
||||
/// 稳定扫描高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 开始螺旋扫描的高度阈值
|
||||
/// 影响扫描阶段的触发时机
|
||||
/// 默认值为200米
|
||||
/// </remarks>
|
||||
public double StableScanHeight { get; set; } = 200.0;
|
||||
|
||||
/// <summary>
|
||||
/// 垂直下降速度,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了扫描和攻击阶段的垂直下降速度
|
||||
/// 默认值为10米/秒
|
||||
/// </remarks>
|
||||
public double VerticalDeclineSpeed { get; set; } = 10.0;
|
||||
|
||||
/// <summary>
|
||||
/// 螺旋扫描旋转速度,单位:弧度/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了螺旋扫描时的旋转角速度
|
||||
/// 4转/秒 = 8π弧度/秒
|
||||
/// 默认值为25.13弧度/秒
|
||||
/// </remarks>
|
||||
public double SpiralRotationSpeed { get; set; } = 8.0 * Math.PI;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描角度,单位:度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了螺旋扫描的锥角
|
||||
/// 默认值为30度
|
||||
/// </remarks>
|
||||
public double ScanAngle { get; set; } = 30.0;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描角度,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将度数转换为弧度供内部计算使用
|
||||
/// </remarks>
|
||||
public double ScanAngleInRadians => ScanAngle * Math.PI / 180.0;
|
||||
#endregion
|
||||
|
||||
#region 探测和攻击阶段参数
|
||||
/// <summary>
|
||||
/// 目标探测距离,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 目标探测的距离阈值
|
||||
/// 影响目标探测阶段的触发时机
|
||||
/// 默认值为150米
|
||||
/// </remarks>
|
||||
public double TargetDetectionDistance { get; set; } = 150.0;
|
||||
|
||||
/// <summary>
|
||||
/// 自毁高度,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 触发自毁的高度阈值
|
||||
/// 保证子弹不会危及友方
|
||||
/// 默认值为20米
|
||||
/// </remarks>
|
||||
public double SelfDestructHeight { get; set; } = 20.0;
|
||||
|
||||
/// <summary>
|
||||
/// 攻击速度,单位:米/秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 攻击阶段的期望速度
|
||||
/// 影响末端制导的精度
|
||||
/// 默认值为2000米/秒
|
||||
/// </remarks>
|
||||
public double AttackSpeed { get; set; } = 2000.0;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 初始化末敏弹子弹药分离参数配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用属性初始化器设置所有默认值:
|
||||
/// - 分离参数:高度1000米,距离1000米,角度45度,触发距离50米
|
||||
/// - 减速参数:加速度250米/秒²,末速度50米/秒
|
||||
/// - 降落伞参数:开伞高度400米,减速度140米/秒²
|
||||
/// - 扫描参数:高度200米,下降速度10米/秒,旋转速度8π弧度/秒,扫描角30度
|
||||
/// - 探测参数:探测距离150米,自毁高度20米,攻击速度200米/秒
|
||||
/// </remarks>
|
||||
public TerminalSensitiveSubmunitionConfig()
|
||||
{
|
||||
// 使用属性初始化器设置的默认值
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光驾束制导系统配置类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类定义了激光驾束制导系统的性能参数:
|
||||
/// - 探测器参数(最小可探测功率、探测器直径)
|
||||
/// - 控制参数(控制场直径、PID参数)
|
||||
/// - 制导参数(最大加速度、非线性增益)
|
||||
/// - 滤波参数(低通滤波系数)
|
||||
/// </remarks>
|
||||
public class LaserBeamRiderGuidanceSystemConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 最小可探测功率,单位:瓦特
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了探测器的灵敏度阈值
|
||||
/// 低于此值时无法有效探测
|
||||
/// </remarks>
|
||||
public double MinDetectablePower { get; set; } = 1e-3;
|
||||
|
||||
/// <summary>
|
||||
/// 探测器直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了探测器的物理尺寸
|
||||
/// 影响系统的接收能力
|
||||
/// </remarks>
|
||||
public double DetectorDiameter { get; set; } = 0.1;
|
||||
|
||||
/// <summary>
|
||||
/// 控制场直径,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了有效制导范围
|
||||
/// 超出此范围将失去制导
|
||||
/// </remarks>
|
||||
public double ControlFieldDiameter { get; set; } = 20.0;
|
||||
|
||||
/// <summary>
|
||||
/// PID控制器比例系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 控制系统对误差的即时响应
|
||||
/// 值越大,响应越快
|
||||
/// </remarks>
|
||||
public double ProportionalGain { get; set; } = 30.0;
|
||||
|
||||
/// <summary>
|
||||
/// PID控制器积分系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于消除稳态误差
|
||||
/// 值越大,稳态误差消除越快
|
||||
/// </remarks>
|
||||
public double IntegralGain { get; set; } = 0.05;
|
||||
|
||||
/// <summary>
|
||||
/// PID控制器微分系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于抑制超调和振荡
|
||||
/// 值越大,系统越稳定
|
||||
/// </remarks>
|
||||
public double DerivativeGain { get; set; } = 5.0;
|
||||
|
||||
/// <summary>
|
||||
/// 非线性增益系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 控制制导系统的非线性特性
|
||||
/// 影响系统对不同大小误差的响应
|
||||
/// </remarks>
|
||||
public double NonlinearGain { get; set; } = 0.5;
|
||||
|
||||
/// <summary>
|
||||
/// 最大制导加速度,单位:米/平方秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 限制制导系统输出的最大加速度
|
||||
/// 防止过大的机动指令
|
||||
/// </remarks>
|
||||
public double MaxGuidanceAcceleration { get; set; } = 50.0;
|
||||
|
||||
/// <summary>
|
||||
/// 低通滤波系数
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于平滑制导指令
|
||||
/// 值越小,滤波效果越强
|
||||
/// </remarks>
|
||||
public double LowPassFilterCoefficient { get; set; } = 0.2;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化激光驾束制导系统配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用属性初始化器设置的默认值:
|
||||
/// - 最小可探测功率:1mW
|
||||
/// - 探测器直径:0.1米
|
||||
/// - 控制场直径:20米
|
||||
/// - PID参数:Kp=30, Ki=0.05, Kd=5
|
||||
/// - 非线性增益:0.5
|
||||
/// - 最大加速度:50 m/s²
|
||||
/// - 滤波系数:0.2
|
||||
/// </remarks>
|
||||
public LaserBeamRiderGuidanceSystemConfig()
|
||||
{
|
||||
// 使用属性初始化器设置的默认值
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 毫米波末制导导引系统配置类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类定义了毫米波末制导导引系统的关键参数:
|
||||
/// - 探测参数(最大探测距离、视场角)
|
||||
/// - 雷达参数(工作频率、脉冲持续时间)
|
||||
/// - 目标识别参数(识别概率、信噪比阈值)
|
||||
/// 这些参数决定了导引系统的探测和跟踪性能
|
||||
/// </remarks>
|
||||
public class MillimeterWaveGuidanceConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大探测范围,单位:米
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了毫米波雷达的最大作用距离
|
||||
/// 超出此范围的目标无法有效探测
|
||||
/// 典型值为5000米
|
||||
/// </remarks>
|
||||
public double MaxDetectionRange { get; set; } = 5000.0;
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达的扫描范围
|
||||
/// 默认设置为45度
|
||||
/// 影响系统的搜索能力
|
||||
/// </remarks>
|
||||
public double FieldOfViewAngle { get; set; } = 45.0;
|
||||
|
||||
/// <summary>
|
||||
/// 视场角,单位:弧度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 将度数转换为弧度供内部计算使用
|
||||
/// </remarks>
|
||||
public double FieldOfViewAngleInRadians => FieldOfViewAngle * Math.PI / 180.0;
|
||||
|
||||
/// <summary>
|
||||
/// 目标识别概率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的成功率
|
||||
/// 影响系统的可靠性
|
||||
/// 典型值为0.95
|
||||
/// </remarks>
|
||||
public double TargetRecognitionProbability { get; set; } = 0.95;
|
||||
|
||||
/// <summary>
|
||||
/// 毫米波频率,单位:赫兹
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达工作频率
|
||||
/// 设置为94GHz
|
||||
/// 影响探测性能和抗干扰能力
|
||||
/// </remarks>
|
||||
public double WaveFrequency { get; set; } = 94e9;
|
||||
|
||||
/// <summary>
|
||||
/// 脉冲持续时间,单位:秒
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了雷达发射脉冲的时长
|
||||
/// 影响距离分辨率
|
||||
/// 典型值为1微秒
|
||||
/// </remarks>
|
||||
public double PulseDuration { get; set; } = 1e-6;
|
||||
|
||||
/// <summary>
|
||||
/// 识别目标的信噪比阈值,单位:分贝
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了目标识别的最小信噪比要求
|
||||
/// 大于此值时认为目标有效
|
||||
/// 典型值为6dB
|
||||
/// </remarks>
|
||||
public double RecognitionSNRThreshold { get; set; } = 6.0;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化毫米波末制导导引系统配置的新实例
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用属性初始化器设置的默认值:
|
||||
/// - 最大探测范围:5000米
|
||||
/// - 视场角:45度
|
||||
/// - 目标识别概率:0.95
|
||||
/// - 工作频率:94GHz
|
||||
/// - 脉冲持续时间:1微秒
|
||||
/// - 信噪比阈值:6dB
|
||||
/// </remarks>
|
||||
public MillimeterWaveGuidanceConfig()
|
||||
{
|
||||
// 使用属性初始化器设置的默认值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,58 +8,29 @@ namespace ThreatSource.Simulation
|
||||
/// 仿真元素的抽象基类,所有仿真中的实体都继承自此类
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供了仿真实体的基本功能:
|
||||
/// 该类提供了仿真实体的基本功能的默认实现:
|
||||
/// - 位置和运动状态管理
|
||||
/// - 生命周期管理(激活/停用)
|
||||
/// - 事件发布机制
|
||||
/// - 状态更新机制
|
||||
/// - 频谱特性管理
|
||||
/// 所有具体的仿真实体(如导弹、目标等)都应继承此类并实现其抽象方法。
|
||||
/// </remarks>
|
||||
public abstract class SimulationElement
|
||||
public abstract class SimulationElement : ISimulationElement, ISpectralCharacteristics
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的唯一标识符
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ID在仿真系统中必须唯一,用于标识和查找实体
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前位置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用三维向量表示实体在空间中的位置
|
||||
/// 坐标系:右手坐标系,X向右,Y向上,Z向前
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual Vector3D Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前速度大小
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒
|
||||
/// 此属性仅表示速度的标量值,方向信息需要结合Velocity属性
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual double Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前速度向量
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米/秒
|
||||
/// 包含速度的大小和方向信息
|
||||
/// 向量的模等于Speed属性值
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual Vector3D Velocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置仿真元素的当前朝向
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 使用欧拉角表示实体的朝向
|
||||
/// 包含偏航角、俯仰角和滚转角
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual Orientation Orientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -94,13 +65,7 @@ namespace ThreatSource.Simulation
|
||||
/// </remarks>
|
||||
public double MillimeterWaveRadiationIntensity { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取仿真元素是否处于活动状态
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示实体当前处于活动状态,可以参与仿真
|
||||
/// false表示实体已停用,不再参与仿真计算
|
||||
/// </remarks>
|
||||
/// <inheritdoc/>
|
||||
public virtual bool IsActive { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
@ -210,7 +175,6 @@ namespace ThreatSource.Simulation
|
||||
public virtual void Activate()
|
||||
{
|
||||
IsActive = true;
|
||||
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -225,7 +189,6 @@ namespace ThreatSource.Simulation
|
||||
public virtual void Deactivate()
|
||||
{
|
||||
IsActive = false;
|
||||
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,16 +83,7 @@ namespace ThreatSource.Simulation
|
||||
/// 包含激光信号的编码类型和编码值
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCode? LaserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否启用编码
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示激光信号使用编码
|
||||
/// false表示激光信号不使用编码
|
||||
/// </remarks>
|
||||
public bool IsCodeEnabled { get; set; }
|
||||
public LaserCodeConfig? LaserCodeConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -127,16 +118,7 @@ namespace ThreatSource.Simulation
|
||||
/// 包含激光信号的编码类型和编码值
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCode? LaserCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否启用编码
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// true表示激光信号使用编码
|
||||
/// false表示激光信号不使用编码
|
||||
/// </remarks>
|
||||
public bool IsCodeEnabled { get; set; }
|
||||
public LaserCodeConfig? LaserCodeConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -241,83 +223,90 @@ namespace ThreatSource.Simulation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体激活事件,表示仿真实体被激活
|
||||
/// 激光波束开始事件,表示激光驾束仪开始发射激光波束
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于通知系统某个实体已进入活动状态
|
||||
/// 触发时机:实体被创建或重新激活时
|
||||
/// </remarks>
|
||||
public class EntityActivatedEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置被激活实体的ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 标识已被激活的实体
|
||||
/// </remarks>
|
||||
public string? ActivatedEntityId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体停用事件,表示仿真实体被停用
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于通知系统某个实体已停止活动
|
||||
/// 触发时机:实体被停用或暂时移除时
|
||||
/// </remarks>
|
||||
public class EntityDeactivatedEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置被停用实体的ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 标识已被停用的实体
|
||||
/// </remarks>
|
||||
public string? DeactivatedEntityId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光波束开始事件,表示激光波束制导开始
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于激光波束制导系统
|
||||
/// 触发时机:开始发射制导激光波束时
|
||||
/// 用于通知系统激光波束开始照射
|
||||
/// 触发时机:激光驾束仪开始工作时
|
||||
/// </remarks>
|
||||
public class LaserBeamStartEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光波束制导器的ID
|
||||
/// 获取或设置激光驾束仪的ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 标识发出激光波束的驾束仪设备
|
||||
/// </remarks>
|
||||
public string? LaserBeamRiderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置波束功率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 激光波束的发射功率
|
||||
/// </remarks>
|
||||
public double BeamPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含激光信号的编码信息
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig? LaserCodeConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光波束更新事件,表示激光波束位置更新
|
||||
/// 激光波束更新事件,表示激光波束状态的更新
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于实时更新激光波束的位置和方向
|
||||
/// 在制导过程中周期性触发
|
||||
/// 用于实时更新激光波束的状态
|
||||
/// 在波束照射过程中周期性触发
|
||||
/// </remarks>
|
||||
public class LaserBeamUpdateEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光波束制导器的ID
|
||||
/// 获取或设置激光驾束仪的ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 标识发出激光波束的驾束仪设备
|
||||
/// </remarks>
|
||||
public string? LaserBeamRiderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置波束功率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 激光波束的发射功率
|
||||
/// </remarks>
|
||||
public double BeamPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置激光编码配置
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 包含激光信号的编码信息
|
||||
/// 用于抗干扰和安全识别
|
||||
/// </remarks>
|
||||
public LaserCodeConfig? LaserCodeConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光波束停止事件,表示激光波束制导结束
|
||||
/// 激光波束停止事件,表示激光驾束仪停止发射激光波束
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 用于通知系统激光波束制导已结束
|
||||
/// 触发时机:停止发射制导激光波束时
|
||||
/// 用于通知系统激光波束已停止
|
||||
/// 触发时机:激光驾束仪停止工作或波束中断时
|
||||
/// </remarks>
|
||||
public class LaserBeamStopEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置激光波束制导器的ID
|
||||
/// 获取或设置激光驾束仪的ID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 标识停止发射的驾束仪设备
|
||||
/// </remarks>
|
||||
public string? LaserBeamRiderId { get; set; }
|
||||
}
|
||||
|
||||
@ -627,7 +616,7 @@ namespace ThreatSource.Simulation
|
||||
/// <remarks>
|
||||
/// 包含成功匹配的编码信息
|
||||
/// </remarks>
|
||||
public LaserCode? MatchedCode { get; set; }
|
||||
public LaserCodeConfig? MatchedCodeConfig { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -661,7 +650,7 @@ namespace ThreatSource.Simulation
|
||||
/// <remarks>
|
||||
/// 导弹期望接收的编码信息
|
||||
/// </remarks>
|
||||
public LaserCode? ExpectedCode { get; set; }
|
||||
public LaserCodeConfig? ExpectedCodeConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置接收到的激光编码
|
||||
@ -669,6 +658,6 @@ namespace ThreatSource.Simulation
|
||||
/// <remarks>
|
||||
/// 导弹实际接收到的编码信息
|
||||
/// </remarks>
|
||||
public LaserCode? ReceivedCode { get; set; }
|
||||
public LaserCodeConfig? ReceivedCodeConfig { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ namespace ThreatSource.Simulation
|
||||
{
|
||||
double distance = Vector3D.Distance(missile.Position, target.Position);
|
||||
Console.WriteLine($"导弹 {missile.Id} 和目标 {target.Id} 之间的距离: {distance}");
|
||||
if (distance <= missile.MissileProperties.ExplosionRadius)
|
||||
if (distance <= missile.Properties.ExplosionRadius)
|
||||
{
|
||||
double damage = CalculateMissileDamage(missile);
|
||||
hitEvents.Add((target, missile, damage));
|
||||
@ -244,8 +244,7 @@ namespace ThreatSource.Simulation
|
||||
{
|
||||
if (evt == null)
|
||||
{
|
||||
Debug.WriteLine("[事件] 错误: 事件对象为空");
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(evt), "事件对象不能为空");
|
||||
}
|
||||
|
||||
var eventType = typeof(T);
|
||||
|
||||
@ -1,165 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Simulation.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于测试的仿真环境适配器
|
||||
/// </summary>
|
||||
public class TestSimulationAdapter : ISimulationAdapter
|
||||
{
|
||||
private readonly Dictionary<string, object> _testEntities = [];
|
||||
private readonly List<object> _receivedEvents = [];
|
||||
private readonly List<object> _publishedEvents = [];
|
||||
private ISimulationManager? _simulationManager;
|
||||
// 存储实体状态的字典
|
||||
private Dictionary<string, object> entityStates = new();
|
||||
// 存储环境数据的字典
|
||||
private Dictionary<string, SimulationEnvironmentData> environmentData = new();
|
||||
// 当前仿真时间
|
||||
private double currentTime = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,初始化测试适配器
|
||||
/// </summary>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public TestSimulationAdapter(ISimulationManager simulationManager)
|
||||
{
|
||||
_simulationManager = simulationManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体
|
||||
/// </summary>
|
||||
/// <param name="id">实体ID</param>
|
||||
/// <returns>实体对象或null</returns>
|
||||
public object? GetEntity(string id)
|
||||
{
|
||||
return _testEntities.TryGetValue(id, out var entity) ? entity : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布事件到外部仿真
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="evt">事件对象</param>
|
||||
public void PublishToExternalSimulation<T>(T evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
_publishedEvents.Add(evt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收来自外部仿真的事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <param name="evt">事件对象</param>
|
||||
public void ReceiveFromExternalSimulation<T>(T evt)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(evt);
|
||||
_receivedEvents.Add(evt);
|
||||
_simulationManager?.PublishEvent(evt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加测试实体
|
||||
/// </summary>
|
||||
/// <param name="id">实体ID</param>
|
||||
/// <param name="entity">实体对象</param>
|
||||
public void AddTestEntity(string id, object entity)
|
||||
{
|
||||
_testEntities[id] = entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除测试实体
|
||||
/// </summary>
|
||||
public void ClearTestEntities()
|
||||
{
|
||||
_testEntities.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已发布的事件
|
||||
/// </summary>
|
||||
/// <returns>已发布的事件列表</returns>
|
||||
public IReadOnlyList<object> GetPublishedEvents()
|
||||
{
|
||||
return _publishedEvents;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的已发布事件
|
||||
/// </summary>
|
||||
/// <typeparam name="T">事件类型</typeparam>
|
||||
/// <returns>指定类型的已发布事件列表</returns>
|
||||
public List<T> GetPublishedEvents<T>() where T : SimulationEvent
|
||||
{
|
||||
return _publishedEvents.OfType<T>().ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取已接收的事件
|
||||
/// </summary>
|
||||
/// <returns>已接收的事件列表</returns>
|
||||
public IReadOnlyList<object> GetReceivedEvents()
|
||||
{
|
||||
return _receivedEvents;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除事件
|
||||
/// </summary>
|
||||
public void ClearEvents()
|
||||
{
|
||||
_publishedEvents.Clear();
|
||||
_receivedEvents.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取实体状态
|
||||
/// </summary>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
public object? 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
54
ThreatSource/src/Target/APC.cs
Normal file
54
ThreatSource/src/Target/APC.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 装甲运输车类,继承自BaseTarget的具体装甲车目标
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供了装甲运输车目标的具体实现:
|
||||
/// - 继承自BaseTarget,获得基本的目标功能
|
||||
/// - 实现装甲运输车特有的属性和行为
|
||||
/// </remarks>
|
||||
public class APC : BaseTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取装甲运输车的类型标识
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 固定返回 TargetType.APC,用于标识这是一个装甲运输车目标
|
||||
/// </remarks>
|
||||
public override TargetType Type => TargetType.APC;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化装甲运输车类的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">装甲运输车的唯一标识符</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造函数设置装甲运输车的初始状态:
|
||||
/// - 调用基类构造函数初始化基本属性
|
||||
/// </remarks>
|
||||
public APC(string id, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters, simulationManager)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新装甲运输车的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 更新过程:
|
||||
/// - 调用基类的更新方法更新基本状态
|
||||
/// - 可以在此添加装甲运输车特有的更新逻辑
|
||||
/// </remarks>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
// TODO: 添加装甲运输车特有的更新逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
193
ThreatSource/src/Target/BaseTarget.cs
Normal file
193
ThreatSource/src/Target/BaseTarget.cs
Normal file
@ -0,0 +1,193 @@
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标基类,实现了目标的通用功能
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供了目标的基本实现:
|
||||
/// - 继承自SimulationElement,具备基本的仿真功能
|
||||
/// - 实现ITarget接口,提供目标特征
|
||||
/// - 包含生命值系统,可以响应伤害
|
||||
/// - 支持位置更新和状态同步
|
||||
/// </remarks>
|
||||
public abstract class BaseTarget : SimulationElement, ITarget
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取目标的类型标识
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 由子类实现,返回具体的目标类型
|
||||
/// </remarks>
|
||||
public abstract TargetType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的毫米波辐射温度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:开尔文
|
||||
/// 表示目标的毫米波辐射特征
|
||||
/// 典型值:350-450K
|
||||
/// </remarks>
|
||||
public double MillimeterWaveRadiationTemperature { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的激光反射率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 无量纲,取值范围:0-1
|
||||
/// 表示目标表面对激光的反射特性
|
||||
/// </remarks>
|
||||
public double LaserReflectivity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的当前生命值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 范围:0-100
|
||||
/// 初始值为100
|
||||
/// 当生命值降至0或以下时,目标被销毁
|
||||
/// </remarks>
|
||||
public double Health { get; set; } = 100.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的长度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// </remarks>
|
||||
public double Length { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的宽度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// </remarks>
|
||||
public double Width { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的高度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// </remarks>
|
||||
public double Height { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的温度分布模式
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 3x3矩阵,表示目标侧视图的温度分布
|
||||
/// </remarks>
|
||||
protected ThermalPattern ThermalPattern { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化目标基类的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">目标的唯一标识符</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造函数设置目标的初始状态:
|
||||
/// - 使用默认朝向
|
||||
/// - 设置初始位置和速度
|
||||
/// - 生命值初始化为100
|
||||
/// </remarks>
|
||||
protected BaseTarget(string id, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters.Position, initialMotionParameters.Orientation, initialMotionParameters.InitialSpeed, simulationManager)
|
||||
{
|
||||
Health = 100.0;
|
||||
// 初始化一个空的温度分布模式
|
||||
ThermalPattern = new ThermalPattern(new double[3, 3], new double[3, 3]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置目标的物理尺寸
|
||||
/// </summary>
|
||||
/// <param name="length">长度(米)</param>
|
||||
/// <param name="width">宽度(米)</param>
|
||||
/// <param name="height">高度(米)</param>
|
||||
public void SetDimensions(double length, double width, double height)
|
||||
{
|
||||
Length = length;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置目标的频谱特征
|
||||
/// </summary>
|
||||
/// <param name="radarCrossSection">雷达散射截面积(平方米)</param>
|
||||
/// <param name="infraredRadiationIntensity">红外辐射强度(瓦特/球面度)</param>
|
||||
/// <param name="ultravioletRadiationIntensity">紫外辐射强度(瓦特/球面度)</param>
|
||||
/// <param name="millimeterWaveRadiationIntensity">毫米波辐射强度(瓦特/球面度)</param>
|
||||
public void SetSpectralCharacteristics(
|
||||
double radarCrossSection,
|
||||
double infraredRadiationIntensity,
|
||||
double ultravioletRadiationIntensity,
|
||||
double millimeterWaveRadiationIntensity)
|
||||
{
|
||||
RadarCrossSection = radarCrossSection;
|
||||
InfraredRadiationIntensity = infraredRadiationIntensity;
|
||||
UltravioletRadiationIntensity = ultravioletRadiationIntensity;
|
||||
MillimeterWaveRadiationIntensity = millimeterWaveRadiationIntensity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置目标的温度分布模式
|
||||
/// </summary>
|
||||
/// <param name="thermalPattern">温度分布模式对象</param>
|
||||
public void SetThermalPattern(ThermalPattern thermalPattern)
|
||||
{
|
||||
ThermalPattern = thermalPattern ?? throw new ArgumentNullException(nameof(thermalPattern));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前的温度分布矩阵
|
||||
/// </summary>
|
||||
/// <returns>当前状态下的温度分布矩阵</returns>
|
||||
public double[,] GetCurrentThermalPattern()
|
||||
{
|
||||
// 根据当前速度判断是否在运动
|
||||
bool isMoving = Velocity.Magnitude() > 0.1; // 速度大于0.1米/秒认为在运动
|
||||
return ThermalPattern.GetPattern(isMoving);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新目标的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 更新过程:
|
||||
/// - 根据当前速度更新位置
|
||||
/// - 位置更新使用简单的线性运动模型
|
||||
/// </remarks>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
// 更新目标的位置
|
||||
Position += Velocity * deltaTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对目标造成伤害
|
||||
/// </summary>
|
||||
/// <param name="damage">伤害值</param>
|
||||
/// <remarks>
|
||||
/// 伤害处理过程:
|
||||
/// - 从当前生命值中扣除伤害值
|
||||
/// - 如果生命值降至0或以下,触发目标销毁事件
|
||||
/// - 销毁事件会通知仿真系统移除该目标
|
||||
/// </remarks>
|
||||
public void TakeDamage(double damage)
|
||||
{
|
||||
Health -= damage;
|
||||
if (Health <= 0)
|
||||
{
|
||||
SimulationManager.PublishEvent(new TargetDestroyedEvent { TargetId = Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
54
ThreatSource/src/Target/Helicopter.cs
Normal file
54
ThreatSource/src/Target/Helicopter.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using ThreatSource.Simulation;
|
||||
using ThreatSource.Utils;
|
||||
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 直升机类,继承自BaseTarget的具体直升机目标
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供了直升机目标的具体实现:
|
||||
/// - 继承自BaseTarget,获得基本的目标功能
|
||||
/// - 实现直升机特有的属性和行为
|
||||
/// </remarks>
|
||||
public class Helicopter : BaseTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取直升机的类型标识
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 固定返回 TargetType.Helicopter,用于标识这是一个直升机目标
|
||||
/// </remarks>
|
||||
public override TargetType Type => TargetType.Helicopter;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化直升机类的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">直升机的唯一标识符</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造函数设置直升机的初始状态:
|
||||
/// - 调用基类构造函数初始化基本属性
|
||||
/// </remarks>
|
||||
public Helicopter(string id, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters, simulationManager)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新直升机的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 更新过程:
|
||||
/// - 调用基类的更新方法更新基本状态
|
||||
/// - 可以在此添加直升机特有的更新逻辑
|
||||
/// </remarks>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
// TODO: 添加直升机特有的更新逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,52 @@
|
||||
using ThreatSource.Utils;
|
||||
using ThreatSource.Simulation;
|
||||
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标类型枚举
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 定义了系统支持的目标类型:
|
||||
/// - 坦克
|
||||
/// - 装甲车
|
||||
/// - 直升机
|
||||
/// 用于目标识别和分类
|
||||
/// </remarks>
|
||||
public enum TargetType
|
||||
{
|
||||
/// <summary>
|
||||
/// 未知类型
|
||||
/// </summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>
|
||||
/// 坦克
|
||||
/// </summary>
|
||||
Tank,
|
||||
|
||||
/// <summary>
|
||||
/// 装甲运输车
|
||||
/// </summary>
|
||||
APC,
|
||||
|
||||
/// <summary>
|
||||
/// 直升机
|
||||
/// </summary>
|
||||
Helicopter
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定义目标对象的基本接口,提供目标的基本特征和属性
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该接口定义了目标的关键特征:
|
||||
/// - 目标类型标识
|
||||
/// - 雷达散射截面积
|
||||
/// - 红外辐射特征
|
||||
/// - 目标物理尺寸
|
||||
/// - 目标特殊频谱特性
|
||||
/// 用于在仿真系统中表示和识别不同类型的目标
|
||||
/// </remarks>
|
||||
public interface ITarget
|
||||
public interface ITarget : ISimulationElement, ISpectralCharacteristics
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取目标的类型标识
|
||||
@ -22,28 +55,7 @@ namespace ThreatSource.Target
|
||||
/// 用于区分不同种类的目标,如坦克、装甲车等
|
||||
/// 在仿真系统中用于目标识别和分类
|
||||
/// </remarks>
|
||||
string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的雷达散射截面积
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:平方米
|
||||
/// 表示目标对雷达波的反射能力
|
||||
/// 影响目标在雷达系统中的探测距离和识别概率
|
||||
/// </remarks>
|
||||
double RadarCrossSection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的红外辐射强度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:瓦特/球面度
|
||||
/// 表示目标的热辐射特征
|
||||
/// 影响红外制导系统的探测和跟踪能力
|
||||
/// 典型值:200-500 W/sr
|
||||
/// </remarks>
|
||||
double InfraredRadiationIntensity { get; }
|
||||
TargetType Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取目标的毫米波辐射温度
|
||||
@ -92,5 +104,25 @@ namespace ThreatSource.Target
|
||||
/// 表示目标在垂直方向上的尺寸
|
||||
/// </remarks>
|
||||
double Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置目标的当前生命值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 范围:0-100
|
||||
/// 初始值为100
|
||||
/// 当生命值降至0或以下时,目标被销毁
|
||||
/// </remarks>
|
||||
double Health { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前的温度分布矩阵
|
||||
/// </summary>
|
||||
/// <returns>当前状态下的温度分布矩阵</returns>
|
||||
/// <remarks>
|
||||
/// 返回3x3矩阵,表示目标侧视图的温度分布
|
||||
/// 根据目标的运动状态返回静止或运动时的温度分布
|
||||
/// </remarks>
|
||||
double[,] GetCurrentThermalPattern();
|
||||
}
|
||||
}
|
||||
@ -4,99 +4,36 @@ using ThreatSource.Utils;
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 坦克类,实现了目标接口的具体坦克目标
|
||||
/// 坦克类,继承自BaseTarget的具体坦克目标
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 该类提供了坦克目标的完整实现:
|
||||
/// - 继承自SimulationElement,具备基本的仿真功能
|
||||
/// - 实现ITarget接口,提供目标特征
|
||||
/// - 包含生命值系统,可以响应伤害
|
||||
/// - 支持位置更新和状态同步
|
||||
/// 该类提供了坦克目标的具体实现:
|
||||
/// - 继承自BaseTarget,获得基本的目标功能
|
||||
/// - 实现坦克特有的属性和行为
|
||||
/// </remarks>
|
||||
public class Tank : SimulationElement, ITarget
|
||||
public class Tank : BaseTarget
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取坦克的类型标识
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 固定返回"Tank",用于标识这是一个坦克目标
|
||||
/// 固定返回 TargetType.Tank,用于标识这是一个坦克目标
|
||||
/// </remarks>
|
||||
public string Type => "Tank";
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克的毫米波辐射温度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:开尔文
|
||||
/// 固定值400.0,表示坦克的毫米波辐射特征
|
||||
/// 典型值:350-450K
|
||||
/// </remarks>
|
||||
public double MillimeterWaveRadiationTemperature { get; set; } = 400.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克的激光反射率
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 无量纲,取值范围:0-1
|
||||
/// 固定值0.3,表示坦克表面对激光的反射特性
|
||||
/// </remarks>
|
||||
public double LaserReflectivity { get; set; } = 0.3;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置坦克的当前生命值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 范围:0-100
|
||||
/// 初始值为100
|
||||
/// 当生命值降至0或以下时,坦克被销毁
|
||||
/// </remarks>
|
||||
public double Health { get; set; } = 100.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克的长度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 固定值6.0,表示坦克的长度
|
||||
/// </remarks>
|
||||
public double Length => 6.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克的宽度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 固定值3.0,表示坦克的宽度
|
||||
/// </remarks>
|
||||
public double Width => 3.0;
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克的高度
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 单位:米
|
||||
/// 固定值2.5,表示坦克的高度
|
||||
/// </remarks>
|
||||
public double Height => 2.5;
|
||||
public override TargetType Type => TargetType.Tank;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化坦克类的新实例
|
||||
/// </summary>
|
||||
/// <param name="id">坦克的唯一标识符</param>
|
||||
/// <param name="position">初始位置坐标</param>
|
||||
/// <param name="speed">初始速度,单位:米/秒</param>
|
||||
/// <param name="initialMotionParameters">初始运动参数</param>
|
||||
/// <param name="simulationManager">仿真管理器实例</param>
|
||||
/// <remarks>
|
||||
/// 构造函数设置坦克的初始状态:
|
||||
/// - 使用默认朝向
|
||||
/// - 设置初始位置和速度
|
||||
/// - 生命值初始化为100
|
||||
/// - 调用基类构造函数初始化基本属性
|
||||
/// </remarks>
|
||||
public Tank(string id, Vector3D position, double speed, ISimulationManager simulationManager)
|
||||
: base(id, position, new Orientation(), speed, simulationManager)
|
||||
public Tank(string id, InitialMotionParameters initialMotionParameters, ISimulationManager simulationManager)
|
||||
: base(id, initialMotionParameters, simulationManager)
|
||||
{
|
||||
// 初始化频谱特性
|
||||
UpdateSpectralSignature();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -105,51 +42,13 @@ namespace ThreatSource.Target
|
||||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||||
/// <remarks>
|
||||
/// 更新过程:
|
||||
/// - 根据当前速度更新位置
|
||||
/// - 位置更新使用简单的线性运动模型
|
||||
/// - 调用基类的更新方法更新基本状态
|
||||
/// - 可以在此添加坦克特有的更新逻辑
|
||||
/// </remarks>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
// 更新坦克的位置
|
||||
Position += Velocity * deltaTime;
|
||||
|
||||
// 更新频谱特性
|
||||
UpdateSpectralSignature();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新频谱特性的默认实现
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 提供坦克的频谱特性
|
||||
/// </remarks>
|
||||
protected override void UpdateSpectralSignature()
|
||||
{
|
||||
RadarCrossSection = 10.0; // 坦克RCS值
|
||||
InfraredRadiationIntensity = 500.0; // 坦克红外辐射强度
|
||||
UltravioletRadiationIntensity = 15.0; // 坦克紫外辐射强度
|
||||
MillimeterWaveRadiationIntensity = 10.0; // 坦克毫米波辐射强度
|
||||
MillimeterWaveRadiationTemperature = 400.0; // 坦克毫米波辐射温度
|
||||
LaserReflectivity = 0.3; // 坦克激光反射率
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对坦克造成伤害
|
||||
/// </summary>
|
||||
/// <param name="damage">伤害值</param>
|
||||
/// <remarks>
|
||||
/// 伤害处理过程:
|
||||
/// - 从当前生命值中扣除伤害值
|
||||
/// - 如果生命值降至0或以下,触发目标销毁事件
|
||||
/// - 销毁事件会通知仿真系统移除该目标
|
||||
/// </remarks>
|
||||
public void TakeDamage(double damage)
|
||||
{
|
||||
Health -= damage;
|
||||
if (Health <= 0)
|
||||
{
|
||||
SimulationManager.PublishEvent(new TargetDestroyedEvent { TargetId = Id });
|
||||
}
|
||||
base.Update(deltaTime);
|
||||
// TODO: 添加坦克特有的更新逻辑
|
||||
}
|
||||
}
|
||||
}
|
||||
250
ThreatSource/src/Target/ThermalPattern.cs
Normal file
250
ThreatSource/src/Target/ThermalPattern.cs
Normal file
@ -0,0 +1,250 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ThreatSource.Target
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标的温度分布模式
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(ThermalPatternConverter))]
|
||||
public class ThermalPattern
|
||||
{
|
||||
/// <summary>
|
||||
/// 温度分布矩阵的大小
|
||||
/// </summary>
|
||||
public const int GRID_SIZE = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 静止状态下的温度分布(摄氏度)
|
||||
/// </summary>
|
||||
public double[,] StaticPattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 运动状态下的温度分布(摄氏度)
|
||||
/// </summary>
|
||||
public double[,] MovingPattern { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始化温度分布模式
|
||||
/// </summary>
|
||||
public ThermalPattern(double[,] staticPattern, double[,] movingPattern)
|
||||
{
|
||||
if (staticPattern.GetLength(0) != GRID_SIZE || staticPattern.GetLength(1) != GRID_SIZE)
|
||||
throw new ArgumentException("Static pattern must be 3x3");
|
||||
if (movingPattern.GetLength(0) != GRID_SIZE || movingPattern.GetLength(1) != GRID_SIZE)
|
||||
throw new ArgumentException("Moving pattern must be 3x3");
|
||||
|
||||
StaticPattern = staticPattern;
|
||||
MovingPattern = movingPattern;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定状态下的温度分布
|
||||
/// </summary>
|
||||
/// <param name="isMoving">目标是否在运动</param>
|
||||
public double[,] GetPattern(bool isMoving)
|
||||
{
|
||||
return isMoving ? MovingPattern : StaticPattern;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算温度梯度特征
|
||||
/// </summary>
|
||||
/// <param name="isMoving">目标是否在运动</param>
|
||||
public double CalculateGradientFeature(bool isMoving)
|
||||
{
|
||||
var pattern = GetPattern(isMoving);
|
||||
|
||||
// 计算发动机区域(右侧)平均温度
|
||||
double engineTemp = (pattern[1, 2] + pattern[2, 2]) / 2.0;
|
||||
|
||||
// 计算前部区域(左侧)平均温度
|
||||
double frontTemp = (pattern[1, 0] + pattern[2, 0]) / 2.0;
|
||||
|
||||
// 计算中部区域平均温度
|
||||
double middleTemp = pattern[1, 1];
|
||||
|
||||
// 计算上部区域平均温度
|
||||
double topTemp = pattern[0, 1];
|
||||
|
||||
// 计算整体平均温度
|
||||
double avgTemp = 0;
|
||||
for (int i = 0; i < GRID_SIZE; i++)
|
||||
for (int j = 0; j < GRID_SIZE; j++)
|
||||
avgTemp += pattern[i, j];
|
||||
avgTemp /= (GRID_SIZE * GRID_SIZE);
|
||||
|
||||
// 1. 发动机区域温度特征(相对于平均温度的比值)
|
||||
double engineFeature = engineTemp / (avgTemp + 0.1);
|
||||
|
||||
// 2. 前后温度梯度(考虑相对差异)
|
||||
double frontBackGradient = (engineTemp - frontTemp) / (avgTemp + 0.1);
|
||||
|
||||
// 3. 垂直温度梯度(发动机区域与上部的温度差异)
|
||||
double verticalGradient = (engineTemp - topTemp) / (avgTemp + 0.1);
|
||||
|
||||
// 4. 温度集中度(发动机区域相对于中部的温度差异)
|
||||
double concentrationGradient = (engineTemp - middleTemp) / (avgTemp + 0.1);
|
||||
|
||||
// 坦克特征权重
|
||||
double engineWeight = 0.4; // 发动机温度特征权重
|
||||
double frontBackWeight = 0.35; // 前后温度梯度权重
|
||||
double verticalWeight = 0.15; // 垂直温度梯度权重
|
||||
double concentrationWeight = 0.1; // 温度集中度权重
|
||||
|
||||
// 归一化并限制各个特征值
|
||||
engineFeature = Math.Min(engineFeature, 1.5) / 1.5;
|
||||
frontBackGradient = Math.Min(Math.Max(frontBackGradient, 0), 1.0);
|
||||
verticalGradient = Math.Min(Math.Max(verticalGradient, 0), 1.0);
|
||||
concentrationGradient = Math.Min(Math.Max(concentrationGradient, 0), 1.0);
|
||||
|
||||
// 计算最终得分
|
||||
return engineFeature * engineWeight +
|
||||
frontBackGradient * frontBackWeight +
|
||||
verticalGradient * verticalWeight +
|
||||
concentrationGradient * concentrationWeight;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ThermalPattern的JSON转换器
|
||||
/// </summary>
|
||||
public class ThermalPatternConverter : JsonConverter<ThermalPattern>
|
||||
{
|
||||
/// <summary>
|
||||
/// 读取ThermalPattern的JSON数据
|
||||
/// </summary>
|
||||
/// <param name="reader">JSON读取器</param>
|
||||
/// <param name="typeToConvert">目标类型</param>
|
||||
/// <param name="options">JSON序列化选项</param>
|
||||
/// <returns>解析后的ThermalPattern对象</returns>
|
||||
public override ThermalPattern Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartObject)
|
||||
{
|
||||
throw new JsonException("Expected StartObject token");
|
||||
}
|
||||
|
||||
double[,] staticPattern = new double[ThermalPattern.GRID_SIZE, ThermalPattern.GRID_SIZE];
|
||||
double[,] movingPattern = new double[ThermalPattern.GRID_SIZE, ThermalPattern.GRID_SIZE];
|
||||
bool hasStatic = false;
|
||||
bool hasMoving = false;
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.EndObject)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reader.TokenType != JsonTokenType.PropertyName)
|
||||
{
|
||||
throw new JsonException("Expected PropertyName token");
|
||||
}
|
||||
|
||||
string propertyName = reader.GetString()!;
|
||||
|
||||
reader.Read(); // Move to the value
|
||||
|
||||
switch (propertyName.ToLower())
|
||||
{
|
||||
case "static":
|
||||
ReadMatrix(ref reader, staticPattern);
|
||||
hasStatic = true;
|
||||
break;
|
||||
case "moving":
|
||||
ReadMatrix(ref reader, movingPattern);
|
||||
hasMoving = true;
|
||||
break;
|
||||
default:
|
||||
reader.Skip(); // Skip description or other properties
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasStatic || !hasMoving)
|
||||
{
|
||||
throw new JsonException("Missing required static or moving pattern");
|
||||
}
|
||||
|
||||
return new ThermalPattern(staticPattern, movingPattern);
|
||||
}
|
||||
|
||||
private static void ReadMatrix(ref Utf8JsonReader reader, double[,] matrix)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.StartArray)
|
||||
{
|
||||
throw new JsonException("Expected StartArray token for matrix");
|
||||
}
|
||||
|
||||
for (int i = 0; i < ThermalPattern.GRID_SIZE; i++)
|
||||
{
|
||||
reader.Read(); // Move to start of row array
|
||||
if (reader.TokenType != JsonTokenType.StartArray)
|
||||
{
|
||||
throw new JsonException($"Expected StartArray token for row {i}");
|
||||
}
|
||||
|
||||
for (int j = 0; j < ThermalPattern.GRID_SIZE; j++)
|
||||
{
|
||||
reader.Read(); // Move to number
|
||||
if (reader.TokenType != JsonTokenType.Number)
|
||||
{
|
||||
throw new JsonException($"Expected Number token at position [{i},{j}]");
|
||||
}
|
||||
matrix[i, j] = reader.GetDouble();
|
||||
}
|
||||
|
||||
reader.Read(); // Move to end of row array
|
||||
if (reader.TokenType != JsonTokenType.EndArray)
|
||||
{
|
||||
throw new JsonException($"Expected EndArray token for row {i}");
|
||||
}
|
||||
}
|
||||
|
||||
reader.Read(); // Move to end of matrix array
|
||||
if (reader.TokenType != JsonTokenType.EndArray)
|
||||
{
|
||||
throw new JsonException("Expected EndArray token for matrix");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将ThermalPattern对象序列化为JSON字符串
|
||||
/// </summary>
|
||||
/// <param name="writer">JSON写入器</param>
|
||||
/// <param name="value">要序列化的ThermalPattern对象</param>
|
||||
/// <param name="options">JSON序列化选项</param>
|
||||
public override void Write(Utf8JsonWriter writer, ThermalPattern value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WritePropertyName("description");
|
||||
writer.WriteStringValue("3x3 matrix representing side view temperature distribution (°C)");
|
||||
|
||||
writer.WritePropertyName("static");
|
||||
WriteMatrix(writer, value.StaticPattern);
|
||||
|
||||
writer.WritePropertyName("moving");
|
||||
WriteMatrix(writer, value.MovingPattern);
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
|
||||
private static void WriteMatrix(Utf8JsonWriter writer, double[,] matrix)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
for (int i = 0; i < ThermalPattern.GRID_SIZE; i++)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
for (int j = 0; j < ThermalPattern.GRID_SIZE; j++)
|
||||
{
|
||||
writer.WriteNumberValue(matrix[i, j]);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,15 +133,17 @@ namespace ThreatSource.Utils
|
||||
/// <summary>
|
||||
/// 向量相等运算符重载
|
||||
/// </summary>
|
||||
public static bool operator ==(Vector3D left, Vector3D right)
|
||||
public static bool operator ==(Vector3D? left, Vector3D? right)
|
||||
{
|
||||
if (ReferenceEquals(left, right)) return true;
|
||||
if (left is null || right is null) return false;
|
||||
return left.X == right.X && left.Y == right.Y && left.Z == right.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量不相等运算符重载
|
||||
/// </summary>
|
||||
public static bool operator !=(Vector3D left, Vector3D right)
|
||||
public static bool operator !=(Vector3D? left, Vector3D? right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
@ -184,26 +184,47 @@ namespace ThreatSource.Utils
|
||||
/// <returns>比例导引产生的加速度向量</returns>
|
||||
/// <remarks>
|
||||
/// 使用比例导引法计算制导加速度:
|
||||
/// - 计算动态预测时间
|
||||
/// - 预测目标未来位置
|
||||
/// - 计算视线角速率
|
||||
/// - 根据比例导引公式计算所需加速度
|
||||
/// 加速度方向垂直于导弹速度方向。
|
||||
/// </remarks>
|
||||
public static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient, Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
|
||||
public static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient,
|
||||
Vector3D missilePosition, Vector3D missileVelocity,
|
||||
Vector3D targetPosition, Vector3D targetVelocity)
|
||||
{
|
||||
// 预测时间(预测目标前进方向该时间后到达的位置,可以调整)
|
||||
double predictionTime = 0.01;
|
||||
|
||||
// 计算导弹到目标的距离
|
||||
Vector3D r = targetPosition - missilePosition;
|
||||
double distance = r.Magnitude();
|
||||
|
||||
// 根据距离和相对速度动态计算预测时间
|
||||
Vector3D relativeVelocity = targetVelocity - missileVelocity;
|
||||
double closingVelocity = -Vector3D.DotProduct(relativeVelocity, r.Normalize());
|
||||
|
||||
// 预测时间计算考虑:
|
||||
// 1. 距离因素:距离越远,预测时间适当增加
|
||||
// 2. 接近速度因素:接近速度越大,预测时间适当减小
|
||||
// 3. 最小和最大限制:确保预测时间在合理范围内
|
||||
double predictionTime = Math.Clamp(
|
||||
distance / (closingVelocity + 1e-6) * 0.1, // 基础预测时间(取时程的10%)
|
||||
0.05, // 最小预测时间:50ms
|
||||
0.5 // 最大预测时间:500ms
|
||||
);
|
||||
|
||||
// 预测目标位置
|
||||
Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime;
|
||||
|
||||
Vector3D r = predictedTargetPosition - missilePosition;
|
||||
|
||||
// 计算视线矢量和视线变化率
|
||||
Vector3D LOS = (predictedTargetPosition - missilePosition).Normalize();
|
||||
Vector3D v = targetVelocity - missileVelocity;
|
||||
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / distance;
|
||||
|
||||
Vector3D LOS = r.Normalize();
|
||||
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude();
|
||||
|
||||
Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * proportionalNavigationCoefficient * missileVelocity.Magnitude();
|
||||
// 计算制导加速度
|
||||
Vector3D acceleration = Vector3D.CrossProduct(
|
||||
Vector3D.CrossProduct(LOS, LOSRate),
|
||||
missileVelocity.Normalize()
|
||||
) * proportionalNavigationCoefficient * missileVelocity.Magnitude();
|
||||
|
||||
return acceleration;
|
||||
}
|
||||
|
||||
@ -1200,9 +1200,6 @@ graph TB
|
||||
#### 4.3.1 事件类型
|
||||
|
||||
1. 实体管理事件
|
||||
- EntityActivatedEvent:实体激活
|
||||
- EntityDeactivatedEvent:实体停用
|
||||
- EntityDestroyedEvent:实体销毁
|
||||
- MissileFireEvent:导弹发射
|
||||
|
||||
2. 激光相关事件
|
||||
|
||||
62
docs/project/design.md
Normal file
62
docs/project/design.md
Normal file
@ -0,0 +1,62 @@
|
||||
# 威胁源仿真库设计文档
|
||||
|
||||
## 接口设计
|
||||
|
||||
### 核心接口继承关系
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
ISimulationElement <|-- ITarget
|
||||
ISpectralCharacteristics <|-- ITarget
|
||||
ISimulationElement <|.. SimulationElement
|
||||
ISpectralCharacteristics <|.. SimulationElement
|
||||
SimulationElement <|-- Tank
|
||||
ITarget <|.. Tank
|
||||
|
||||
class ISimulationElement {
|
||||
+string Id
|
||||
+Vector3D Position
|
||||
+Vector3D Velocity
|
||||
+double Speed
|
||||
+Orientation Orientation
|
||||
+bool IsActive
|
||||
+Update(deltaTime)
|
||||
+Activate()
|
||||
+Deactivate()
|
||||
+GetStatus()
|
||||
}
|
||||
|
||||
class ISpectralCharacteristics {
|
||||
+double RadarCrossSection
|
||||
+double InfraredRadiationIntensity
|
||||
+double UltravioletRadiationIntensity
|
||||
+double MillimeterWaveRadiationIntensity
|
||||
}
|
||||
|
||||
class ITarget {
|
||||
+string Type
|
||||
+double MillimeterWaveRadiationTemperature
|
||||
+double LaserReflectivity
|
||||
+double Length
|
||||
+double Width
|
||||
+double Height
|
||||
+double Health
|
||||
}
|
||||
```
|
||||
|
||||
### 设计说明
|
||||
|
||||
1. **接口分层**
|
||||
- `ISimulationElement`: 定义所有仿真元素的基本行为,包括位置、运动状态和生命周期管理
|
||||
- `ISpectralCharacteristics`: 定义实体的频谱特性,包括雷达散射截面积、红外辐射等
|
||||
- `ITarget`: 继承上述两个接口,并添加目标特有的属性(尺寸、生命值等)
|
||||
|
||||
2. **实现层次**
|
||||
- `SimulationElement`: 抽象基类,实现 `ISimulationElement` 和 `ISpectralCharacteristics` 的基本功能
|
||||
- `Tank`: 继承 `SimulationElement` 并实现 `ITarget` 接口,获得基类功能的同时实现目标特有的属性和行为
|
||||
|
||||
3. **设计优势**
|
||||
- 接口隔离:将不同职责的功能分散到不同接口中
|
||||
- 代码复用:通用功能在 `SimulationElement` 中实现
|
||||
- 扩展性:新的实体类型可以方便地接入系统
|
||||
- 维护性:频谱特性的修改只需要关注 `ISpectralCharacteristics` 接口
|
||||
@ -11,6 +11,7 @@ using ThreatSource.Sensor;
|
||||
using ThreatSource.Target;
|
||||
using ThreatSource.Guidance;
|
||||
using ThreatSource.Indicator;
|
||||
using ThreatSource.Data;
|
||||
|
||||
namespace ThreatSource.Tools.MissileSimulation
|
||||
{
|
||||
@ -23,6 +24,8 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
public event EventHandler? SimulationEnded;
|
||||
|
||||
private readonly ISimulationManager simulationManager;
|
||||
private readonly ThreatSourceFactory _threatSourceFactory;
|
||||
private readonly ThreatSourceDataManager _dataManager;
|
||||
private readonly Dictionary<string, BaseMissile> missiles;
|
||||
private readonly Dictionary<string, SimulationElement> targets;
|
||||
private readonly Dictionary<string, SimulationElement> indicators;
|
||||
@ -35,6 +38,8 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
public ComprehensiveMissileSimulator()
|
||||
{
|
||||
simulationManager = new SimulationManager();
|
||||
_dataManager = new ThreatSourceDataManager();
|
||||
_threatSourceFactory = new ThreatSourceFactory(_dataManager, simulationManager);
|
||||
missiles = new Dictionary<string, BaseMissile>();
|
||||
targets = new Dictionary<string, SimulationElement>();
|
||||
indicators = new Dictionary<string, SimulationElement>();
|
||||
@ -48,7 +53,7 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
private void InitializeSimulation()
|
||||
{
|
||||
// 添加目标(坦克)
|
||||
AddTarget("Tank_1", new Vector3D(0, 0, 0));
|
||||
AddTankTarget();
|
||||
|
||||
// 添加各种类型的导弹
|
||||
AddLaserSemiActiveMissile();
|
||||
@ -65,15 +70,19 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// <summary>
|
||||
/// 添加目标
|
||||
/// </summary>
|
||||
private void AddTarget(string targetId, Vector3D position)
|
||||
private void AddTankTarget()
|
||||
{
|
||||
var target = new Tank(targetId, position, 0, simulationManager)
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Position = position
|
||||
Position = new Vector3D(0, 0, 0),
|
||||
Orientation = new Orientation(Math.PI, 0.0, 0.0),
|
||||
InitialSpeed = 0
|
||||
};
|
||||
string targetId = "Tank_1";
|
||||
var target = _threatSourceFactory.CreateTarget(targetId, "mbt_001", launchParams);
|
||||
targets[targetId] = target;
|
||||
simulationManager.RegisterEntity(targetId, target);
|
||||
Console.WriteLine($"添加目标 {targetId},位置:{position}");
|
||||
Console.WriteLine($"添加目标 {targetId},位置:{launchParams.Position}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -81,27 +90,17 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddLaserSemiActiveMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "LSGM_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 800,
|
||||
MaxFlightTime = 10,
|
||||
MaxFlightDistance = 5000,
|
||||
MaxAcceleration = 400,
|
||||
InitialPosition = new Vector3D(2000, 100, 100),
|
||||
InitialSpeed = 700,
|
||||
InitialOrientation = new Orientation(Math.PI, -0.05, 0),
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
SelfDestructHeight = 0,
|
||||
Type = MissileType.LaserSemiActiveGuidance
|
||||
Position = new Vector3D(2000, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, -0.05, 0),
|
||||
InitialSpeed = 700
|
||||
};
|
||||
|
||||
var missile = new LaserSemiActiveGuidedMissile(properties, simulationManager);
|
||||
missiles["LSGM_1"] = missile;
|
||||
simulationManager.RegisterEntity("LSGM_1", missile);
|
||||
Console.WriteLine($"注册激光半主动制导导弹 LSGM_1");
|
||||
string missileId = "LSGM_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "lsgm_001", "Tank_1", launchParams);
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册激光半主动制导导弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -109,27 +108,17 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddLaserBeamRiderMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "LBRM_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 400,
|
||||
MaxFlightTime = 10,
|
||||
MaxFlightDistance = 3000,
|
||||
MaxAcceleration = 400,
|
||||
InitialPosition = new Vector3D(2000, 10, 100),
|
||||
InitialSpeed = 300,
|
||||
InitialOrientation = new Orientation(Math.PI, 0.0, 0.0),
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
SelfDestructHeight = 0,
|
||||
Type = MissileType.LaserBeamRiderGuidance
|
||||
Position = new Vector3D(2000, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, 0.0, 0.0),
|
||||
InitialSpeed = 300
|
||||
};
|
||||
|
||||
var missile = new LaserBeamRiderMissile(properties, simulationManager);
|
||||
missiles["LBRM_1"] = missile;
|
||||
simulationManager.RegisterEntity("LBRM_1", missile);
|
||||
Console.WriteLine($"注册激光驾束制导导弹 LBRM_1");
|
||||
string missileId = "LBRM_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "hj10", "Tank_1", launchParams);
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册激光驾束制导导弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -137,40 +126,19 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddTerminalSensitiveMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "TSM_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 1000,
|
||||
MaxFlightTime = 100,
|
||||
MaxFlightDistance = 5000,
|
||||
MaxAcceleration = 200,
|
||||
InitialPosition = new Vector3D(3000, 0, 0),
|
||||
InitialSpeed = 800,
|
||||
InitialOrientation = new Orientation(Math.PI, 0, 0),
|
||||
SelfDestructHeight = 0,
|
||||
Type = MissileType.TerminalSensitiveMissile
|
||||
Position = new Vector3D(3000, 0, 100),
|
||||
Orientation = new Orientation(Math.PI, 0, 0),
|
||||
InitialSpeed = 800
|
||||
};
|
||||
|
||||
var submunitionProperties = new MissileProperties
|
||||
{
|
||||
MaxSpeed = 2000,
|
||||
MaxFlightTime = 60,
|
||||
MaxFlightDistance = 2000,
|
||||
MaxAcceleration = 300,
|
||||
ProportionalNavigationCoefficient = 4,
|
||||
Mass = 10,
|
||||
ExplosionRadius = 5,
|
||||
HitProbability = 0.9,
|
||||
SelfDestructHeight = 20,
|
||||
Type = MissileType.TerminalSensitiveSubmunition
|
||||
};
|
||||
string missileId = "TSM_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "tsm_001", "Tank_1", launchParams);
|
||||
|
||||
var missile = new TerminalSensitiveMissile("Tank_1", properties, submunitionProperties, 1, simulationManager);
|
||||
missiles["TSM_1"] = missile;
|
||||
simulationManager.RegisterEntity("TSM_1", missile);
|
||||
Console.WriteLine($"注册末敏弹 TSM_1");
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册末敏弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -178,27 +146,18 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddInfraredCommandMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "ICGM_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 400,
|
||||
MaxFlightTime = 60,
|
||||
MaxFlightDistance = 2100,
|
||||
MaxAcceleration = 100,
|
||||
InitialPosition = new Vector3D(2000, 10, 100),
|
||||
InitialSpeed = 300,
|
||||
InitialOrientation = new Orientation(Math.PI, 0.0, 0),
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
SelfDestructHeight = 0,
|
||||
Type = MissileType.InfraredCommandGuidance
|
||||
Position = new Vector3D(2000, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, 0.0, 0),
|
||||
InitialSpeed = 300
|
||||
};
|
||||
|
||||
var missile = new InfraredCommandGuidedMissile(properties, simulationManager);
|
||||
missiles["ICGM_1"] = missile;
|
||||
simulationManager.RegisterEntity("ICGM_1", missile);
|
||||
Console.WriteLine($"注册红外指令制导导弹 ICGM_1");
|
||||
string missileId = "ICGM_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "irc_001", "Tank_1", launchParams);
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册红外指令制导导弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -206,27 +165,17 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddInfraredImagingMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "ITGM_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 400,
|
||||
MaxFlightTime = 60,
|
||||
MaxFlightDistance = 5000,
|
||||
MaxAcceleration = 50,
|
||||
InitialPosition = new Vector3D(2000, 20, 100),
|
||||
InitialSpeed = 300,
|
||||
InitialOrientation = new Orientation(Math.PI, 0.0, 0),
|
||||
SelfDestructHeight = 0,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
Type = MissileType.InfraredImagingTerminalGuidance
|
||||
Position = new Vector3D(2000, 20, 50),
|
||||
Orientation = new Orientation(Math.PI, 0.0, 0),
|
||||
InitialSpeed = 300
|
||||
};
|
||||
|
||||
var missile = new InfraredImagingTerminalGuidedMissile(properties, simulationManager);
|
||||
missiles["ITGM_1"] = missile;
|
||||
simulationManager.RegisterEntity("ITGM_1", missile);
|
||||
Console.WriteLine($"注册红外成像末制导导弹 ITGM_1");
|
||||
string missileId = "ITGM_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "itg_001", "Tank_1", launchParams);
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册红外成像末制导导弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -234,27 +183,17 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
/// </summary>
|
||||
private void AddMillimeterWaveMissile()
|
||||
{
|
||||
var properties = new MissileProperties
|
||||
var launchParams = new InitialMotionParameters
|
||||
{
|
||||
Id = "MMWG_1",
|
||||
Mass = 50,
|
||||
ExplosionRadius = 5,
|
||||
MaxSpeed = 400,
|
||||
MaxFlightTime = 60,
|
||||
MaxFlightDistance = 5000,
|
||||
MaxAcceleration = 50,
|
||||
InitialPosition = new Vector3D(2000, 200, 100),
|
||||
InitialSpeed = 300,
|
||||
InitialOrientation = new Orientation(Math.PI, 0.0, 0),
|
||||
SelfDestructHeight = 0,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
Type = MissileType.MillimeterWaveTerminalGuidance
|
||||
};
|
||||
|
||||
var missile = new MillimeterWaveTerminalGuidedMissile(properties, simulationManager);
|
||||
missiles["MMWG_1"] = missile;
|
||||
simulationManager.RegisterEntity("MMWG_1", missile);
|
||||
Console.WriteLine($"注册毫米波末制导导弹 MMWG_1");
|
||||
Position = new Vector3D(2000, 20, 100),
|
||||
Orientation = new Orientation(Math.PI, 0.0, 0),
|
||||
InitialSpeed = 300
|
||||
};
|
||||
string missileId = "MMWG_1";
|
||||
var missile = _threatSourceFactory.CreateMissile(missileId, "mmw_001", "Tank_1", launchParams);
|
||||
missiles[missileId] = missile;
|
||||
simulationManager.RegisterEntity(missileId, missile);
|
||||
Console.WriteLine($"注册毫米波末制导导弹 {missileId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -263,62 +202,43 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
private void AddSensorsAndDesignators()
|
||||
{
|
||||
// 添加激光目标指示器
|
||||
var laserDesignator = new LaserDesignator(
|
||||
"LD_1",
|
||||
"Tank_1",
|
||||
"LSGM_1",
|
||||
0,
|
||||
new LaserDesignatorConfig
|
||||
{
|
||||
Id = "LD_1",
|
||||
InitialPosition = new Vector3D(2000, 150, 100),
|
||||
LaserPower = 1000,
|
||||
LaserDivergenceAngle = 0.001
|
||||
},
|
||||
simulationManager
|
||||
);
|
||||
indicators["LD_1"] = laserDesignator;
|
||||
simulationManager.RegisterEntity("LD_1", laserDesignator);
|
||||
Console.WriteLine("注册激光目标指示器 LD_1");
|
||||
string laserDesignatorId = "LD_1";
|
||||
var laserDesignatorLaunchParams = new InitialMotionParameters
|
||||
{
|
||||
Position = new Vector3D(2100, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, 0, 0),
|
||||
InitialSpeed = 0
|
||||
};
|
||||
var laserDesignator = _threatSourceFactory.CreateIndicator(laserDesignatorId, "ld_001", "Tank_1", "LSGM_1", laserDesignatorLaunchParams);
|
||||
indicators[laserDesignatorId] = (SimulationElement)laserDesignator;
|
||||
simulationManager.RegisterEntity(laserDesignatorId, laserDesignator);
|
||||
Console.WriteLine($"注册激光目标指示器 {laserDesignatorId}");
|
||||
|
||||
// 添加激光驾束仪
|
||||
var laserBeamRider = new LaserBeamRider(
|
||||
"LBR_1",
|
||||
"LBRM_1",
|
||||
"Tank_1",
|
||||
0,
|
||||
new LaserBeamRiderConfig
|
||||
{
|
||||
Id = "LBR_1",
|
||||
InitialPosition = new Vector3D(2000, 10, 100),
|
||||
LaserPower = 1000,
|
||||
ControlFieldDiameter = 6
|
||||
},
|
||||
simulationManager
|
||||
);
|
||||
indicators["LBR_1"] = laserBeamRider;
|
||||
simulationManager.RegisterEntity("LBR_1", laserBeamRider);
|
||||
Console.WriteLine("注册激光驾束仪 LBR_1");
|
||||
string laserBeamRiderId = "LBR_1";
|
||||
var laserBeamRiderLaunchParams = new InitialMotionParameters
|
||||
{
|
||||
Position = new Vector3D(2100, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, 0, 0),
|
||||
InitialSpeed = 0
|
||||
};
|
||||
var laserBeamRider = _threatSourceFactory.CreateIndicator(laserBeamRiderId, "br_001", "Tank_1", "LBRM_1", laserBeamRiderLaunchParams);
|
||||
indicators[laserBeamRiderId] = (SimulationElement)laserBeamRider;
|
||||
simulationManager.RegisterEntity(laserBeamRiderId, laserBeamRider);
|
||||
Console.WriteLine($"注册激光驾束仪 {laserBeamRiderId}");
|
||||
|
||||
// 添加红外测角仪
|
||||
var infraredTracker = new InfraredTracker(
|
||||
"IT_1",
|
||||
"Tank_1",
|
||||
new InfraredTrackerConfig
|
||||
{
|
||||
Id = "IT_1",
|
||||
InitialPosition = new Vector3D(2000, 0, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, 0, 0),
|
||||
MaxTrackingRange = 10000,
|
||||
FieldOfView = Math.PI / 4,
|
||||
AngleMeasurementAccuracy = 0.0005,
|
||||
UpdateFrequency = 100
|
||||
},
|
||||
simulationManager
|
||||
);
|
||||
indicators["IT_1"] = infraredTracker;
|
||||
simulationManager.RegisterEntity("IT_1", infraredTracker);
|
||||
Console.WriteLine("注册红外测角仪 IT_1");
|
||||
string infraredTrackerId = "IT_1";
|
||||
var infraredTrackerLaunchParams = new InitialMotionParameters
|
||||
{
|
||||
Position = new Vector3D(2100, 10, 100),
|
||||
Orientation = new Orientation(Math.PI, 0, 0),
|
||||
InitialSpeed = 0
|
||||
};
|
||||
var infraredTracker = _threatSourceFactory.CreateIndicator(infraredTrackerId, "ir_001", "Tank_1", "ITGM_1", infraredTrackerLaunchParams);
|
||||
indicators[infraredTrackerId] = (SimulationElement)infraredTracker;
|
||||
simulationManager.RegisterEntity(infraredTrackerId, infraredTracker);
|
||||
Console.WriteLine($"注册红外测角仪 {infraredTrackerId}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -383,12 +303,12 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
}
|
||||
break;
|
||||
case "ICGM_1": // 红外指令制导导弹
|
||||
case "ITGM_1": // 红外成像末制导导弹
|
||||
if (indicators.ContainsKey("IT_1"))
|
||||
{
|
||||
indicators["IT_1"].Activate();
|
||||
}
|
||||
break;
|
||||
case "ITGM_1": // 红外成像末制导导弹
|
||||
case "TSM_1": // 末敏弹
|
||||
case "MMWG_1": // 毫米波末制导导弹
|
||||
// 这些导弹使用自身的传感器系统
|
||||
@ -594,14 +514,14 @@ namespace ThreatSource.Tools.MissileSimulation
|
||||
foreach (var missile in activeMissiles)
|
||||
{
|
||||
// 获取导弹的初始属性
|
||||
var properties = missile.GetType().GetField("properties",
|
||||
var launchParams = missile.GetType().GetField("launchParams",
|
||||
System.Reflection.BindingFlags.NonPublic |
|
||||
System.Reflection.BindingFlags.Instance)?.GetValue(missile) as MissileProperties;
|
||||
System.Reflection.BindingFlags.Instance)?.GetValue(missile) as InitialMotionParameters;
|
||||
|
||||
if (properties != null)
|
||||
if (launchParams != null)
|
||||
{
|
||||
// 重置导弹位置和状态
|
||||
missile.Position = properties.InitialPosition;
|
||||
missile.Position = launchParams.Position;
|
||||
missile.Velocity = Vector3D.Zero;
|
||||
}
|
||||
missile.Deactivate();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user