From 17eb9826b55634b3a1454aeb58a7bad03566a50a Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Mon, 19 May 2025 16:35:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E5=AF=BC=E5=BC=B9?= =?UTF-8?q?=E7=9A=84=E7=BA=A2=E5=A4=96=E5=92=8C=E7=B4=AB=E5=A4=96=E8=BE=90?= =?UTF-8?q?=E5=B0=84=E5=BC=BA=E5=BA=A6=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + ThreatSource.Tests/SwerlingRcsModelTests.cs | 388 ++++++++++++++++++ .../data/missiles/composite/cg_001.toml | 2 + .../data/missiles/ir_command/irc_001.toml | 2 + .../data/missiles/ir_imaging/itg_001.toml | 2 + .../data/missiles/laser_beam_rider/hj10.toml | 2 + .../missiles/laser_semi_active/lsgm_001.toml | 2 + ThreatSource/data/missiles/mmw/mmw_001.toml | 2 + ThreatSource/src/Equipment/BaseEquipment.cs | 24 +- .../Guidance/LaserSemiActiveGuidanceSystem.cs | 2 - ThreatSource/src/Indicator/BaseIndicator.cs | 2 +- ThreatSource/src/Jammer/BaseJammer.cs | 2 +- ThreatSource/src/MIssile/BaseMissile.cs | 45 +- ThreatSource/src/MIssile/MissileProperties.cs | 44 +- ThreatSource/src/Sensor/BaseSensor.cs | 2 +- 15 files changed, 484 insertions(+), 38 deletions(-) create mode 100644 ThreatSource.Tests/SwerlingRcsModelTests.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index c9a5cd2..1685e51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - 增加了SwerlingRCS回波模型 - 在毫米波制导中使用SwerlingRCS回波模型获取目标RCS - 增加了扫描周期计时器,用于控制RCS的更新 +- 增加了导弹的红外和紫外辐射强度属性 ## [1.1.19] - 2025-05-18 - 增加了装备的RCS特征矩阵 diff --git a/ThreatSource.Tests/SwerlingRcsModelTests.cs b/ThreatSource.Tests/SwerlingRcsModelTests.cs new file mode 100644 index 0000000..9c06ba0 --- /dev/null +++ b/ThreatSource.Tests/SwerlingRcsModelTests.cs @@ -0,0 +1,388 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using ThreatSource.Utils; +using ThreatSource.Equipment; + +namespace ThreatSource.Tests +{ + [TestClass] + public class SwerlingRcsModelTests + { + private const double DefaultAverageRcs = 10.0; // 默认平均RCS值,单位:平方米 + private const string TargetId1 = "target_tank_001"; // 测试用目标ID 1 + private const string TargetId2 = "target_heli_002"; // 测试用目标ID 2 + private const int TestSeed = 12345; // 测试用随机数种子 + + /// + /// 测试:默认构造函数应成功初始化。 + /// + [TestMethod] + public void Constructor_DefaultSeed_InitializesSuccessfully() + { + // 准备 (Arrange) + SwerlingRcsModel model; + + // 操作 (Act) + model = new SwerlingRcsModel(); + + // 断言 (Assert) + Assert.IsNotNull(model, "使用默认种子构造模型实例不应为null。"); + } + + /// + /// 测试:带特定种子的构造函数应成功初始化。 + /// + [TestMethod] + public void Constructor_WithSpecificSeed_InitializesSuccessfully() + { + // 准备 (Arrange) + SwerlingRcsModel model; + + // 操作 (Act) + model = new SwerlingRcsModel(TestSeed); + + // 断言 (Assert) + Assert.IsNotNull(model, "使用特定种子构造模型实例不应为null。"); + } + + /// + /// 测试:当目标是坦克且静止时,其RCS行为应类似Swerling I (慢起伏,使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Tank_Static_BehavesAsSwerlingI() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + // 第一次调用,isNewScanPeriod为false但由于是首次,应采样并缓存 + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + // 第二次调用,isNewScanPeriod为false,应从缓存获取 + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreEqual(rcs1, rcs2, "对于Swerling I模型 (Tank, Static),在同一扫描周期内(isNewScanPeriod=false),RCS值应从缓存读取且保持不变。"); + Assert.IsTrue(rcs1 > 0, "RCS值应大于0。"); + } + + /// + /// 测试:当目标是直升机且静止时,其RCS行为应类似Swerling II (快起伏,不使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Helicopter_Static_BehavesAsSwerlingII() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + // 对于快起伏,即使ID相同,种子固定情况下,连续调用也应基于随机数序列产生可预测的不同值 + // 注意:这里比较的是"不同",但因为种子固定,这两个值本身是确定的。 + // 如果需要严格验证"不同",可以比较两者差的绝对值大于某个小量,但更简单的做法是验证它们不相等。 + Assert.AreNotEqual(rcs1, rcs2, "对于Swerling II模型 (Helicopter, Static),连续调用RCS值理论上应不同(因为是快起伏,每次都重新采样)。"); + Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。"); + Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。"); + } + + + /// + /// 测试:当目标是坦克且机动时,其RCS行为应类似Swerling III (慢起伏,使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Tank_Maneuvering_BehavesAsSwerlingIII() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreEqual(rcs1, rcs2, "对于Swerling III模型 (Tank, Maneuvering),在同一扫描周期内,RCS值应从缓存读取且保持不变。"); + Assert.IsTrue(rcs1 > 0, "RCS值应大于0。"); + } + + /// + /// 测试:当目标是直升机且机动时,其RCS行为应类似Swerling IV (快起伏,不使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Helicopter_Maneuvering_BehavesAsSwerlingIV() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreNotEqual(rcs1, rcs2, "对于Swerling IV模型 (Helicopter, Maneuvering),连续调用RCS值应不同。"); + Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。"); + Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。"); + } + + /// + /// 测试:当目标是坦克且匀速运动时,其RCS行为应类似Swerling I (慢起伏,使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Tank_ConstantVelocity_BehavesAsSwerlingI() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.ConstantVelocity, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.ConstantVelocity, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreEqual(rcs1, rcs2, "对于Swerling I模型 (Tank, ConstantVelocity),在同一扫描周期内,RCS值应从缓存读取且保持不变。"); + Assert.IsTrue(rcs1 > 0, "RCS值应大于0。"); + } + + /// + /// 测试:当目标是直升机且匀速运动时,其RCS行为应类似Swerling II (快起伏,不使用缓存)。 + /// + [TestMethod] + public void GetRealtimeRcs_Helicopter_ConstantVelocity_BehavesAsSwerlingII() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.ConstantVelocity, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.ConstantVelocity, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreNotEqual(rcs1, rcs2, "对于Swerling II模型 (Helicopter, ConstantVelocity),连续调用RCS值应不同。"); + Assert.IsTrue(rcs1 > 0, "第一个RCS值应大于0。"); + Assert.IsTrue(rcs2 > 0, "第二个RCS值应大于0。"); + } + + /// + /// 测试:当目标类型未知时,应默认为Swerling I行为。 + /// + [TestMethod] + public void GetRealtimeRcs_UnknownEquipment_BehavesAsSwerlingI() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) + double rcs1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Unknown, MotionStateType.Static, DefaultAverageRcs, false); + double rcs2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Unknown, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreEqual(rcs1, rcs2, "对于未知装备类型,应默认为Swerling I行为,RCS值在同一扫描周期内应保持不变。"); + Assert.IsTrue(rcs1 > 0, "RCS值应大于0。"); + } + + + /// + /// 测试:慢起伏模型在同一扫描周期内(isNewScanPeriod=false)应返回缓存的RCS值。 + /// + [TestMethod] + public void GetRealtimeRcs_SlowFluctuation_SameScanPeriod_ReturnsCachedValue() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + // 首次调用,isNewScanPeriod 为 true 或 false 都会导致采样和缓存 (对于Swerling I) + double initialRcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true); + + // 操作 (Act) + // 后续调用,isNewScanPeriod 为 false + double cachedRcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreEqual(initialRcs, cachedRcs, "慢起伏模型在同一扫描周期内应返回相同的缓存RCS值。"); + } + + /// + /// 测试:慢起伏模型在新扫描周期开始时(isNewScanPeriod=true)应更新并返回新的缓存RCS值。 + /// + [TestMethod] + public void GetRealtimeRcs_SlowFluctuation_NewScanPeriod_UpdatesAndReturnsNewCachedValue() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); // 使用固定种子 + double rcsScan1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 操作 (Act) + // 新扫描周期开始 + double rcsScan2PeriodStart = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true); + // 在新扫描周期内再次获取,应与周期开始时相同 + double rcsScan2SamePeriod = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + // 由于种子固定,rcsScan1 和 rcsScan2PeriodStart 应该不同(因为重新采样了) + // 但对于不同的随机数序列,它们也可能偶然相同,所以这个断言不是绝对的,更多的是检查行为 + // 更可靠的测试是验证 rcsScan2PeriodStart 和 rcsScan2SamePeriod 相同 + Assert.AreNotEqual(rcsScan1, rcsScan2PeriodStart, "新扫描周期开始时,RCS值应重新采样,与旧周期的值不同(高概率)。"); + Assert.AreEqual(rcsScan2PeriodStart, rcsScan2SamePeriod, "在新扫描周期内,后续获取的RCS值应与周期开始时采样并缓存的值相同。"); + Assert.IsTrue(rcsScan1 > 0, "第一个扫描周期的RCS值应大于0。"); + Assert.IsTrue(rcsScan2PeriodStart > 0, "第二个扫描周期开始的RCS值应大于0。"); + } + + /// + /// 测试:当平均RCS为0时,GetRealtimeRcs应返回0。 + /// + [TestMethod] + public void GetRealtimeRcs_AverageRcsZero_ReturnsZero() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(); + + // 操作 (Act) + double rcsS1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, 0.0, false); + double rcsS2 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, 0.0, false); + double rcsS3 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Maneuvering, 0.0, false); + double rcsS4 = model.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Maneuvering, 0.0, false); + + // 断言 (Assert) + Assert.AreEqual(0.0, rcsS1, "Swerling I,平均RCS为0时,应返回0。"); + Assert.AreEqual(0.0, rcsS2, "Swerling II,平均RCS为0时,应返回0。"); + Assert.AreEqual(0.0, rcsS3, "Swerling III,平均RCS为0时,应返回0。"); + Assert.AreEqual(0.0, rcsS4, "Swerling IV,平均RCS为0时,应返回0。"); + } + + /// + /// 测试:当平均RCS为负数时,GetRealtimeRcs应返回0。 + /// + [TestMethod] + public void GetRealtimeRcs_AverageRcsNegative_ReturnsZero() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(); + + // 操作 (Act) + double rcs = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, -5.0, false); + + // 断言 (Assert) + Assert.AreEqual(0.0, rcs, "平均RCS为负数时,应返回0。"); + } + + /// + /// 测试:对于Swerling I模型,如果targetId为null,应抛出ArgumentNullException。 + /// + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void GetRealtimeRcs_SwerlingI_NullTargetId_ThrowsArgumentNullException() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(); + + // 操作 (Act) + model.GetRealtimeRcs(null!, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + } + + /// + /// 测试:对于Swerling I模型,如果targetId为空字符串,应抛出ArgumentNullException。 + /// + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void GetRealtimeRcs_SwerlingI_EmptyTargetId_ThrowsArgumentNullException() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(); + + // 操作 (Act) + model.GetRealtimeRcs(string.Empty, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + } + + /// + /// 测试:对于Swerling III模型,如果targetId为null,应抛出ArgumentNullException。 + /// + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void GetRealtimeRcs_SwerlingIII_NullTargetId_ThrowsArgumentNullException() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(); + + // 操作 (Act) + model.GetRealtimeRcs(null!, EquipmentType.Tank, MotionStateType.Maneuvering, DefaultAverageRcs, false); + } + + + /// + /// 测试:ClearCachedRcs应清除特定目标的缓存,导致下次调用重新采样。 + /// + [TestMethod] + public void ClearCachedRcs_SlowFluctuation_ForcesNewSampleForSpecificTarget() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + double rcs1Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + double rcs1Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 另一个目标以验证其缓存不受影响 + + // 操作 (Act) + model.ClearCachedRcs(TargetId1); // 清除TargetId1的缓存 + double rcs2Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 重新获取TargetId1的RCS + double rcs2Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); // 再次获取TargetId2的RCS + + // 断言 (Assert) + Assert.AreNotEqual(rcs1Target1, rcs2Target1, "清除缓存后,TargetId1的RCS值应重新采样而不同(高概率)。"); + Assert.AreEqual(rcs1Target2, rcs2Target2, "清除TargetId1的缓存不应影响TargetId2的缓存值。"); + Assert.IsTrue(rcs1Target1 > 0); + Assert.IsTrue(rcs2Target1 > 0); + } + + /// + /// 测试:ClearAllCachedRcs应清除所有目标的缓存,导致下次所有慢起伏目标调用都重新采样。 + /// + [TestMethod] + public void ClearAllCachedRcs_SlowFluctuation_ForcesNewSamplesForAllTargets() + { + // 准备 (Arrange) + var model = new SwerlingRcsModel(TestSeed); + double rcs1Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + double rcs1Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 操作 (Act) + model.ClearAllCachedRcs(); // 清除所有缓存 + double rcs2Target1 = model.GetRealtimeRcs(TargetId1, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + double rcs2Target2 = model.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + + // 断言 (Assert) + Assert.AreNotEqual(rcs1Target1, rcs2Target1, "清除所有缓存后,TargetId1的RCS值应重新采样而不同(高概率)。"); + Assert.AreNotEqual(rcs1Target2, rcs2Target2, "清除所有缓存后,TargetId2的RCS值应重新采样而不同(高概率)。"); + Assert.IsTrue(rcs1Target1 > 0); + Assert.IsTrue(rcs1Target2 > 0); + Assert.IsTrue(rcs2Target1 > 0); + Assert.IsTrue(rcs2Target2 > 0); + } + + /// + /// 测试:使用相同种子的两个SwerlingRcsModel实例应产生可复现的RCS序列。 + /// + [TestMethod] + public void GetRealtimeRcs_WithSameSeed_GeneratesReproducibleSequence() + { + // 准备 (Arrange) + var model1 = new SwerlingRcsModel(TestSeed); + var model2 = new SwerlingRcsModel(TestSeed); + + // 操作 (Act) & 断言 (Assert) + // 以Swerling II (快起伏) 为例,因为它不依赖缓存和isNewScanPeriod + for (int i = 0; i < 10; i++) + { + double rcsM1 = model1.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false); + double rcsM2 = model2.GetRealtimeRcs(TargetId1, EquipmentType.Helicopter, MotionStateType.Static, DefaultAverageRcs, false); + Assert.AreEqual(rcsM1, rcsM2, $"在第 {i+1} 次调用时,使用相同种子的两个模型产生的RCS值应相同。"); + Assert.IsTrue(rcsM1 > 0, $"Model1, 调用 {i+1}, RCS 值应大于0。"); + } + + // 测试Swerling I (慢起伏) + double rcsS1M1_Initial = model1.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true); + double rcsS1M2_Initial = model2.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, true); + Assert.AreEqual(rcsS1M1_Initial, rcsS1M2_Initial, "Swerling I,相同种子,首次调用(isNewScanPeriod=true),RCS值应相同。"); + + double rcsS1M1_Cached = model1.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + double rcsS1M2_Cached = model2.GetRealtimeRcs(TargetId2, EquipmentType.Tank, MotionStateType.Static, DefaultAverageRcs, false); + Assert.AreEqual(rcsS1M1_Cached, rcsS1M2_Cached, "Swerling I,相同种子,后续调用(isNewScanPeriod=false),缓存的RCS值应相同。"); + Assert.AreEqual(rcsS1M1_Initial, rcsS1M1_Cached, "Swerling I,Model1,后续调用应返回首次缓存的值。"); + } + } +} \ No newline at end of file diff --git a/ThreatSource/data/missiles/composite/cg_001.toml b/ThreatSource/data/missiles/composite/cg_001.toml index 5da05e5..fb8c5b3 100644 --- a/ThreatSource/data/missiles/composite/cg_001.toml +++ b/ThreatSource/data/missiles/composite/cg_001.toml @@ -19,6 +19,8 @@ Mass = 25.0 ExplosionRadius = 5.5 HitProbability = 0.9 SelfDestructHeight = 0.0 +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) # --- 复合制导特定属性 --- CompositeWorkMode = "Serial" # 工作模式:Serial (串行) 或 Parallel (并行) # FusionStrategy = "UseHighestPriority" # 仅在并行模式下相关 diff --git a/ThreatSource/data/missiles/ir_command/irc_001.toml b/ThreatSource/data/missiles/ir_command/irc_001.toml index fec61cd..0cd0ea8 100644 --- a/ThreatSource/data/missiles/ir_command/irc_001.toml +++ b/ThreatSource/data/missiles/ir_command/irc_001.toml @@ -19,6 +19,8 @@ Mass = 23.5 # 质量 (千克) ExplosionRadius = 5.0 # 爆炸半径 (米) HitProbability = 0.9 # 命中概率 SelfDestructHeight = 0.0 # 自毁高度 (米) +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) # TrackerSensitivity, CommandLatency, IrSignature 在JSON中为null,此处省略 [InfraredCommandGuidanceConfig] diff --git a/ThreatSource/data/missiles/ir_imaging/itg_001.toml b/ThreatSource/data/missiles/ir_imaging/itg_001.toml index 2205993..bc8c951 100644 --- a/ThreatSource/data/missiles/ir_imaging/itg_001.toml +++ b/ThreatSource/data/missiles/ir_imaging/itg_001.toml @@ -19,6 +19,8 @@ Mass = 25.0 ExplosionRadius = 5.5 HitProbability = 0.9 SelfDestructHeight = 0.0 +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) [InfraredImagingGuidanceConfig] MaxDetectionRange = 1000.0 # 最大探测距离 (米), JSON中为1000,对应C#默认为1000.0 diff --git a/ThreatSource/data/missiles/laser_beam_rider/hj10.toml b/ThreatSource/data/missiles/laser_beam_rider/hj10.toml index 376e97d..62b7aa6 100644 --- a/ThreatSource/data/missiles/laser_beam_rider/hj10.toml +++ b/ThreatSource/data/missiles/laser_beam_rider/hj10.toml @@ -19,6 +19,8 @@ Mass = 24.5 # 质量 (千克) ExplosionRadius = 5.0 # 爆炸半径 (米) HitProbability = 0.9 # 命中概率 SelfDestructHeight = 0.0 # 自毁高度 (米) +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) [Properties.LaserCodeConfig] # 激光编码配置 IsCodeEnabled = true # 是否启用编码 diff --git a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml index 58b752b..b27f9f3 100644 --- a/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml +++ b/ThreatSource/data/missiles/laser_semi_active/lsgm_001.toml @@ -20,6 +20,8 @@ Mass = 22.0 # 导弹质量 (kg) ExplosionRadius = 5.0 # 爆炸半径 (米) HitProbability = 0.9 # 固有命中概率 (0.0 到 1.0) SelfDestructHeight = 0.0 # 离地自毁高度 (米) +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) [Properties.LaserCodeConfig] # properties内部的激光编码配置 IsCodeEnabled = true # 激光编码系统是否启用? diff --git a/ThreatSource/data/missiles/mmw/mmw_001.toml b/ThreatSource/data/missiles/mmw/mmw_001.toml index f499e7e..8982a9b 100644 --- a/ThreatSource/data/missiles/mmw/mmw_001.toml +++ b/ThreatSource/data/missiles/mmw/mmw_001.toml @@ -19,6 +19,8 @@ Mass = 28.0 # 质量 (千克) ExplosionRadius = 5.0 # 爆炸半径 (米) HitProbability = 0.9 # 命中概率 SelfDestructHeight = 0.0 # 自毁高度 (米) +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) [MillimeterWaveGuidanceConfig] MaxDetectionRange = 5000.0 # 最大探测距离 (米) diff --git a/ThreatSource/src/Equipment/BaseEquipment.cs b/ThreatSource/src/Equipment/BaseEquipment.cs index ed8cdad..eeff7d8 100644 --- a/ThreatSource/src/Equipment/BaseEquipment.cs +++ b/ThreatSource/src/Equipment/BaseEquipment.cs @@ -1,3 +1,4 @@ +using System.Reflection; using ThreatSource.Simulation; namespace ThreatSource.Equipment @@ -104,15 +105,22 @@ namespace ThreatSource.Equipment { // 获取基础状态信息 var statusInfo = base.GetStatusInfo(); - + // 添加装备特有属性 - statusInfo.ExtendedProperties["Health"] = Health; - statusInfo.ExtendedProperties["Length"] = Properties.Length; - statusInfo.ExtendedProperties["Width"] = Properties.Width; - statusInfo.ExtendedProperties["Height"] = Properties.Height; - statusInfo.ExtendedProperties["InfraredRadiationIntensity"] = Properties.InfraredRadiationIntensity; - statusInfo.ExtendedProperties["MillimeterWaveRadiationIntensity"] = Properties.MillimeterWaveRadiationIntensity; - statusInfo.ExtendedProperties["UltravioletRadiationIntensity"] = Properties.UltravioletRadiationIntensity; + if (Properties != null) + { + var propertiesType = Properties.GetType(); + var props = propertiesType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + foreach (var prop in props) + { + if (prop.CanRead) // 确保属性是可读的 + { + object? propValue = prop.GetValue(Properties); + statusInfo.ExtendedProperties[prop.Name] = propValue ?? string.Empty; + } + } + } return statusInfo; } diff --git a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs index a315214..7a4da81 100644 --- a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs @@ -478,8 +478,6 @@ namespace ThreatSource.Guidance // 将合成激光信号传递给四象限探测器 quadrantDetector.ProcessLaserSignal(ReceivedLaserPower, spotOffset); - - Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 目标位置={TargetPosition}"); } catch (Exception ex) { diff --git a/ThreatSource/src/Indicator/BaseIndicator.cs b/ThreatSource/src/Indicator/BaseIndicator.cs index 611017d..c6ce07c 100644 --- a/ThreatSource/src/Indicator/BaseIndicator.cs +++ b/ThreatSource/src/Indicator/BaseIndicator.cs @@ -245,7 +245,7 @@ namespace ThreatSource.Indicator // 获取基类状态信息 var statusInfo = base.GetStatusInfo(); - // 添加制导系统特有属性 + // 添加指示器特有属性 statusInfo.ExtendedProperties["TargetId"] = TargetId ?? ""; statusInfo.ExtendedProperties["MissileId"] = MissileId ?? ""; statusInfo.ExtendedProperties["lastKnownTargetPosition"] = _lastKnownTargetPosition ?? Vector3D.Zero; diff --git a/ThreatSource/src/Jammer/BaseJammer.cs b/ThreatSource/src/Jammer/BaseJammer.cs index a1c0620..70ef87d 100644 --- a/ThreatSource/src/Jammer/BaseJammer.cs +++ b/ThreatSource/src/Jammer/BaseJammer.cs @@ -223,7 +223,7 @@ namespace ThreatSource.Jammer // 获取基类状态信息 var statusInfo = base.GetStatusInfo(); - // 添加制导系统特有属性 + // 添加干扰器特有属性 statusInfo.ExtendedProperties["JammingType"] = JammingType; statusInfo.ExtendedProperties["State"] = State; statusInfo.ExtendedProperties["IsJamming"] = IsJamming; diff --git a/ThreatSource/src/MIssile/BaseMissile.cs b/ThreatSource/src/MIssile/BaseMissile.cs index 30ae5bb..9b59c57 100644 --- a/ThreatSource/src/MIssile/BaseMissile.cs +++ b/ThreatSource/src/MIssile/BaseMissile.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using ThreatSource.Simulation; using ThreatSource.Utils; +using System.Reflection; namespace ThreatSource.Missile { @@ -456,22 +457,38 @@ namespace ThreatSource.Missile // 获取基础状态信息 var statusInfo = base.GetStatusInfo(); - // 添加导弹固有属性(通过MissileProperties) - statusInfo.ExtendedProperties["Type"] = Properties.Type; - statusInfo.ExtendedProperties["MaxSpeed"] = Properties.MaxSpeed; - statusInfo.ExtendedProperties["MaxAcceleration"] = Properties.MaxAcceleration; - statusInfo.ExtendedProperties["MaxRange"] = Properties.MaxFlightDistance; - statusInfo.ExtendedProperties["MaxFlightTime"] = Properties.MaxFlightTime; - statusInfo.ExtendedProperties["ExplosionRadius"] = Properties.ExplosionRadius; - statusInfo.ExtendedProperties["Mass"] = Properties.Mass; + // 使用反射动态添加来自 this.Properties 的导弹固有属性 + if (Properties != null) + { + var propertiesType = Properties.GetType(); + var props = propertiesType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + foreach (var prop in props) + { + 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; + } + } + } - // 添加导弹运行时状态 - statusInfo.ExtendedProperties["FlightTime"] = FlightTime; - statusInfo.ExtendedProperties["FlightDistance"] = FlightDistance; - statusInfo.ExtendedProperties["EngineBurnTime"] = EngineBurnTime; - statusInfo.ExtendedProperties["IsGuidance"] = IsGuidance; + // 添加 BaseMissile 类的运行时状态参数 + statusInfo.ExtendedProperties["FlightTime"] = FlightTime; + statusInfo.ExtendedProperties["FlightDistance"] = FlightDistance; + statusInfo.ExtendedProperties["EngineBurnTime"] = EngineBurnTime; + statusInfo.ExtendedProperties["IsGuidance"] = IsGuidance; statusInfo.ExtendedProperties["LostGuidanceTime"] = LostGuidanceTime; - statusInfo.ExtendedProperties["GuidanceAcceleration"] = GuidanceAcceleration; + statusInfo.ExtendedProperties["GuidanceAcceleration"] = GuidanceAcceleration; return statusInfo; } diff --git a/ThreatSource/src/MIssile/MissileProperties.cs b/ThreatSource/src/MIssile/MissileProperties.cs index 3979de2..eef1e0a 100644 --- a/ThreatSource/src/MIssile/MissileProperties.cs +++ b/ThreatSource/src/MIssile/MissileProperties.cs @@ -209,6 +209,15 @@ namespace ThreatSource.Missile /// public class MissileProperties { + /// + /// 获取或设置导弹的类型 + /// + /// + /// 决定导弹的制导方式和行为特征 + /// 影响导弹的性能参数和作战能力 + /// + public MissileType Type { get; set; } + /// /// 获取或设置导弹的最大速度限制 /// @@ -319,13 +328,22 @@ namespace ThreatSource.Missile public double MaxEngineBurnTime { get; set; } /// - /// 获取或设置导弹的类型 + /// 获取或设置红外辐射强度 /// /// - /// 决定导弹的制导方式和行为特征 - /// 影响导弹的性能参数和作战能力 + /// 单位:瓦特/球面度 + /// 表示导弹在红外波段的发射功率 /// - public MissileType Type { get; set; } + public double InfraredRadiationIntensity { get; set; } + + /// + /// 获取或设置紫外辐射强度 + /// + /// + /// 单位:瓦特/球面度 + /// 表示导弹在紫外波段的发射功率 + /// + public double UltravioletRadiationIntensity { get; set; } /// /// 获取或设置激光编码配置 @@ -357,13 +375,13 @@ namespace ThreatSource.Missile /// 复合制导模式下,多个制导系统的工作方式。默认为串行。 /// 仅当 Type 为 CompositeGuidance 时有效。 /// - public CompositeWorkType CompositeWorkMode { get; set; } = CompositeWorkType.Serial; + public CompositeWorkType CompositeWorkMode { get; set; } /// /// 并行工作模式下的指令融合策略。默认为使用最高优先级的指令。 /// 仅当 Type 为 CompositeGuidance 且 CompositeWorkMode 为 Parallel 时有效。 /// - public CommandFusionStrategy FusionStrategy { get; set; } = CommandFusionStrategy.UseHighestPriority; + public CommandFusionStrategy FusionStrategy { get; set; } /// /// 初始化导弹配置类的新实例 @@ -377,8 +395,6 @@ namespace ThreatSource.Missile public MissileProperties() { SetDefaultValues(); - Type = MissileType.StandardMissile; - LaserCodeConfig = new LaserCodeConfig(); GuidanceSuite = []; } @@ -395,6 +411,7 @@ namespace ThreatSource.Missile /// public void SetDefaultValues() { + Type = MissileType.StandardMissile; MaxSpeed = 400; MaxFlightTime = 60; MaxFlightDistance = 5000; @@ -407,11 +424,16 @@ namespace ThreatSource.Missile ExplosionRadius = 5; HitProbability = 0.9; SelfDestructHeight = 0; + InfraredRadiationIntensity = 100.0; + UltravioletRadiationIntensity = 100.0; + LaserCodeConfig = new LaserCodeConfig(); // 重置复合制导相关属性的默认值 - CompositeWorkMode = CompositeWorkType.Serial; - FusionStrategy = CommandFusionStrategy.UseHighestPriority; - if (GuidanceSuite != null) GuidanceSuite.Clear(); else GuidanceSuite = new List(); + if(Type == MissileType.CompositeGuidance) + { + CompositeWorkMode = CompositeWorkType.Serial; + FusionStrategy = CommandFusionStrategy.UseHighestPriority; + } } } } \ No newline at end of file diff --git a/ThreatSource/src/Sensor/BaseSensor.cs b/ThreatSource/src/Sensor/BaseSensor.cs index c10e9d8..c98aada 100644 --- a/ThreatSource/src/Sensor/BaseSensor.cs +++ b/ThreatSource/src/Sensor/BaseSensor.cs @@ -303,7 +303,7 @@ namespace ThreatSource.Sensor // 获取基础状态信息 var statusInfo = base.GetStatusInfo(); - // 添加传感器状态 + // 添加传感器特有状态信息 statusInfo.ExtendedProperties["IsJammed"] = IsJammed.ToString(); statusInfo.ExtendedProperties["IsBlockingJammed"] = IsBlockingJammed.ToString(); statusInfo.ExtendedProperties["SensorData"] = GetSensorData().ToString() ?? "无数据";