diff --git a/ThreatSource/data/missiles/composite/cg_001.toml b/ThreatSource/data/missiles/composite/cg_001.toml index 13f5475..5ef26e7 100644 --- a/ThreatSource/data/missiles/composite/cg_001.toml +++ b/ThreatSource/data/missiles/composite/cg_001.toml @@ -29,7 +29,7 @@ CompositeWorkMode = "Serial" # 工作模式:Serial (串行) 或 Parallel (并 # 第一个制导阶段:毫米波 [[Properties.GuidanceSuite]] ComponentName = "MMW_Phase1_Cruise" -GuidanceSystemType = "MillimeterWaveTerminalGuidance" # 必须与C#工厂中的类型字符串匹配 +GuidanceSystemType = "MillimeterWaveTerminalGuidance" # 必须与工厂中的类型字符串匹配 ActivationTrigger = "OnLaunch" # 激活触发器:OnLaunch, AfterFlightTime, DistanceToTargetThreshold, PreviousStageComplete ActivationValue = 0.0 # 触发器关联值 (例如:飞行时间秒数,距离米数) Priority = 0 # 优先级 (例如:0为最高) @@ -40,7 +40,7 @@ ContinueChainOnFailure = true # 失败后继续尝试下一个 # 第二个制导阶段:红外成像末制导 [[Properties.GuidanceSuite]] ComponentName = "IR_Phase2_Terminal" -GuidanceSystemType = "InfraredImagingTerminalGuidance" # 必须与C#工厂中的类型字符串匹配 +GuidanceSystemType = "InfraredImagingTerminalGuidance" # 必须与工厂中的类型字符串匹配 ActivationTrigger = "PreviousStageComplete" # 例如:在飞行一段时间后切换 (或者 PreviousStageComplete) ActivationValue = 10.0 # 例如:飞行10秒后激活红外阶段 (如果 CruiseTime 是 5s,这里可能需要调整) Priority = 1 # 优先级低于毫米波 diff --git a/ThreatSource/data/missiles/composite/cg_002.toml b/ThreatSource/data/missiles/composite/cg_002.toml new file mode 100644 index 0000000..88ca6d7 --- /dev/null +++ b/ThreatSource/data/missiles/composite/cg_002.toml @@ -0,0 +1,86 @@ +# 毫米波-红外成像末制导导弹-001 配置 +Type = "CompositeGuidance" + +[Name] +Zh = "毫米波-红外成像末制导导弹-001" +En = "Millimeter Wave-IR Imaging Terminal Guided Missile-001" + +[Properties] +Type = "CompositeGuidance" +MaxSpeed = 250.0 +MaxFlightTime = 60.0 +MaxFlightDistance = 5000.0 +MaxAcceleration = 100.0 +ProportionalNavigationCoefficient = 4.0 +LaunchAcceleration = 100.0 +MaxEngineBurnTime = 2.5 +CruiseTime = 4.0 +Mass = 25.0 +ExplosionRadius = 5.0 +HitProbability = 0.9 +SelfDestructHeight = 0.0 +InfraredRadiationIntensity = 96.0 # 红外辐射强度 (瓦特/球面度) +UltravioletRadiationIntensity = 100.0 # 紫外辐射强度 (瓦特/球面度) +# --- 复合制导特定属性 --- +CompositeWorkMode = "Serial" # 工作模式:Serial (串行) 或 Parallel (并行) +# FusionStrategy = "UseHighestPriority" # 仅在并行模式下相关 + +# --- 制导组件套件 (GuidanceSuite) --- +# 第一个制导阶段:激光半主动制导 +[[Properties.GuidanceSuite]] +ComponentName = "LaserSemiActive_Phase1_Terminal" +GuidanceSystemType = "LaserSemiActiveGuidance" # 必须与工厂中的类型字符串匹配 +ActivationTrigger = "OnLaunch" # 激活触发器:OnLaunch, AfterFlightTime, DistanceToTargetThreshold, PreviousStageComplete +ActivationValue = 0.0 # 触发器关联值 (例如:飞行时间秒数,距离米数) +Priority = 0 # 优先级 (例如:0为最高) +MaxTimeToAcquireGuidanceSeconds = 5.0 # 获取制导的最大时间 +MinTimeWithGuidanceBeforeSwitchSeconds = 0.2 # 稳定跟踪0.2秒后切换(因为毫米波跟踪不稳定) +ContinueChainOnFailure = true # 失败后继续尝试下一个 + +# 第二个制导阶段:红外成像末制导 +[[Properties.GuidanceSuite]] +ComponentName = "IR_Phase2_Terminal" +GuidanceSystemType = "InfraredImagingTerminalGuidance" # 必须与工厂中的类型字符串匹配 +ActivationTrigger = "PreviousStageComplete" # 例如:在飞行一段时间后切换 (或者 PreviousStageComplete) +ActivationValue = 10.0 # 例如:飞行10秒后激活红外阶段 (如果 CruiseTime 是 5s,这里可能需要调整) +Priority = 1 # 优先级低于毫米波 +MaxTimeToAcquireGuidanceSeconds = 5.0 # 获取制导的最大时间 +MinTimeWithGuidanceBeforeSwitchSeconds = 60.0 # 设置为MaxFlightTime,使其持续制导 +ContinueChainOnFailure = false # 这是最后一个,失败也无需继续 + +# --- 各制导模式的详细配置 --- +[LaserSemiActiveGuidanceConfig] # 激光半主动制导系统配置 +FieldOfViewAngle = 30.0 # 传感器视场角 (度) +LensDiameter = 0.1 # 传感器透镜直径 (米) +SensorDiameter = 0.03 # 探测器/传感器本身直径 (米) +FocusedSpotDiameter = 0.006 # 传感器上聚焦激光光斑直径 (米) +ReflectionCoefficient = 0.2 # 目标激光反射系数 (0.0 到 1.0) +TargetReflectiveArea = 1.0 # 目标有效反射面积 (m^2) +LockThreshold = 1.0e-8 # 锁定目标的最小接收功率 (瓦特, 例如 1.0e-8 W) +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) + +[LaserSemiActiveGuidanceConfig.LaserCodeConfig] # properties内部的激光编码配置 +IsCodeEnabled = true # 激光编码系统是否启用? +IsCodeMatchRequired = true # 制导是否需要匹配激光编码? + +[LaserSemiActiveGuidanceConfig.LaserCodeConfig.Code] # 具体的激光编码详情 +CodeType = "PRF" # 激光编码类型 (例如 PRF) +CodeValue = 1010 # 激光编码的实际值 + +[InfraredImagingGuidanceConfig] +MaxDetectionRange = 1000.0 # 最大探测距离 (米) +SearchFieldOfView = 12.0 # 搜索视场角 (度) +TrackFieldOfView = 6.0 # 跟踪视场角 (度) +ImageWidth = 640 # 图像宽度 (像素) +ImageHeight = 480 # 图像高度 (像素) +BackgroundIntensity = 1.0e-4 # 背景辐射强度 (瓦特/球面度) +SearchRecognitionProbability = 0.6 # 搜索模式目标识别概率阈值 +TrackRecognitionProbability = 0.8 # 跟踪模式目标识别概率阈值 +TargetLostTolerance = 0.3 # 目标丢失容忍时间 (秒) +LockConfirmationTime = 0.5 # 锁定确认时间 (秒) +JammingResistanceThreshold = 1.0e-5 # 干扰抗性阈值 (瓦特) +Wavelength = 3.0 # 波长 (微米) \ No newline at end of file diff --git a/ThreatSource/src/Data/ThreatSourceDataManager.cs b/ThreatSource/src/Data/ThreatSourceDataManager.cs index ac7c731..9721698 100644 --- a/ThreatSource/src/Data/ThreatSourceDataManager.cs +++ b/ThreatSource/src/Data/ThreatSourceDataManager.cs @@ -103,7 +103,7 @@ namespace ThreatSource.Data componentConfig.SpecificConfig = data.InfraredImagingGuidanceConfig; topLevelConfigName = nameof(data.InfraredImagingGuidanceConfig); break; - case "lasers semiactiveguidance": + case "lasersemiactiveguidance": assignedConfig = data.LaserSemiActiveGuidanceConfig; componentConfig.SpecificConfig = data.LaserSemiActiveGuidanceConfig; topLevelConfigName = nameof(data.LaserSemiActiveGuidanceConfig); @@ -131,7 +131,7 @@ namespace ThreatSource.Data { if (assignedConfig == null && (typeKey == "millimeterwaveterminalguidance" || typeKey == "millimeterwave" || - typeKey == "infraredimagingterminalguidance" || typeKey == "lasers semiactiveguidance" || + typeKey == "infraredimagingterminalguidance" || typeKey == "lasersemiactiveguidance" || typeKey == "laserbeamriderguidance" || typeKey == "infraredcommandguidance")) { Debug.WriteLine($"[ThreatSourceDataManager] Error: SpecificConfig for component '{componentConfig.ComponentName}' (Type: {componentConfig.GuidanceSystemType}) remains NULL. The corresponding top-level config 'data.{topLevelConfigName}' was likely missing or null in the TOML file '{Path.GetFileName(file)}'."); diff --git a/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs b/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs index 6f54906..c0b57cc 100644 --- a/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/InfraredImagingGuidanceSystem.cs @@ -501,7 +501,7 @@ namespace ThreatSource.Guidance } else // 窗口未满 { - foundThisFrame = isRecognizedThisFrame; // foundThisFrame反映本帧直接识别结果 + foundThisFrame = isRecognizedThisFrame; if (isRecognizedThisFrame) targetPosition = currentEntity.KState.Position; Debug.WriteLine($"[IR IMAGING SEARCH] 目标 {searchModeFocusCandidateId} 正在收集数据,窗口 ({activeRecognitionHistory.Count}/{COMMON_RECOGNITION_WINDOW_SIZE}). 本帧识别: {isRecognizedThisFrame}"); } @@ -510,10 +510,9 @@ namespace ThreatSource.Guidance case WorkMode.Track: if (currentlyTrackedTargetId == null || currentEntity.Id != currentlyTrackedTargetId) { - continue; // 不是当前正在跟踪的目标 + continue; } - // 当前是跟踪目标,且已通过外层基本检查 var image_track = imageGenerator.GenerateImage(currentEntity, missilePosition, overallTransmittance, SimulationManager); var trackResult = targetRecognizer.RecognizeTarget(image_track, currentEntity); isRecognizedThisFrame = trackResult.Type == targetType && trackResult.Confidence >= config.TrackRecognitionProbability; @@ -583,8 +582,7 @@ namespace ThreatSource.Guidance Debug.WriteLine($"[IR IMAGING LOCK] 锁定目标 {currentlyTrackedTargetId} 通过基本检查。"); break; } - - // 如果在Search模式下成功切换到Track,或者在Track/Lock模式下处理了目标(无论成功与否),则不再继续遍历此帧中的其他实体 + if (foundThisFrame || currentMode != WorkMode.Search || (currentMode == WorkMode.Search && currentlyTrackedTargetId != null) ) { break; diff --git a/ThreatSource/src/MIssile/CompositeGuidedMissile.cs b/ThreatSource/src/MIssile/CompositeGuidedMissile.cs index dd32b17..4d469a9 100644 --- a/ThreatSource/src/MIssile/CompositeGuidedMissile.cs +++ b/ThreatSource/src/MIssile/CompositeGuidedMissile.cs @@ -50,12 +50,12 @@ namespace ThreatSource.Missile /// /// 经过优先级排序的制导组件配置列表。 /// - private List sortedGuidanceConfigs = new List(); + private readonly List sortedGuidanceConfigs = []; /// /// 经过优先级排序的制导系统实例列表,与 sortedGuidanceConfigs 一一对应。 /// - private List sortedGuidanceSystems = new List(); + private readonly List sortedGuidanceSystems = []; /// /// 当前活动的制导组件配置。 @@ -99,12 +99,12 @@ namespace ThreatSource.Missile /// protected void InitializeGuidanceSuite() { - this.sortedGuidanceSystems.Clear(); - this.sortedGuidanceConfigs.Clear(); - this.guidanceChainHaltedOrCompleted = false; - this.currentGuidancePhaseIndex = -1; // 重置索引,表示从头开始 - this.currentActiveGuidance = null; - this.currentActiveConfig = null; + sortedGuidanceSystems.Clear(); + sortedGuidanceConfigs.Clear(); + guidanceChainHaltedOrCompleted = false; + currentGuidancePhaseIndex = -1; + currentActiveGuidance = null; + currentActiveConfig = null; if (Properties.GuidanceSuite != null && Properties.GuidanceSuite.Count > 0) { @@ -128,23 +128,23 @@ namespace ThreatSource.Missile foreach (var tuple in tempGuidanceList) { - this.sortedGuidanceConfigs.Add(tuple.Item1); - this.sortedGuidanceSystems.Add(tuple.Item2); + sortedGuidanceConfigs.Add(tuple.Item1); + sortedGuidanceSystems.Add(tuple.Item2); } - if (this.sortedGuidanceSystems.Count > 0) + if (sortedGuidanceSystems.Count > 0) { - this.currentGuidancePhaseIndex = -1; // 设置为-1,以便TryActivateNextGuidanceSystem能正确激活第一个 + currentGuidancePhaseIndex = -1; } else { - this.guidanceChainHaltedOrCompleted = true; // 没有可用的制导系统 + guidanceChainHaltedOrCompleted = true; Debug.WriteLine("[CompositeGuidance.Initialize] 未配置或未能创建任何有效的制导系统。"); } } else { - this.guidanceChainHaltedOrCompleted = true; + guidanceChainHaltedOrCompleted = true; Debug.WriteLine("[CompositeGuidance.Initialize] GuidanceSuite 为空。"); } Debug.WriteLine($"[CompositeGuidance.Initialize] 初始化完成。排序后的制导系统数量: {sortedGuidanceSystems.Count}"); @@ -175,6 +175,15 @@ namespace ThreatSource.Missile { return null; } + case "lasersemiactiveguidance": + if (config.SpecificConfig is LaserSemiActiveGuidanceConfig laserConfig) + { + return new LaserSemiActiveGuidanceSystem(config.ComponentName, Id, Properties.MaxAcceleration, Properties.ProportionalNavigationCoefficient, laserConfig, SimulationManager); + } + else + { + return null; + } default: return null; } @@ -199,12 +208,7 @@ namespace ThreatSource.Missile if (currentActiveGuidance is SimulationElement se) { - se.Update(deltaTime); // Assuming Update is part of SimulationElement or BaseGuidanceSystem which inherits it - } - else - { - // Fallback or error if it's not a SimulationElement but Update is needed. - // For now, we assume all IGuidanceSystem are also SimulationElement for Update. + se.Update(deltaTime); } if (currentActiveConfig == null) @@ -233,7 +237,7 @@ namespace ThreatSource.Missile // 如果不是最后一个制导阶段,则尝试切换到下一个 Debug.WriteLine($"[CompositeGuidance.Logic] 模块 {currentActiveConfig.ComponentName} 完成任务 (稳定制导持续达标),切换到下一阶段。"); TryActivateNextGuidanceSystem(deactivatePrevious: true); - return; // 切换后立即返回,避免同一帧内处理新激活的模块 + return; } else { @@ -242,9 +246,8 @@ namespace ThreatSource.Missile if (!guidanceChainHaltedOrCompleted) // 避免重复打印 { Debug.WriteLine($"[CompositeGuidance.Logic] 最后一个制导模块 {currentActiveConfig.ComponentName} 已满足稳定条件并将持续工作。"); - guidanceChainHaltedOrCompleted = true; // 标记配置的切换链已完成 + guidanceChainHaltedOrCompleted = true; } - // 不返回,允许后续的超时和干扰检查继续作用于这个最后一个阶段 } } } @@ -355,9 +358,7 @@ namespace ThreatSource.Missile public override void Update(double deltaTime) { if (!IsActive) return; - - // 更新飞行阶段 (Launch, Cruise, Terminal) - // 这部分逻辑保持不变,因为它控制导弹的物理飞行状态和阶段转换 + switch (currentFlightStage) { case CompositeFlightStage.Launch: @@ -377,10 +378,7 @@ namespace ThreatSource.Missile { UpdateGuidanceLogic(deltaTime); } - // else if (Properties.CompositeWorkMode == CompositeWorkType.Parallel) { /* 未来可扩展并行逻辑 */ } - - // 在所有逻辑更新后,统一设置导弹的制导状态和加速度 if (currentActiveGuidance != null && currentActiveGuidance.HasGuidance) { this.IsGuidance = true; @@ -404,11 +402,7 @@ namespace ThreatSource.Missile currentFlightStage = CompositeFlightStage.Launch; // 重置制导链状态 - InitializeGuidanceSuite(); // 重新初始化以获取最新的排序和重置内部状态 - // currentGuidancePhaseIndex = -1; // InitializeGuidanceSuite 内部会处理 - // guidanceChainHaltedOrCompleted = false; // InitializeGuidanceSuite 内部会处理 - // currentActiveGuidance = null; // InitializeGuidanceSuite 内部会处理 - // currentActiveConfig = null; // InitializeGuidanceSuite 内部会处理 + InitializeGuidanceSuite(); currentPhaseActivationTime = -1.0; currentPhaseStableGuidanceTime = -1.0; @@ -460,10 +454,7 @@ namespace ThreatSource.Missile } currentActiveGuidance = null; } - // sortedGuidanceSystems 中的其他已创建但未活动的系统,如果它们有需要清理的状态,也应考虑 - // 但通常 Deactivate 是针对活动组件的。InitializeGuidanceSuite 会在下次 Fire 时重建。 - - guidanceChainHaltedOrCompleted = true; // 标记为不再活动 + guidanceChainHaltedOrCompleted = true; currentActiveConfig = null; Debug.WriteLine($"[CompositeGuidedMissile.Deactivate] 导弹 {Id} 已停用. 活动制导系统已处理."); } @@ -485,16 +476,14 @@ namespace ThreatSource.Missile for (int i = 0; i < sortedGuidanceSystems.Count; i++) { var guidanceSystem = sortedGuidanceSystems[i]; - if (guidanceSystem is SimulationElement simElement) // 检查并转换 + if (guidanceSystem is SimulationElement simElement) { string statusString = simElement.GetStatusInfo().ToString(); string keyName = $"SubGuidanceSystem_Status_{i}"; statusInfo.ExtendedProperties[keyName] = statusString; } - else if (guidanceSystem != null) // 如果不是SimulationElement但非null,记录一个警告或默认值 + else if (guidanceSystem != null) { - string keyName = $"SubGuidanceSystem_Status_{i}"; - statusInfo.ExtendedProperties[keyName] = "错误: 制导系统不是 SimulationElement 或为null."; Debug.WriteLine($"[CompositeGuidedMissile.GetStatusInfo] 警告: 制导系统 at index {i} (type: {guidanceSystem.GetType().Name}) 不是 SimulationElement 或为null."); } } diff --git a/tools/ComprehensiveMissileSimulator.cs b/tools/ComprehensiveMissileSimulator.cs index e81f425..62aeef5 100644 --- a/tools/ComprehensiveMissileSimulator.cs +++ b/tools/ComprehensiveMissileSimulator.cs @@ -439,7 +439,7 @@ namespace ThreatSource.Tools.MissileSimulation Speed = 10 }; string missileId = "CGGM_1"; - var missile = _threatSourceFactory.CreateMissile(missileId, "cg_001", "Tank_1", motionParameters); + var missile = _threatSourceFactory.CreateMissile(missileId, "cg_002", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); Console.WriteLine($"注册复合制导导弹 {missileId}"); diff --git a/tools/Program.cs b/tools/Program.cs index 0552a81..65137f3 100644 --- a/tools/Program.cs +++ b/tools/Program.cs @@ -42,8 +42,8 @@ namespace ThreatSource.Tools.MissileSimulation } Console.WriteLine($"1. 选择导弹 ({missileStatus})"); - Console.WriteLine($"2. 配置传感器 {sensorStatusString}"); - Console.WriteLine($"3. 配置干扰 {simulator.GetActiveJammingDescription()} {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}"); + Console.WriteLine($"2. 选择指示器 {sensorStatusString}"); + Console.WriteLine($"3. 选择干扰方式 {simulator.GetActiveJammingDescription()} {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}"); Console.WriteLine($"4. 设置日志级别 (当前级别: {simulator.CurrentLogLevel})"); Console.WriteLine($"5. 开始仿真 {(string.IsNullOrEmpty(simulator.SelectedMissileId) ? "(需先选导弹)" : "")}"); Console.WriteLine($"6. 设置仿真步长 (当前: {simulator.TimeStep}s)"); @@ -225,12 +225,12 @@ namespace ThreatSource.Tools.MissileSimulation { while (true) { - Console.WriteLine("\n--- 配置传感器和指示器 ---"); - Console.WriteLine("当前传感器状态:"); + Console.WriteLine("\n--- 选择指示器 ---"); + Console.WriteLine("当前指示器状态:"); var indicators = simulator.GetActiveIndicators(); if (indicators.Length == 0) { - Console.WriteLine("当前导弹类型没有可配置的独立传感器/指示器,或未实现获取接口。"); + Console.WriteLine("当前导弹类型没有可配置的指示器,或未实现获取接口。"); } else { @@ -240,7 +240,7 @@ namespace ThreatSource.Tools.MissileSimulation } } Console.WriteLine(" 0. 返回主菜单"); - Console.Write("请选择切换状态的传感器,或返回: "); + Console.Write("请选择切换状态的指示器,或返回: "); string input = Console.ReadLine()?.ToLower() ?? string.Empty; if (input == "0") @@ -286,12 +286,12 @@ namespace ThreatSource.Tools.MissileSimulation while (true) { - Console.WriteLine("\n--- 配置干扰方式 ---"); + Console.WriteLine("\n--- 选择干扰方式 ---"); Console.WriteLine($"当前导弹: {simulator.SelectedMissileDisplayName}"); if (availableJammingOptions.Length == 0) { - Console.WriteLine("当前导弹类型没有可配置的干扰选项。"); + Console.WriteLine("当前导弹类型没有可选择的干扰方式。"); } else {