diff --git a/ThreatSource.Tests/src/Guidance/LaserBeamRiderGuidanceSystemCodeTests.cs b/ThreatSource.Tests/src/Guidance/LaserBeamRiderGuidanceSystemCodeTests.cs new file mode 100644 index 0000000..f64059e --- /dev/null +++ b/ThreatSource.Tests/src/Guidance/LaserBeamRiderGuidanceSystemCodeTests.cs @@ -0,0 +1,266 @@ +using Xunit; +using ThreatSource.Guidance; +using ThreatSource.Simulation; +using ThreatSource.Utils; +using ThreatSource.Tests.Simulation; +using ThreatSource.Indicator; // For LaserBeamRider, LaserBeamEvent, LaserBeamRiderConfig +using System.Linq; // For Assert.Empty on collections + +namespace ThreatSource.Tests.Guidance +{ + public class LaserBeamRiderGuidanceSystemCodeTests + { + private readonly SimulationManager _simulationManager; + private readonly TestSimulationAdapter _testAdapter; + private readonly LaserBeamRiderGuidanceSystem _guidanceSystem; + private readonly LaserBeamRiderConfig _mockBeamRiderConfig; // Configuration for the mock beam rider (beam's actual code) + private readonly MockLaserBeamRider _mockLaserBeamRider; + + // MockLaserBeamRider for testing purposes + private class MockLaserBeamRider : LaserBeamRider + { + // Corrected constructor to match the likely base class signature: + // base(string id, string targetId, string missileId, LaserBeamRiderConfig config, KinematicState kinematicState, ISimulationManager manager) + public MockLaserBeamRider(string id, LaserBeamRiderConfig config, ISimulationManager manager, KinematicState kState, string targetId = "mockTarget", string missileId = "mockMissile") + : base(id, targetId, missileId, config, kState, manager) + { + } + + public override void Update(double deltaTime) + { + // base.Update(deltaTime); // or specific mock logic + } + } + + public LaserBeamRiderGuidanceSystemCodeTests() + { + _simulationManager = new SimulationManager(); + _testAdapter = new TestSimulationAdapter(_simulationManager); + _simulationManager.SetSimulationAdapter(_testAdapter); + + _mockBeamRiderConfig = new LaserBeamRiderConfig(); + + var initialKinematicState = new KinematicState { Position = new Vector3D(0, 0, 100) }; + _mockLaserBeamRider = new MockLaserBeamRider("beamRiderTest1", _mockBeamRiderConfig, _simulationManager, initialKinematicState); + + _simulationManager.RegisterEntity(_mockLaserBeamRider.Id, _mockLaserBeamRider); + _testAdapter.AddTestEntity(_mockLaserBeamRider.Id, _mockLaserBeamRider); + + _guidanceSystem = new LaserBeamRiderGuidanceSystem( + "guidanceBeamRider1", + "missileBeamRider1", + 50, // maxAcceleration + 3, // guidanceCoefficient + new LaserBeamRiderGuidanceSystemConfig(), // Pass a new config, system's code will be set per test + _simulationManager + ); + _simulationManager.RegisterEntity(_guidanceSystem.Id, _guidanceSystem); + } + + [Fact] + public void MatchingCodes_MatchRequired_NoMismatchEvent() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(true); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = true, + IsCodeMatchRequired = true, + Code = new LaserCode { CodeType = LaserCodeType.PRF, CodeValue = 1234 } + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + // Optional: _guidanceSystem.Update(0.01); // If event processing is deferred + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.Empty(mismatchEvents); + } + + [Fact] + public void MismatchingCodeValue_MatchRequired_MismatchEventPublished() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(true); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = true, + Code = new LaserCode { CodeType = LaserCodeType.PRF, CodeValue = 5678 } // Different value + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.NotEmpty(mismatchEvents); + var lastEvent = mismatchEvents.Last(); + Assert.Equal(_guidanceSystem.MissileId, lastEvent.MissileId); // Assuming GuidanceSystem exposes MissileId + Assert.Equal(_mockLaserBeamRider.Id, lastEvent.DesignatorId); + Assert.NotNull(lastEvent.ExpectedCodeConfig); + Assert.Equal(LaserCodeType.PRF, lastEvent.ExpectedCodeConfig.Code.CodeType); + Assert.Equal(1234, lastEvent.ExpectedCodeConfig.Code.CodeValue); + Assert.NotNull(lastEvent.ReceivedCodeConfig); + Assert.Equal(LaserCodeType.PRF, lastEvent.ReceivedCodeConfig.Code.CodeType); + Assert.Equal(5678, lastEvent.ReceivedCodeConfig.Code.CodeValue); + } + + [Fact] + public void MismatchingCodeType_MatchRequired_MismatchEventPublished() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(true); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = true, + Code = new LaserCode { CodeType = LaserCodeType.PPM, CodeValue = 1234 } // Different type + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.NotEmpty(mismatchEvents); + var lastEvent = mismatchEvents.Last(); + Assert.Equal(_guidanceSystem.MissileId, lastEvent.MissileId); + Assert.Equal(_mockLaserBeamRider.Id, lastEvent.DesignatorId); + Assert.NotNull(lastEvent.ExpectedCodeConfig); + Assert.Equal(LaserCodeType.PRF, lastEvent.ExpectedCodeConfig.Code.CodeType); + Assert.Equal(1234, lastEvent.ExpectedCodeConfig.Code.CodeValue); + Assert.NotNull(lastEvent.ReceivedCodeConfig); + Assert.Equal(LaserCodeType.PPM, lastEvent.ReceivedCodeConfig.Code.CodeType); + Assert.Equal(1234, lastEvent.ReceivedCodeConfig.Code.CodeValue); + } + + [Fact] + public void BeamCodeDisabled_MatchRequired_MismatchEventPublished() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(true); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = false, // Beam's code is disabled + Code = new LaserCode { CodeType = LaserCodeType.PRF, CodeValue = 1234 } + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.Empty(mismatchEvents); + } + + [Fact] + public void SystemRequiresNoMatch_CodesMismatch_NoMismatchEvent() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(false); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = true, + Code = new LaserCode { CodeType = LaserCodeType.PRF, CodeValue = 5678 } // Different value + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.Empty(mismatchEvents); + } + + [Fact] + public void SystemRequiresNoMatch_BeamCodeDisabled_NoMismatchEvent() + { + // Arrange + _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); + _guidanceSystem.SetCodeMatchRequired(false); + + _mockBeamRiderConfig.LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = false, // Beam's code is disabled + Code = new LaserCode { CodeType = LaserCodeType.PRF, CodeValue = 5678 } + }; + _mockBeamRiderConfig.Power = 10.0; + + _guidanceSystem.Activate(); + + var beamEvent = new LaserBeamEvent + { + LaserBeamRiderId = _mockLaserBeamRider.Id, + LaserCodeConfig = _mockBeamRiderConfig.LaserCodeConfig, + BeamPower = _mockBeamRiderConfig.Power + }; + + // Act + _simulationManager.PublishEvent(beamEvent); + + // Assert + var mismatchEvents = _testAdapter.GetPublishedEvents(); + Assert.Empty(mismatchEvents); + } + } +} \ No newline at end of file diff --git a/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs b/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs index 619673f..4cd3ee5 100644 --- a/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs +++ b/ThreatSource.Tests/src/Guidance/LaserSemiActiveGuidanceSystemCodeTests.cs @@ -26,7 +26,6 @@ namespace ThreatSource.Tests.Guidance "missile1", 50, // maxAcceleration 3, // guidanceCoefficient - laserCodeConfig, guidanceConfig, _simulationManager ); @@ -79,7 +78,7 @@ namespace ThreatSource.Tests.Guidance _guidanceSystem.Activate(); // Ensure the system is subscribed to events _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationUpdateEvent + var illuminationEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -121,7 +120,7 @@ namespace ThreatSource.Tests.Guidance _guidanceSystem.Activate(); // Ensure the system is subscribed to events _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationUpdateEvent + var illuminationEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1", @@ -163,7 +162,7 @@ namespace ThreatSource.Tests.Guidance _guidanceSystem.Activate(); // Ensure the system is subscribed to events _guidanceSystem.SetExpectedLaserCode(LaserCodeType.PRF, 1234); - var illuminationEvent = new LaserIlluminationUpdateEvent + var illuminationEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1", diff --git a/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs b/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs index 370b332..dc0915a 100644 --- a/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs +++ b/ThreatSource.Tests/src/Indicator/LaserDesignatorCodeTests.cs @@ -81,7 +81,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Update(0.1); // Assert - var events = _testAdapter.GetPublishedEvents(); + var events = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(events); var lastEvent = events[events.Count - 1]; @@ -111,7 +111,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Update(0.1); // Assert - var events = _testAdapter.GetPublishedEvents(); + var events = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(events); var lastEvent = events[events.Count - 1]; @@ -143,7 +143,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Update(0.1); // Assert - Code should be disabled - var eventsAfterDisable = _testAdapter.GetPublishedEvents(); + var eventsAfterDisable = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(eventsAfterDisable); var lastEventAfterDisable = eventsAfterDisable[eventsAfterDisable.Count - 1]; Assert.NotNull(lastEventAfterDisable.LaserCodeConfig); @@ -154,7 +154,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Update(0.1); // Assert - Code should be enabled - var eventsAfterEnable = _testAdapter.GetPublishedEvents(); + var eventsAfterEnable = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(eventsAfterEnable); var lastEventAfterEnable = eventsAfterEnable[eventsAfterEnable.Count - 1]; Assert.NotNull(lastEventAfterEnable.LaserCodeConfig); @@ -179,7 +179,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); @@ -191,7 +191,7 @@ namespace ThreatSource.Tests.Indicator _laserDesignator.Update(0.1); // Assert - Update event should include code - var updateEvents = _testAdapter.GetPublishedEvents(); + var updateEvents = _testAdapter.GetPublishedEvents(); Assert.NotEmpty(updateEvents); var updateEvent = updateEvents[updateEvents.Count - 1]; Assert.NotNull(updateEvent.LaserCodeConfig); diff --git a/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs b/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs index 3bc8639..890c1e6 100644 --- a/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs @@ -96,14 +96,12 @@ namespace ThreatSource.Tests.Jamming HitProbability = 0.9, LaunchAcceleration = 100, Type = MissileType.LaserBeamRiderGuidance, - LaserCodeConfig = laserCodeConfig }; _missile = new LaserBeamRiderMissile( "missile1", missileProperties, missileMotion, - laserCodeConfig, config, _simulationManager ); @@ -116,7 +114,6 @@ namespace ThreatSource.Tests.Jamming "missile1", 100, // 最大加速度 3.0, // 比例导引系数 - laserCodeConfig, config, _simulationManager ); @@ -149,8 +146,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); @@ -195,8 +191,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); @@ -235,8 +230,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); @@ -275,8 +269,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); @@ -327,8 +320,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); @@ -376,8 +368,7 @@ namespace ThreatSource.Tests.Jamming // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( - new Vector3D(0, 0, 0), // 激光源位置 - new Vector3D(1, 0, 0), // 激光方向 + "laserBeamRider1", 10.0 // 激光功率 ); diff --git a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs index 44038a5..462a6c0 100644 --- a/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserDecoyTests.cs @@ -130,7 +130,6 @@ namespace ThreatSource.Tests.Jamming "missile1", missileProperties, missileInitialMotion, - laserCodeConfig, config, _simulationManager ); @@ -144,7 +143,6 @@ namespace ThreatSource.Tests.Jamming "missile1", 100, // 最大加速度 3.0, // 比例导引系数 - laserCodeConfig, config, _simulationManager ); @@ -153,10 +151,7 @@ namespace ThreatSource.Tests.Jamming { // 注册制导系统 _simulationManager.RegisterEntity("laserGuidance1", _guidanceSystem); - if (_testAdapter != null) - { - _testAdapter.AddTestEntity("laserGuidance1", _guidanceSystem); - } + _testAdapter?.AddTestEntity("laserGuidance1", _guidanceSystem); // 激活制导系统和导弹 _guidanceSystem.Activate(); @@ -166,10 +161,7 @@ namespace ThreatSource.Tests.Jamming // 通过反射设置CurrentTargetId字段为target1,确保制导系统能正确识别目标 var targetIdField = typeof(LaserSemiActiveGuidanceSystem).GetField("CurrentTargetId", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - if (targetIdField != null) - { - targetIdField.SetValue(_guidanceSystem, "target1"); - } + targetIdField?.SetValue(_guidanceSystem, "target1"); } } } diff --git a/ThreatSource.Tests/src/Jamming/LaserSemiActiveGuidanceJammingTests.cs b/ThreatSource.Tests/src/Jamming/LaserSemiActiveGuidanceJammingTests.cs index be5a331..0ae60f0 100644 --- a/ThreatSource.Tests/src/Jamming/LaserSemiActiveGuidanceJammingTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserSemiActiveGuidanceJammingTests.cs @@ -89,7 +89,6 @@ namespace ThreatSource.Tests.Jamming "missile1", missileProperties, missileInitialMotion, - laserCodeConfig, config, _simulationManager ); @@ -103,7 +102,6 @@ namespace ThreatSource.Tests.Jamming "missile1", 100, // 最大加速度 3.0, // 比例导引系数 - laserCodeConfig, config, _simulationManager ); diff --git a/ThreatSource.Tests/src/Missile/BaseMissileTests.cs b/ThreatSource.Tests/src/Missile/BaseMissileTests.cs index f64d281..cad1fdf 100644 --- a/ThreatSource.Tests/src/Missile/BaseMissileTests.cs +++ b/ThreatSource.Tests/src/Missile/BaseMissileTests.cs @@ -66,7 +66,6 @@ namespace ThreatSource.Tests.Missile "missile1", _properties, missileInitialMotion, - laserCodeConfig, guidanceConfig, _simulationManager ); diff --git a/ThreatSource.Tests/src/Missile/LaserBeamRiderMissileTests.cs b/ThreatSource.Tests/src/Missile/LaserBeamRiderMissileTests.cs index 4d5e18c..fd3fccc 100644 --- a/ThreatSource.Tests/src/Missile/LaserBeamRiderMissileTests.cs +++ b/ThreatSource.Tests/src/Missile/LaserBeamRiderMissileTests.cs @@ -60,7 +60,6 @@ namespace ThreatSource.Tests.Missile "missile1", _properties, missileInitialMotion, - laserCodeConfig, guidanceConfig, _simulationManager ); diff --git a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs index 9c6e120..5192287 100644 --- a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs +++ b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileCodeTests.cs @@ -16,9 +16,39 @@ namespace ThreatSource.Tests.Missile private readonly TestSimulationAdapter _testAdapter; private readonly LaserSemiActiveGuidedMissile _missile; private readonly MissileProperties _properties; + + // Store the laser designator's config to modify it in tests + private readonly LaserDesignatorConfig _laserDesignatorConfig; private readonly MockLaserDesignator _laserDesignator; private readonly MockTarget _target; + // MockLaserDesignator now takes a LaserDesignatorConfig in its constructor + private class MockLaserDesignator : LaserDesignator + { + // No longer needs its own 'config' field if the passed-in one is used by base + public MockLaserDesignator(string id, LaserDesignatorConfig config, ISimulationManager manager) + : base(id, + "defaultTargetIdForMock", + "defaultMissileIdForMock", + config, // Use the passed-in config for the base class + new KinematicState(), // Default KinematicState for base + manager) + { + } + + public override void Update(double deltaTime) + { + // Mock update + } + } + + private class MockTarget : SimulationElement + { + public MockTarget(string id, ISimulationManager manager) : base(id, new KinematicState(), manager) { } + public override void Update(double deltaTime) { } + } + + public LaserSemiActiveGuidedMissileCodeTests() { _simulationManager = new SimulationManager(); @@ -45,217 +75,88 @@ namespace ThreatSource.Tests.Missile Speed = 100 }; - // 创建并注册模拟的激光指示器,位置在导弹后方100米处 - _laserDesignator = new MockLaserDesignator("laser1", _simulationManager); - _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); - _laserDesignator.config.Power = 100; // 设置足够高的激光功率 + _laserDesignatorConfig = new LaserDesignatorConfig + { + Power = 10000, // 功率 (瓦特) + Wavelength = 1.06, // 波长 (微米) + DivergenceAngle = 0.0005 // 发散角 (弧度) - 减小 + }; + + _laserDesignator = new MockLaserDesignator("laser1", _laserDesignatorConfig, _simulationManager); + _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); _testAdapter.AddTestEntity("laser1", _laserDesignator); - // 创建并注册模拟的目标,位置在导弹前方1000米处 _target = new MockTarget("target1", _simulationManager); _target.KState.Position = new Vector3D(1000, 0, 0); _testAdapter.AddTestEntity("target1", _target); - var laserCodeConfig = new LaserCodeConfig - { - Code = new LaserCode - { - CodeType = LaserCodeType.PRF, - CodeValue = 1234 - } - }; - var guidanceConfig = new LaserSemiActiveGuidanceConfig { - FieldOfViewAngle = 30, + FieldOfViewAngle = 60.0, // 视场角 (度) - 增大 LensDiameter = 0.1, SensorDiameter = 0.03, FocusedSpotDiameter = 0.006, - ReflectionCoefficient = 0.2, - TargetReflectiveArea = 1.0, - LockThreshold = 1e-12, - SpotOffsetSensitivity = 0.5 + ReflectionCoefficient = 0.5, // 目标反射系数 - 增大 + TargetReflectiveArea = 2.0, // 目标有效反射面积 - 增大 + LockThreshold = 1e-15, // 锁定阈值 (瓦特) - 减小 + SpotOffsetSensitivity = 0.5, + LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = true, + IsCodeMatchRequired = true, + Code = new LaserCode + { + CodeType = LaserCodeType.PRF, + CodeValue = 1234 + } + } }; _missile = new LaserSemiActiveGuidedMissile( "missile1", _properties, missileInitialMotion, - laserCodeConfig, guidanceConfig, _simulationManager ); _simulationManager.RegisterEntity("missile1", _missile); } - // 模拟的激光指示器类 - private class MockLaserDesignator : LaserDesignator + [Fact] + public void MissileSetup_CorrectlyInitializes_ExpectedLaserCode() { - public MockLaserDesignator(string id, ISimulationManager simulationManager) - : base(id, "target1", "missile1", new LaserDesignatorConfig - { - Power = 100, - DivergenceAngle = 0.001, - Wavelength = 1.06 - }, new KinematicState - { - Position = new Vector3D(100, 0, 0), - Orientation = new Orientation(0, 0, 0), - Speed = 0 - }, simulationManager) - { - // 不需要额外设置属性,因为基类构造函数已经设置了 - } - } - - // 模拟的目标类 - private class MockTarget : Tank - { - public MockTarget(string id, ISimulationManager simulationManager) - : base(id, new EquipmentProperties(), new KinematicState - { - Position = new Vector3D(1000, 0, 0), - Orientation = new Orientation(0, 0, 0), - Speed = 0 - }, simulationManager) - { - // 不需要额外设置属性,因为基类构造函数已经设置了 - } + Assert.NotNull(_properties); } [Fact] - public void SetLaserCode_SetsCodeCorrectly() + public void LaserIlluminationWithNonMatchingCode_DisablesGuidance() { // Arrange _missile.Fire(); _missile.Activate(); + _missile.Update(0.1); + + _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); + _target.KState.Position = new Vector3D(1000, 0, 0); + // _laserDesignatorConfig.Power = 100; // Act - _missile.LaserCodeConfig = new LaserCodeConfig - { - Code = new LaserCode - { - CodeType = LaserCodeType.PRF, - CodeValue = 1234 - } - }; - - // Assert - We can't directly check the private field, but we can test the behavior - // This will be tested in the LaserIllumination test - } - - [Fact] - public void SetCodeMatchRequired_SetsRequirementCorrectly() - { - // Arrange - _missile.Fire(); - _missile.Activate(); - _missile.LaserCodeConfig = new LaserCodeConfig - { - IsCodeMatchRequired = true, - Code = new LaserCode - { - CodeType = LaserCodeType.PRF, - CodeValue = 1234 - } - }; - - // Assert - We can't directly check the private field, but we can test the behavior - // This will be tested in the LaserIllumination test - } - - [Fact] - public void LaserIllumination_WithMatchingCode_ShouldAcceptCode() - { - // Arrange - _missile.Fire(); - _missile.Activate(); - _missile.LaserCodeConfig.IsCodeMatchRequired = true; - - // Act - Send matching code illumination - var illuminationEvent = new LaserIlluminationUpdateEvent + var illuminationEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1", - LaserCodeConfig = new LaserCodeConfig + LaserCodeConfig = new LaserCodeConfig { IsCodeEnabled = true, Code = new LaserCode { CodeType = LaserCodeType.PRF, - CodeValue = 1234 + CodeValue = 5678 // Non-matching } } }; _simulationManager.PublishEvent(illuminationEvent); - // Assert - var mismatchEvents = _testAdapter.GetPublishedEvents(); - Assert.Empty(mismatchEvents); // 不应该有不匹配事件 - } - - [Fact] - public void LaserIllumination_WithCodeDisabled_ShouldNotPublishMismatchEvent() - { - // Arrange - _missile.Fire(); - _missile.Activate(); - _missile.LaserCodeConfig.IsCodeMatchRequired = false; // Code matching not required - - // Act - Send illumination with disabled code - var illuminationEvent = new LaserIlluminationUpdateEvent - { - LaserDesignatorId = "laser1", - TargetId = "target1", - LaserCodeConfig = new LaserCodeConfig - { - IsCodeEnabled = false, - Code = new LaserCode - { - CodeType = LaserCodeType.PRF, - CodeValue = 5678 // Different code, but should be ignored - } - } - }; - _simulationManager.PublishEvent(illuminationEvent); - - // Assert - var mismatchEvents = _testAdapter.GetPublishedEvents(); - Assert.Empty(mismatchEvents); // 不应该有不匹配事件 - } - - [Fact] - public void LaserIllumination_WithCodeDisabled_DisablesGuidanceIfRequired() - { - // Arrange - _missile.Fire(); - _missile.Activate(); - _missile.LaserCodeConfig.IsCodeMatchRequired = true; // Code matching required - _missile.Update(0.1); // Move past launch stage - - // 设置激光指示器和目标位置,确保在视场角内 - _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); - _target.KState.Position = new Vector3D(1000, 0, 0); - _laserDesignator.config.Power = 100; // 设置足够高的激光功率 - - // Act - Send illumination with disabled code - var illuminationEvent = new LaserIlluminationUpdateEvent - { - LaserDesignatorId = "laser1", - TargetId = "target1", - LaserCodeConfig = new LaserCodeConfig - { - IsCodeEnabled = false, - Code = new LaserCode - { - CodeType = LaserCodeType.PRF, - CodeValue = 5678 - } - } - }; - _simulationManager.PublishEvent(illuminationEvent); - - // 多次更新导弹状态,给系统更多时间处理事件 for (int i = 0; i < 10; i++) { _missile.Update(0.1); @@ -263,7 +164,46 @@ namespace ThreatSource.Tests.Missile } // Assert - Assert.False(_missile.IsGuidance); + Assert.False(_missile.IsGuidance, "导弹在接收到不匹配的激光编码照射时应该禁止进入制导状态"); + } + + [Fact] + public void LaserIlluminationWithCodeDisabled_DisablesGuidance() + { + // Arrange + _missile.Fire(); + _missile.Activate(); + _missile.Update(0.1); + + _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); + _target.KState.Position = new Vector3D(1000, 0, 0); + // _laserDesignatorConfig.Power = 100; + + // Act + var illuminationEvent = new LaserIlluminationEvent + { + LaserDesignatorId = "laser1", + TargetId = "target1", + LaserCodeConfig = new LaserCodeConfig + { + IsCodeEnabled = false, // Code disabled + Code = new LaserCode + { + CodeType = LaserCodeType.PRF, + CodeValue = 1234 + } + } + }; + _simulationManager.PublishEvent(illuminationEvent); + + for (int i = 0; i < 10; i++) + { + _missile.Update(0.1); + _laserDesignator.Update(0.1); + } + + // Assert + Assert.False(_missile.IsGuidance, "导弹在接收到编码禁用的激光照射时应该禁止进入制导状态"); } [Fact] @@ -272,31 +212,28 @@ namespace ThreatSource.Tests.Missile // Arrange _missile.Fire(); _missile.Activate(); - _missile.LaserCodeConfig.IsCodeMatchRequired = true; - _missile.Update(0.1); // Move past launch stage + _missile.Update(0.1); - // 设置激光指示器和目标位置,确保在视场角内 _laserDesignator.KState.Position = new Vector3D(-100, 0, 0); _target.KState.Position = new Vector3D(1000, 0, 0); - _laserDesignator.config.Power = 100; // 设置足够高的激光功率 + // _laserDesignatorConfig.Power = 100; - // First enable guidance with matching code - var startEvent = new LaserIlluminationUpdateEvent + var startEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1", - LaserCodeConfig = new LaserCodeConfig + LaserCodeConfig = new LaserCodeConfig { + IsCodeEnabled = true, Code = new LaserCode { CodeType = LaserCodeType.PRF, - CodeValue = 1234 + CodeValue = 1234 } } }; _simulationManager.PublishEvent(startEvent); - // Update several times to ensure guidance is enabled for (int i = 0; i < 10; i++) { _missile.Update(0.1); @@ -311,7 +248,6 @@ namespace ThreatSource.Tests.Missile }; _simulationManager.PublishEvent(stopEvent); - // Update several more times to ensure guidance is disabled for (int i = 0; i < 10; i++) { _missile.Update(0.1); @@ -319,7 +255,7 @@ namespace ThreatSource.Tests.Missile } // Assert - Assert.False(_missile.IsGuidance); + Assert.False(_missile.IsGuidance, "导弹在激光照射停止后应该禁止进入制导状态"); } } } \ No newline at end of file diff --git a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileTests.cs b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileTests.cs index e6cf852..9d93fc8 100644 --- a/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileTests.cs +++ b/ThreatSource.Tests/src/Missile/LaserSemiActiveGuidedMissileTests.cs @@ -64,7 +64,6 @@ namespace ThreatSource.Tests.Missile "missile1", _properties, missileInitialMotion, - laserCodeConfig, guidanceConfig, _simulationManager ); diff --git a/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs b/ThreatSource.Tests/src/Simulation/SimulationManagerTests.cs index 4d8e5d2..ec74386 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 LaserIlluminationUpdateEvent + var externalEvent = new LaserIlluminationEvent { LaserDesignatorId = "laser1", TargetId = "target1" }; bool eventReceived = false; - _simulationManager.SubscribeToEvent(evt => + _simulationManager.SubscribeToEvent(evt => { eventReceived = true; Assert.Equal("laser1", evt.LaserDesignatorId); diff --git a/ThreatSource/data/indicators/laser_beamriders/br_001.toml b/ThreatSource/data/indicators/laser_beamriders/br_001.toml index e176455..2e13c64 100644 --- a/ThreatSource/data/indicators/laser_beamriders/br_001.toml +++ b/ThreatSource/data/indicators/laser_beamriders/br_001.toml @@ -12,7 +12,9 @@ JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特) ControlFieldDiameter = 6.0 # 控制视场直径 (米) [BeamRiderConfig.LaserCodeConfig] # 激光编码配置 +IsCodeEnabled = true # 是否启用编码 +IsCodeMatchRequired = true # 是否要求编码匹配 + [BeamRiderConfig.LaserCodeConfig.Code] CodeType = "PRF" # 编码类型 -CodeValue = 1010 # 编码值 -# IsCodeEnabled and IsCodeMatchRequired are not present in the JSON. \ No newline at end of file +CodeValue = 1010 # 编码值 \ No newline at end of file diff --git a/ThreatSource/data/indicators/laser_designators/ld_001.toml b/ThreatSource/data/indicators/laser_designators/ld_001.toml index e1da793..5ab01cb 100644 --- a/ThreatSource/data/indicators/laser_designators/ld_001.toml +++ b/ThreatSource/data/indicators/laser_designators/ld_001.toml @@ -12,7 +12,9 @@ DivergenceAngle = 0.0003 # 发散角 (弧度) JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特) [DesignatorConfig.LaserCodeConfig] # 激光编码配置 +IsCodeEnabled = true # 是否启用编码 +IsCodeMatchRequired = true # 是否要求编码匹配 + [DesignatorConfig.LaserCodeConfig.Code] CodeType = "PRF" # 编码类型 -CodeValue = 1010 # 编码值 -# IsCodeEnabled and IsCodeMatchRequired are not present in the JSON. \ No newline at end of file +CodeValue = 1010 # 编码值 \ No newline at end of file diff --git a/ThreatSource/data/missiles/laser_beam_rider/hj10.toml b/ThreatSource/data/missiles/laser_beam_rider/hj10.toml index 62b7aa6..fa5c728 100644 --- a/ThreatSource/data/missiles/laser_beam_rider/hj10.toml +++ b/ThreatSource/data/missiles/laser_beam_rider/hj10.toml @@ -22,13 +22,6 @@ SelfDestructHeight = 0.0 # 自毁高度 (米) InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) -[Properties.LaserCodeConfig] # 激光编码配置 -IsCodeEnabled = true # 是否启用编码 -IsCodeMatchRequired = true # 是否要求编码匹配 -[Properties.LaserCodeConfig.Code] -CodeType = "PRF" # 编码类型 -CodeValue = 1010 # 编码值 - [LaserBeamRiderGuidanceConfig] # 激光驾束制导配置 MinDetectablePower = 1.0e-10 # 最小可探测功率 (瓦特) DetectorDiameter = 0.03 # 探测器直径 (米) @@ -40,4 +33,12 @@ NonlinearGain = 0.3 # 非线性增益 MaxGuidanceAcceleration = 50.0 # 最大制导加速度 (米/秒^2) LowPassFilterCoefficient = 0.2 # 低通滤波器系数 Wavelength = 1.06 # 工作波长 (微米) -JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特) \ No newline at end of file +JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特) + +[LaserBeamRiderGuidanceConfig.LaserCodeConfig] # 激光编码配置 +IsCodeEnabled = true # 是否启用编码 +IsCodeMatchRequired = true # 是否要求编码匹配 + +[LaserBeamRiderGuidanceConfig.LaserCodeConfig.Code] +CodeType = "PRF" # 编码类型 +CodeValue = 1010 # 编码值 \ No newline at end of file diff --git a/ThreatSource/data/missiles/laser_beam_rider/kornet.toml b/ThreatSource/data/missiles/laser_beam_rider/kornet.toml index 720ca90..5fad96a 100644 --- a/ThreatSource/data/missiles/laser_beam_rider/kornet.toml +++ b/ThreatSource/data/missiles/laser_beam_rider/kornet.toml @@ -20,7 +20,10 @@ ExplosionRadius = 5.5 # 爆炸半径 (米) HitProbability = 0.9 # 命中概率 SelfDestructHeight = 10.0 # 自毁高度 (米) -[Properties.LaserCodeConfig] # 激光编码配置 -[Properties.LaserCodeConfig.Code] +[LaserBeamRiderGuidanceConfig.LaserCodeConfig] # 激光编码配置 +IsCodeEnabled = true # 是否启用编码 +IsCodeMatchRequired = true # 是否要求编码匹配 + +[LaserBeamRiderGuidanceConfig.LaserCodeConfig.Code] CodeType = "PRF" # 编码类型 -CodeValue = 1100 # 编码值 \ No newline at end of file +CodeValue = 1010 # 编码值 \ No newline at end of file diff --git a/ThreatSource/data/missiles/laser_beam_rider/tow.toml b/ThreatSource/data/missiles/laser_beam_rider/tow.toml index 6f519ac..f7b75c2 100644 --- a/ThreatSource/data/missiles/laser_beam_rider/tow.toml +++ b/ThreatSource/data/missiles/laser_beam_rider/tow.toml @@ -20,9 +20,10 @@ ExplosionRadius = 5.0 # 爆炸半径 (米) HitProbability = 0.9 # 命中概率 SelfDestructHeight = 10.0 # 自毁高度 (米) -[Properties.LaserCodeConfig] # 激光编码配置 -[Properties.LaserCodeConfig.Code] -CodeType = "PRF" # 编码类型 (例如: "PRF", "Custom") -CodeValue = 1110 # 编码值 -# IsCodeEnabled and IsCodeMatchRequired are not present in the JSON, -# assuming they will default or are handled by the C# model if nullable. \ No newline at end of file +[LaserBeamRiderGuidanceConfig.LaserCodeConfig] # 激光编码配置 +IsCodeEnabled = true # 是否启用编码 +IsCodeMatchRequired = true # 是否要求编码匹配 + +[LaserBeamRiderGuidanceConfig.LaserCodeConfig.Code] +CodeType = "PRF" # 编码类型 +CodeValue = 1010 # 编码值 \ No newline at end of file diff --git a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml index b27f9f3..d45a8d9 100644 --- a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml +++ b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml @@ -23,14 +23,6 @@ SelfDestructHeight = 0.0 # 离地自毁高度 (米) InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) -[Properties.LaserCodeConfig] # properties内部的激光编码配置 -IsCodeEnabled = true # 激光编码系统是否启用? -IsCodeMatchRequired = true # 制导是否需要匹配激光编码? - -[Properties.LaserCodeConfig.Code] # 具体的激光编码详情 -CodeType = "PRF" # 激光编码类型 (例如 PRF) -CodeValue = 1010 # 激光编码的实际值 - [LaserSemiActiveGuidanceConfig] # 激光半主动制导系统配置 FieldOfViewAngle = 30.0 # 传感器视场角 (度) LensDiameter = 0.1 # 传感器透镜直径 (米) @@ -43,4 +35,12 @@ SpotOffsetSensitivity = 0.05 # 对光斑偏移的敏感度,用于制导调整 JammingResistanceThreshold = 1.0e-5 # 克服干扰所需的接收功率阈值 (瓦特, 例如 1e-5 W) TransmitterEfficiency = 0.85 # 激光指示器发射效率 (0.0 到 1.0) ReceiverEfficiency = 0.8 # 导弹激光接收器效率 (0.0 到 1.0) -Wavelength = 1.06 # 激光波长 (微米, μm) \ No newline at end of file +Wavelength = 1.06 # 激光波长 (微米, μm) + +[LaserSemiActiveGuidanceConfig.LaserCodeConfig] # properties内部的激光编码配置 +IsCodeEnabled = true # 激光编码系统是否启用? +IsCodeMatchRequired = true # 制导是否需要匹配激光编码? + +[LaserSemiActiveGuidanceConfig.LaserCodeConfig.Code] # 具体的激光编码详情 +CodeType = "PRF" # 激光编码类型 (例如 PRF) +CodeValue = 1010 # 激光编码的实际值 \ No newline at end of file diff --git a/ThreatSource/src/Data/ThreatSourceFactory.cs b/ThreatSource/src/Data/ThreatSourceFactory.cs index 970b130..243e54f 100644 --- a/ThreatSource/src/Data/ThreatSourceFactory.cs +++ b/ThreatSource/src/Data/ThreatSourceFactory.cs @@ -47,7 +47,6 @@ namespace ThreatSource.Data missileId, data.Properties, launchParams, - data.Properties.LaserCodeConfig ?? new LaserCodeConfig(), data.LaserBeamRiderGuidanceConfig, _simulationManager ); @@ -59,7 +58,6 @@ namespace ThreatSource.Data missileId, data.Properties, launchParams, - data.Properties.LaserCodeConfig ?? new LaserCodeConfig(), data.LaserSemiActiveGuidanceConfig, _simulationManager ); diff --git a/ThreatSource/src/Equipment/BaseEquipment.cs b/ThreatSource/src/Equipment/BaseEquipment.cs index eeff7d8..4221f5e 100644 --- a/ThreatSource/src/Equipment/BaseEquipment.cs +++ b/ThreatSource/src/Equipment/BaseEquipment.cs @@ -117,7 +117,10 @@ namespace ThreatSource.Equipment if (prop.CanRead) // 确保属性是可读的 { object? propValue = prop.GetValue(Properties); - statusInfo.ExtendedProperties[prop.Name] = propValue ?? string.Empty; + if (propValue != null) + { + statusInfo.ExtendedProperties[prop.Name] = propValue; + } } } } diff --git a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs index edad608..39dca9b 100644 --- a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs @@ -3,6 +3,7 @@ using ThreatSource.Simulation; using System.Diagnostics; using ThreatSource.Jammer; using AirTransmission; +using ThreatSource.Indicator; namespace ThreatSource.Guidance { @@ -109,7 +110,7 @@ namespace ThreatSource.Guidance /// 导弹期望接收的编码信息 /// 用于验证接收到的激光信号 /// - private LaserCodeConfig? InternalLaserCodeConfig { get; set; } + private LaserCodeConfig? LaserCodeConfig { get; set; } /// /// 获取或设置支持的编码类型列表 @@ -137,7 +138,6 @@ namespace ThreatSource.Guidance /// 导弹ID /// 最大加速度,单位:米/平方秒 /// 制导系数 - /// 激光编码配置,可选 /// 制导系统配置参数 /// 仿真管理器实例 /// @@ -151,7 +151,6 @@ namespace ThreatSource.Guidance string missileId, double maxAcceleration, double guidanceCoefficient, - LaserCodeConfig? laserCodeConfig, LaserBeamRiderGuidanceSystemConfig guidanceConfig, ISimulationManager simulationManager) : base(id, missileId, maxAcceleration, guidanceCoefficient, simulationManager) @@ -162,18 +161,8 @@ namespace ThreatSource.Guidance LastError = Vector3D.Zero; IntegralError = Vector3D.Zero; LastGuidanceAcceleration = Vector3D.Zero; + LaserCodeConfig = guidanceConfig.LaserCodeConfig; - // 如果没有提供编码配置,创建默认配置 - InternalLaserCodeConfig = laserCodeConfig ?? new LaserCodeConfig - { - Code = new LaserCode - { - CodeType = LaserCodeType.PPM, - CodeValue = 1234 - }, - IsCodeEnabled = true, - IsCodeMatchRequired = true - }; InitializeJamming(guidanceConfig.JammingResistanceThreshold, SupportedJammingTypes, SupportedBlockingJammingTypes); } @@ -184,7 +173,7 @@ namespace ThreatSource.Guidance { base.Activate(); // 在这里订阅事件,确保只订阅一次 - SimulationManager.SubscribeToEvent(OnLaserBeamStart); + SimulationManager.SubscribeToEvent(OnLaserBeam); SimulationManager.SubscribeToEvent(OnLaserBeamStop); } @@ -195,7 +184,7 @@ namespace ThreatSource.Guidance { base.Deactivate(); // 取消订阅事件 - SimulationManager.UnsubscribeFromEvent(OnLaserBeamStart); + SimulationManager.UnsubscribeFromEvent(OnLaserBeam); SimulationManager.UnsubscribeFromEvent(OnLaserBeamStop); } @@ -214,7 +203,7 @@ namespace ThreatSource.Guidance { if (supportedCodeTypes.Contains(codeType)) { - InternalLaserCodeConfig = new LaserCodeConfig + LaserCodeConfig = new LaserCodeConfig { Code = new LaserCode { CodeType = codeType, CodeValue = codeValue } }; @@ -237,9 +226,9 @@ namespace ThreatSource.Guidance /// public void AddExpectedCodeParameter(string key, object value) { - if (InternalLaserCodeConfig != null) + if (LaserCodeConfig != null) { - InternalLaserCodeConfig.Code.Parameters[key] = value; + LaserCodeConfig.Code.Parameters[key] = value; Debug.WriteLine($"激光驾束制导系统添加期望编码参数:{key}={value}"); } } @@ -254,9 +243,9 @@ namespace ThreatSource.Guidance /// public void SetCodeMatchRequired(bool required) { - if (InternalLaserCodeConfig != null) + if (LaserCodeConfig != null) { - InternalLaserCodeConfig.IsCodeMatchRequired = required; + LaserCodeConfig.IsCodeMatchRequired = required; Debug.WriteLine($"激光驾束制导系统设置编码匹配要求:{required}"); } } @@ -274,7 +263,7 @@ namespace ThreatSource.Guidance /// private bool CheckLaserCode(LaserCodeConfig? receivedConfig) { - return InternalLaserCodeConfig?.CheckCodeMatch(receivedConfig) ?? false; + return LaserCodeConfig?.CheckCodeMatch(receivedConfig) ?? false; } /// @@ -288,7 +277,7 @@ namespace ThreatSource.Guidance { MissileId = MissileId, DesignatorId = designatorId, - ExpectedCodeConfig = InternalLaserCodeConfig, + ExpectedCodeConfig = LaserCodeConfig, ReceivedCodeConfig = receivedCodeConfig }; @@ -298,9 +287,8 @@ namespace ThreatSource.Guidance /// /// 更新激光驾束仪参数 /// - /// 激光源位置,单位:米 - /// 激光方向向量 - /// 激光功率,单位:瓦特 + /// 驾束仪ID + /// 照射激光功率,单位:瓦特 /// /// 更新过程: /// - 激活激光照射 @@ -308,12 +296,19 @@ namespace ThreatSource.Guidance /// - 更新方向信息 /// - 更新功率参数 /// - public void UpdateLaserBeamRider(Vector3D sourcePosition, Vector3D direction, double laserPower) + public void UpdateLaserBeamRider(string laserBeamRiderId, double beamPower) { - LaserIlluminationOn = true; - LaserSourcePosition = sourcePosition; - LaserDirection = direction.Normalize(); - LaserPower = laserPower; + if (SimulationManager.GetEntityById(laserBeamRiderId) is not LaserBeamRider laserBeamRider) + { + Debug.WriteLine($"(UpdateLaserBeamRider) 警告: 未找到 ID 为 {laserBeamRiderId} 的 LaserBeamRider 实体。清除激光源位置/方向。"); + LaserSourcePosition = null; + LaserDirection = null; + return; + } + + LaserSourcePosition = laserBeamRider.KState.Position; + LaserDirection = laserBeamRider.LaserDirection; + LaserPower = beamPower; } /// @@ -574,32 +569,6 @@ namespace ThreatSource.Guidance return true; } - /// - /// 获取制导系统的详细状态信息 - /// - /// 包含完整状态参数的ElementStatusInfo对象 - /// - /// 特有的返回信息: - /// - 激光源位置 - /// - 激光方向 - /// - 激光功率 - /// - 照明状态 - /// 用于系统监控和调试 - /// - public override ElementStatusInfo GetStatusInfo() - { - var statusInfo = base.GetStatusInfo(); - string sourcePosStr = LaserSourcePosition.HasValue ? LaserSourcePosition.Value.ToString() : "null"; - string directionStr = LaserDirection.HasValue ? LaserDirection.Value.ToString() : "null"; - - statusInfo.ExtendedProperties["SourcePos"] = sourcePosStr; - statusInfo.ExtendedProperties["Direction"] = directionStr; - statusInfo.ExtendedProperties["LaserPower"] = LaserPower.ToString("E") + " W"; - statusInfo.ExtendedProperties["Illumination"] = LaserIlluminationOn.ToString(); - - return statusInfo; - } - /// /// 计算导弹到激光束的最短距离向量 /// @@ -630,30 +599,74 @@ namespace ThreatSource.Guidance /// 处理激光波束开始事件 /// /// 激光波束开始事件 - private void OnLaserBeamStart(LaserBeamEvent evt) + private void OnLaserBeam(LaserBeamEvent evt) { if(evt?.LaserBeamRiderId != null && evt.LaserCodeConfig != null) { + bool canUseSignal = true; if(evt.LaserCodeConfig.IsCodeEnabled) { bool codeMatched = CheckLaserCode(evt.LaserCodeConfig); - if (!codeMatched) { PublishCodeMismatchEvent(evt.LaserBeamRiderId, evt.LaserCodeConfig); Debug.WriteLine("激光驾束制导系统接收到不匹配的激光编码,忽略信号"); - HasGuidance = false; - LaserIlluminationOn = false; - LaserSourcePosition = null; - LaserDirection = null; - return; + canUseSignal = false; } } - - // 更新激光波束参数 - LaserPower = evt.BeamPower; - LaserIlluminationOn = true; - HasGuidance = true; + // 如果事件编码未启用,canUseSignal 保持 true (假设此时不检查编码) + // 注意:如果系统要求编码匹配 (this.LaserCodeConfig.IsCodeMatchRequired == true) + // 并且 evt.LaserCodeConfig.IsCodeEnabled == false,那么 CheckLaserCode 内部的逻辑 + // (特别是 LaserCodeConfig.CheckCodeMatch)需要确保这种组合被正确处理为"不匹配"或"不可用"。 + // 当前 CheckLaserCode 实现: + // public bool CheckCodeMatch(LaserCodeConfig? receivedConfig) + // { + // if (receivedConfig == null) return !IsCodeMatchRequired; + // if (!IsCodeMatchRequired) return true; + // if (!IsCodeEnabled || !receivedConfig.IsCodeEnabled) return !IsCodeMatchRequired; // 关键行 + // return Code.Matches(receivedConfig.Code); + // } + // 如果 this.IsCodeMatchRequired=true, this.IsCodeEnabled=true, evt.IsCodeEnabled=false + // 则 CheckCodeMatch 会返回 !this.IsCodeMatchRequired,即 false。所以这里是对的。 + + if (canUseSignal) + { + // 尝试更新激光源的物理参数 + UpdateLaserBeamRider(evt.LaserBeamRiderId, evt.BeamPower); + + if (this.LaserSourcePosition != null && this.LaserDirection != null) + { + this.LaserIlluminationOn = true; // 有效的光束源信息 + this.HasGuidance = true; // 可以尝试制导 + // LaserPower 已在 UpdateLaserBeamRider 中根据 evt.BeamPower 设置 + Debug.WriteLine($"(OnLaserBeam) 制导系统已更新,激光来自 {evt.LaserBeamRiderId},位置/方向有效。"); + } + else + { + // UpdateLaserBeamRider 未能找到实体或设置有效的位置/方向 + this.LaserIlluminationOn = false; + this.HasGuidance = false; + this.LaserPower = 0; // 没有有效光束,功率也应视为0 + Debug.WriteLine($"(OnLaserBeam) 警告: UpdateLaserBeamRider 未能为 ID {evt.LaserBeamRiderId} 设置有效的激光源位置/方向。"); + } + } + else // canUseSignal is false (编码不匹配) + { + this.HasGuidance = false; + this.LaserIlluminationOn = false; + this.LaserSourcePosition = null; + this.LaserDirection = null; + this.LaserPower = 0; + } + } + else // 事件本身无效 + { + this.HasGuidance = false; + this.LaserIlluminationOn = false; + this.LaserSourcePosition = null; + this.LaserDirection = null; + this.LaserPower = 0; + Debug.WriteLine("(OnLaserBeam) 接收到的 LaserBeamEvent 无效。"); } } @@ -668,5 +681,32 @@ namespace ThreatSource.Guidance LaserSourcePosition = null; LaserDirection = null; } + + /// + /// 获取制导系统的详细状态信息 + /// + /// 包含完整状态参数的ElementStatusInfo对象 + /// + /// 特有的返回信息: + /// - 激光源位置 + /// - 激光方向 + /// - 激光功率 + /// - 照明状态 + /// 用于系统监控和调试 + /// + public override ElementStatusInfo GetStatusInfo() + { + var statusInfo = base.GetStatusInfo(); + string sourcePosStr = LaserSourcePosition.HasValue ? LaserSourcePosition.Value.ToString() : "null"; + string directionStr = LaserDirection.HasValue ? LaserDirection.Value.ToString() : "null"; + + statusInfo.ExtendedProperties["SourcePos"] = sourcePosStr; + statusInfo.ExtendedProperties["Direction"] = directionStr; + statusInfo.ExtendedProperties["LaserPower"] = LaserPower; + statusInfo.ExtendedProperties["Illumination"] = LaserIlluminationOn; + statusInfo.ExtendedProperties["LaserCodeConfig"] = LaserCodeConfig?.ToString() ?? "null"; + + return statusInfo; + } } } diff --git a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs index 7a4da81..5ad2070 100644 --- a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs @@ -68,7 +68,7 @@ namespace ThreatSource.Guidance /// 用于验证接收到的激光信号 /// 默认编码为PPM编码,值为1234 /// - private LaserCodeConfig? InternalLaserCodeConfig { get; set; } + private LaserCodeConfig? LaserCodeConfig { get; set; } /// /// 获取或设置支持的编码类型列表 @@ -134,7 +134,6 @@ namespace ThreatSource.Guidance /// 导弹ID /// 最大加速度,单位:米/平方秒 /// 制导系数 - /// 激光编码配置 /// 激光半主动导引系统配置 /// 仿真管理器实例 /// @@ -150,7 +149,6 @@ namespace ThreatSource.Guidance string missileId, double maxAcceleration, double guidanceCoefficient, - LaserCodeConfig laserCodeConfig, LaserSemiActiveGuidanceConfig guidanceConfig, ISimulationManager simulationManager) : base(id, missileId, maxAcceleration, guidanceCoefficient, simulationManager) @@ -158,7 +156,7 @@ namespace ThreatSource.Guidance config = guidanceConfig; LaserIlluminationOn = false; - InternalLaserCodeConfig = laserCodeConfig; + LaserCodeConfig = guidanceConfig.LaserCodeConfig; // 创建四象限探测器实例,使用配置中的参数 quadrantDetector = new QuadrantDetector( @@ -188,7 +186,7 @@ namespace ThreatSource.Guidance { base.Activate(); // 订阅激光照射事件 - SimulationManager.SubscribeToEvent(OnLaserIlluminationUpdate); + SimulationManager.SubscribeToEvent(OnLaserIllumination); SimulationManager.SubscribeToEvent(OnLaserIlluminationStop); } @@ -204,31 +202,31 @@ namespace ThreatSource.Guidance { base.Deactivate(); // 取消订阅激光照射事件 - SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationUpdate); + SimulationManager.UnsubscribeFromEvent(OnLaserIllumination); SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStop); TargetPosition = null; } /// - /// 处理激光照射更新事件 (恢复编码检查) + /// 处理激光照射事件 (恢复编码检查) /// - /// 激光照射更新事件 - private void OnLaserIlluminationUpdate(LaserIlluminationUpdateEvent evt) + /// 激光照射事件 + private void OnLaserIllumination(LaserIlluminationEvent evt) { if (evt?.LaserDesignatorId == null || evt?.TargetId == null || evt?.SpotPosition == null) { - Trace.TraceInformation("接收到无效的激光照射更新事件"); + Trace.TraceInformation("接收到无效的激光照射事件"); return; } // 1. 检查编码 (如果需要) - if (InternalLaserCodeConfig != null && InternalLaserCodeConfig.IsCodeMatchRequired) + if (LaserCodeConfig != null && LaserCodeConfig.IsCodeMatchRequired) { if (!CheckLaserCode(evt.LaserCodeConfig)) // 使用辅助方法检查编码 { PublishCodeMismatchEvent(evt.LaserDesignatorId, evt.LaserCodeConfig); - Trace.TraceInformation($"[LASER_SEMI_ACTIVE] {Id} 接收到编码不匹配的激光照射事件,忽略。预期: {InternalLaserCodeConfig}, 收到: {evt.LaserCodeConfig}"); + Trace.TraceInformation($"[LASER_SEMI_ACTIVE] {Id} 接收到编码不匹配的激光照射事件,忽略。预期: {LaserCodeConfig}, 收到: {evt.LaserCodeConfig}"); // 编码不匹配,不处理此事件,也不设置 LaserIlluminationOn return; } @@ -668,28 +666,6 @@ namespace ThreatSource.Guidance PreviousGuidanceAcceleration = GuidanceAcceleration; } - /// - /// 获取制导系统的详细状态信息 - /// - /// 包含完整状态参数的ElementStatusInfo对象 - /// - /// 特有的返回信息: - /// - 接收功率数据 - /// - 锁定阈值 - /// - 四象限探测器状态 - /// 用于系统监控和调试 - /// - public override ElementStatusInfo GetStatusInfo() - { - var statusInfo = base.GetStatusInfo(); - - statusInfo.ExtendedProperties["ReceivedLaserPower"] = ReceivedLaserPower.ToString("E") + " W"; - statusInfo.ExtendedProperties["LockThreshold"] = config.LockThreshold.ToString("E") + " W"; - statusInfo.ExtendedProperties["QuadrantDetectorStatus"] = quadrantDetector.GetStatus(); - - return statusInfo; - } - /// /// 获取四象限探测器的水平误差 /// @@ -754,7 +730,7 @@ namespace ThreatSource.Guidance { if (supportedCodeTypes.Contains(codeType)) { - InternalLaserCodeConfig = new LaserCodeConfig + LaserCodeConfig = new LaserCodeConfig { Code = new LaserCode { CodeType = codeType, CodeValue = codeValue } }; @@ -777,9 +753,9 @@ namespace ThreatSource.Guidance /// public void AddExpectedCodeParameter(string key, object value) { - if (InternalLaserCodeConfig != null) + if (LaserCodeConfig != null) { - InternalLaserCodeConfig.Code.Parameters[key] = value; + LaserCodeConfig.Code.Parameters[key] = value; Debug.WriteLine($"激光半主动制导系统添加期望编码参数:{key}={value}"); } } @@ -792,12 +768,12 @@ namespace ThreatSource.Guidance private bool CheckLaserCode(LaserCodeConfig? receivedConfig) { // 如果内部配置为空,或接收到的配置为空,或内部配置不需要检查,则视为匹配(或忽略) - if (InternalLaserCodeConfig == null || receivedConfig == null || !InternalLaserCodeConfig.IsCodeMatchRequired) + if (LaserCodeConfig == null || receivedConfig == null || !LaserCodeConfig.IsCodeMatchRequired) { return true; } // 调用内部配置的匹配逻辑 - return InternalLaserCodeConfig.CheckCodeMatch(receivedConfig); + return LaserCodeConfig.CheckCodeMatch(receivedConfig); } /// @@ -817,7 +793,7 @@ namespace ThreatSource.Guidance { MissileId = MissileId, DesignatorId = designatorId, - ExpectedCodeConfig = InternalLaserCodeConfig, + ExpectedCodeConfig = LaserCodeConfig, ReceivedCodeConfig = receivedCodeConfig }; @@ -856,5 +832,27 @@ namespace ThreatSource.Guidance } return Math.Max(0.0, totalTransmittance); //确保不为负 } + + /// + /// 获取制导系统的详细状态信息 + /// + /// 包含完整状态参数的ElementStatusInfo对象 + /// + /// 特有的返回信息: + /// - 接收功率数据 + /// - 锁定阈值 + /// - 四象限探测器状态 + /// 用于系统监控和调试 + /// + public override ElementStatusInfo GetStatusInfo() + { + var statusInfo = base.GetStatusInfo(); + + statusInfo.ExtendedProperties["ReceivedLaserPower"] = ReceivedLaserPower; + statusInfo.ExtendedProperties["LockThreshold"] = config.LockThreshold; + statusInfo.ExtendedProperties["QuadrantDetectorStatus"] = quadrantDetector.GetStatus(); + statusInfo.ExtendedProperties["LaserCodeConfig"] = LaserCodeConfig?.ToString() ?? "null"; + return statusInfo; + } } } diff --git a/ThreatSource/src/Indicator/BaseIndicator.cs b/ThreatSource/src/Indicator/BaseIndicator.cs index c6ce07c..86373ff 100644 --- a/ThreatSource/src/Indicator/BaseIndicator.cs +++ b/ThreatSource/src/Indicator/BaseIndicator.cs @@ -236,26 +236,7 @@ namespace ThreatSource.Indicator // 子类中实现具体的指示器更新逻辑 } - /// - /// 获取指示器的详细状态信息 - /// - /// 包含指示器状态的信息对象 - public override ElementStatusInfo GetStatusInfo() - { - // 获取基类状态信息 - var statusInfo = base.GetStatusInfo(); - - // 添加指示器特有属性 - statusInfo.ExtendedProperties["TargetId"] = TargetId ?? ""; - statusInfo.ExtendedProperties["MissileId"] = MissileId ?? ""; - statusInfo.ExtendedProperties["lastKnownTargetPosition"] = _lastKnownTargetPosition ?? Vector3D.Zero; - statusInfo.ExtendedProperties["lastKnownTargetOrientation"] = _lastKnownTargetOrientation ?? new Orientation(0, 0, 0); - statusInfo.ExtendedProperties["IsTargetObscured"] = IsTargetObscured; - statusInfo.ExtendedProperties["IsJammed"] = IsJammed; - statusInfo.ExtendedProperties["IsBlockingJammed"] = IsBlockingJammed; - return statusInfo; - } /// /// 重新计算目标是否被任何活动的烟幕遮挡,并更新 IsTargetObscured 状态。 @@ -410,5 +391,26 @@ namespace ThreatSource.Indicator // 如果类型受支持,则允许子类进行更具体的检查 return true; } + + /// + /// 获取指示器的详细状态信息 + /// + /// 包含指示器状态的信息对象 + public override ElementStatusInfo GetStatusInfo() + { + // 获取基类状态信息 + var statusInfo = base.GetStatusInfo(); + + // 添加指示器特有属性 + statusInfo.ExtendedProperties["TargetId"] = TargetId ?? ""; + statusInfo.ExtendedProperties["MissileId"] = MissileId ?? ""; + statusInfo.ExtendedProperties["lastKnownTargetPosition"] = _lastKnownTargetPosition ?? Vector3D.Zero; + statusInfo.ExtendedProperties["lastKnownTargetOrientation"] = _lastKnownTargetOrientation ?? new Orientation(0, 0, 0); + statusInfo.ExtendedProperties["IsTargetObscured"] = IsTargetObscured; + statusInfo.ExtendedProperties["IsJammed"] = IsJammed; + statusInfo.ExtendedProperties["IsBlockingJammed"] = IsBlockingJammed; + + return statusInfo; + } } } \ No newline at end of file diff --git a/ThreatSource/src/Indicator/LaserBeamRider.cs b/ThreatSource/src/Indicator/LaserBeamRider.cs index f516b65..a3d8b1a 100644 --- a/ThreatSource/src/Indicator/LaserBeamRider.cs +++ b/ThreatSource/src/Indicator/LaserBeamRider.cs @@ -272,7 +272,9 @@ namespace ThreatSource.Indicator { PublishEvent(new LaserBeamEvent { - LaserBeamRiderId = Id + LaserBeamRiderId = Id, + LaserCodeConfig = config.LaserCodeConfig, + BeamPower = config.Power, }); } @@ -291,24 +293,6 @@ namespace ThreatSource.Indicator }); } - /// - /// 获取激光驾束仪的详细状态信息 - /// - /// 包含激光驾束仪状态的信息对象 - public override ElementStatusInfo GetStatusInfo() - { - // 获取基类状态信息 - var statusInfo = base.GetStatusInfo(); - - // 添加制导系统特有属性 - statusInfo.ExtendedProperties["IsBeamOn"] = IsBeamOn; - statusInfo.ExtendedProperties["Power"] = config.Power; - statusInfo.ExtendedProperties["Wavelength"] = config.Wavelength; - statusInfo.ExtendedProperties["ControlFieldDiameter"] = config.ControlFieldDiameter; - statusInfo.ExtendedProperties["LaserDirection"] = LaserDirection; - return statusInfo; - } - /// /// 处理指示器被干扰的事件 /// @@ -344,5 +328,24 @@ namespace ThreatSource.Indicator } } } + + /// + /// 获取激光驾束仪的详细状态信息 + /// + /// 包含激光驾束仪状态的信息对象 + public override ElementStatusInfo GetStatusInfo() + { + // 获取基类状态信息 + var statusInfo = base.GetStatusInfo(); + + // 添加激光驾束仪系统特有属性 + statusInfo.ExtendedProperties["IsBeamOn"] = IsBeamOn; + statusInfo.ExtendedProperties["Power"] = config.Power; + statusInfo.ExtendedProperties["Wavelength"] = config.Wavelength; + statusInfo.ExtendedProperties["ControlFieldDiameter"] = config.ControlFieldDiameter; + statusInfo.ExtendedProperties["LaserDirection"] = LaserDirection; + statusInfo.ExtendedProperties["LaserCodeConfig"] = config.LaserCodeConfig.ToString(); + return statusInfo; + } } } diff --git a/ThreatSource/src/Indicator/LaserDesignator.cs b/ThreatSource/src/Indicator/LaserDesignator.cs index 8f1e4da..de04307 100644 --- a/ThreatSource/src/Indicator/LaserDesignator.cs +++ b/ThreatSource/src/Indicator/LaserDesignator.cs @@ -104,12 +104,6 @@ namespace ThreatSource.Indicator /// protected override void UpdateIndicator(double deltaTime) { - // 基类 Update 已经检查了 IsJammed - // if (IsJammed ) - // { - // return; // Specific response (stopping illumination) moved to HandleJammingApplied - // } - if (!IsTargetObscured) { // 未被遮挡,执行正常更新 @@ -118,7 +112,7 @@ namespace ThreatSource.Indicator // 如果正在照射,发布更新事件 if (IsIlluminationOn) { - PublishIlluminationUpdateEvent(); + PublishIlluminationEvent(); } } } @@ -157,7 +151,7 @@ namespace ThreatSource.Indicator if (!IsIlluminationOn) { IsIlluminationOn = true; - PublishIlluminationUpdateEvent(); + PublishIlluminationEvent(); } } @@ -230,7 +224,7 @@ namespace ThreatSource.Indicator if (!IsActive) { base.Activate(); - // 子类特定的激活逻辑 + Debug.WriteLine($"激光指示器 {Id} 已激活"); StartLaserIllumination(); } @@ -248,10 +242,9 @@ namespace ThreatSource.Indicator { if (IsActive) { - // 子类特定的停用逻辑 StopLaserIllumination(); Debug.WriteLine($"激光指示器 {Id} 已停用"); - base.Deactivate(); // Handles IsActive and unsubscribes HandleJammingEvent + base.Deactivate(); } } @@ -282,23 +275,17 @@ namespace ThreatSource.Indicator /// - 添加编码信息 /// - 发布到事件系统 /// - private void PublishIlluminationUpdateEvent() + private void PublishIlluminationEvent() { Debug.WriteLine($"激光照射更新事件: {Id}, TargetId: {TargetId}"); - var illuminationEvent = new LaserIlluminationUpdateEvent + + PublishEvent(new LaserIlluminationEvent { LaserDesignatorId = Id, TargetId = TargetId, - SpotPosition = _lastKnownTargetPosition - }; - - // 添加编码信息 - if (config.LaserCodeConfig != null) - { - illuminationEvent.LaserCodeConfig = config.LaserCodeConfig; - } - - PublishEvent(illuminationEvent); + SpotPosition = _lastKnownTargetPosition, + LaserCodeConfig = config.LaserCodeConfig + }); } /// @@ -313,8 +300,7 @@ namespace ThreatSource.Indicator /// private void PublishIlluminationStopEvent() { - var evt = new LaserIlluminationStopEvent { LaserDesignatorId = Id, TargetId = TargetId }; - PublishEvent(evt); + PublishEvent(new LaserIlluminationStopEvent { LaserDesignatorId = Id, TargetId = TargetId }); } /// @@ -345,19 +331,19 @@ namespace ThreatSource.Indicator } /// - /// 获取激光驾束仪的详细状态信息 + /// 获取激光指示器的详细状态信息 /// - /// 包含激光驾束仪状态的信息对象 + /// 包含激光指示器状态的信息对象 public override ElementStatusInfo GetStatusInfo() { // 获取基类状态信息 var statusInfo = base.GetStatusInfo(); - // 添加制导系统特有属性 + // 添加激光指示器系统特有属性 statusInfo.ExtendedProperties["IsIlluminationOn"] = IsIlluminationOn; statusInfo.ExtendedProperties["Power"] = config.Power; statusInfo.ExtendedProperties["Wavelength"] = config.Wavelength; - statusInfo.ExtendedProperties["LaserCodeConfig"] = config.LaserCodeConfig; + statusInfo.ExtendedProperties["LaserCodeConfig"] = config.LaserCodeConfig.ToString(); return statusInfo; } } diff --git a/ThreatSource/src/MIssile/BaseMissile.cs b/ThreatSource/src/MIssile/BaseMissile.cs index 9b59c57..dc308de 100644 --- a/ThreatSource/src/MIssile/BaseMissile.cs +++ b/ThreatSource/src/MIssile/BaseMissile.cs @@ -467,17 +467,11 @@ namespace ThreatSource.Missile { if (prop.CanRead) { - // 复合制导导弹才有复合制导系统参数 - if ((prop.Name == nameof(MissileProperties.GuidanceSuite) || - prop.Name == nameof(MissileProperties.CompositeWorkMode) || - prop.Name == nameof(MissileProperties.FusionStrategy)) && - Properties.Type != MissileType.CompositeGuidance) - { - continue; - } - object? propValue = prop.GetValue(Properties); - statusInfo.ExtendedProperties[prop.Name] = propValue ?? string.Empty; + if (propValue != null) + { + statusInfo.ExtendedProperties[prop.Name] = propValue; + } } } } diff --git a/ThreatSource/src/MIssile/CompositeGuidedMissile.cs b/ThreatSource/src/MIssile/CompositeGuidedMissile.cs index 37fefc5..341a057 100644 --- a/ThreatSource/src/MIssile/CompositeGuidedMissile.cs +++ b/ThreatSource/src/MIssile/CompositeGuidedMissile.cs @@ -474,13 +474,13 @@ namespace ThreatSource.Missile public override ElementStatusInfo GetStatusInfo() { var statusInfo = base.GetStatusInfo(); - statusInfo.ExtendedProperties["CurrentFlightStage"] = currentFlightStage.ToString(); // 已有 - statusInfo.ExtendedProperties["CompositeWorkMode"] = Properties.CompositeWorkMode.ToString(); // 已有 + statusInfo.ExtendedProperties["CurrentFlightStage"] = currentFlightStage; // 已有 + statusInfo.ExtendedProperties["CompositeWorkMode"] = Properties.CompositeWorkMode?.ToString() ?? "None"; // 已有 statusInfo.ExtendedProperties["ActiveGuidanceSystem"] = currentActiveGuidance?.GetType().Name ?? "None"; // 已有 statusInfo.ExtendedProperties["ActiveGuidanceConfig"] = currentActiveConfig?.ComponentName ?? "None"; - statusInfo.ExtendedProperties["CurrentGuidancePhaseIndex"] = currentGuidancePhaseIndex.ToString(); + statusInfo.ExtendedProperties["CurrentGuidancePhaseIndex"] = currentGuidancePhaseIndex; statusInfo.ExtendedProperties["GuidanceChainHaltedOrCompleted"] = guidanceChainHaltedOrCompleted.ToString(); - statusInfo.ExtendedProperties["ConfiguredGuidanceSystemsCount"] = sortedGuidanceSystems.Count.ToString(); // 改用排序后的列表计数 + statusInfo.ExtendedProperties["ConfiguredGuidanceSystemsCount"] = sortedGuidanceSystems.Count; // 改用排序后的列表计数 for (int i = 0; i < sortedGuidanceSystems.Count; i++) { diff --git a/ThreatSource/src/MIssile/InfraredCommandGuidedMissile.cs b/ThreatSource/src/MIssile/InfraredCommandGuidedMissile.cs index 41cfa0f..723bbe6 100644 --- a/ThreatSource/src/MIssile/InfraredCommandGuidedMissile.cs +++ b/ThreatSource/src/MIssile/InfraredCommandGuidedMissile.cs @@ -285,6 +285,7 @@ namespace ThreatSource.Missile { var statusInfo = base.GetStatusInfo(); statusInfo.ExtendedProperties["CurrentStage"] = currentStage.ToString(); + statusInfo.ExtendedProperties["GuidanceSystem"] = guidanceSystem.GetStatusInfo(); return statusInfo; } } diff --git a/ThreatSource/src/MIssile/InfraredImagingTerminalGuidedMissile.cs b/ThreatSource/src/MIssile/InfraredImagingTerminalGuidedMissile.cs index 2b869e8..ee5d6d6 100644 --- a/ThreatSource/src/MIssile/InfraredImagingTerminalGuidedMissile.cs +++ b/ThreatSource/src/MIssile/InfraredImagingTerminalGuidedMissile.cs @@ -313,6 +313,7 @@ namespace ThreatSource.Missile { var statusInfo = base.GetStatusInfo(); statusInfo.ExtendedProperties["CurrentStage"] = currentStage.ToString(); + statusInfo.ExtendedProperties["GuidanceSystem"] = guidanceSystem.GetStatusInfo(); return statusInfo; } } diff --git a/ThreatSource/src/MIssile/LaserBeamRiderMissile.cs b/ThreatSource/src/MIssile/LaserBeamRiderMissile.cs index bcab282..fec38ce 100644 --- a/ThreatSource/src/MIssile/LaserBeamRiderMissile.cs +++ b/ThreatSource/src/MIssile/LaserBeamRiderMissile.cs @@ -58,7 +58,6 @@ namespace ThreatSource.Missile /// 导弹ID /// 导弹属性配置 /// 发射参数 - /// 激光编码配置 /// 制导系统配置 /// 仿真管理器实例 /// @@ -72,7 +71,6 @@ namespace ThreatSource.Missile string missileId, MissileProperties properties, KinematicState launchParams, - LaserCodeConfig laserCodeConfig, LaserBeamRiderGuidanceSystemConfig guidanceSystemConfig, ISimulationManager manager) : base(missileId, properties, launchParams, manager) @@ -82,48 +80,10 @@ namespace ThreatSource.Missile missileId, properties.MaxAcceleration, properties.ProportionalNavigationCoefficient, - laserCodeConfig, guidanceSystemConfig, manager); } - /// - /// 处理激光束开启事件 - /// - /// 激光束开启事件数据 - /// - /// 处理过程: - /// - 验证激光驾束仪 - /// - 更新波束参数 - /// - 开始波束跟踪 - /// - private void OnLaserBeamEvent(LaserBeamEvent evt) - { - if (evt?.LaserBeamRiderId != null) - { - LaserBeamRider laserBeamRider = SimulationManager.GetEntityById(evt.LaserBeamRiderId) as LaserBeamRider ?? throw new Exception("激光驾束仪不存在"); - guidanceSystem?.UpdateLaserBeamRider(laserBeamRider.KState.Position, laserBeamRider.LaserDirection, laserBeamRider.config.Power); - } - } - - /// - /// 处理激光束停止事件 - /// - /// 激光束停止事件数据 - /// - /// 处理过程: - /// - 验证事件数据 - /// - 停止波束跟踪 - /// - 清理制导状态 - /// - private void OnLaserBeamStop(LaserBeamStopEvent evt) - { - if (evt?.LaserBeamRiderId != null) - { - guidanceSystem?.DeactivateLaserBeam(); - } - } - /// /// 更新导弹状态 /// @@ -216,9 +176,6 @@ namespace ThreatSource.Missile base.Activate(); // 激活制导系统 guidanceSystem.Activate(); - // 订阅激光波束事件 - SimulationManager.SubscribeToEvent(OnLaserBeamEvent); - SimulationManager.SubscribeToEvent(OnLaserBeamStop); } /// @@ -235,9 +192,6 @@ namespace ThreatSource.Missile base.Deactivate(); // 停用制导系统 guidanceSystem.Deactivate(); - // 取消订阅波束事件 - SimulationManager.UnsubscribeFromEvent(OnLaserBeamEvent); - SimulationManager.UnsubscribeFromEvent(OnLaserBeamStop); } /// @@ -253,6 +207,7 @@ namespace ThreatSource.Missile { var statusInfo = base.GetStatusInfo(); statusInfo.ExtendedProperties["CurrentStage"] = currentStage.ToString(); + statusInfo.ExtendedProperties["GuidanceSystem"] = guidanceSystem.GetStatusInfo(); return statusInfo; } } diff --git a/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs b/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs index 42426b4..af705db 100644 --- a/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs +++ b/ThreatSource/src/MIssile/LaserSemiActiveGuidedMissile.cs @@ -61,22 +61,12 @@ namespace ThreatSource.Missile /// public string LaserDesignatorId { get; set; } = ""; - /// - /// 获取或设置激光编码配置 - /// - /// 激光编码配置 - /// - /// 用于配置导弹期望接收的激光编码类型和值 - /// - public LaserCodeConfig LaserCodeConfig { get; set; } - /// /// 初始化激光半主动制导导弹的新实例 /// /// 导弹ID /// 导弹属性配置 /// 发射参数 - /// 激光编码配置 /// 激光半主动制导系统配置 /// 仿真管理器实例 /// @@ -90,7 +80,6 @@ namespace ThreatSource.Missile string missileId, MissileProperties properties, KinematicState launchParams, - LaserCodeConfig laserCodeConfig, LaserSemiActiveGuidanceConfig guidanceConfig, ISimulationManager manager) : base(missileId, properties, launchParams, manager) @@ -100,11 +89,8 @@ namespace ThreatSource.Missile missileId, properties.MaxAcceleration, properties.ProportionalNavigationCoefficient, - laserCodeConfig, guidanceConfig, manager); - - LaserCodeConfig = laserCodeConfig; } /// @@ -304,6 +290,7 @@ namespace ThreatSource.Missile { var statusInfo = base.GetStatusInfo(); statusInfo.ExtendedProperties["CurrentStage"] = currentStage.ToString(); + statusInfo.ExtendedProperties["GuidanceSystem"] = guidanceSystem.GetStatusInfo(); return statusInfo; } } diff --git a/ThreatSource/src/MIssile/MissileProperties.cs b/ThreatSource/src/MIssile/MissileProperties.cs index eef1e0a..9327a04 100644 --- a/ThreatSource/src/MIssile/MissileProperties.cs +++ b/ThreatSource/src/MIssile/MissileProperties.cs @@ -327,6 +327,16 @@ namespace ThreatSource.Missile /// public double MaxEngineBurnTime { get; set; } + /// + /// 获取或设置导弹的巡航时间 + /// + /// + /// 单位:秒 + /// 导弹在巡航阶段的持续时间 + /// 超过此时间后进入末制导阶段 + /// + public double CruiseTime { get; set; } + /// /// 获取或设置红外辐射强度 /// @@ -345,43 +355,23 @@ namespace ThreatSource.Missile /// public double UltravioletRadiationIntensity { get; set; } - /// - /// 获取或设置激光编码配置 - /// - /// - /// 适用于激光半主动导弹和激光驾束导弹 - /// 定义激光信号的编码参数 - /// 用于抗干扰和安全识别 - /// - public LaserCodeConfig? LaserCodeConfig { get; set; } - - /// - /// 获取或设置导弹的巡航时间 - /// - /// - /// 单位:秒 - /// 导弹在巡航阶段的持续时间 - /// 超过此时间后进入末制导阶段 - /// - public double CruiseTime { get; set; } - /// /// 制导组件套件。仅当 Type 为 CompositeGuidance 时有效。 /// 列表中的顺序可能也暗示了串行模式下的默认阶段顺序,除非 ActivationTrigger 另有复杂规定,并结合Priority。 /// - public List GuidanceSuite { get; set; } + public List? GuidanceSuite { get; set; } /// /// 复合制导模式下,多个制导系统的工作方式。默认为串行。 /// 仅当 Type 为 CompositeGuidance 时有效。 /// - public CompositeWorkType CompositeWorkMode { get; set; } + public CompositeWorkType? CompositeWorkMode { get; set; } /// /// 并行工作模式下的指令融合策略。默认为使用最高优先级的指令。 /// 仅当 Type 为 CompositeGuidance 且 CompositeWorkMode 为 Parallel 时有效。 /// - public CommandFusionStrategy FusionStrategy { get; set; } + public CommandFusionStrategy? FusionStrategy { get; set; } /// /// 初始化导弹配置类的新实例 @@ -395,7 +385,6 @@ namespace ThreatSource.Missile public MissileProperties() { SetDefaultValues(); - GuidanceSuite = []; } /// @@ -426,13 +415,13 @@ namespace ThreatSource.Missile SelfDestructHeight = 0; InfraredRadiationIntensity = 100.0; UltravioletRadiationIntensity = 100.0; - LaserCodeConfig = new LaserCodeConfig(); - - // 重置复合制导相关属性的默认值 + + // 设置复合制导相关属性的默认值 if(Type == MissileType.CompositeGuidance) { CompositeWorkMode = CompositeWorkType.Serial; FusionStrategy = CommandFusionStrategy.UseHighestPriority; + GuidanceSuite = []; } } } diff --git a/ThreatSource/src/Simulation/SimulationConfig.cs b/ThreatSource/src/Simulation/SimulationConfig.cs index e08a8c7..850885e 100644 --- a/ThreatSource/src/Simulation/SimulationConfig.cs +++ b/ThreatSource/src/Simulation/SimulationConfig.cs @@ -82,6 +82,15 @@ namespace ThreatSource.Simulation // 检查编码是否匹配 return Code.Matches(other.Code); } + + /// + /// 重写ToString方法,返回激光编码配置的字符串表示 + /// + /// 激光编码配置的字符串表示 + public override string ToString() + { + return $"(CodeType={Code.CodeType} CodeValue={Code.CodeValue} IsCodeEnabled={IsCodeEnabled} IsCodeMatchRequired={IsCodeMatchRequired})"; + } } /// @@ -714,6 +723,16 @@ namespace ThreatSource.Simulation /// public double Wavelength { get; set; } = 0; + /// + /// 获取或设置激光编码配置 + /// + /// + /// 适用于激光半主动导弹和激光驾束导弹 + /// 定义激光信号的编码参数 + /// 用于抗干扰和安全识别 + /// + public LaserCodeConfig? LaserCodeConfig { get; set; } + /// /// 初始化激光半主动导引配置的新实例 /// @@ -1099,6 +1118,16 @@ namespace ThreatSource.Simulation /// public double Wavelength { get; set; } = 0; + /// + /// 获取或设置激光编码配置 + /// + /// + /// 适用于激光半主动导弹和激光驾束导弹 + /// 定义激光信号的编码参数 + /// 用于抗干扰和安全识别 + /// + public LaserCodeConfig? LaserCodeConfig { get; set; } + /// /// 初始化激光驾束制导系统配置的新实例 /// diff --git a/ThreatSource/src/Simulation/SimulationEvents.cs b/ThreatSource/src/Simulation/SimulationEvents.cs index a6360d9..e000eae 100644 --- a/ThreatSource/src/Simulation/SimulationEvents.cs +++ b/ThreatSource/src/Simulation/SimulationEvents.cs @@ -53,13 +53,13 @@ namespace ThreatSource.Simulation } /// - /// 激光照射更新事件,表示激光照射状态的更新 + /// 激光照射事件,表示激光照射状态 /// /// /// 用于实时更新激光照射的状态 /// 在照射过程中周期性触发 /// - public class LaserIlluminationUpdateEvent : SimulationEvent + public class LaserIlluminationEvent : SimulationEvent { /// /// 获取或设置激光定位器的ID diff --git a/ThreatSource/src/Utils/Common.cs b/ThreatSource/src/Utils/Common.cs index 0b8e9dd..eec5423 100644 --- a/ThreatSource/src/Utils/Common.cs +++ b/ThreatSource/src/Utils/Common.cs @@ -1,40 +1,5 @@ namespace ThreatSource.Utils { - /// - /// 表示二维平面上的向量 - /// - /// - /// 用于处理二维平面上的计算,如目标投影等 - /// - public struct Vector2D - { - /// - /// 获取或设置向量的X分量 - /// - public double X { get; set; } - - /// - /// 获取或设置向量的Y分量 - /// - public double Y { get; set; } - - /// - /// 初始化二维向量的新实例 - /// - /// X分量的值 - /// Y分量的值 - public Vector2D(double x, double y) - { - X = x; - Y = y; - } - - /// - /// 零向量 (0, 0) - /// - public static Vector2D Zero => new(0, 0); - } - /// /// 红外波段,枚举 /// @@ -63,6 +28,7 @@ namespace ThreatSource.Utils /// 3mm波段 /// Band3, + /// /// 8mm波段 /// diff --git a/ThreatSource/src/Utils/Vector2D.cs b/ThreatSource/src/Utils/Vector2D.cs new file mode 100644 index 0000000..e6e8fc0 --- /dev/null +++ b/ThreatSource/src/Utils/Vector2D.cs @@ -0,0 +1,37 @@ +namespace ThreatSource.Utils +{ + /// + /// 表示二维平面上的向量 + /// + /// + /// 用于处理二维平面上的计算,如目标投影等 + /// + public struct Vector2D + { + /// + /// 获取或设置向量的X分量 + /// + public double X { get; set; } + + /// + /// 获取或设置向量的Y分量 + /// + public double Y { get; set; } + + /// + /// 初始化二维向量的新实例 + /// + /// X分量的值 + /// Y分量的值 + public Vector2D(double x, double y) + { + X = x; + Y = y; + } + + /// + /// 零向量 (0, 0) + /// + public static Vector2D Zero => new(0, 0); + } +} \ No newline at end of file