From 639bb2b4456d1f2f3cf90aa718c333344fd0f6e2 Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Wed, 9 Apr 2025 19:42:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E9=A3=8E=E5=90=91?= =?UTF-8?q?=E9=A3=8E=E9=80=9F=E7=9A=84=E5=BD=B1=E5=93=8D=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=A4=A7=E6=B0=94=E9=80=8F=E8=BF=87=E7=8E=87=E5=BD=B1?= =?UTF-8?q?=E5=93=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +- ThreatSource.Tests/ThreatSource.Tests.csproj | 7 + .../LaserSemiActiveGuidanceSystemCodeTests.cs | 16 +- .../src/Indicator/LaserDesignatorCodeTests.cs | 2 +- .../src/Indicator/LaserDesignatorTests.cs | 3 +- .../src/Jamming/LaserDecoyTests.cs | 15 +- .../Jamming/LaserDesignatorJammingTests.cs | 3 +- .../LaserSemiActiveGuidedMissileCodeTests.cs | 15 +- ...SemiActiveGuidedMissileIntegrationTests.cs | 5 +- .../src/Simulation/SimulationManagerTests.cs | 4 +- .../src/Utils/AtmosphereDllWrapperTests.cs | 181 ++++ ThreatSource/ThreatSource.csproj | 7 + .../indicators/laser_beamriders/br_001.json | 1 + .../indicators/laser_designators/ld_001.json | 7 +- .../missiles/laser_semi_active/lsgm_001.json | 11 +- ThreatSource/data/weathers/heavy_fog.json | 15 + ThreatSource/data/weathers/heavy_rain.json | 15 + ThreatSource/data/weathers/heavy_snow.json | 15 + ThreatSource/data/weathers/light_fog.json | 15 + ThreatSource/data/weathers/light_rain.json | 15 + ThreatSource/data/weathers/light_snow.json | 15 + ThreatSource/data/weathers/medium_fog.json | 15 + ThreatSource/data/weathers/medium_rain.json | 15 + ThreatSource/data/weathers/medium_snow.json | 15 + ThreatSource/data/weathers/sandstorm.json | 15 + ThreatSource/data/weathers/sunny.json | 15 + ThreatSource/lib/AirTransmission.dll | Bin 0 -> 18944 bytes ThreatSource/lib/AirTransmission.xml | 908 ++++++++++++++++++ .../src/Data/{Models.cs => DataModels.cs} | 94 +- .../src/Data/ThreatSourceDataManager.cs | 52 + ThreatSource/src/Data/ThreatSourceFactory.cs | 22 + .../Guidance/InfraredCommandGuidanceSystem.cs | 70 +- .../src/Guidance/InfraredImageGenerator.cs | 104 +- .../Guidance/InfraredImagingGuidanceSystem.cs | 15 +- .../src/Guidance/InfraredTargetRecognizer.cs | 65 +- .../Guidance/LaserBeamRiderGuidanceSystem.cs | 25 +- .../Guidance/LaserSemiActiveGuidanceSystem.cs | 487 ++++------ .../Guidance/MillimeterWaveGuidanceSystem.cs | 17 +- ThreatSource/src/Indicator/LaserDesignator.cs | 52 +- ThreatSource/src/MIssile/BaseMissile.cs | 89 +- .../MIssile/LaserSemiActiveGuidedMissile.cs | 30 +- ThreatSource/src/Sensor/QuadrantDetector.cs | 98 +- ThreatSource/src/Simulation/DecoyTarget.cs | 52 +- .../src/Simulation/ISimulationManager.cs | 29 +- .../src/Simulation/SimulationConfig.cs | 78 +- .../src/Simulation/SimulationEvents.cs | 80 +- .../src/Simulation/SimulationManager.cs | 45 +- ThreatSource/src/Target/Tank.cs | 36 +- .../src/Utils/AtmosphereDllWrapper.cs | 157 +++ ThreatSource/src/Utils/LaserCode.cs | 2 - ThreatSource/src/Utils/MotionAlgorithm.cs | 24 + VERSION | 2 +- docs/project/develop_log.md | 28 + docs/project/theory.md | 126 +++ tools/ComprehensiveMissileSimulator.cs | 59 +- tools/ThreatSource.Tools.csproj | 4 + 56 files changed, 2554 insertions(+), 744 deletions(-) create mode 100644 ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs create mode 100644 ThreatSource/data/weathers/heavy_fog.json create mode 100644 ThreatSource/data/weathers/heavy_rain.json create mode 100644 ThreatSource/data/weathers/heavy_snow.json create mode 100644 ThreatSource/data/weathers/light_fog.json create mode 100644 ThreatSource/data/weathers/light_rain.json create mode 100644 ThreatSource/data/weathers/light_snow.json create mode 100644 ThreatSource/data/weathers/medium_fog.json create mode 100644 ThreatSource/data/weathers/medium_rain.json create mode 100644 ThreatSource/data/weathers/medium_snow.json create mode 100644 ThreatSource/data/weathers/sandstorm.json create mode 100644 ThreatSource/data/weathers/sunny.json create mode 100644 ThreatSource/lib/AirTransmission.dll create mode 100644 ThreatSource/lib/AirTransmission.xml rename ThreatSource/src/Data/{Models.cs => DataModels.cs} (82%) create mode 100644 ThreatSource/src/Utils/AtmosphereDllWrapper.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d28d0..4a11aec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,14 @@ - 支持与 Simulink 模型的数据交互 - 实现实时仿真数据同步 - 处理不同时间步长的协调 -- 增加风向风速的影响 -- 增加大气透过率影响 - 毫米波跟踪和锁定阶段采用脉冲多普勒制导、目标 RCS 特征矩阵 - 多种发射弹道模式:低平弹道、高抛弹道、俯冲弹道 - 双模、多模制导 +## [0.2.10] - 2025-04-09 +- 增加了风向风速的影响 +- 增加大气透过率影响 + ## [0.2.9] - 2025-04-04 - 增加了半主动激光制导的假目标干扰和测试用例 diff --git a/ThreatSource.Tests/ThreatSource.Tests.csproj b/ThreatSource.Tests/ThreatSource.Tests.csproj index 3d1a722..d80fbcc 100644 --- a/ThreatSource.Tests/ThreatSource.Tests.csproj +++ b/ThreatSource.Tests/ThreatSource.Tests.csproj @@ -20,5 +20,12 @@ + + + + ..\ThreatSource\lib\AirTransmission.dll + True + + \ No newline at end of file diff --git a/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs b/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs index 3f51530..6948a26 100644 --- a/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs +++ b/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs @@ -80,7 +80,7 @@ namespace ThreatSource.Tests.Guidance // Arrange _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -96,7 +96,7 @@ namespace ThreatSource.Tests.Guidance }; // Act - _guidanceSystem.ProcessLaserIlluminationEvent(illuminationEvent); + _guidanceSystem.ProcessLaserIlluminationUpdateEvent(illuminationEvent); // Assert var matchEvents = _testAdapter.GetPublishedEvents(); @@ -116,7 +116,7 @@ namespace ThreatSource.Tests.Guidance // Arrange _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -132,7 +132,7 @@ namespace ThreatSource.Tests.Guidance }; // Act - _guidanceSystem.ProcessLaserIlluminationEvent(illuminationEvent); + _guidanceSystem.ProcessLaserIlluminationUpdateEvent(illuminationEvent); // Assert var mismatchEvents = _testAdapter.GetPublishedEvents(); @@ -155,7 +155,7 @@ namespace ThreatSource.Tests.Guidance // Arrange _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -171,7 +171,7 @@ namespace ThreatSource.Tests.Guidance }; // Act - _guidanceSystem.ProcessLaserIlluminationEvent(illuminationEvent); + _guidanceSystem.ProcessLaserIlluminationUpdateEvent(illuminationEvent); // Assert var mismatchEvents = _testAdapter.GetPublishedEvents(); @@ -194,7 +194,7 @@ namespace ThreatSource.Tests.Guidance // Arrange _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -210,7 +210,7 @@ namespace ThreatSource.Tests.Guidance }; // Act - _guidanceSystem.ProcessLaserIlluminationEvent(illuminationEvent); + _guidanceSystem.ProcessLaserIlluminationUpdateEvent(illuminationEvent); // Assert - No mismatch events should be published var mismatchEvents = _testAdapter.GetPublishedEvents(); diff --git a/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs b/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs index a4ba138..c3b7d84 100644 --- a/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs +++ b/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs @@ -172,7 +172,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Activate(); // Assert - Start event should include code - var startEvents = _testAdapter.GetPublishedEvents(); + var startEvents = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(startEvents); var startEvent = startEvents[startEvents.Count - 1]; Assert.NotNull(startEvent.LaserCodeConfig); diff --git a/ThreatSource.Tests/src/Indicator/LaserDesignatorTests.cs b/ThreatSource.Tests/src/Indicator/LaserDesignatorTests.cs index 83d1ca0..75c26f0 100644 --- a/ThreatSource.Tests/src/Indicator/LaserDesignatorTests.cs +++ b/ThreatSource.Tests/src/Indicator/LaserDesignatorTests.cs @@ -27,8 +27,7 @@ namespace ThreatSource.Tests.Indicator LaserPower = 1000, LaserDivergenceAngle = 0.001, JammingResistanceThreshold = 10000, - MinWavelength = 1.0, - MaxWavelength = 1.1 + LaserWavelength = 1.06 }; var tankInitialMotion = new InitialMotionParameters diff --git a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs index b3c33ee..6bd5fbd 100644 --- a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs @@ -163,8 +163,7 @@ namespace ThreatSource.Tests.Jamming } }, JammingResistanceThreshold = 1.0, - MinWavelength = 1.06, - MaxWavelength = 1.07 + LaserWavelength = 1.06 }; // 创建虚拟激光指示器并注册 - 更靠近目标 @@ -296,8 +295,7 @@ namespace ThreatSource.Tests.Jamming } }, JammingResistanceThreshold = 1.0, - MinWavelength = 1.06, - MaxWavelength = 1.07 + LaserWavelength = 1.06 }; // 创建虚拟激光指示器并注册 @@ -419,8 +417,7 @@ namespace ThreatSource.Tests.Jamming } }, JammingResistanceThreshold = 1.0, - MinWavelength = 1.06, - MaxWavelength = 1.07 + LaserWavelength = 1.06 }; // 创建虚拟激光指示器并注册 @@ -558,8 +555,7 @@ namespace ThreatSource.Tests.Jamming } }, JammingResistanceThreshold = 1.0, - MinWavelength = 1.06, - MaxWavelength = 1.07 + LaserWavelength = 1.06 }; // 创建虚拟激光指示器并注册 @@ -821,8 +817,7 @@ namespace ThreatSource.Tests.Jamming } }, JammingResistanceThreshold = 1.0, - MinWavelength = 1.06, - MaxWavelength = 1.07 + LaserWavelength = 1.06 }; // 创建虚拟激光指示器并注册 - 距离目标2000米 diff --git a/ThreatSource.Tests/src/Jamming/LaserDesignatorJammingTests.cs b/ThreatSource.Tests/src/Jamming/LaserDesignatorJammingTests.cs index 6c974c3..c71f1e6 100644 --- a/ThreatSource.Tests/src/Jamming/LaserDesignatorJammingTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserDesignatorJammingTests.cs @@ -31,8 +31,7 @@ namespace ThreatSource.Tests.Jamming LaserPower = 100, LaserDivergenceAngle = 0.001, JammingResistanceThreshold = 0.01, // 设置干扰抗性阈值为10mW,适应球面扩散模型 - MinWavelength = 1.0, - MaxWavelength = 1.1 + LaserWavelength = 1.06 }; // 初始化激光指示器 diff --git a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs index 95a52c5..ba24f50 100644 --- a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs +++ b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs @@ -112,8 +112,7 @@ namespace ThreatSource.Tests.Missile { LaserPower = 100, LaserDivergenceAngle = 0.001, - MinWavelength = 1.0, - MaxWavelength = 1.1 + LaserWavelength = 1.06 }, new InitialMotionParameters { Position = new Vector3D(100, 0, 0), @@ -211,7 +210,7 @@ namespace ThreatSource.Tests.Missile _laserDesignator.LaserPower = 100; // 设置足够高的激光功率 // Act - Send matching code illumination - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -256,7 +255,7 @@ namespace ThreatSource.Tests.Missile _laserDesignator.LaserPower = 100; // 设置足够高的激光功率 // Act - Send mismatching code illumination - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -301,8 +300,8 @@ namespace ThreatSource.Tests.Missile _laserDesignator.LaserPower = 100; // 设置足够高的激光功率 // Act - Send illumination with code disabled - var illuminationEvent = new LaserIlluminationStartEvent - { + var illuminationEvent = new LaserIlluminationUpdateEvent + { LaserDesignatorId = "laser1", TargetId = "target1", LaserCodeConfig = new LaserCodeConfig @@ -339,7 +338,7 @@ namespace ThreatSource.Tests.Missile _missile.Update(0.1); // Move past launch stage // Act - Send illumination with code disabled - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -382,7 +381,7 @@ namespace ThreatSource.Tests.Missile _laserDesignator.LaserPower = 100; // 设置足够高的激光功率 // First enable guidance with matching code - var startEvent = new LaserIlluminationStartEvent + var startEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1", diff --git a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileIntegrationTests.cs b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileIntegrationTests.cs index e4ff4dd..80edf4b 100644 --- a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileIntegrationTests.cs +++ b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileIntegrationTests.cs @@ -77,8 +77,7 @@ namespace ThreatSource.Tests.Missile { LaserPower = 100, LaserDivergenceAngle = 0.001, - MinWavelength = 1.0, - MaxWavelength = 1.1 + LaserWavelength = 1.06 }; _laserDesignator = new LaserDesignator( @@ -164,7 +163,7 @@ namespace ThreatSource.Tests.Missile } // 手动创建并发布激光照射开始事件,确保事件被正确传递到制导系统 - var illuminationEvent = new LaserIlluminationStartEvent + var illuminationEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = _laserDesignator.Id, TargetId = _target.Id, diff --git a/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs b/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs index 2767310..4d8e5d2 100644 --- a/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs +++ b/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs @@ -83,14 +83,14 @@ namespace ThreatSource.Tests.Simulation public void TestExternalEventReception() { // Arrange - var externalEvent = new LaserIlluminationStartEvent + var externalEvent = new LaserIlluminationUpdateEvent { LaserDesignatorId = "laser1", TargetId = "target1" }; bool eventReceived = false; - _simulationManager.SubscribeToEvent(evt => + _simulationManager.SubscribeToEvent(evt => { eventReceived = true; Assert.Equal("laser1", evt.LaserDesignatorId); diff --git a/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs b/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs new file mode 100644 index 0000000..6a49aeb --- /dev/null +++ b/ThreatSource.Tests/src/Utils/AtmosphereDllWrapperTests.cs @@ -0,0 +1,181 @@ +using System; +using Xunit; +using ThreatSource.Utils; +using AirTransmission; + +namespace ThreatSource.Tests.Utils +{ + public class AtmosphereDllWrapperTests + { + [Fact] + public void CalculateTransmittance_LaserType_ReturnsExpectedValue() + { + // Arrange - 创建一个标准天气条件 + var weather = new Weather( + type: WeatherType.Clear, + temperature: 20.0, + relativeHumidity: 50.0, + visibility: 10.0, // 单位:km + precipitation: 0.0 + ); + + double distance = 1.0; // 1km + var radiationType = RadiationType.Laser; + double wavelength = 1.064; // 常见的YAG激光波长(微米) + + // Act - 调用被测试方法 + double transmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance * 1000, // 转换为米 + radiationType, + wavelength, + weather + ); + + // Assert - 验证结果在合理范围内 + Console.WriteLine($"激光透过率: {transmittance:F6}"); + Assert.True(transmittance >= 0.0); + Assert.True(transmittance <= 1.0); + Assert.NotEqual(0.0, transmittance); // 确保不是0 + } + + [Fact] + public void CalculateTransmittance_InfraredType_ReturnsExpectedValue() + { + // Arrange - 创建一个标准天气条件 + var weather = new Weather( + type: WeatherType.Clear, + temperature: 20.0, + relativeHumidity: 50.0, + visibility: 10.0, // 单位:km + precipitation: 0.0 + ); + + double distance = 1.0; // 1km + var radiationType = RadiationType.Infrared; + double wavelength = 8.0; // 中波红外波长(微米) + + // Act - 调用被测试方法 + double transmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance * 1000, // 转换为米 + radiationType, + wavelength, + weather + ); + + // Assert - 验证结果在合理范围内 + Console.WriteLine($"红外透过率: {transmittance:F6}"); + Assert.True(transmittance >= 0.0); + Assert.True(transmittance <= 1.0); + Assert.NotEqual(0.0, transmittance); // 确保不是0 + } + + [Fact] + public void CalculateAtmosphericTurbulence_ReturnsExpectedValue() + { + // Arrange - 创建一个标准天气条件 + var weather = new Weather( + type: WeatherType.Clear, + temperature: 20.0, + relativeHumidity: 50.0, + visibility: 10.0, // 单位:km + precipitation: 0.0 + ); + + double wavelength = 1.064; // 常见的YAG激光波长(微米) + double distance = 1.0; // 1km + double height = 10.0; // 10m高度 + + // Act - 调用被测试方法 + double turbulenceEffect = AtmosphereDllWrapper.CalculateAtmosphericTurbulence( + wavelength, + distance * 1000, // 转换为米 + weather, + height + ); + + // Assert - 验证结果在合理范围内 + Console.WriteLine($"湍流效应: {turbulenceEffect:F6}"); + Assert.True(turbulenceEffect >= 0.0); + Assert.True(turbulenceEffect <= 1.0); + Assert.NotEqual(0.0, turbulenceEffect); // 确保不是0 + } + + [Fact] + public void CalculateSmokeScreenTransmittance_ReturnsExpectedValue() + { + double wavelength = 1.064; // 常见的YAG激光波长(微米) + double smokeConcentration = 1.0; // 烟雾浓度(g/m³) + double smokeThickness = 50.0; // 烟幕厚度(m) + + // Act - 调用被测试方法 + double smokeTransmittance = AtmosphereDllWrapper.CalculateSmokeScreenTransmittance( + wavelength, + smokeConcentration, + smokeThickness + ); + + // Assert - 验证结果在合理范围内 + Console.WriteLine($"烟幕透过率: {smokeTransmittance:F6}"); + Assert.True(smokeTransmittance >= 0.0); + Assert.True(smokeTransmittance <= 1.0); + } + + [Fact] + public void CalculateTransmittance_DifferentWeatherConditions_ShowsVariation() + { + // Arrange - 创建不同的天气条件 + var clearWeather = new Weather( + type: WeatherType.Clear, + temperature: 25.0, + relativeHumidity: 50.0, + visibility: 10.0, // 单位:km + precipitation: 0.0 + ); + + var foggyWeather = new Weather( + type: WeatherType.Fog, + temperature: 15.0, + relativeHumidity: 90.0, + visibility: 0.5, // 单位:km + precipitation: 0.0 + ); + + var rainyWeather = new Weather( + type: WeatherType.Rain, + temperature: 18.0, + relativeHumidity: 95.0, + visibility: 2.0, // 单位:km + precipitation: 5.0 + ); + + double distance = 1.0; // 1km + var radiationType = RadiationType.Laser; + double wavelength = 1.064; // 常见的YAG激光波长(微米) + + // Act - 调用被测试方法 + double clearTransmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance * 1000, radiationType, wavelength, clearWeather); // 转换为米 + + double foggyTransmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance * 1000, radiationType, wavelength, foggyWeather); // 转换为米 + + double rainyTransmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance * 1000, radiationType, wavelength, rainyWeather); // 转换为米 + + // Assert - 验证不同天气条件对透过率有影响 + Console.WriteLine($"晴天透过率: {clearTransmittance:F6}"); + Console.WriteLine($"雾天透过率: {foggyTransmittance:F6}"); + Console.WriteLine($"雨天透过率: {rainyTransmittance:F6}"); + + // 验证所有值在有效范围内 + Assert.True(clearTransmittance >= 0.0 && clearTransmittance <= 1.0); + Assert.True(foggyTransmittance >= 0.0 && foggyTransmittance <= 1.0); + Assert.True(rainyTransmittance >= 0.0 && rainyTransmittance <= 1.0); + + // 确保所有透过率都不是0 + Assert.NotEqual(0.0, clearTransmittance); + Assert.NotEqual(0.0, foggyTransmittance); + Assert.NotEqual(0.0, rainyTransmittance); + } + } +} \ No newline at end of file diff --git a/ThreatSource/ThreatSource.csproj b/ThreatSource/ThreatSource.csproj index f9254cc..77b6cfd 100644 --- a/ThreatSource/ThreatSource.csproj +++ b/ThreatSource/ThreatSource.csproj @@ -12,4 +12,11 @@ + + + $(ProjectDir)lib\AirTransmission.dll + True + + + \ No newline at end of file diff --git a/ThreatSource/data/indicators/laser_beamriders/br_001.json b/ThreatSource/data/indicators/laser_beamriders/br_001.json index a686115..b19de60 100644 --- a/ThreatSource/data/indicators/laser_beamriders/br_001.json +++ b/ThreatSource/data/indicators/laser_beamriders/br_001.json @@ -6,6 +6,7 @@ "type": "LaserBeamRider", "beamRiderConfig": { "laserPower": 1000, + "laserWavelength": 1.06, "controlFieldDiameter": 6.0, "laserCodeConfig": { "code": { diff --git a/ThreatSource/data/indicators/laser_designators/ld_001.json b/ThreatSource/data/indicators/laser_designators/ld_001.json index bc4b84a..9dc8216 100644 --- a/ThreatSource/data/indicators/laser_designators/ld_001.json +++ b/ThreatSource/data/indicators/laser_designators/ld_001.json @@ -5,10 +5,9 @@ }, "type": "LaserDesignator", "designatorConfig": { - "laserPower": 1000, - "laserDivergenceAngle": 0.0002, - "minWavelength": 1.0, - "maxWavelength": 1.1, + "laserPower": 5000, + "laserDivergenceAngle": 0.0003, + "laserWavelength": 1.06, "laserCodeConfig": { "code": { "codeType": "PRF", diff --git a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.json b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.json index bbc0434..2c85ffb 100644 --- a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.json +++ b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.json @@ -8,8 +8,8 @@ "maxSpeed": 800.0, "maxFlightTime": 60.0, "maxFlightDistance": 4000.0, - "maxAcceleration": 100.0, - "proportionalNavigationCoefficient": 3.0, + "maxAcceleration": 50.0, + "proportionalNavigationCoefficient": 2.0, "launchAcceleration": 100.0, "maxEngineBurnTime": 0.1, "cruiseTime": 5.0, @@ -34,7 +34,10 @@ "reflectionCoefficient": 0.2, "targetReflectiveArea": 1.0, "lockThreshold": 1e-12, - "spotOffsetSensitivity": 0.5, - "jammingResistanceThreshold": 1e-3 + "spotOffsetSensitivity": 0.05, + "jammingResistanceThreshold": 1e-3, + "transmitterEfficiency": 0.85, + "receiverEfficiency": 0.8, + "laserWavelength": 1.06 } } \ No newline at end of file diff --git a/ThreatSource/data/weathers/heavy_fog.json b/ThreatSource/data/weathers/heavy_fog.json new file mode 100644 index 0000000..ca03b1e --- /dev/null +++ b/ThreatSource/data/weathers/heavy_fog.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "浓雾", + "en": "Heavy Fog" + }, + "type": "Fog", + "temperature": 8.0, + "relativeHumidity": 99.0, + "visibility": 0.1, + "precipitation": 0.0, + "cO2Concentration": 415.0, + "pressure": 998.0, + "windSpeed": 0.0, + "windDirection": 0.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/heavy_rain.json b/ThreatSource/data/weathers/heavy_rain.json new file mode 100644 index 0000000..f7c99e2 --- /dev/null +++ b/ThreatSource/data/weathers/heavy_rain.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "大雨", + "en": "Heavy Rain" + }, + "type": "Rain", + "temperature": 16.0, + "relativeHumidity": 95.0, + "visibility": 2.0, + "precipitation": 25.0, + "cO2Concentration": 415.0, + "pressure": 985.0, + "windSpeed": 8.0, + "windDirection": 180.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/heavy_snow.json b/ThreatSource/data/weathers/heavy_snow.json new file mode 100644 index 0000000..3a929d1 --- /dev/null +++ b/ThreatSource/data/weathers/heavy_snow.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "大雪", + "en": "Heavy Snow" + }, + "type": "Snow", + "temperature": -7.0, + "relativeHumidity": 85.0, + "visibility": 1.0, + "precipitation": 8.0, + "cO2Concentration": 410.0, + "pressure": 990.0, + "windSpeed": 6.0, + "windDirection": 270.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/light_fog.json b/ThreatSource/data/weathers/light_fog.json new file mode 100644 index 0000000..693e6f5 --- /dev/null +++ b/ThreatSource/data/weathers/light_fog.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "轻雾", + "en": "Light Fog" + }, + "type": "Fog", + "temperature": 12.0, + "relativeHumidity": 95.0, + "visibility": 0.8, + "precipitation": 0.0, + "cO2Concentration": 415.0, + "pressure": 1000.0, + "windSpeed": 0.5, + "windDirection": 20.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/light_rain.json b/ThreatSource/data/weathers/light_rain.json new file mode 100644 index 0000000..38bcfb5 --- /dev/null +++ b/ThreatSource/data/weathers/light_rain.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "小雨", + "en": "Light Rain" + }, + "type": "Rain", + "temperature": 20.0, + "relativeHumidity": 80.0, + "visibility": 6.0, + "precipitation": 5.0, + "cO2Concentration": 415.0, + "pressure": 1005.0, + "windSpeed": 3.0, + "windDirection": 180.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/light_snow.json b/ThreatSource/data/weathers/light_snow.json new file mode 100644 index 0000000..bb656e0 --- /dev/null +++ b/ThreatSource/data/weathers/light_snow.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "小雪", + "en": "Light Snow" + }, + "type": "Snow", + "temperature": -3.0, + "relativeHumidity": 75.0, + "visibility": 4.0, + "precipitation": 2.0, + "cO2Concentration": 410.0, + "pressure": 1002.0, + "windSpeed": 3.0, + "windDirection": 270.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/medium_fog.json b/ThreatSource/data/weathers/medium_fog.json new file mode 100644 index 0000000..5236375 --- /dev/null +++ b/ThreatSource/data/weathers/medium_fog.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "中雾", + "en": "Medium Fog" + }, + "type": "Fog", + "temperature": 10.0, + "relativeHumidity": 98.0, + "visibility": 0.4, + "precipitation": 0.0, + "cO2Concentration": 415.0, + "pressure": 1000.0, + "windSpeed": 0.2, + "windDirection": 10.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/medium_rain.json b/ThreatSource/data/weathers/medium_rain.json new file mode 100644 index 0000000..4fe1d6f --- /dev/null +++ b/ThreatSource/data/weathers/medium_rain.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "中雨", + "en": "Medium Rain" + }, + "type": "Rain", + "temperature": 18.0, + "relativeHumidity": 90.0, + "visibility": 4.0, + "precipitation": 15.0, + "cO2Concentration": 415.0, + "pressure": 995.0, + "windSpeed": 6.0, + "windDirection": 180.0 +} diff --git a/ThreatSource/data/weathers/medium_snow.json b/ThreatSource/data/weathers/medium_snow.json new file mode 100644 index 0000000..1b43fe4 --- /dev/null +++ b/ThreatSource/data/weathers/medium_snow.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "中雪", + "en": "Medium Snow" + }, + "type": "Snow", + "temperature": -5.0, + "relativeHumidity": 80.0, + "visibility": 2.0, + "precipitation": 4.0, + "cO2Concentration": 410.0, + "pressure": 1000.0, + "windSpeed": 4.0, + "windDirection": 270.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/sandstorm.json b/ThreatSource/data/weathers/sandstorm.json new file mode 100644 index 0000000..992bec2 --- /dev/null +++ b/ThreatSource/data/weathers/sandstorm.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "沙尘", + "en": "Sandstorm" + }, + "type": "Dust", + "temperature": 30.0, + "relativeHumidity": 25.0, + "visibility": 1.5, + "precipitation": 0.0, + "cO2Concentration": 430.0, + "pressure": 1005.0, + "windSpeed": 12.0, + "windDirection": 315.0 +} \ No newline at end of file diff --git a/ThreatSource/data/weathers/sunny.json b/ThreatSource/data/weathers/sunny.json new file mode 100644 index 0000000..6dbbffa --- /dev/null +++ b/ThreatSource/data/weathers/sunny.json @@ -0,0 +1,15 @@ +{ + "name": { + "zh": "晴天", + "en": "Sunny" + }, + "type": "Clear", + "temperature": 25.0, + "relativeHumidity": 45.0, + "visibility": 15.0, + "precipitation": 0.0, + "cO2Concentration": 415.0, + "pressure": 1018.0, + "windSpeed": 1.2, + "windDirection": 90.0 +} \ No newline at end of file diff --git a/ThreatSource/lib/AirTransmission.dll b/ThreatSource/lib/AirTransmission.dll new file mode 100644 index 0000000000000000000000000000000000000000..26c424a37d0d32835a02ed4f6a47ae1557d69fd3 GIT binary patch literal 18944 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 literal 0 HcmV?d00001 diff --git a/ThreatSource/lib/AirTransmission.xml b/ThreatSource/lib/AirTransmission.xml new file mode 100644 index 0000000..b54dc0c --- /dev/null +++ b/ThreatSource/lib/AirTransmission.xml @@ -0,0 +1,908 @@ + + + + AirTransmission + + + + + 天气参数结构体,用于封装天气相关的参数 + + + + + 辐射类型枚举,用于指定不同类型的电磁波 + + + + + 大气透过率计算器,提供各种电磁波在大气中传输的透过率计算方法 + + + 支持以下电磁波类型的透过率计算: + - 激光(包含湍流效应) + - 红外线 + - 紫外线 + - 毫米波 + 可以处理各种天气条件和烟雾环境 + + + + + 计算激光在给定天气条件和距离下的大气透过率 + + 天气条件 + 传输距离(米) + 大气透过率 + + + + 计算红外线在给定条件下的大气透过率 + + 天气条件 + 传输距离(米) + 大气透过率 + + + + 计算毫米波在给定条件下的大气透过率 + + 天气条件 + 传输距离(米) + 大气透过率 + + + + 计算紫外线在给定天气条件和距离下的大气透过率 + + 天气条件 + 传输距离(米) + 大气透过率 + + + + 计算湍流效应对激光透过率的影响 + + 天气条件 + 传输距离(米) + 传输高度(米) + 大气透过率 + + + + 计算烟幕对电磁波的透过率 + + 波长(微米) + 烟幕浓度(g/m³) + 烟幕厚度(米) + 烟幕透过率(0到1之间的值) + + + + 计算双程传输后接收到的辐射功率 + + 大气透过率 + 激光能量(焦耳) + 脉冲宽度(纳秒) + 目标距离(米) + 接收器距离(米) + 目标反射率 + 接收到的辐射功率(瓦特) + + + + 计算单程传输后接收到的辐射功率 + + 大气透过率 + 目标辐射(W/Sr) + 接收器距离(米) + 接收到的辐射功率(W/Sr) + + + + 导出函数:计算大气透过率 + + 辐射类型(0:激光, 1:红外, 2:紫外, 3:毫米波) + 波长(微米) + 传输距离(米) + 天气参数 + 透过率(0到1之间的值) + + + + 导出函数:计算大气湍流影响 + + 波长(微米) + 传输距离(米) + 天气参数 + 传输高度(米) + 湍流效应(0到1之间的值,1表示无影响,0表示完全衰减) + + + + 导出函数:计算烟幕透过率 + + 波长(微米) + 烟幕浓度(g/m³) + 烟幕厚度(米) + 烟幕透过率(0到1之间的值) + + + + 大气湍流模型类,用于计算大气湍流对光传输的影响 + + + 主要功能: + - 计算大气折射率结构常数 + - 计算湍流引起的光束抖动 + - 计算闪烁指数 + - 评估湍流对光传输的综合影响 + + + + + 波数常量,单位:m^-1 + + + 基于1.06微米波长(常用的Nd:YAG激光器波长)计算:k = 2π/λ + + + + + 计算大气湍流对光传输的综合影响 + + 传输距离(公里) + 传输高度(米) + 天气条件 + 湍流效应(0到1之间的值,1表示无影响,0表示完全衰减) + + + + 使用标准的 Hufnagel-Valley 模型计算大气折射率结构常数 + + 高度(米) + 风速(米/秒) + 大气折射率结构常数 + + + + 计算弗里德参数(Fried parameter) + + 大气折射率结构常数 + 传输距离(公里) + 弗里德参数(米) + + + + 计算闪烁指数(Scintillation Index) + + 大气折射率结构常数 + 波数 + 传输距离(公里) + 闪烁指数(无量纲) + + + + 计算光束漂移(Beam Wander) + + 大气折射率结构常数 + 传输距离(公里) + 传输高度(米) + 光束漂移(弧度) + + + + 计算相干长度(Coherence Length) + + 大气折射率结构常数 + 传输距离(公里) + 相干长度(米) + + + + 计算到达角(Angle of Arrival) + + 大气折射率结构常数 + 传输距离(公里) + 接收器口径(米) + 到达角(弧度) + + + + 计算等晕角(Isoplanatism Angle) + + 大气折射率结构常数 + 传输距离(公里) + 等晕角(弧度) + + + + 红外线透过率计算模型,用于计算红外线在大气中的传输特性 + + + 主要功能: + - 计算红外线在不同天气条件下的透过率 + - 使用光谱模型法进行计算 + - 考虑大气分子吸收(主要是水汽和CO2) + - 计算各种天气条件(雨、雪、雾、沙尘)的衰减效应 + + + + + 红外波段最小波长,单位:微米 + + + + + 红外波段最大波长,单位:微米 + + + + + 光谱分段数 + + + + + 主要计算波长,单位:微米 + + + 选择10μm作为主要计算波长,因为这是大气窗口区 + + + + + 计算给定距离的红外线透过率 + + 传输距离,单位:米 + 红外线透过率,范围:0-1 + + 计算过程: + 1. 将光谱分为多个波段 + 2. 对每个波段计算衰减 + 3. 考虑天气条件的影响 + 4. 综合得到最终透过率 + + + + + 计算特定波长的波段衰减 + + 波长,单位:微米 + 波段衰减系数,单位:km^-1 + + 包含三种衰减机制: + - 瑞利散射(Rayleigh散射) + - 米氏散射(Mie散射) + - 分子吸收 + + + + + 计算瑞利散射系数 + + 波长,单位:微米 + 瑞利散射系数,单位:km^-1 + + 使用改进的瑞利散射公式,考虑温度和压力的影响 + + + + + 计算米氏散射系数 + + 波长,单位:微米 + 米氏散射系数,单位:km^-1 + + 基于能见度和气溶胶密度计算米氏散射 + + + + + 计算分子吸收系数 + + 波长,单位:微米 + 分子吸收系数,单位:km^-1 + + 主要考虑水汽和CO2的吸收 + + + + + 获取特定波长的光谱权重 + + 波长,单位:微米 + 光谱权重,范围:0-1 + + 根据黑体辐射理论计算光谱权重 + + + + + 计算天气效应对透过率的影响 + + 传输距离,单位:米 + 天气影响因子,范围:0-1 + + 综合考虑: + - 降水(雨、雪)的影响 + - 雾的衰减效应 + - 沙尘的影响 + + + + + 激光透过率计算模型,用于计算激光在大气中的传输特性 + + + 主要功能: + - 计算激光在不同天气条件下的透过率 + - 考虑大气湍流效应 + - 处理烟雾对激光传输的影响 + - 计算各种天气条件(雨、雪、雾、沙尘)的衰减效应 + + + + + 激光透过率计算模型,用于计算激光在大气中的传输特性 + + + 主要功能: + - 计算激光在不同天气条件下的透过率 + - 考虑大气湍流效应 + - 处理烟雾对激光传输的影响 + - 计算各种天气条件(雨、雪、雾、沙尘)的衰减效应 + + + + + 激光波长常量,单位:微米 + + + 默认使用1.06μm波长,对应Nd:YAG激光器的基频输出 + + + + + 计算给定距离的激光透过率 + + 传输距离,单位:米 + 激光透过率,范围:0-1 + + 计算过程考虑: + - 分子散射和吸收 + - 气溶胶散射 + - 降水(雨、雪)衰减 + - 雾和沙尘的影响 + + + + + 计算雨对激光的衰减系数K + + 波长(微米) + 雨衰减系数K + + + + 计算雨对激光的衰减系数α + + 波长(微米) + 雨衰减系数α + + + + 计算雪对激光的衰减系数K + + 波长(微米) + 雪衰减系数K + + + + 计算雪对激光的衰减系数α + + 波长(微米) + 雪衰减系数α + + + + 计算激光的总衰减因子 + + 激光总衰减因子 + + + + 计算分子散射因子 + + 分子散射因子 + + + + 计算气溶胶散射因子 + + 气溶胶散射因子 + + + + 计算雾对激光的衰减 + + 传输路径长度(米) + 雾对激光的衰减 + + + + 毫米波透过率计算模型,用于计算毫米波在大气中的传输特性 + + + 主要功能: + - 计算毫米波在不同天气条件下的透过率 + - 考虑大气分子散射和吸收 + - 处理水汽和氧气的吸收 + - 计算各种天气条件(雨、雪、雾、沙尘)的衰减效应 + + 波长说明: + 虽然毫米波通常用毫米表示波长,但为了与其他电磁波计算保持一致, + 本模型中统一使用微米(μm)作为波长单位。 + 例如:3.19mm = 3190μm + + + + + 毫米波波长常量,单位:微米 + + + 3.19mm = 3190μm,对应94GHz频率 + 该频率是毫米波雷达常用工作频率 + + + + + 计算给定距离的毫米波透过率 + + 传输距离,单位:米 + 毫米波透过率,范围:0-1 + + 计算过程考虑: + - 分子散射和吸收 + - 水汽吸收 + - 氧气吸收 + - 降水(雨、雪)衰减 + - 雾和沙尘的影响 + + + + + 计算分子散射系数 + + 分子散射系数,单位:km^-1 + + 使用修正的瑞利散射公式,考虑温度和压力的影响 + + + + + 计算气溶胶散射系数 + + 气溶胶散射系数(km^-1) + + + + 计算水汽吸收系数 + + 水汽吸收系数(km^-1) + + + + 计算水汽密度 + + 水汽密度(g/m³) + + + + 计算氧气吸收系数 + + 氧气吸收系数(km^-1) + + + + 计算雾对毫米波的衰减 + + 传输路径长度(米) + 雾衰减 + + + + 烟幕透过率模型,用于计算不同波长电磁波在烟幕中的透过率 + + + + + 计算烟幕对电磁波的透过率 + + 波长(微米) + 烟幕浓度(g/m³) + 烟幕厚度(米) + 烟幕透过率(0到1之间的值) + + + + 根据波长获取烟幕衰减系数 + + 波长(微米) + 烟幕衰减系数(m²/g) + + + + 大气透过率计算的基础模型类,提供了各种大气条件下的透过率计算方法 + + + 包含以下主要衰减机制的计算: + - 分子散射和吸收 + - 气溶胶散射和吸收 + - 降水(雨、雪)衰减 + - 沙尘和雾的衰减 + + 所有波长相关计算统一使用微米(μm)作为单位: + - 激光:1.06μm + - 红外:3-12μm + - 紫外:0.2-0.4μm + - 毫米波:3190μm(3.19mm,对应94GHz) + + + + + 大气透过率计算的基础模型类,提供了各种大气条件下的透过率计算方法 + + + 包含以下主要衰减机制的计算: + - 分子散射和吸收 + - 气溶胶散射和吸收 + - 降水(雨、雪)衰减 + - 沙尘和雾的衰减 + + 所有波长相关计算统一使用微米(μm)作为单位: + - 激光:1.06μm + - 红外:3-12μm + - 紫外:0.2-0.4μm + - 毫米波:3190μm(3.19mm,对应94GHz) + + + + + 标准大气透过率常量 + + + 在标准大气条件下(23km能见度,1013.25hPa气压,20℃温度)的透过率值 + + + + + 标准能见度常量,单位:千米 + + + + + 标准气溶胶密度常量,单位:粒子/立方厘米 + + + + + 当前天气条件对象 + + + + + 温度,单位:开尔文 + + + 由摄氏度转换而来:K = ℃ + 273.15 + + + + + 大气压力(百帕) + + + + + 相对湿度(百分比) + + + + + 气溶胶密度(粒子/立方厘米) + + + + + 能见度(公里) + + + + + 是否下雨 + + + + + 降雨量(毫米/小时) + + + + + 是否有雾 + + + + + 是否有沙尘 + + + + + 是否下雪 + + + + + 降雪量(毫米/小时) + + + + + 二氧化碳浓度(ppm) + + + + + 计算给定距离的大气透过率 + + 传输距离(米) + 大气透过率(0到1之间的值) + + + + 根据能见度计算气溶胶密度 + + 能见度(公里) + 气溶胶密度(粒子/立方厘米) + + + + 计算雨对电磁波的衰减系数K + + 波长(微米) + 雨衰减系数K + + + + 计算雨对电磁波的衰减系数α + + 波长(微米) + 雨衰减系数α + + + + 计算雪对电磁波的衰减系数K + + 波长(微米) + 雪衰减系数K + + + + 计算雪对电磁波的衰减系数α + + 波长(微米) + 雪衰减系数α + + + + 计算雨对电磁波的衰减 + + 传输路径长度(米) + 波长(微米) + 雨衰减(dB) + + + + 计算雪对电磁波的衰减 + + 传输路径长度(米) + 波长(微米) + 雪衰减(dB) + + + + 计算沙尘对电磁波的衰减 + + 传输路径长度(米) + 沙尘衰减(dB) + + + + 计算能见度因子 + + 能见度因子 + + + + 紫外线透过率计算模型,用于计算紫外线在大气中的传输特性 + + + 主要功能: + - 计算紫外线在不同天气条件下的透过率 + - 使用光谱模型法进行计算 + - 考虑臭氧层吸收 + - 计算各种天气条件(雨、雪、雾、沙尘)的衰减效应 + + + + + 紫外波段最小波长,单位:微米 + + + + + 紫外波段最大波长,单位:微米 + + + + + 光谱分段数 + + + + + 主要计算波长,单位:微米 + + + 选择0.308μm作为主要计算波长,这是XeCl准分子激光器的输出波长 + + + + + 计算给定距离的紫外线透过率 + + 传输距离,单位:米 + 紫外线透过率,范围:0-1 + + 计算过程: + 1. 将光谱分为多个波段 + 2. 对每个波段计算衰减 + 3. 考虑天气条件的影响 + 4. 综合得到最终透过率 + + + + + 天气条件类,用于描述大气传输计算所需的天气参数 + + + 包含以下主要天气参数: + - 天气类型(晴天、雨天、雪天等) + - 温度 + - 相对湿度 + - 能见度 + - 降水量 + - CO2浓度 + + 天气类型 + 温度(摄氏度) + 相对湿度(百分比) + 能见度(公里) + 降水量(毫米/小时),可选 + 二氧化碳浓度(ppm),默认415ppm + 大气压力(hPa),默认1013.25hPa + 风速(m/s),默认0m/s + 风向(0-360度),默认0度 + + + + 天气条件类,用于描述大气传输计算所需的天气参数 + + + 包含以下主要天气参数: + - 天气类型(晴天、雨天、雪天等) + - 温度 + - 相对湿度 + - 能见度 + - 降水量 + - CO2浓度 + + 天气类型 + 温度(摄氏度) + 相对湿度(百分比) + 能见度(公里) + 降水量(毫米/小时),可选 + 二氧化碳浓度(ppm),默认415ppm + 大气压力(hPa),默认1013.25hPa + 风速(m/s),默认0m/s + 风向(0-360度),默认0度 + + + + 天气类型 + + + + + 温度(摄氏度) + + + + + 相对湿度(百分比) + + + + + 能见度(公里) + + + + + 降水量(毫米/小时) + + + + + 二氧化碳浓度(ppm) + + + + + 大气压力(hPa) + + + + + 风速(m/s) + + + + + 风向(0-360度, 0度为北, 顺时针) + + + + + 打印天气信息 + + 天气条件对象 + + 输出格式: + 天气类型: [类型], 温度: [温度]°C, 相对湿度: [湿度]%, 能见度: [能见度]km, 降水量: [降水量]mm/h, 大气压力: [大气压力]kPa, 风速: [风速]m/s, 风向: [风向]度 + + + + + 天气类型枚举 + + + + + 晴朗天气 + + + + + 雨天 + + + + + 雪天 + + + + + 雾天 + + + + + 沙尘天气 + + + + diff --git a/ThreatSource/src/Data/Models.cs b/ThreatSource/src/Data/DataModels.cs similarity index 82% rename from ThreatSource/src/Data/Models.cs rename to ThreatSource/src/Data/DataModels.cs index 43790bd..a3ab9e6 100644 --- a/ThreatSource/src/Data/Models.cs +++ b/ThreatSource/src/Data/DataModels.cs @@ -1,8 +1,7 @@ -using System.Collections.Generic; -using ThreatSource.Utils; using ThreatSource.Missile; using ThreatSource.Simulation; using ThreatSource.Target; +using AirTransmission; namespace ThreatSource.Data { /// @@ -432,4 +431,95 @@ namespace ThreatSource.Data return new ThermalPattern(ThermalPattern.StaticPattern, ThermalPattern.MovingPattern); } } + + /// + /// 天气数据模型 + /// + /// + /// 包含天气的基本信息和参数 + /// 用于创建和初始化天气实例 + /// + public class WeatherData + { + /// + /// 获取或设置天气的多语言名称 + /// + /// + /// 包含中英文名称 + /// 用于显示和文档 + /// + public LocalizedName Name { get; set; } = new(); + + /// + /// 获取或设置天气类型 + /// + /// + /// 可选值:Clear(晴天)、Rain(雨天)、Snow(雪天)、Fog(雾天)、Dust(沙尘天气) + /// + public WeatherType Type { get; set; } = WeatherType.Clear; + + /// + /// 获取或设置温度(摄氏度) + /// + /// + /// 影响大气透过率和探测效果 + /// + public double Temperature { get; set; } = 25.0; + + /// + /// 获取或设置相对湿度(百分比) + /// + /// + /// 影响大气透过率和探测效果 + /// + public double RelativeHumidity { get; set; } = 50.0; + + /// + /// 获取或设置能见度(公里) + /// + /// + /// 影响可视区域和探测范围 + /// + public double Visibility { get; set; } = 10.0; + + /// + /// 获取或设置降水量(毫米/小时) + /// + /// + /// 可选项,影响天气效果和探测精度 + /// + public double Precipitation { get; set; } = 0.0; + + /// + /// 获取或设置二氧化碳浓度(ppm) + /// + /// + /// 影响大气成分和透过率 + /// + public double CO2Concentration { get; set; } = 415.0; + + /// + /// 获取或设置大气压力(hPa) + /// + /// + /// 影响大气透过率和探测效果 + /// + public double Pressure { get; set; } = 1013.25; + + /// + /// 获取或设置风速(米/秒) + /// + /// + /// 影响弹道计算和飞行路径 + /// + public double WindSpeed { get; set; } = 0.0; + + /// + /// 获取或设置风向(角度,0为北,顺时针增加) + /// + /// + /// 影响弹道计算和飞行路径 + /// + public double WindDirection { get; set; } = 0.0; + } } \ No newline at end of file diff --git a/ThreatSource/src/Data/ThreatSourceDataManager.cs b/ThreatSource/src/Data/ThreatSourceDataManager.cs index c64a554..55ffe8c 100644 --- a/ThreatSource/src/Data/ThreatSourceDataManager.cs +++ b/ThreatSource/src/Data/ThreatSourceDataManager.cs @@ -36,6 +36,7 @@ namespace ThreatSource.Data private readonly Dictionary _indicators = new(); private readonly Dictionary _sensors = new(); private readonly Dictionary _targets = new(); + private readonly Dictionary _weathers = new(); /// /// 初始化威胁源数据管理器 @@ -59,6 +60,7 @@ namespace ThreatSource.Data LoadIndicators(Path.Combine(path, "indicators")); LoadSensors(Path.Combine(path, "sensors")); LoadTargets(Path.Combine(path, "targets")); + LoadWeathers(Path.Combine(path, "weathers")); } /// @@ -214,6 +216,39 @@ namespace ThreatSource.Data } } + /// + /// 加载天气数据 + /// + /// 天气数据目录路径 + private void LoadWeathers(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); + var data = JsonSerializer.Deserialize(jsonContent, _jsonOptions); + if (data != null) + { + string model = Path.GetFileNameWithoutExtension(file); + _weathers[model] = data; + Console.WriteLine($"已加载天气数据:{model}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"加载天气数据文件失败:{file},错误:{ex.Message}"); + Console.WriteLine($"异常堆栈:{ex.StackTrace}"); + } + } + } + /// /// 获取导弹配置数据 /// @@ -262,6 +297,18 @@ namespace ThreatSource.Data throw new KeyNotFoundException($"Target {model} not found"); } + /// + /// 获取天气配置数据 + /// + /// 天气类型 + /// 天气配置数据 + public WeatherData GetWeather(string weatherType) + { + if (_weathers.TryGetValue(weatherType, out var data)) + return data; + throw new KeyNotFoundException($"Weather {weatherType} not found"); + } + /// /// 获取所有可用的导弹ID列表 /// @@ -281,5 +328,10 @@ namespace ThreatSource.Data /// 获取所有可用的目标ID列表 /// public IEnumerable GetAvailableTargets() => _targets.Keys; + + /// + /// 获取所有可用的天气ID列表 + /// + public IEnumerable GetAvailableWeathers() => _weathers.Keys; } } \ No newline at end of file diff --git a/ThreatSource/src/Data/ThreatSourceFactory.cs b/ThreatSource/src/Data/ThreatSourceFactory.cs index 40265ab..8a1c927 100644 --- a/ThreatSource/src/Data/ThreatSourceFactory.cs +++ b/ThreatSource/src/Data/ThreatSourceFactory.cs @@ -3,6 +3,7 @@ using ThreatSource.Missile; using ThreatSource.Indicator; using ThreatSource.Target; using ThreatSource.Simulation; +using AirTransmission; // 直接引用AirTransmission命名空间,以便使用WeatherCondition namespace ThreatSource.Data { @@ -238,5 +239,26 @@ namespace ThreatSource.Data throw new ArgumentException($"不支持的目标类型: {data.Type}"); } } + + /// + /// 创建天气实例 + /// + /// 天气模型 + /// 天气条件 + public Weather CreateWeather(string weatherModel) + { + var data = _dataManager.GetWeather(weatherModel); + return new Weather( + data.Type, + data.Temperature, + data.RelativeHumidity, + data.Visibility, + data.Precipitation, + data.CO2Concentration, + data.Pressure, + data.WindSpeed, + data.WindDirection + ); + } } } \ No newline at end of file diff --git a/ThreatSource/src/Guidance/InfraredCommandGuidanceSystem.cs b/ThreatSource/src/Guidance/InfraredCommandGuidanceSystem.cs index b20fc30..ccf886b 100644 --- a/ThreatSource/src/Guidance/InfraredCommandGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/InfraredCommandGuidanceSystem.cs @@ -94,7 +94,7 @@ namespace ThreatSource.Guidance lastTrackerToTargetVector = Vector3D.Zero; lastDesiredDirection = Vector3D.Zero; turnRate = 0; - InitializeJamming(guidanceConfig.JammingResistanceThreshold, new List { JammingType.Infrared }); + InitializeJamming(guidanceConfig.JammingResistanceThreshold, [JammingType.Infrared]); } /// @@ -113,7 +113,14 @@ namespace ThreatSource.Guidance base.Update(deltaTime, missilePosition, missileVelocity); if (!IsJammed) { - CalculateGuidanceAcceleration(deltaTime); + if (HasGuidance) + { + CalculateGuidanceAcceleration(deltaTime); + } + else + { + GuidanceAcceleration = Vector3D.Zero; + } } else { @@ -152,43 +159,36 @@ namespace ThreatSource.Guidance /// - 生成制导指令 /// - 限制最大加速度 /// - protected void CalculateGuidanceAcceleration(double deltaTime) + protected void CalculateGuidanceAcceleration(double deltaTime) { - if (HasGuidance) - { - // 计算期望飞行方向(从导弹指向目标) - Vector3D currentDesiredDirection = (lastTrackerToTargetVector - lastTrackerToMissileVector).Normalize(); + // 计算期望飞行方向(从导弹指向目标) + Vector3D currentDesiredDirection = (lastTrackerToTargetVector - lastTrackerToMissileVector).Normalize(); - // 计算当前飞行方向 - Vector3D currentDirection = Velocity.Normalize(); - // 更新转向速率 - if (lastDesiredDirection != Vector3D.Zero) - { - double instantTurnRate = Vector3D.CrossProduct(lastDesiredDirection, currentDesiredDirection).Magnitude() / deltaTime; - turnRate = turnRate * (1 - TurnRateSmoothingFactor) + instantTurnRate * TurnRateSmoothingFactor; - } - - // 计算带有提前量的期望方向 - Vector3D leadDirection = Vector3D.CrossProduct(currentDesiredDirection, Vector3D.CrossProduct(currentDesiredDirection, currentDirection).Normalize()); - Vector3D desiredDirectionWithLead = (currentDesiredDirection + leadDirection * turnRate * LeadTimeFactor).Normalize(); - // 计算转向轴 - Vector3D turnAxis = Vector3D.CrossProduct(currentDirection, desiredDirectionWithLead).Normalize(); - // 计算所需转向角度 - double turnAngle = Vector3D.AngleBetween(currentDirection, desiredDirectionWithLead); - // 计算制导加速度 - double accelerationMagnitude = ProportionalNavigationCoefficient * turnAngle * Velocity.Magnitude(); - GuidanceAcceleration = Vector3D.CrossProduct(turnAxis, currentDirection) * accelerationMagnitude; - // 限制最大加速度 - if (GuidanceAcceleration.Magnitude() > MaxAcceleration) - { - GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration; - } - lastDesiredDirection = currentDesiredDirection; - } - else + // 计算当前飞行方向 + Vector3D currentDirection = Velocity.Normalize(); + // 更新转向速率 + if (lastDesiredDirection != Vector3D.Zero) { - GuidanceAcceleration = Vector3D.Zero; + double instantTurnRate = Vector3D.CrossProduct(lastDesiredDirection, currentDesiredDirection).Magnitude() / deltaTime; + turnRate = turnRate * (1 - TurnRateSmoothingFactor) + instantTurnRate * TurnRateSmoothingFactor; } + + // 计算带有提前量的期望方向 + Vector3D leadDirection = Vector3D.CrossProduct(currentDesiredDirection, Vector3D.CrossProduct(currentDesiredDirection, currentDirection).Normalize()); + Vector3D desiredDirectionWithLead = (currentDesiredDirection + leadDirection * turnRate * LeadTimeFactor).Normalize(); + // 计算转向轴 + Vector3D turnAxis = Vector3D.CrossProduct(currentDirection, desiredDirectionWithLead).Normalize(); + // 计算所需转向角度 + double turnAngle = Vector3D.AngleBetween(currentDirection, desiredDirectionWithLead); + // 计算制导加速度 + double accelerationMagnitude = ProportionalNavigationCoefficient * turnAngle * Velocity.Magnitude(); + GuidanceAcceleration = Vector3D.CrossProduct(turnAxis, currentDirection) * accelerationMagnitude; + // 限制最大加速度 + if (GuidanceAcceleration.Magnitude() > MaxAcceleration) + { + GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration; + } + lastDesiredDirection = currentDesiredDirection; } /// diff --git a/ThreatSource/src/Guidance/InfraredImageGenerator.cs b/ThreatSource/src/Guidance/InfraredImageGenerator.cs index 6c44906..9042584 100644 --- a/ThreatSource/src/Guidance/InfraredImageGenerator.cs +++ b/ThreatSource/src/Guidance/InfraredImageGenerator.cs @@ -1,6 +1,7 @@ using System; using ThreatSource.Target; using ThreatSource.Utils; +using AirTransmission; // 添加引用 namespace ThreatSource.Guidance { @@ -12,6 +13,7 @@ namespace ThreatSource.Guidance /// - 计算目标在图像平面上的投影 /// - 根据目标特性生成红外强度 /// - 添加背景噪声 + /// - 考虑大气透过率影响 /// public class InfraredImageGenerator { @@ -35,6 +37,11 @@ namespace ThreatSource.Guidance /// private readonly double backgroundIntensity; + /// + /// 红外波长,单位:微米 + /// + private readonly double wavelength; + /// /// 随机数生成器 /// @@ -52,16 +59,19 @@ namespace ThreatSource.Guidance /// 图像高度 /// 视场角 /// 背景辐射强度,单位:W/sr,典型地表背景约0.01-0.1 W/sr + /// 红外波长,单位:微米,默认为3.0(中波红外) public InfraredImageGenerator( int imageWidth = 640, int imageHeight = 512, double fieldOfView = Math.PI / 18, - double backgroundIntensity = 0.01) + double backgroundIntensity = 0.01, + double wavelength = 3.0) { this.imageWidth = imageWidth; this.imageHeight = imageHeight; this.fieldOfView = fieldOfView; this.backgroundIntensity = backgroundIntensity; + this.wavelength = wavelength; // Initialize coordinate system with default values forward = Vector3D.UnitZ; @@ -77,7 +87,7 @@ namespace ThreatSource.Guidance // 计算视线方向 forward = (targetPosition - missilePosition).Normalize(); - Console.WriteLine($"Line of sight direction: {forward}"); + Console.WriteLine($"视线方向: {forward}"); // 选择合适的上方向 Vector3D worldUp = Math.Abs(Vector3D.DotProduct(forward, Vector3D.UnitZ)) > 0.99 @@ -105,7 +115,7 @@ namespace ThreatSource.Guidance double angleX = Math.Atan2(x, z); double angleY = Math.Atan2(y, z); - Console.WriteLine($"Projection angles: X={angleX:F6} rad, Y={angleY:F6} rad"); + Console.WriteLine($"投影角度: X={angleX:F6} 弧度, Y={angleY:F6} 弧度"); return (angleX, angleY); } @@ -119,20 +129,46 @@ namespace ThreatSource.Guidance 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); } + /// + /// 计算大气透过率 + /// + /// 距离(米) + /// 天气条件 + /// 大气透过率(0-1之间) + private double CalculateAtmosphericTransmittance(double distance, Weather? weather) + { + double transmittance; + + if (weather == null) + { + // 如果没有天气信息,使用基于距离的简化模型 + transmittance = Math.Exp(-0.2 * distance / 1000.0); // 0.2/km的衰减率 + return transmittance; + } + + // 使用AtmosphereDllWrapper计算红外波段的透过率 + transmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance, + RadiationType.Infrared, + wavelength, + weather); + + return transmittance; + } + /// /// 生成目标的红外图像 /// /// 目标对象 /// 导弹位置 /// 导弹速度 + /// 天气条件 /// 红外图像 - public InfraredImage GenerateImage(ITarget target, Vector3D missilePosition, Vector3D missileVelocity) + public InfraredImage GenerateImage(ITarget target, Vector3D missilePosition, Vector3D missileVelocity, Weather? weather) { // 更新视线坐标系 UpdateLineOfSightFrame(missilePosition, target.Position); @@ -156,14 +192,13 @@ namespace ThreatSource.Guidance 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})"); + Console.WriteLine($"生成目标 {target.Id} 的图像,尺寸: {pixelLength}x{pixelWidth} 像素,目标中心: ({centerX}, {centerY})"); - // 生成目标图像 - GenerateTargetIntensity(image, centerX, centerY, pixelLength, pixelWidth, target, distance); + // 生成目标图像,传递距离参数 + GenerateTargetIntensity(image, centerX, centerY, pixelLength, pixelWidth, target, distance, weather); // 添加背景和噪声 - AddBackgroundAndNoise(image); + AddBackgroundAndNoise(image, weather); return image; } @@ -178,10 +213,14 @@ namespace ThreatSource.Guidance int pixelLength, int pixelWidth, ITarget target, - double distance) + double distance, + Weather? weather) { - // 计算目标辐射强度 - double targetIntensity = target.InfraredRadiationIntensity / Math.Pow(distance, 1.8); + // 计算大气透过率 + double transmittance = CalculateAtmosphericTransmittance(distance, weather); + + // 计算目标辐射强度,考虑距离和大气透过率的影响 + double targetIntensity = target.InfraredRadiationIntensity * transmittance / Math.Pow(distance, 1.8); // 计算分布参数 double sigmaX = pixelLength / 6.0; @@ -218,20 +257,41 @@ namespace ThreatSource.Guidance } } - Console.WriteLine($"Target intensity distribution:"); - Console.WriteLine($" Pixels set: {pixelsSet}"); - Console.WriteLine($" Max set intensity: {maxSetIntensity:F6} W/sr"); + Console.WriteLine($"目标强度分布: 像素设置: {pixelsSet}, 最大强度: {maxSetIntensity:F6} W/sr"); } /// /// 添加背景辐射和噪声 /// - private void AddBackgroundAndNoise(InfraredImage image) + private void AddBackgroundAndNoise(InfraredImage image, Weather? weather) { double maxIntensityBefore = double.MinValue; double maxIntensityAfter = double.MinValue; int pixelsModified = 0; + // 根据天气条件调整背景噪声水平 + double noiseLevel = 0.2; // 默认噪声水平 + double bgIntensity = backgroundIntensity; + + if (weather != null) + { + // 雾、雨、雪等天气增加背景噪声 + if (weather.Type == WeatherType.Fog) + { + noiseLevel = 0.5; + bgIntensity *= (1.0 + (1.0 - weather.Visibility / 10.0)); // 雾增加背景辐射 + } + else if (weather.Type == WeatherType.Rain || weather.Type == WeatherType.Snow) + { + noiseLevel = 0.3; + // 降水增加噪声水平 + if (weather.Precipitation > 0) + { + noiseLevel += 0.1 * Math.Min(1.0, weather.Precipitation / 10.0); + } + } + } + for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) @@ -240,14 +300,14 @@ namespace ThreatSource.Guidance maxIntensityBefore = Math.Max(maxIntensityBefore, currentIntensity); // 只在非目标区域添加背景 - if (currentIntensity < backgroundIntensity * 0.1) + if (currentIntensity < bgIntensity * 0.1) { - currentIntensity = backgroundIntensity; + currentIntensity = bgIntensity; pixelsModified++; } // 添加高斯噪声 - double noise = (random.NextDouble() - 0.5) * backgroundIntensity * 0.2; + double noise = (random.NextDouble() - 0.5) * bgIntensity * noiseLevel; currentIntensity += noise; // 确保非负 diff --git a/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs b/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs index eb70ab4..7b3c6a5 100644 --- a/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs @@ -4,6 +4,7 @@ using ThreatSource.Target; using ThreatSource.Utils; using ThreatSource.Jamming; using System.Diagnostics; +using AirTransmission; // 添加引用 namespace ThreatSource.Guidance { @@ -121,13 +122,15 @@ namespace ThreatSource.Guidance 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 ); - InitializeJamming(guidanceConfig.JammingResistanceThreshold, new List { JammingType.Infrared }); + InitializeJamming(guidanceConfig.JammingResistanceThreshold, [JammingType.Infrared]); SwitchToSearchMode(); // 初始化为搜索模式 } @@ -300,13 +303,15 @@ namespace ThreatSource.Guidance 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"); + Console.WriteLine($"切换到搜索模式, 视场角: {config.SearchFieldOfView * 180 / Math.PI} 度"); } /// @@ -322,13 +327,15 @@ namespace ThreatSource.Guidance { 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"); + Console.WriteLine($"切换到跟踪模式, 视场角: {config.TrackFieldOfView * 180 / Math.PI} 度"); } /// @@ -386,7 +393,7 @@ namespace ThreatSource.Guidance if (angle <= currentFov / 2) { // 生成红外图像 - var image = imageGenerator.GenerateImage(target, missilePosition, missileVelocity); + var image = imageGenerator.GenerateImage(target, missilePosition, missileVelocity, SimulationManager.CurrentWeather ); switch (currentMode) { diff --git a/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs b/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs index f2d06f4..10895d3 100644 --- a/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs +++ b/ThreatSource/src/Guidance/InfraredTargetRecognizer.cs @@ -118,23 +118,32 @@ namespace ThreatSource.Guidance /// 识别结果 public RecognitionResult RecognizeTarget(InfraredImage image, ITarget target) { - // 1. 图像分割,提取目标区域 + // 图像分割,提取目标区域 var segment = SegmentTarget(image); if (!segment.IsValid) { - Console.WriteLine("No valid segment found in image"); + Console.WriteLine("没有有效的分割区域"); return new RecognitionResult(TargetType.Unknown, 0.0, (0, 0), (0, 0)); } - // 2. 提取目标特征 + // 检查目标区域尺寸是否足够大 + int minRequiredWidth = 10; + int minRequiredHeight = 5; + if (segment.Size.Width < minRequiredWidth && segment.Size.Height < minRequiredHeight) + { + Console.WriteLine($"目标区域过小: {segment.Size.Width}x{segment.Size.Height} 像素,低于最小要求 {minRequiredWidth}x{minRequiredHeight}"); + return new RecognitionResult(TargetType.Unknown, 0.0, segment.Center, segment.Size); + } + + // 提取目标特征 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}"); + Console.WriteLine($"提取的特征: 长宽比={features.AspectRatio:F2}, 尺寸={features.Size:F2}, 强度模式={features.IntensityPattern:F2}, 温度梯度={features.TemperatureGradient:F2}"); - // 3. 特征匹配和分类 + // 特征匹配和分类 var (type, confidence) = ClassifyTarget(features); - Console.WriteLine($"Classification result: Type={type}, Confidence={confidence:F2}"); + Console.WriteLine($"分类结果: 类型={type}, 置信度={confidence:F2}"); - // 4. 返回识别结果 + // 返回识别结果 return new RecognitionResult( type, confidence, @@ -172,12 +181,12 @@ namespace ThreatSource.Guidance } } - Console.WriteLine($"Segmentation results:"); - Console.WriteLine($" Pixels above threshold: {pixelsAboveThreshold}"); + Console.WriteLine($"分割结果:"); + Console.WriteLine($" 像素超过阈值: {pixelsAboveThreshold}"); if (found) { - Console.WriteLine($" Target bounds: ({minX},{minY}) to ({maxX},{maxY})"); - Console.WriteLine($" Target size: {maxX - minX + 1}x{maxY - minY + 1} pixels"); + Console.WriteLine($" 目标边界: ({minX},{minY}) 到 ({maxX},{maxY})"); + Console.WriteLine($" 目标尺寸: {maxX - minX + 1}x{maxY - minY + 1} 像素"); } if (!found) @@ -225,13 +234,13 @@ namespace ThreatSource.Guidance // 取两个基准中的较大值作为最终阈值 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}"); + Console.WriteLine($"图像统计:"); + Console.WriteLine($" 最大强度: {maxIntensity:F6}"); + Console.WriteLine($" 最小强度: {minIntensity:F6}"); + Console.WriteLine($" 平均强度: {mean:F6}"); + Console.WriteLine($" 背景阈值: {backgroundThreshold:F6}"); + Console.WriteLine($" 目标阈值: {targetThreshold:F6}"); + Console.WriteLine($" 最终阈值: {threshold:F6}"); return threshold; } @@ -312,7 +321,7 @@ namespace ThreatSource.Guidance double[,] thermalPattern = target.GetCurrentThermalPattern(); if (thermalPattern == null) { - Console.WriteLine("No thermal pattern available, using image-based gradient calculation"); + Console.WriteLine("没有温度分布数据, 使用图像计算梯度"); return CalculateImageBasedGradient(image, segment); } @@ -320,7 +329,7 @@ namespace ThreatSource.Guidance // 判断目标是否在运动 bool isMoving = IsTargetMoving(image, segment); - Console.WriteLine($"Target movement status: {(isMoving ? "Moving" : "Static")}"); + Console.WriteLine($"目标运动状态: {(isMoving ? "移动" : "静止")}"); // 使用温度分布模式计算梯度特征 double gradientFeature = pattern.CalculateGradientFeature(isMoving); @@ -550,7 +559,7 @@ namespace ThreatSource.Guidance foreach (var kvp in targetFeatures) { double score = CalculateMatchScore(features, kvp.Value, weights); - Console.WriteLine($"Match score for {kvp.Key}: {score:F2}"); + Console.WriteLine($"匹配得分: {kvp.Key}: {score:F2}"); if (score > bestScore) { bestScore = score; @@ -560,7 +569,7 @@ namespace ThreatSource.Guidance // 使用自适应阈值 double threshold = CalculateAdaptiveThreshold(features); - Console.WriteLine($"Adaptive threshold: {threshold:F2}"); + Console.WriteLine($"自适应阈值: {threshold:F2}"); return bestScore > threshold ? (bestMatch, bestScore) : @@ -613,11 +622,11 @@ namespace ThreatSource.Guidance 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})"); + Console.WriteLine($"特征匹配得分:"); + Console.WriteLine($" 长宽比: {aspectRatioScore:F2} (权重: {weights[0]:F2})"); + Console.WriteLine($" 尺寸: {sizeScore:F2} (权重: {weights[1]:F2})"); + Console.WriteLine($" 模式: {patternScore:F2} (权重: {weights[2]:F2})"); + Console.WriteLine($" 梯度: {gradientScore:F2} (权重: {weights[3]:F2})"); // 加权平均 double totalScore = aspectRatioScore * weights[0] + @@ -625,7 +634,7 @@ namespace ThreatSource.Guidance patternScore * weights[2] + gradientScore * weights[3]; - Console.WriteLine($" Total Score: {totalScore:F2}"); + Console.WriteLine($" 总得分: {totalScore:F2}"); return totalScore; } diff --git a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs index 6e4a2c4..f9c8108 100644 --- a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs @@ -2,6 +2,7 @@ using ThreatSource.Utils; using ThreatSource.Simulation; using System.Diagnostics; using ThreatSource.Jamming; +using AirTransmission; namespace ThreatSource.Guidance { @@ -193,7 +194,7 @@ namespace ThreatSource.Guidance IsCodeEnabled = true, IsCodeMatchRequired = true }; - InitializeJamming(guidanceConfig.JammingResistanceThreshold, new List { JammingType.Laser }); + InitializeJamming(guidanceConfig.JammingResistanceThreshold, [JammingType.Laser]); } /// @@ -404,6 +405,7 @@ namespace ThreatSource.Guidance } else { + HasGuidance = false; GuidanceAcceleration = Vector3D.Zero; } } @@ -482,8 +484,19 @@ namespace ThreatSource.Guidance double receivedPower = powerDensity * detectorArea; // 考虑大气衰减(可选) - // double atmosphericTransmittance = Math.Exp(-attenuationCoefficient * distance); - // receivedPower *= atmosphericTransmittance; + // 计算大气透过率,如果当前天气为null,则认为大气透过率为1.0 + double atmosphericTransmittance = 1.0; + + if(SimulationManager.CurrentWeather != null) + { + atmosphericTransmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance, + RadiationType.Laser, + config.LaserWavelength, + SimulationManager.CurrentWeather); + } + + receivedPower *= atmosphericTransmittance; return receivedPower; } @@ -504,12 +517,6 @@ namespace ThreatSource.Guidance /// protected void CalculateGuidanceAcceleration(double deltaTime) { - if (!HasGuidance) - { - GuidanceAcceleration = Vector3D.Zero; - return; - } - // 计算导弹到激光束的最短距离 Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam(); diff --git a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs index 743a30c..0b35187 100644 --- a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs @@ -4,9 +4,7 @@ using ThreatSource.Sensor; using ThreatSource.Indicator; using System.Diagnostics; using ThreatSource.Jamming; -using System; -using System.Collections.Generic; -using System.Linq; +using AirTransmission; namespace ThreatSource.Guidance { @@ -34,6 +32,15 @@ namespace ThreatSource.Guidance /// private Vector3D TargetPosition { get; set; } + /// + /// 获取或设置接收到的激光功率 + /// + /// + /// 记录接收到的激光功率 + /// 用于制导计算 + /// + private double ReceivedLaserPower { get; set; } + /// /// 获取或设置激光照射状态 /// @@ -43,33 +50,6 @@ namespace ThreatSource.Guidance /// private bool LaserIlluminationOn { get; set; } - /// - /// 获取或设置激光指示器位置 - /// - /// - /// 记录激光发射源的三维位置 - /// 用于功率计算 - /// - private Vector3D LaserDesignatorPosition { get; set; } - - /// - /// 获取或设置激光功率,单位:瓦特 - /// - /// - /// 记录激光源的发射功率 - /// 影响系统的探测距离 - /// - private double LaserPower { get; set; } - - /// - /// 获取或设置激光发散角,单位:弧度 - /// - /// - /// 记录激光束的发散角度 - /// 影响光斑大小和功率密度 - /// - private double LaserDivergenceAngle { get; set; } - /// /// 获取或设置期望的激光编码 /// @@ -87,12 +67,12 @@ namespace ThreatSource.Guidance /// 定义导弹支持的编码类型 /// 默认支持PRF、PPM和PWM编码 /// - private readonly List supportedCodeTypes = new List - { + private readonly List supportedCodeTypes = + [ LaserCodeType.PRF, LaserCodeType.PPM, LaserCodeType.PWM - }; + ]; /// /// 四象限探测器实例 @@ -110,29 +90,32 @@ namespace ThreatSource.Guidance /// /// 定义了四象限探测器对光斑偏移的响应灵敏度 /// 影响制导系统的响应速度和稳定性 - /// 典型值为0.5 + /// 典型值为0.05 /// - private double SpotOffsetSensitivity { get; set; } = 0.5; + private double SpotOffsetSensitivity { get; set; } = 0.05; /// - /// 当前跟踪的目标ID + /// 上一次的制导加速度,用于平滑处理 /// - private string? CurrentTargetId { get; set; } + /// + /// 用于实现加速度平滑处理 + /// 减少加速度突变,使导弹飞行更稳定 + /// + private Vector3D PreviousGuidanceAcceleration { get; set; } = Vector3D.Zero; /// - /// 激光源列表,包括真实目标和诱偏目标 + /// 加速度平滑系数 /// - private readonly List<(SimulationElement Source, Vector3D Position, double Power)> laserSources = []; + /// + /// 范围(0,1],值越小平滑效果越强 + /// 影响加速度的平滑程度 + /// + private const double AccelerationSmoothingFactor = 0.5; /// - /// 上次更新激光源的时间 + /// 激光目标列表,包括真实目标和诱偏目标 /// - private DateTime LastLaserSourceUpdateTime { get; set; } = DateTime.MinValue; - - /// - /// 激光源更新间隔,单位:秒 - /// - private double LaserSourceUpdateInterval { get; set; } = 0.1; + private readonly List<(SimulationElement Target, SimulationElement Source)> laserTargets = []; /// /// 初始化激光半主动制导系统的新实例 @@ -164,8 +147,6 @@ namespace ThreatSource.Guidance TargetPosition = Vector3D.Zero; LaserIlluminationOn = false; - LaserDesignatorPosition = Vector3D.Zero; - LaserPower = 0; InternalLaserCodeConfig = laserCodeConfig; // 创建四象限探测器实例,使用配置中的参数 @@ -177,7 +158,10 @@ namespace ThreatSource.Guidance // 设置光斑偏移灵敏度 SpotOffsetSensitivity = config.SpotOffsetSensitivity; - InitializeJamming(guidanceConfig.JammingResistanceThreshold, new List { JammingType.Laser }); + // 初始化加速度平滑处理 + PreviousGuidanceAcceleration = Vector3D.Zero; + + InitializeJamming(guidanceConfig.JammingResistanceThreshold, [JammingType.Laser]); } /// @@ -193,11 +177,13 @@ namespace ThreatSource.Guidance { base.Activate(); // 订阅激光照射事件 - SimulationManager.SubscribeToEvent(OnLaserIlluminationStart); SimulationManager.SubscribeToEvent(OnLaserIlluminationUpdate); SimulationManager.SubscribeToEvent(OnLaserIlluminationStop); // 订阅激光干扰事件 SimulationManager.SubscribeToEvent(OnLaserJamming); + + // 订阅诱偏目标照射事件 + SimulationManager.SubscribeToEvent(OnDecoyTargetIllumination); } /// @@ -212,41 +198,14 @@ namespace ThreatSource.Guidance { base.Deactivate(); // 取消订阅激光照射事件 - SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStart); SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationUpdate); SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStop); - SimulationManager.UnsubscribeFromEvent(OnLaserJamming); - } - /// - /// 处理激光照射开始事件 - /// - /// 激光照射开始事件 - private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt) - { - if (evt?.LaserDesignatorId != null && evt?.TargetId != null) - { - try - { - LaserDesignator laserDesignator = SimulationManager.GetEntityById(evt.LaserDesignatorId) as LaserDesignator ?? throw new Exception("激光指示器不存在"); - SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在"); - - // 更新激光指示器信息 - UpdateLaserDesignator(laserDesignator.Position, target.Position, - laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle); - - // 处理激光照射开始事件 - ProcessLaserIlluminationEvent(evt); - } - catch (Exception ex) - { - Trace.WriteLine($"处理激光照射开始事件时出错: {ex.Message}"); - } - } - else - { - Trace.WriteLine("警告:激光照射开始事件缺少必要参数"); - } + // 取消订阅激光干扰事件 + SimulationManager.UnsubscribeFromEvent(OnLaserJamming); + + // 取消订阅诱偏目标照射事件 + SimulationManager.UnsubscribeFromEvent(OnDecoyTargetIllumination); } /// @@ -261,11 +220,13 @@ namespace ThreatSource.Guidance { LaserDesignator laserDesignator = SimulationManager.GetEntityById(evt.LaserDesignatorId) as LaserDesignator ?? throw new Exception("激光指示器不存在"); SimulationElement target = SimulationManager.GetEntityById(evt.TargetId) as SimulationElement ?? throw new Exception("目标不存在"); - - // 更新激光指示器信息 - UpdateLaserDesignator(laserDesignator.Position, target.Position, - laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle); + // 添加激光目标 + if (!laserTargets.Any(t => t.Target.Id == target.Id)) + { + laserTargets.Add((target, laserDesignator)); + } + // 处理激光照射更新事件 ProcessLaserIlluminationUpdateEvent(evt); } @@ -285,12 +246,29 @@ namespace ThreatSource.Guidance /// /// 激光照射停止事件 private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt) - { - // 停用激光指示器 - DeactivateLaserDesignator(); - + { LaserIlluminationOn = false; HasGuidance = false; // 禁用制导 + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 + } + + /// + /// 处理诱偏目标照射事件 + /// + /// 诱偏目标照射事件 + private void OnDecoyTargetIllumination(DecoyTargetIlluminationEvent evt) + { + if (evt?.DecoyTargetId != null) + { + DecoyTarget decoyTarget = SimulationManager.GetEntityById(evt.DecoyTargetId) as DecoyTarget ?? throw new Exception("诱偏目标不存在"); + SimulationElement decoySource = SimulationManager.GetEntityById(decoyTarget.SourceId) as SimulationElement ?? throw new Exception("诱偏源不存在"); + + if (!laserTargets.Any(t => t.Target.Id == decoyTarget.Id)) + { + laserTargets.Add((decoyTarget, decoySource)); + } + Console.WriteLine($"诱偏目标照射事件,诱偏目标ID: {evt.DecoyTargetId},诱偏源ID: {decoySource.Id},诱偏目标位置: {decoyTarget.Position}"); + } } /// @@ -344,6 +322,7 @@ namespace ThreatSource.Guidance { LaserIlluminationOn = false; HasGuidance = false; + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 } } } @@ -362,49 +341,6 @@ namespace ThreatSource.Guidance } } - /// - /// 更新激光指示器参数 - /// - /// 激光源位置,单位:米 - /// 目标位置,单位:米 - /// 激光功率,单位:瓦特 - /// 激光发散角,单位:弧度 - /// - /// 更新过程: - /// - 激活激光照射 - /// - 更新位置信息 - /// - 更新目标信息 - /// - 更新激光参数 - /// - public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, double laserPower, double laserDivergenceAngle) - { - LaserIlluminationOn = true; - LaserDesignatorPosition = sourcePosition; - TargetPosition = targetPosition; - LaserPower = laserPower; - LaserDivergenceAngle = laserDivergenceAngle; - } - - /// - /// 关闭激光照射系统 - /// - /// - /// 关闭过程: - /// - 停止激光照射 - /// - 清除位置信息 - /// - 清除目标信息 - /// - 清除激光参数 - /// - 重置光斑偏移标志 - /// - public void DeactivateLaserDesignator() - { - LaserIlluminationOn = false; - LaserDesignatorPosition = Vector3D.Zero; - TargetPosition = Vector3D.Zero; - LaserPower = 0; - LaserDivergenceAngle = 0; - } - /// /// 更新制导系统的状态和计算结果 /// @@ -416,16 +352,9 @@ namespace ThreatSource.Guidance base.Update(deltaTime, missilePosition, missileVelocity); if (!IsJammed) - { - // 定期更新视野内的激光源 - if ((DateTime.Now - LastLaserSourceUpdateTime).TotalSeconds >= LaserSourceUpdateInterval) - { - UpdateLaserSources(); - LastLaserSourceUpdateTime = DateTime.Now; - } - + { // 处理接收到的所有激光信号 - ProcessLaserSignals(); + ProcessLaserTargets(); if (LaserIlluminationOn) { @@ -439,138 +368,102 @@ namespace ThreatSource.Guidance else { GuidanceAcceleration = Vector3D.Zero; + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 } } else { HasGuidance = false; GuidanceAcceleration = Vector3D.Zero; + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 } } else { HasGuidance = false; GuidanceAcceleration = Vector3D.Zero; - } - } - - /// - /// 更新视野内的激光源 - /// - /// - /// 收集视野内的所有激光源,包括真实目标和诱偏目标 - /// - private void UpdateLaserSources() - { - try - { - // 清空现有激光源 - laserSources.Clear(); - - // 如果当前有激光照射的真实目标,添加到激光源列表 - if (TargetPosition != Vector3D.Zero && LaserIlluminationOn) - { - if (SimulationManager.GetEntityById(CurrentTargetId ?? "") is SimulationElement targetEntity) - { - laserSources.Add((targetEntity, TargetPosition, LaserPower)); - } - } - - // 获取所有诱偏目标 - var decoyTargets = SimulationManager.GetEntitiesByType(); - foreach (var decoy in decoyTargets) - { - if (decoy.IsActive()) - { - laserSources.Add((decoy, decoy.Position, decoy.DecoyPower)); - } - } - - Debug.WriteLine($"更新激光源: 共{laserSources.Count}个激光源"); - } - catch (Exception ex) - { - Trace.WriteLine($"更新激光源时出错: {ex.Message}"); + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 } } /// - /// 处理接收到的所有激光信号 + /// 处理接收到的所有激光目标 /// /// - /// 基于接收到的激光信号计算合成光斑位置 + /// 基于接收到的激光目标计算合成光斑位置 /// - private void ProcessLaserSignals() + private void ProcessLaserTargets() { try { + Console.WriteLine($"处理激光信号: 激光目标数量={laserTargets.Count}"); + // 如果没有激光源,返回 - if (laserSources.Count == 0) + if (laserTargets.Count == 0) { LaserIlluminationOn = false; return; } // 计算所有激光源的总接收功率和加权位置 - double totalPower = 0; + ReceivedLaserPower = 0.0; Vector3D weightedPosition = Vector3D.Zero; - Vector3D weightedSourcePosition = Vector3D.Zero; - double weightedPower = 0; - foreach (var source in laserSources) + foreach (var target in laserTargets) { - // 计算接收功率 - double receivedPower = CalculateReceivedPower(source.Position); - // 计算角度偏差,判断是否在视野范围内 - double angleDeviation = CalculateAngleDeviation(source.Position); + double angleDeviation = CalculateAngleDeviation(target.Target.Position); if (angleDeviation > config.FieldOfViewAngleInRadians / 2) { + Console.WriteLine($"处理激光信号: 目标超出视野范围,目标ID: {target.Target.Id}"); continue; // 目标超出视野范围 } + + double receivedPower = 0; + Console.WriteLine($"处理激光信号: 目标ID: {target.Target.Id}"); + if (target.Target is DecoyTarget decoy) + { + // 计算接收功率 + receivedPower = CalculateReceivedPower(target.Source.Position, target.Target.Position, decoy.DecoyPower, decoy.DecoyLaserDivergenceAngle); + Console.WriteLine($"处理激光信号: 诱偏目标接收功率={receivedPower:E}W, 诱偏目标ID: {target.Target.Id}"); + } + else if (target.Source is LaserDesignator laserDesignator) + { + // 计算接收功率 + receivedPower = CalculateReceivedPower(target.Source.Position, target.Target.Position, laserDesignator.LaserPower, laserDesignator.LaserDivergenceAngle); + Console.WriteLine($"处理激光信号: 真实目标接收功率={receivedPower:E}W, 真实目标ID: {target.Target.Id}"); + } // 累加功率 - totalPower += receivedPower; + ReceivedLaserPower += receivedPower; + Console.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W"); // 加权位置 - weightedPosition += source.Position * receivedPower; - - // 如果是诱偏目标,获取其诱偏源位置和功率 - if (source.Source is DecoyTarget decoy) - { - weightedSourcePosition += decoy.SourcePosition * receivedPower; - weightedPower += decoy.DecoyPower * receivedPower; - } - else - { - // 对于真实目标,使用已知的LaserDesignatorPosition - weightedSourcePosition += LaserDesignatorPosition * receivedPower; - weightedPower += LaserPower * receivedPower; - } + weightedPosition += target.Target.Position * receivedPower; + Console.WriteLine($"处理激光信号: 加权位置={weightedPosition}"); } // 如果总功率为0,表示没有在视野范围内的激光源 - if (totalPower <= 0) + if (ReceivedLaserPower <= 0) { LaserIlluminationOn = false; return; } // 计算加权平均位置 - TargetPosition = weightedPosition / totalPower; + TargetPosition = weightedPosition / ReceivedLaserPower; + + Console.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 加权平均目标位置={TargetPosition}"); // 更新激光照射参数 - LaserIlluminationOn = true; - LaserDesignatorPosition = weightedSourcePosition / totalPower; - LaserPower = weightedPower / totalPower; - + LaserIlluminationOn = true; // 计算光斑偏移 Vector2D spotOffset = CalculateSpotOffset(); // 将合成激光信号传递给四象限探测器 - quadrantDetector.ProcessLaserSignal(totalPower, spotOffset); + quadrantDetector.ProcessLaserSignal(ReceivedLaserPower, spotOffset); - Debug.WriteLine($"处理激光信号: 总功率={totalPower:E}W, 目标位置={TargetPosition}"); + Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 目标位置={TargetPosition}"); } catch (Exception ex) { @@ -581,18 +474,41 @@ namespace ThreatSource.Guidance /// /// 计算从特定位置接收到的激光功率 /// + /// 激光源位置 /// 目标位置 + /// 激光功率 + /// 激光发散角 /// 接收到的激光功率,单位:瓦特 - private double CalculateReceivedPower(Vector3D targetPos) + private double CalculateReceivedPower(Vector3D sourcePos, Vector3D targetPos, double laserPower, double laserDivergenceAngle) { - double distanceDesignatorToTarget = (LaserDesignatorPosition - targetPos).Magnitude(); + double distanceDesignatorToTarget = (sourcePos - targetPos).Magnitude(); double distanceMissileToTarget = (Position - targetPos).Magnitude(); + // 计算大气透过率 (1.使用从激光源到目标的单程透过率,2.使用从目标到导弹的单程透过率) + // 如果当前天气为null,则认为大气透过率为1.0 + double atmosphericTransmittanceToTarget = 1.0; + double atmosphericTransmittanceToMissile = 1.0; + + if(SimulationManager.CurrentWeather != null) + { + atmosphericTransmittanceToTarget = AtmosphereDllWrapper.CalculateTransmittance( + distanceDesignatorToTarget, + RadiationType.Laser, + config.LaserWavelength, + SimulationManager.CurrentWeather); + + atmosphericTransmittanceToMissile = AtmosphereDllWrapper.CalculateTransmittance( + distanceMissileToTarget, + RadiationType.Laser, + config.LaserWavelength, + SimulationManager.CurrentWeather); + } + // 计算目标处的光斑面积 - double spotAreaAtTarget = Math.PI * Math.Pow(distanceDesignatorToTarget * Math.Tan(LaserDivergenceAngle), 2); + double spotAreaAtTarget = Math.PI * Math.Pow(distanceDesignatorToTarget * Math.Tan(laserDivergenceAngle), 2); - // 计算目标处的激光功率密度 - double powerDensityAtTarget = LaserPower / spotAreaAtTarget; + // 计算目标处的激光功率密度,考虑大气衰减和发射系统透过率 + double powerDensityAtTarget = laserPower * atmosphericTransmittanceToTarget * config.TransmitterEfficiency / spotAreaAtTarget; // 计算从目标反射的总功率 double reflectedPower = powerDensityAtTarget * config.TargetReflectiveArea * config.ReflectionCoefficient; @@ -600,8 +516,8 @@ namespace ThreatSource.Guidance // 计算反射光在导弹处的扩散面积(假设漫反射) double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceMissileToTarget, 2); - // 计算导弹接收到的功率 - double receivedPower = reflectedPower / reflectedSpotArea; + // 计算导弹接收到的功率,考虑大气衰减和接收系统透过率 + double receivedPower = reflectedPower * atmosphericTransmittanceToMissile * config.ReceiverEfficiency / reflectedSpotArea; // 计算镜头接收到的功率比例 double lensArea = Math.PI * Math.Pow(config.LensDiameter / 2, 2); @@ -615,6 +531,10 @@ namespace ThreatSource.Guidance // 计算最终接收到的功率 double finalReceivedPower = receivedPower * powerRatio * focusingFactor; + + Debug.WriteLine($"激光功率计算: 源->目标距离={distanceDesignatorToTarget:F1}m (透过率={atmosphericTransmittanceToTarget:F3}), " + + $"目标->导弹距离={distanceMissileToTarget:F1}m (透过率={atmosphericTransmittanceToMissile:F3}), " + + $"最终功率={finalReceivedPower:E}W"); return finalReceivedPower; } @@ -698,6 +618,7 @@ namespace ThreatSource.Guidance /// - 使用四象限探测器获取目标方向 /// - 计算比例导引加速度 /// - 限制最大加速度 + /// - 应用加速度平滑处理 /// protected void CalculateGuidanceAcceleration(double deltaTime) { @@ -719,15 +640,22 @@ namespace ThreatSource.Guidance guidanceDirection = guidanceDirection.Normalize() * 0.01; } - // 计算制导加速度,与速度垂直 - GuidanceAcceleration = guidanceDirection * ProportionalNavigationCoefficient * Velocity.Magnitude(); + // 计算新的制导加速度,与速度垂直 + Vector3D newGuidanceAcceleration = guidanceDirection * ProportionalNavigationCoefficient * Velocity.Magnitude(); // 限制最大加速度 double maxAcceleration = MaxAcceleration; - if (GuidanceAcceleration.Magnitude() > maxAcceleration) + if (newGuidanceAcceleration.Magnitude() > maxAcceleration) { - GuidanceAcceleration = GuidanceAcceleration.Normalize() * maxAcceleration; + newGuidanceAcceleration = newGuidanceAcceleration.Normalize() * maxAcceleration; } + + // 应用加速度平滑处理 + GuidanceAcceleration = PreviousGuidanceAcceleration * (1 - AccelerationSmoothingFactor) + + newGuidanceAcceleration * AccelerationSmoothingFactor; + + // 保存当前加速度用于下次平滑计算 + PreviousGuidanceAcceleration = GuidanceAcceleration; } /// @@ -745,8 +673,7 @@ namespace ThreatSource.Guidance public override string GetStatus() { return base.GetStatus() + - $" 激光目标指示器功率: {LaserPower}," + - $" 接收到的激光功率: {CalculateReceivedPower(TargetPosition):E} W," + + $" 接收到的激光功率: {ReceivedLaserPower:E} W," + $" 锁定阈值: {config.LockThreshold:E} W," + $" 四象限探测器: {quadrantDetector.GetStatus()}"; } @@ -845,28 +772,6 @@ namespace ThreatSource.Guidance } } - /// - /// 处理激光照射事件 - /// - /// 激光照射事件 - /// - /// 处理过程: - /// - 检查编码是否匹配 - /// - 如果要求匹配且不匹配,则忽略信号 - /// - 如果匹配或不要求匹配,则处理信号 - /// - 更新激光照射状态 - /// - 计算接收到的激光功率 - /// - 计算光斑偏移并传递给四象限探测器 - /// - 根据四象限探测器的锁定状态更新制导状态 - /// - public void ProcessLaserIlluminationEvent(LaserIlluminationStartEvent illuminationEvent) - { - ProcessLaserIlluminationCommon( - illuminationEvent.LaserDesignatorId, - illuminationEvent.LaserCodeConfig, - true); // 初始照射 - } - /// /// 处理激光照射更新事件 /// @@ -877,74 +782,29 @@ namespace ThreatSource.Guidance /// - 如果要求匹配且不匹配,则忽略信号 /// - 如果匹配或不要求匹配,则处理信号 /// - 更新激光照射状态 - /// - 计算接收到的激光功率 - /// - 计算光斑偏移并传递给四象限探测器 - /// - 根据四象限探测器的锁定状态更新制导状态 /// public void ProcessLaserIlluminationUpdateEvent(LaserIlluminationUpdateEvent illuminationEvent) { - ProcessLaserIlluminationCommon( - illuminationEvent.LaserDesignatorId, - illuminationEvent.LaserCodeConfig, - false); // 更新照射 - } - - /// - /// 处理激光照射事件的共同逻辑 - /// - /// 激光指示器ID - /// 激光编码配置 - /// 是否是初始照射(开始事件) - /// - /// 处理过程: - /// - 检查编码是否匹配 - /// - 如果要求匹配且不匹配,则忽略信号 - /// - 如果匹配或不要求匹配,则处理信号 - /// - 更新激光照射状态 - /// - 计算接收到的激光功率 - /// - 计算光斑偏移并传递给四象限探测器 - /// - 根据四象限探测器的锁定状态更新制导状态 - /// - private void ProcessLaserIlluminationCommon(string? laserDesignatorId, - LaserCodeConfig? laserCodeConfig, bool isInitialIllumination) - { - if (laserCodeConfig != null) + if (illuminationEvent.LaserCodeConfig != null) { - bool codeMatched = InternalLaserCodeConfig?.CheckCodeMatch(laserCodeConfig) ?? false; + bool codeMatched = InternalLaserCodeConfig?.CheckCodeMatch(illuminationEvent.LaserCodeConfig) ?? false; if (!codeMatched) { // 发布编码不匹配事件 - PublishCodeMismatchEvent(laserDesignatorId, laserCodeConfig); + PublishCodeMismatchEvent(illuminationEvent.LaserDesignatorId, illuminationEvent.LaserCodeConfig); Trace.WriteLine("激光半主动制导系统接收到不匹配的激光编码,忽略信号"); HasGuidance = false; // 禁用制导 LaserIlluminationOn = false; // 禁用激光照射状态,确保四象限探测器不处理信号 // 重置四象限探测器状态 quadrantDetector.ProcessLaserSignal(0, new Vector2D(0, 0)); + PreviousGuidanceAcceleration = Vector3D.Zero; // 重置历史加速度 return; } else - { - // 如果编码匹配,继续处理 - // 只有在初始照射或激光尚未开启时才发布编码匹配事件 - if (isInitialIllumination || !LaserIlluminationOn) - { - // 发布编码匹配事件 - PublishCodeMatchEvent(laserDesignatorId, laserCodeConfig); - } - + { // 更新激光照射状态 LaserIlluminationOn = true; - - // 计算接收到的激光功率 - double receivedPower = CalculateReceivedPower(TargetPosition); - - // 计算光斑偏移并传递给四象限探测器 - Vector2D spotOffset = CalculateSpotOffset(); - quadrantDetector.ProcessLaserSignal(receivedPower, spotOffset); - - // 更新制导状态 - 根据四象限探测器的锁定状态 - HasGuidance = quadrantDetector.IsTargetLocked; } } } @@ -964,29 +824,6 @@ namespace ThreatSource.Guidance HasGuidance = false; // 禁用制导 } - /// - /// 发布编码匹配事件 - /// - /// 激光定位器ID - /// 匹配的编码配置 - /// - /// 发布过程: - /// - 创建事件对象 - /// - 设置事件属性 - /// - 发布到事件系统 - /// - private void PublishCodeMatchEvent(string? designatorId, LaserCodeConfig? matchedCodeConfig) - { - var matchEvent = new LaserCodeMatchEvent - { - MissileId = ParentId, - DesignatorId = designatorId, - MatchedCodeConfig = matchedCodeConfig - }; - - PublishEvent(matchEvent); - } - /// /// 发布编码不匹配事件 /// diff --git a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs index 9ad2f2a..1672411 100644 --- a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs @@ -3,6 +3,7 @@ using ThreatSource.Utils; using ThreatSource.Target; using System.Diagnostics; using ThreatSource.Jamming; +using AirTransmission; namespace ThreatSource.Guidance { @@ -161,7 +162,7 @@ namespace ThreatSource.Guidance lastTargetPosition = Vector3D.Zero; lastTargetVelocity = Vector3D.Zero; - InitializeJamming(config.JammingResistanceThreshold, new List { JammingType.MillimeterWave }); + InitializeJamming(config.JammingResistanceThreshold, [JammingType.MillimeterWave]); SwitchToSearchMode(); // 初始化为搜索模式 } @@ -696,6 +697,20 @@ namespace ThreatSource.Guidance double signalPower = (transmitPower * Math.Pow(antennaGain, 2) * Math.Pow(wavelength, 2) * radarCrossSection) / (Math.Pow(4 * Math.PI, 3) * Math.Pow(distance, 4) * totalLoss); + // 考虑大气透过率,如果当前天气为null,则认为大气透过率为1.0 + double atmosphericTransmittance = 1.0; + + if(SimulationManager.CurrentWeather != null) + { + atmosphericTransmittance = AtmosphereDllWrapper.CalculateTransmittance( + distance, + RadiationType.MillimeterWave, + wavelength, + SimulationManager.CurrentWeather); + } + + signalPower *= atmosphericTransmittance; + // 计算噪声功率 double noisePower = k * T0 * bandwidth * noiseFigure; diff --git a/ThreatSource/src/Indicator/LaserDesignator.cs b/ThreatSource/src/Indicator/LaserDesignator.cs index d1d94e6..e9c3bfc 100644 --- a/ThreatSource/src/Indicator/LaserDesignator.cs +++ b/ThreatSource/src/Indicator/LaserDesignator.cs @@ -79,22 +79,13 @@ namespace ThreatSource.Indicator public LaserCodeConfig LaserCodeConfig { get; set; } /// - /// 获取或设置最小工作波长,单位:微米 + /// 获取或设置工作波长,单位:微米 /// /// - /// 指示器工作所需的最小波长 + /// 指示器工作所需的工作波长 /// 用于波长范围匹配检查 /// - public double MinWavelength { get; private set; } = 1.0; - - /// - /// 获取或设置最大工作波长,单位:微米 - /// - /// - /// 指示器工作所需的最大波长 - /// 用于波长范围匹配检查 - /// - public double MaxWavelength { get; private set; } = 1.1; + public double Wavelength { get; private set; } = 1.06; /// /// 初始化激光指示器的新实例 @@ -123,8 +114,7 @@ namespace ThreatSource.Indicator LaserDivergenceAngle = config.LaserDivergenceAngle; LaserCodeConfig = config.LaserCodeConfig; JammingThreshold = config.JammingResistanceThreshold; - MinWavelength = config.MinWavelength; - MaxWavelength = config.MaxWavelength; + Wavelength = config.LaserWavelength; // 设置干扰阈值并添加支持的干扰类型 InitializeJamming(JammingThreshold, [JammingType.Laser]); @@ -183,7 +173,7 @@ namespace ThreatSource.Indicator if (!IsIlluminationOn) { IsIlluminationOn = true; - PublishIlluminationStartEvent(); + PublishIlluminationUpdateEvent(); } } @@ -232,7 +222,7 @@ namespace ThreatSource.Indicator }; // 检查波长匹配(激光特定逻辑) - bool isWavelengthInRange = evt.Wavelength >= MinWavelength && evt.Wavelength <= MaxWavelength; + bool isWavelengthInRange = evt.Wavelength == Wavelength; // 使用JammableComponent进行干扰判断 if (isWavelengthInRange) @@ -334,36 +324,6 @@ namespace ThreatSource.Indicator } } - /// - /// 发布激光照射开始事件 - /// - /// - /// 发布过程: - /// - 创建事件对象 - /// - 设置事件属性 - /// - 添加编码信息 - /// - 发布到事件系统 - /// - private void PublishIlluminationStartEvent() - { - Debug.WriteLine($"激光照射开始事件: {Id}, TargetId: {TargetId}"); - - var illuminationEvent = new LaserIlluminationStartEvent - { - LaserDesignatorId = Id, - TargetId = TargetId - }; - - // 添加编码信息 - if (LaserCodeConfig != null) - { - illuminationEvent.LaserCodeConfig = LaserCodeConfig; - } - - // 发布事件 - PublishEvent(illuminationEvent); - } - /// /// 发布激光照射更新事件 /// diff --git a/ThreatSource/src/MIssile/BaseMissile.cs b/ThreatSource/src/MIssile/BaseMissile.cs index cbc0ad1..a55e040 100644 --- a/ThreatSource/src/MIssile/BaseMissile.cs +++ b/ThreatSource/src/MIssile/BaseMissile.cs @@ -177,29 +177,22 @@ namespace ThreatSource.Missile /// 时间步长,单位:秒 /// /// 更新过程: - /// - 计算合加速度 + /// - 计算包含风影响的合加速度 /// - 根据制导状态选择运动更新方法 /// - 更新导弹的位置和速度 /// protected virtual void UpdateMotionState(double deltaTime) { - //Vector3D acceleration = CalculateAcceleration(Velocity); - - Vector3D acceleration; + // 计算包含风影响的合加速度 + Vector3D acceleration = CalculateAcceleration(Velocity); if (IsGuidance) { - // 在有制导情况下使用制导加速度 - acceleration = GuidanceAcceleration; - // 制导条件下,使用四阶龙格-库塔方法更新导弹的位置和速度 (Position, Velocity) = MotionAlgorithm.RungeKutta4(deltaTime, Position, Velocity, acceleration); } else { - // 在无制导情况下使用零向量作为加速度 - acceleration = Vector3D.Zero; - // 无制导条件下,使用运动学方程更新导弹的位置和速度 (Position, Velocity) = MotionAlgorithm.CalculateBallisticMotion(Position, Velocity, acceleration, deltaTime); } @@ -228,18 +221,25 @@ namespace ThreatSource.Missile /// 合加速度向量 /// /// 计算过程: - /// - 计算空气阻力加速度 - /// - 合成制导、推力和阻力加速度 + /// - 获取当前风速向量 + /// - 计算空气阻力加速度(已考虑风) + /// - 合成总加速度(制导加速度 + 推力加速度 + 空气阻力加速度) /// - 限制合加速度不超过最大值 /// private Vector3D CalculateAcceleration(Vector3D velocity) { - // 计算空气阻力的影响 - Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Properties.Mass; + // 获取当前风速向量 + Vector3D windVector = GetWindVectorFromWeather(); + // 计算空气阻力加速度(考虑风的影响) + Vector3D dragAcceleration = CalculateDragAcceleration(velocity, windVector); + + // 合成总加速度(制导加速度 + 推力加速度 + 空气阻力加速度) Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration; - Debug.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, 推力加速度: {ThrustAcceleration}, 空气阻力加速度: {dragAcceleration}"); + Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, " + + $"推力加速度: {ThrustAcceleration}, 空气阻力加速度(含风影响): {dragAcceleration}"); + if (totalAcceleration.Magnitude() > Properties.MaxAcceleration) { totalAcceleration = totalAcceleration.Normalize() * Properties.MaxAcceleration; @@ -249,26 +249,65 @@ namespace ThreatSource.Missile } /// - /// 计算空气阻力 + /// 从天气系统获取当前的风速向量 /// - /// 当前速度大小,单位:米/秒 - /// 空气阻力大小,单位:牛顿 + /// 风速向量,单位:米/秒 + private Vector3D GetWindVectorFromWeather() + { + var weather = SimulationManager.CurrentWeather; + if (weather == null) + return Vector3D.Zero; + + return MotionAlgorithm.CalculateWindVector(weather.WindSpeed, weather.WindDirection); + } + + /// + /// 计算空气阻力加速度,考虑风的影响 + /// + /// 物体速度向量 + /// 风速向量 + /// 空气阻力加速度向量,单位:米/秒² /// /// 计算公式: - /// F = 0.5 * Cd * ρ * A * v² + /// a = (0.5 * Cd * ρ * A * v²) / m * (-v_rel_norm) /// 其中: /// - Cd:阻力系数 /// - ρ:空气密度 /// - A:参考面积 - /// - v:速度 + /// - v:物体相对于空气的速度 + /// - m:物体质量 + /// - v_rel_norm:相对速度的单位向量 /// - private static double CalculateDrag(double speed) + private Vector3D CalculateDragAcceleration(Vector3D velocity, Vector3D windVector) { - const double dragCoefficient = 0.1; // 减小阻力系数 + const double dragCoefficient = 0.1; // 阻力系数 const double airDensity = 1.225; // 海平面空气密度,kg/m^3 - const double referenceArea = 0.01; // 减小导弹的参考面积,m^2 - - return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed; + const double referenceArea = 0.01; // 导弹的参考面积,m^2 + + // 计算物体相对于空气的速度 + Vector3D relativeVelocity = velocity - windVector; + double relativeSpeed = relativeVelocity.Magnitude(); + + // 如果相对速度接近零,返回零加速度 + if (relativeSpeed < 0.001) + return Vector3D.Zero; + + // 计算空气阻力加速度大小 + double dragAccelerationMagnitude = 0.5 * dragCoefficient * airDensity * referenceArea * relativeSpeed * relativeSpeed / Properties.Mass; + + // 计算单位向量的各个分量 + double normX = relativeVelocity.X / relativeSpeed; + double normY = relativeVelocity.Y / relativeSpeed; + double normZ = relativeVelocity.Z / relativeSpeed; + + // 空气阻力加速度方向与相对速度方向相反(每个分量都取反) + Vector3D dragAcceleration = new Vector3D( + -normX * dragAccelerationMagnitude, + -normY * dragAccelerationMagnitude, + -normZ * dragAccelerationMagnitude + ); + + return dragAcceleration; } /// diff --git a/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs b/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs index 3b0db95..9f5a9c0 100644 --- a/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs +++ b/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs @@ -1,8 +1,6 @@ using ThreatSource.Simulation; using ThreatSource.Utils; using ThreatSource.Guidance; -using ThreatSource.Indicator; -using ThreatSource.Target; namespace ThreatSource.Missile { @@ -215,32 +213,10 @@ namespace ThreatSource.Missile { // 更新制导系统 guidanceSystem.Update(deltaTime, Position, Velocity); - - // 根据制导系统的HasGuidance属性设置IsGuidance - if (guidanceSystem is LaserSemiActiveGuidanceSystem laserGuidance) - { - // 只有当四象限探测器锁定目标时,才启用制导 - IsGuidance = laserGuidance.HasGuidance && laserGuidance.IsQuadrantDetectorLocked(); - - // 打印激光能量和制导加速度 - string guidanceStatus = laserGuidance.GetStatus(); - double accelerationMagnitude = GuidanceAcceleration.Magnitude(); - } - else - { - IsGuidance = false; // 默认情况下禁用制导 - } - // 获取制导加速度 - if (IsGuidance) - { - GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration(); - } - else - { - // 如果没有制导,则将制导加速度设置为零向量 - GuidanceAcceleration = Vector3D.Zero; - } + GuidanceAcceleration = guidanceSystem.GetGuidanceAcceleration(); + // 设置制导状态 + IsGuidance = guidanceSystem.HasGuidance; } /// diff --git a/ThreatSource/src/Sensor/QuadrantDetector.cs b/ThreatSource/src/Sensor/QuadrantDetector.cs index 5b83ad2..842baef 100644 --- a/ThreatSource/src/Sensor/QuadrantDetector.cs +++ b/ThreatSource/src/Sensor/QuadrantDetector.cs @@ -76,6 +76,43 @@ namespace ThreatSource.Sensor /// public double VerticalError { get; private set; } + /// + /// 滤波后的水平方向误差 + /// + /// + /// 对原始水平误差进行滤波后的值 + /// 用于减少误差信号的噪声和快速变化 + /// + private double filteredHorizontalError = 0; + + /// + /// 滤波后的垂直方向误差 + /// + /// + /// 对原始垂直误差进行滤波后的值 + /// 用于减少误差信号的噪声和快速变化 + /// + private double filteredVerticalError = 0; + + /// + /// 误差滤波系数 + /// + /// + /// 控制滤波的强度,值越小滤波越强 + /// 范围:(0,1] + /// 值为1时无滤波效果 + /// + private const double errorFilterFactor = 0.15; + + /// + /// 误差死区阈值 + /// + /// + /// 小于此值的误差将被视为零 + /// 用于避免对微小误差的过度响应 + /// + private const double errorDeadZone = 0.01; + /// /// 获取总接收功率,单位:瓦特 /// @@ -120,6 +157,8 @@ namespace ThreatSource.Sensor HorizontalError = 0; VerticalError = 0; + filteredHorizontalError = 0; + filteredVerticalError = 0; TotalReceivedPower = 0; IsTargetLocked = false; } @@ -152,6 +191,8 @@ namespace ThreatSource.Sensor } HorizontalError = 0; VerticalError = 0; + filteredHorizontalError = 0; + filteredVerticalError = 0; return; } @@ -233,23 +274,44 @@ namespace ThreatSource.Sensor if (TotalReceivedPower > 0) { // 计算水平误差 - HorizontalError = ((quadrantSignals[0] + quadrantSignals[3]) - + double rawHorizontalError = ((quadrantSignals[0] + quadrantSignals[3]) - (quadrantSignals[1] + quadrantSignals[2])) / TotalReceivedPower; // 计算垂直误差 - VerticalError = ((quadrantSignals[0] + quadrantSignals[1]) - + double rawVerticalError = ((quadrantSignals[0] + quadrantSignals[1]) - (quadrantSignals[2] + quadrantSignals[3])) / TotalReceivedPower; // 限制误差范围在[-1, 1]之间 - HorizontalError = Math.Max(-1, Math.Min(1, HorizontalError)); - VerticalError = Math.Max(-1, Math.Min(1, VerticalError)); + HorizontalError = Math.Max(-1, Math.Min(1, rawHorizontalError)); + VerticalError = Math.Max(-1, Math.Min(1, rawVerticalError)); + + // 应用误差滤波 + filteredHorizontalError = filteredHorizontalError * (1 - errorFilterFactor) + + HorizontalError * errorFilterFactor; + filteredVerticalError = filteredVerticalError * (1 - errorFilterFactor) + + VerticalError * errorFilterFactor; + + // 应用误差死区 + if (Math.Abs(filteredHorizontalError) < errorDeadZone) + filteredHorizontalError = 0; + if (Math.Abs(filteredVerticalError) < errorDeadZone) + filteredVerticalError = 0; + + // 使用滤波后的误差替代原始误差 + HorizontalError = filteredHorizontalError; + VerticalError = filteredVerticalError; + + // 增强调试输出,同时显示水平和垂直误差 + Console.WriteLine($"原始误差: 水平={rawHorizontalError:F6}, 垂直={rawVerticalError:F6}, 滤波后: 水平={HorizontalError:F6}, 垂直={VerticalError:F6}"); } else { HorizontalError = 0; VerticalError = 0; + filteredHorizontalError = 0; + filteredVerticalError = 0; } } @@ -260,32 +322,34 @@ namespace ThreatSource.Sensor /// 灵敏度系数 /// 修正后的目标方向向量 /// - /// 计算过程: - /// - 根据水平和垂直误差计算修正角度 - /// - 应用修正角度到当前方向 - /// - 返回修正后的方向向量 + /// 使用通用的正交基构建方法 + /// 不依赖于特定的坐标系 + /// 适用于任何飞行姿态 /// public Vector3D GetTargetDirection(Vector3D currentDirection, double sensitivity) { - // 如果未锁定目标,返回当前方向 if (!IsTargetLocked) { return currentDirection; } - - // 获取当前方向的标准正交基 + + // 1. 获取当前方向的单位向量 Vector3D forward = currentDirection.Normalize(); - Vector3D right = Vector3D.CrossProduct(Vector3D.UnitY, forward).Normalize(); + + // 2. 构建任意正交基 + // 选择一个非平行于forward的向量来构建正交基 + Vector3D temp = Math.Abs(forward.X) < 0.9 ? Vector3D.UnitX : Vector3D.UnitY; + Vector3D right = Vector3D.CrossProduct(temp, forward).Normalize(); Vector3D up = Vector3D.CrossProduct(forward, right).Normalize(); - // 根据误差和灵敏度计算修正向量 + // 3. 在这个局部坐标系中应用误差修正 + // HorizontalError 对应 right 方向 + // VerticalError 对应 up 方向 Vector3D correction = right * (HorizontalError * sensitivity) + up * (VerticalError * sensitivity); - // 应用修正并归一化 - Vector3D targetDirection = (forward + correction).Normalize(); - - return targetDirection; + // 4. 计算新的方向向量并归一化 + return (forward + correction).Normalize(); } /// diff --git a/ThreatSource/src/Simulation/DecoyTarget.cs b/ThreatSource/src/Simulation/DecoyTarget.cs index 94e78a3..0052d0c 100644 --- a/ThreatSource/src/Simulation/DecoyTarget.cs +++ b/ThreatSource/src/Simulation/DecoyTarget.cs @@ -16,6 +16,11 @@ namespace ThreatSource.Simulation /// 获取或设置诱偏源功率,单位:瓦特 /// public double DecoyPower { get; set; } + + /// + /// 获取或设置诱偏激光发散角,单位:弧度 + /// + public double DecoyLaserDivergenceAngle { get; set; } /// /// 获取或设置反射系数 @@ -30,7 +35,7 @@ namespace ThreatSource.Simulation /// /// 获取或设置诱偏源位置 /// - public Vector3D SourcePosition { get; set; } + public string SourceId { get; set; } /// /// 获取创建时间 @@ -46,23 +51,25 @@ namespace ThreatSource.Simulation /// 初始化激光诱偏目标的新实例 /// /// 目标ID + /// 诱偏源ID /// 目标位置 /// 诱偏源功率 + /// 诱偏激光发散角 /// 反射系数 /// 有效反射面积 /// 生命周期 - /// 诱偏源位置 /// 仿真管理器 - public DecoyTarget(string id, Vector3D position, double decoyPower, - double reflectionCoefficient, double reflectiveArea, double lifeTime, - Vector3D sourcePosition, ISimulationManager simulationManager) + public DecoyTarget(string id, string sourceId, Vector3D position, double decoyPower, + double decoyLaserDivergenceAngle, double reflectionCoefficient, double reflectiveArea, double lifeTime, + ISimulationManager simulationManager) : base(id, position, new Orientation(), 0, simulationManager) // 诱偏目标通常是静止的,速度为0 { + SourceId = sourceId; DecoyPower = decoyPower; + DecoyLaserDivergenceAngle = decoyLaserDivergenceAngle; ReflectionCoefficient = reflectionCoefficient; ReflectiveArea = reflectiveArea; LifeTime = lifeTime; - SourcePosition = sourcePosition; CreationTime = DateTime.Now; } @@ -70,40 +77,11 @@ namespace ThreatSource.Simulation /// 检查诱偏目标是否仍然活跃 /// /// 如果目标仍然活跃返回true,否则返回false - public bool IsActive() + public bool IsDecoyActive() { return (DateTime.Now - CreationTime).TotalSeconds < LifeTime; } - /// - /// 计算在特定位置接收到的反射功率 - /// - /// 观察者位置 - /// 激光发散角 - /// 计算得到的反射功率,单位:瓦特 - public double CalculateReflectedPower(Vector3D observerPosition, double laserDivergenceAngle) - { - double distanceSourceToDecoy = (SourcePosition - Position).Magnitude(); - double distanceDecoyToObserver = (Position - observerPosition).Magnitude(); - - // 计算诱偏源处的光斑面积 - double spotAreaAtDecoy = Math.PI * Math.Pow(distanceSourceToDecoy * Math.Tan(laserDivergenceAngle), 2); - - // 计算诱偏源处的激光功率密度 - double powerDensityAtDecoy = DecoyPower / spotAreaAtDecoy; - - // 计算从诱偏源反射的总功率 - double reflectedPower = powerDensityAtDecoy * ReflectiveArea * ReflectionCoefficient; - - // 计算反射光在观察者处的扩散面积(假设漫反射) - double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceDecoyToObserver, 2); - - // 计算观察者接收到的功率 - double receivedPower = reflectedPower / reflectedSpotArea; - - return receivedPower; - } - /// /// 更新诱偏目标状态 /// @@ -111,7 +89,7 @@ namespace ThreatSource.Simulation public override void Update(double deltaTime) { // 如果生命周期结束,从仿真中移除 - if (!IsActive()) + if (!IsDecoyActive()) { SimulationManager.UnregisterEntity(Id); } diff --git a/ThreatSource/src/Simulation/ISimulationManager.cs b/ThreatSource/src/Simulation/ISimulationManager.cs index f3e7541..560f326 100644 --- a/ThreatSource/src/Simulation/ISimulationManager.cs +++ b/ThreatSource/src/Simulation/ISimulationManager.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using ThreatSource.Utils; +using AirTransmission; namespace ThreatSource.Simulation { @@ -100,25 +101,37 @@ namespace ThreatSource.Simulation } /// - /// 仿真管理器接口,提供仿真系统的核心功能 + /// 仿真管理器接口,定义仿真系统的核心功能 /// /// - /// 该接口定义了仿真系统的主要功能,包括: - /// - 事件系统:用于实体间的通信和状态同步 - /// - 实体管理:负责实体的注册、注销和查询 - /// - 第三方集成:支持与其他仿真环境的对接 + /// 该接口定义了仿真系统应提供的基本功能: + /// - 事件系统:支持发布/订阅模式的事件处理 + /// - 实体管理:实体的注册、注销和查询 + /// - 仿真控制:启动、暂停、恢复和停止仿真 + /// - 第三方集成:支持与外部仿真环境的对接 /// public interface ISimulationManager { /// - /// 当前仿真时间 + /// 获取当前仿真状态 + /// + SimulationState State { get; } + + /// + /// 获取当前仿真时间 /// double CurrentTime { get; } /// - /// 仿真状态 + /// 获取当前天气系统 /// - SimulationState State { get; } + Weather? CurrentWeather { get; } + + /// + /// 设置当前天气 + /// + /// 天气条件 + void SetWeather(Weather weather); /// /// 启动仿真系统 diff --git a/ThreatSource/src/Simulation/SimulationConfig.cs b/ThreatSource/src/Simulation/SimulationConfig.cs index 6e115a1..1a68b6a 100644 --- a/ThreatSource/src/Simulation/SimulationConfig.cs +++ b/ThreatSource/src/Simulation/SimulationConfig.cs @@ -1,5 +1,12 @@ using System.Runtime.CompilerServices; using ThreatSource.Utils; +using System.Collections.Generic; // Added for Dictionary +using ThreatSource.Missile; // For MissileProperties +using ThreatSource.Target; // For Target properties if needed +using ThreatSource.Sensor; // For Sensor configs +using ThreatSource.Jamming; // For Jammer configs +using ThreatSource.Indicator; // For Indicator configs +using AirTransmission; // Added for WeatherType enum namespace ThreatSource.Simulation { @@ -134,24 +141,14 @@ namespace ThreatSource.Simulation public double JammingResistanceThreshold { get; set; } = 1.0; /// - /// 获取或设置最小工作波长 + /// 获取或设置工作波长 /// /// /// 单位:微米 - /// 激光指示器工作的最小波长 + /// 激光指示器工作的波长 /// 影响激光干扰的匹配判断 /// - public double MinWavelength { get; set; } = 1.0; - - /// - /// 获取或设置最大工作波长 - /// - /// - /// 单位:微米 - /// 激光指示器工作的最大波长 - /// 影响激光干扰的匹配判断 - /// - public double MaxWavelength { get; set; } = 1.1; + public double LaserWavelength { get; set; } = 1.06; } /// @@ -622,7 +619,10 @@ namespace ThreatSource.Simulation /// - 反射系数:0.2 /// - 反射面积:1.0平方米 /// - 锁定阈值:1e-12瓦特 - /// - 灵敏度:0.5 + /// - 灵敏度:0.05 + /// - 发射系统透过率:0.85 + /// - 接收系统透过率:0.8 + /// - 激光波长:1.06微米 /// public class LaserSemiActiveGuidanceConfig { @@ -716,9 +716,9 @@ namespace ThreatSource.Simulation /// /// 定义了四象限探测器对光斑偏移的响应灵敏度 /// 影响制导系统的响应速度和稳定性 - /// 默认值为0.5 + /// 默认值为0.2 /// - public double SpotOffsetSensitivity { get; set; } = 0.5; + public double SpotOffsetSensitivity { get; set; } = 0.05; /// /// 干扰抗性阈值,单位:瓦特 @@ -730,6 +730,36 @@ namespace ThreatSource.Simulation /// public double JammingResistanceThreshold { get; set; } = 1e-12; + /// + /// 发射系统透过率 + /// + /// + /// 定义了激光从发射器到外部的能量传输效率 + /// 范围:[0,1],1表示无损耗 + /// 默认值为0.85 + /// + public double TransmitterEfficiency { get; set; } = 0.85; + + /// + /// 接收系统透过率 + /// + /// + /// 定义了接收系统的光学元件传输效率 + /// 范围:[0,1],1表示无损耗 + /// 默认值为0.8 + /// + public double ReceiverEfficiency { get; set; } = 0.8; + + /// + /// 激光波长,单位:微米 + /// + /// + /// 定义了激光的工作波长 + /// 影响大气透过率和目标反射特性 + /// 默认值为1.06微米(Nd:YAG激光器) + /// + public double LaserWavelength { get; set; } = 1.06; + /// /// 初始化激光半主动导引配置的新实例 /// @@ -742,7 +772,10 @@ namespace ThreatSource.Simulation /// - 反射系数:0.2 /// - 反射面积:1.0平方米 /// - 锁定阈值:1e-12瓦特 - /// - 灵敏度:0.5 + /// - 灵敏度:0.2 + /// - 发射系统透过率:0.85 + /// - 接收系统透过率:0.8 + /// - 激光波长:1.06微米 /// public LaserSemiActiveGuidanceConfig() { @@ -1063,6 +1096,17 @@ namespace ThreatSource.Simulation /// public double JammingResistanceThreshold { get; set; } = 1e-3; + + /// + /// 激光波长,单位:纳米 + /// + /// + /// 定义了激光的波长 + /// 影响激光的传输特性和探测性能 + /// 默认值为1.06纳米 + /// + public double LaserWavelength { get; set; } = 1.06; + /// /// 初始化激光驾束制导系统配置的新实例 /// diff --git a/ThreatSource/src/Simulation/SimulationEvents.cs b/ThreatSource/src/Simulation/SimulationEvents.cs index b66c100..9847aee 100644 --- a/ThreatSource/src/Simulation/SimulationEvents.cs +++ b/ThreatSource/src/Simulation/SimulationEvents.cs @@ -52,41 +52,6 @@ namespace ThreatSource.Simulation public string? TargetId { get; set; } } - /// - /// 激光照射开始事件,表示激光定位器开始照射目标 - /// - /// - /// 用于激光半主动导引系统 - /// 触发时机:激光定位器开始照射目标时 - /// - public class LaserIlluminationStartEvent : SimulationEvent - { - /// - /// 获取或设置激光定位器的ID - /// - /// - /// 标识发出激光的定位器设备 - /// - public string? LaserDesignatorId { get; set; } - - /// - /// 获取或设置被照射目标的ID - /// - /// - /// 标识被激光照射的目标实体 - /// - public string? TargetId { get; set; } - - /// - /// 获取或设置激光编码信息 - /// - /// - /// 包含激光信号的编码类型和编码值 - /// 用于抗干扰和安全识别 - /// - public LaserCodeConfig? LaserCodeConfig { get; set; } - } - /// /// 激光照射更新事件,表示激光照射状态的更新 /// @@ -786,54 +751,21 @@ namespace ThreatSource.Simulation } /// - /// 诱偏目标创建事件,表示创建了一个新的激光诱偏目标 + /// 诱偏目标照射事件,表示诱偏目标被照射 /// /// - /// 用于通知系统新的诱偏目标已创建 - /// 触发时机:激光诱偏目标被创建时 + /// 用于模拟诱偏目标被照射的情况 + /// 触发时机:诱偏目标被照射时 /// - public class DecoyTargetCreatedEvent : SimulationEvent + public class DecoyTargetIlluminationEvent : SimulationEvent { /// /// 获取或设置诱偏目标的ID /// /// - /// 标识新创建的诱偏目标 + /// 标识被照射的诱偏目标 /// public string? DecoyTargetId { get; set; } - - /// - /// 获取或设置诱偏目标的位置 - /// - /// - /// 诱偏目标在三维空间中的位置 - /// - public Vector3D DecoyPosition { get; set; } - - /// - /// 获取或设置诱偏源的功率 - /// - /// - /// 单位:瓦特 - /// 诱偏源的发射功率 - /// - public double DecoyPower { get; set; } - - /// - /// 获取或设置诱偏源的位置 - /// - /// - /// 诱偏发射设备在三维空间中的位置 - /// - public Vector3D SourcePosition { get; set; } - - /// - /// 获取或设置诱偏目标的生命周期 - /// - /// - /// 单位:秒 - /// 诱偏目标的有效存在时间 - /// - public double LifeTime { get; set; } } + } diff --git a/ThreatSource/src/Simulation/SimulationManager.cs b/ThreatSource/src/Simulation/SimulationManager.cs index 9a7fbf3..6a883f8 100644 --- a/ThreatSource/src/Simulation/SimulationManager.cs +++ b/ThreatSource/src/Simulation/SimulationManager.cs @@ -2,6 +2,7 @@ using System.Diagnostics; using ThreatSource.Missile; using ThreatSource.Target; using ThreatSource.Utils; +using AirTransmission; namespace ThreatSource.Simulation { @@ -52,8 +53,6 @@ namespace ThreatSource.Simulation /// private ISimulationAdapter? _simulationAdapter; - - private SimulationState _state = SimulationState.Stopped; /// @@ -71,6 +70,16 @@ namespace ThreatSource.Simulation /// private double _timeStep; + /// + /// 当前天气系统 + /// + private Weather? _currentWeather; + + /// + /// 获取当前天气系统 + /// + public Weather? CurrentWeather => _currentWeather; + /// /// 启动仿真系统 /// @@ -167,8 +176,8 @@ namespace ThreatSource.Simulation var activeTargets = entities.Values.OfType().Where(e => e.IsActive).ToList(); var hitEvents = new List<(Tank tank, BaseMissile missile, double damage)>(); - Console.WriteLine($"activeMissiles: {activeMissiles.Count}"); - Console.WriteLine($"activeTargets: {activeTargets.Count}"); + Console.WriteLine($"活动导弹数量: {activeMissiles.Count}"); + Console.WriteLine($"活动目标数量: {activeTargets.Count}"); // 收集所有的命中信息 foreach (var missile in activeMissiles) @@ -525,5 +534,33 @@ namespace ThreatSource.Simulation PublishEvent(evt); } #endregion + + /// + /// 设置当前天气 + /// + /// 天气条件 + public void SetWeather(Weather weather) + { + _currentWeather = weather; + Console.WriteLine($"已设置天气:{weather.Type}"); + + // 通知其他实体天气已变化 + var evt = new WeatherChangedEvent + { + NewWeather = weather + }; + PublishEvent(evt); + } + } + + /// + /// 天气变化事件,当天气系统变化时触发 + /// + public class WeatherChangedEvent : SimulationEvent + { + /// + /// 新的天气系统 + /// + public Weather? NewWeather { get; set; } } } \ No newline at end of file diff --git a/ThreatSource/src/Target/Tank.cs b/ThreatSource/src/Target/Tank.cs index cfec237..ae1a6b2 100644 --- a/ThreatSource/src/Target/Tank.cs +++ b/ThreatSource/src/Target/Tank.cs @@ -22,6 +22,14 @@ namespace ThreatSource.Target /// public override TargetType Type => TargetType.Tank; + /// + /// 获取或设置诱偏目标的ID + /// + /// + /// 标识诱偏目标 + /// + public string? DecoyTargetId { get; set; } + /// /// 获取或设置诱偏功率,单位:瓦特 /// @@ -76,6 +84,18 @@ namespace ThreatSource.Target public override void Update(double deltaTime) { base.Update(deltaTime); + // 发布诱偏目标照射事件 + if (DecoyTargetId != null) + { + if(SimulationManager.GetEntityById(DecoyTargetId) is DecoyTarget decoyTarget && decoyTarget.IsDecoyActive()) + { + var illuminationEvent = new DecoyTargetIlluminationEvent + { + DecoyTargetId = DecoyTargetId + }; + SimulationManager.PublishEvent(illuminationEvent); + } + } // TODO: 添加坦克特有的更新逻辑 } @@ -109,12 +129,13 @@ namespace ThreatSource.Target // 创建诱偏目标 var decoyTarget = new DecoyTarget( decoyId, + Id, decoyPosition, power, + DecoyLaserDivergenceAngle, reflectionCoefficient, reflectiveArea, lifetime, - Position, // 诱偏源位置为坦克位置 SimulationManager ); @@ -123,17 +144,8 @@ namespace ThreatSource.Target // 激活诱偏目标 decoyTarget.Activate(); - - // 发布诱偏目标创建事件 - var createdEvent = new DecoyTargetCreatedEvent - { - DecoyTargetId = decoyId, - DecoyPosition = decoyPosition, - DecoyPower = power, - SourcePosition = Position, - LifeTime = lifetime - }; - SimulationManager.PublishEvent(createdEvent); + + DecoyTargetId = decoyId; return decoyId; } diff --git a/ThreatSource/src/Utils/AtmosphereDllWrapper.cs b/ThreatSource/src/Utils/AtmosphereDllWrapper.cs new file mode 100644 index 0000000..10a5d7e --- /dev/null +++ b/ThreatSource/src/Utils/AtmosphereDllWrapper.cs @@ -0,0 +1,157 @@ +using AirTransmission; // 引用 .NET DLL 的命名空间 +using System; + +namespace ThreatSource.Utils +{ + /// + /// 封装对 AirTransmission.dll 中大气透过率计算逻辑的调用 + /// + public class AtmosphereDllWrapper + { + /// + /// 初始化 AtmosphereDllWrapper 类的新实例 + /// (当前无需特殊初始化) + /// + public AtmosphereDllWrapper() + { + // 构造函数为空,因为我们直接调用静态方法 + } + + /// + /// 计算两点之间的大气透过率 + /// + /// 距离(米) + /// 电磁波类型 + /// 波长(单位:微米) + /// 天气条件 + /// 透过率因子(0.0 到 1.0) + public static double CalculateTransmittance(double distance, RadiationType radiationType, double wavelength, Weather weather) + { + try + { + // 创建WeatherParameters结构体 + var parameters = new WeatherParameters + { + Temperature = weather.Temperature, + RelativeHumidity = weather.RelativeHumidity, + Visibility = weather.Visibility, + Pressure = weather.Pressure, + Precipitation = weather.Precipitation, + CO2Concentration = weather.CO2Concentration, + WindSpeed = weather.WindSpeed, + WindDirection = weather.WindDirection, + WeatherType = (int)weather.Type + }; + + // 将距离从米转换为公里(库函数期望距离以公里为单位) + double distanceInKm = distance / 1000.0; + + // 调用导出方法 + double transmittance = AtmosphericTransmittanceCalculator.CalculateTransmittanceExport( + (int)radiationType, + wavelength, + distanceInKm, // 使用公里单位 + parameters); + + Console.WriteLine($"[透过率] 类型: {radiationType}, 波长: {wavelength:F2}um, 距离: {distance:F1}m -> {transmittance:F3}"); + + return Math.Clamp(transmittance, 0.0, 1.0); + } + catch (Exception ex) + { + Console.WriteLine($"调用AirTransmission计算透过率时出错 (类型: {radiationType}, 波长: {wavelength}um, 距离: {distance}m): {ex.Message}"); + // 发生错误时返回一个保守的默认值 + return 0.8; + } + } + + /// + /// 计算激光在大气中的透过率 + /// + /// 传输距离(米) + /// 激光波长(微米) + /// 天气条件 + /// 激光的大气透过率(0.0到1.0) + /// + /// 这是一个便捷方法,专门用于计算激光的大气透过率。 + /// 内部调用CalculateTransmittance方法,使用RadiationType.Laser作为参数。 + /// + public static double CalculateLaserTransmittance(double distance, double wavelength, Weather weather) + { + return CalculateTransmittance(distance, RadiationType.Laser, wavelength, weather); + } + + /// + /// 计算大气湍流影响 + /// + /// 波长(微米) + /// 传输距离(米) + /// 天气条件 + /// 传输高度(米) + /// 湍流效应(0到1之间的值,1表示无影响,0表示完全衰减) + public static double CalculateAtmosphericTurbulence(double wavelength, double distance, Weather weather, double height) + { + try + { + // 创建WeatherParameters结构体 + var parameters = new WeatherParameters + { + Temperature = weather.Temperature, + RelativeHumidity = weather.RelativeHumidity, + Visibility = weather.Visibility, + Pressure = weather.Pressure, + Precipitation = weather.Precipitation, + CO2Concentration = weather.CO2Concentration, + WindSpeed = weather.WindSpeed, + WindDirection = weather.WindDirection, + WeatherType = (int)weather.Type + }; + + // 将距离从米转换为公里(库函数期望距离以公里为单位) + double distanceInKm = distance / 1000.0; + + // 调用导出方法 + double turbulenceEffect = AtmosphericTransmittanceCalculator.CalculateAtmosphericTurbulenceExport( + wavelength, + distanceInKm, // 使用公里单位 + parameters, + height); // 使用米单位 + + Console.WriteLine($"[湍流效应] 波长: {wavelength:F2}um, 距离: {distance:F1}m, 高度: {height:F1}m -> {turbulenceEffect:F3}"); + return turbulenceEffect; + } + catch (Exception ex) + { + Console.WriteLine($"计算湍流效应时出错 (波长: {wavelength}um, 距离: {distance}m, 高度: {height}m): {ex.Message}"); + return 1.0; // 假设无影响 + } + } + + /// + /// 计算烟幕透过率 + /// + /// 波长(微米) + /// 烟幕浓度(g/m³) + /// 烟幕厚度(米) + /// 烟幕透过率(0到1之间的值) + public static double CalculateSmokeScreenTransmittance(double wavelength, double smokeConcentration, double smokeThickness) + { + try + { + // 调用导出方法 + double smokeTransmittance = AtmosphericTransmittanceCalculator.CalculateSmokeScreenTransmittanceExport( + wavelength, + smokeConcentration, + smokeThickness); // 使用米单位 + + Console.WriteLine($"[烟幕透过率] 波长: {wavelength:F2}um, 浓度: {smokeConcentration:F1}g/m³, 厚度: {smokeThickness:F1}m -> {smokeTransmittance:F3}"); + return smokeTransmittance; + } + catch (Exception ex) + { + Console.WriteLine($"计算烟幕透过率时出错 (波长: {wavelength}um, 浓度: {smokeConcentration}g/m³, 厚度: {smokeThickness}m): {ex.Message}"); + return 0.0; // 假设完全衰减 + } + } + } +} \ No newline at end of file diff --git a/ThreatSource/src/Utils/LaserCode.cs b/ThreatSource/src/Utils/LaserCode.cs index a872398..4ef921b 100644 --- a/ThreatSource/src/Utils/LaserCode.cs +++ b/ThreatSource/src/Utils/LaserCode.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; - namespace ThreatSource.Utils { /// diff --git a/ThreatSource/src/Utils/MotionAlgorithm.cs b/ThreatSource/src/Utils/MotionAlgorithm.cs index 4ed07bd..d1f3423 100644 --- a/ThreatSource/src/Utils/MotionAlgorithm.cs +++ b/ThreatSource/src/Utils/MotionAlgorithm.cs @@ -284,5 +284,29 @@ namespace ThreatSource.Utils vector.Z + gaussianZ ); } + + /// + /// 根据风速和风向计算风速向量 + /// + /// 风速,单位:米/秒 + /// 风向,0-360度,0为北方,顺时针方向 + /// 风速向量,单位:米/秒 + /// + /// 将风速和风向转换为三维风速向量 + /// 风向是0-360度,0为北方,顺时针方向 + /// 在坐标系中,北方对应+Z,东方对应+X + /// + public static Vector3D CalculateWindVector(double windSpeed, double windDirection) + { + // 风向是0-360度,0为北方,顺时针方向 + double windDirectionRad = windDirection * Math.PI / 180.0; + + // 在水平面上分解风向 + // 北方对应+Z,东方对应+X + double windX = windSpeed * Math.Sin(windDirectionRad); // 东西分量 + double windZ = windSpeed * Math.Cos(windDirectionRad); // 南北分量 + + return new Vector3D(windX, 0, windZ); + } } } diff --git a/VERSION b/VERSION index d81f1c3..d156ab4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.9 \ No newline at end of file +0.2.10 \ No newline at end of file diff --git a/docs/project/develop_log.md b/docs/project/develop_log.md index 6f3025e..1c94f15 100644 --- a/docs/project/develop_log.md +++ b/docs/project/develop_log.md @@ -7,6 +7,34 @@ - 事件描述 - 分析处理 +## 2025-04-09 改进各导弹导弹制导系统的大气透过率计算 + +- 使用AtmosphereDllWrapper封装的计算函数,实现了激光在大气中传输的透过率精确计算 +- 添加了新的CalculateLaserTransmittance方法,简化对大气透过率的计算 +- 改进了接收功率计算逻辑,考虑了以下因素: + - 激光从发射器到目标的大气衰减 + - 目标反射光从目标到导弹的大气衰减 + - 发射系统透过率和接收系统透过率 + - 激光波长对透过率的影响 + - 增加了红外图像的最小像素限制 +- 模拟效果改进: + - 在不同天气条件下的导引性能变化更加符合物理规律 + - 远距离目标的锁定概率降低,符合实际武器系统特性 + - 雾天、雨天等恶劣天气条件下制导性能降低,更加真实 + +## 2025-03-10 优化激光半主动导弹的制导加速度计算 + +- 降低了比例导引系数从 3 降至 2,使最大加速度从 ±18 降低到 ±12左右 +- 降低了四象限探测器的灵敏度spotOffsetSensitivity,从 0.5 到 0.05 +- 实现了制导加速度平滑处理机制,通过加速度历史值加权平均的方式减少突变 +- 利用四象限探测器误差死区机制(误差阈值0.01),当探测器误差在死区范围内时不产生制导指令 +- 修改后的效果: + - 当光斑在四象限探测器中心位置时,制导加速度保持为0 + - 微小光斑偏移不再引起过度调整 + - 制导加速度变化更加平滑,减少了能量消耗 + - 导弹飞行轨迹更加稳定,飞行姿态变化更平滑 +- 系统稳定性得到显著提升,特别是在瞄准目标过程中的稳定性 + ## 2025-03-05 修改各导弹运行中的一些 BUG,修改日志的输出方式 - 修改了日志的输出方式,使用 Debug 和 Trace 输出日志 - 修改了 Vector3D 中归一化和点积的计算,避免因为浮点数的精度问题导致出现NaN错误 diff --git a/docs/project/theory.md b/docs/project/theory.md index 55aed57..a1ec553 100644 --- a/docs/project/theory.md +++ b/docs/project/theory.md @@ -71,3 +71,129 @@ z &= \sin(\alpha)\cos(\beta) 其中: - α:扫描半径角(与前向轴夹角) - β:扫描方位角(旋转角度) + +# 激光半主动导引头接收功率计算 + +## 1. 基本原理 + +激光半主动导引系统工作原理:地面或机载激光指示器照射目标,目标反射激光能量,导弹上的导引头接收反射激光,通过四象限探测器确定目标方位,实现精确打击。 + +## 2. 激光能量传输模型 + +激光能量在传输过程中受多种因素影响,包括发散、大气衰减、反射损耗等。激光从发射到被导弹接收分为两个阶段: + +### 2.1 发射器到目标阶段 + +激光功率密度在目标处的计算: + +```math +I_{target} = \frac{P_t \cdot \tau_a(R_1) \cdot \tau_t}{\pi \cdot (R_1 \cdot \tan(\theta/2))^2} +``` + +其中: +- $I_{target}$:目标处的激光功率密度(W/m²) +- $P_t$:激光发射功率(W) +- $\tau_a(R_1)$:大气透过率(从发射器到目标) +- $\tau_t$:发射系统透过率 +- $R_1$:发射器到目标的距离(m) +- $\theta$:激光发散角(rad) + +### 2.2 目标到导弹阶段 + +目标反射光被导弹接收的功率计算: + +```math +P_r = I_{target} \cdot \rho \cdot A_{target} \cdot \tau_a(R_2) \cdot \tau_r \cdot \frac{A_{receiver}}{2\pi \cdot R_2^2} +``` + +其中: +- $P_r$:导弹接收的功率(W) +- $\rho$:目标反射系数 +- $A_{target}$:目标有效反射面积(m²) +- $\tau_a(R_2)$:大气透过率(从目标到导弹) +- $\tau_r$:接收系统透过率 +- $A_{receiver}$:接收器有效面积(m²) +- $R_2$:目标到导弹的距离(m) + +### 2.3 综合计算公式 + +综合上述两个阶段,导弹接收功率的完整计算公式为: + +```math +P_r = \frac{P_t \cdot \tau_a(R_1) \cdot \tau_t \cdot \rho \cdot A_{target} \cdot \tau_a(R_2) \cdot \tau_r \cdot A_{receiver}}{2\pi^2 \cdot R_1^2 \cdot R_2^2 \cdot \tan^2(\theta/2)} +``` + +## 3. 接收光学系统处理 + +### 3.1 光学系统聚焦效应 + +当入射光通过接收光学系统聚焦时,功率密度会增加: + +```math +G_{focus} = \frac{A_{sensor}}{A_{spot}} +``` + +其中: +- $G_{focus}$:聚焦增益 +- $A_{sensor}$:传感器面积 +- $A_{spot}$:聚焦光斑面积 + +### 3.2 最终接收功率 + +考虑光学系统效应后的最终接收功率: + +```math +P_{final} = P_r \cdot \min(1, \frac{A_{lens}}{A_{illuminated}}) \cdot G_{focus} +``` + +其中: +- $P_{final}$:最终接收功率(W) +- $A_{lens}$:接收镜头面积 +- $A_{illuminated}$:入射光照射面积 +- $G_{focus}$:聚焦增益 + +## 4. 锁定判断 + +探测器根据接收功率与锁定阈值的比较,判断是否锁定目标: + +```math +\text{目标锁定} = \begin{cases} +\text{是}, & \text{如果}\ P_{final} \geq P_{threshold} \\ +\text{否}, & \text{如果}\ P_{final} < P_{threshold} +\end{cases} +``` + +其中: +- $P_{threshold}$:锁定阈值功率(典型值为10⁻¹²W) + +## 5. 影响因素分析 + +### 5.1 距离影响 +接收功率与距离的四次方成反比,是最敏感的影响因素: + +```math +P_r \propto \frac{1}{R_1^2 \cdot R_2^2} +``` + +### 5.2 天气条件影响 +不同天气条件下的有效探测距离对比(假设其他条件相同): + +| 天气条件 | 相对探测距离 | +|---------|-------------| +| 晴朗 | 100% | +| 轻雾 | 60-80% | +| 浓雾 | 20-40% | +| 雨天 | 40-60% | +| 雪天 | 30-50% | + +### 5.3 目标特性影响 +目标反射特性对接收功率的影响: + +```math +P_r \propto \rho \cdot A_{target} +``` + +典型目标反射系数: +- 金属表面:0.2-0.9 +- 涂装表面:0.1-0.3 +- 植被背景:0.1-0.2 diff --git a/tools/ComprehensiveMissileSimulator.cs b/tools/ComprehensiveMissileSimulator.cs index 31d8e6a..8c9a343 100644 --- a/tools/ComprehensiveMissileSimulator.cs +++ b/tools/ComprehensiveMissileSimulator.cs @@ -12,6 +12,7 @@ using ThreatSource.Target; using ThreatSource.Guidance; using ThreatSource.Indicator; using ThreatSource.Data; +using AirTransmission; namespace ThreatSource.Tools.MissileSimulation { @@ -52,6 +53,9 @@ namespace ThreatSource.Tools.MissileSimulation /// private void InitializeSimulation() { + // 添加天气 + AddWeathers(); + // 添加目标(坦克) AddTankTarget(); @@ -65,6 +69,19 @@ namespace ThreatSource.Tools.MissileSimulation // 添加各种传感器和指示器 AddSensorsAndDesignators(); + + + } + + /// + /// 添加天气 + /// + private void AddWeathers() + { + // 创建雨天天气并设置为当前天气 + var rainWeather = _threatSourceFactory.CreateWeather("sunny"); + simulationManager.SetWeather(rainWeather); + Console.WriteLine("已添加并设置晴天天气环境"); } /// @@ -83,6 +100,10 @@ namespace ThreatSource.Tools.MissileSimulation targets[targetId] = target; simulationManager.RegisterEntity(targetId, target); Console.WriteLine($"添加目标 {targetId},位置:{launchParams.Position}"); + + // 添加诱偏目标 + Tank tank = (Tank)target; + tank.LaunchLaserDecoy(new Vector3D(0, 0, 1), 50, 25, 20); } /// @@ -92,8 +113,8 @@ namespace ThreatSource.Tools.MissileSimulation { var launchParams = new InitialMotionParameters { - Position = new Vector3D(2000, 10, 100), - Orientation = new Orientation(Math.PI, -0.05, 0), + Position = new Vector3D(2000, 1, 100), + Orientation = new Orientation(Math.PI, 0.05, 0), InitialSpeed = 700 }; string missileId = "LSGM_1"; @@ -449,6 +470,19 @@ namespace ThreatSource.Tools.MissileSimulation /// private void PrintSimulationStatus() { + // 打印当前天气状态 + var weather = simulationManager.CurrentWeather; + if (weather != null) + { + Console.WriteLine("\n========== 天气状态 =========="); + Console.WriteLine($"天气类型: {weather.Type}"); + Console.WriteLine($"温度: {weather.Temperature}°C"); + Console.WriteLine($"湿度: {weather.RelativeHumidity}%"); + Console.WriteLine($"能见度: {weather.Visibility}公里"); + Console.WriteLine($"风速: {weather.WindSpeed}米/秒"); + Console.WriteLine($"风向: {weather.WindDirection}°"); + } + // 打印所有活跃导弹的状态 var activeMissiles = simulationManager.GetEntitiesByType() .Where(m => m.IsActive); @@ -619,5 +653,26 @@ namespace ThreatSource.Tools.MissileSimulation Console.WriteLine($"指示器 {GetIndicatorDisplayName(indicator)} 已{(indicator.IsActive ? "激活" : "停用")}"); } } + + /// + /// 切换天气 + /// + /// 天气类型 + public void SwitchWeather(string weatherType) + { + // 创建新的天气实例 + var newWeather = _threatSourceFactory.CreateWeather(weatherType); + + // 设置为当前天气 + simulationManager.SetWeather(newWeather); + + // 打印天气详情 + Console.WriteLine($"已切换到 {weatherType} 天气环境"); + Console.WriteLine($"温度: {newWeather.Temperature}°C"); + Console.WriteLine($"湿度: {newWeather.RelativeHumidity}%"); + Console.WriteLine($"能见度: {newWeather.Visibility}公里"); + Console.WriteLine($"风速: {newWeather.WindSpeed}米/秒"); + Console.WriteLine($"风向: {newWeather.WindDirection}°"); + } } } \ No newline at end of file diff --git a/tools/ThreatSource.Tools.csproj b/tools/ThreatSource.Tools.csproj index 197e1de..f26d3dd 100644 --- a/tools/ThreatSource.Tools.csproj +++ b/tools/ThreatSource.Tools.csproj @@ -9,6 +9,10 @@ + + ../ThreatSource/lib/AirTransmission.dll + True +