diff --git a/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs b/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs index 890c1e6..02e7168 100644 --- a/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs +++ b/ThreatSource.Tests/src/Jamming/LaserBeamRiderGuidanceJammingTests.cs @@ -142,7 +142,7 @@ namespace ThreatSource.Tests.Jamming Assert.IsNotNull(_guidanceSystem, "激光驾束引导系统不应为空"); Assert.IsNotNull(_missile, "导弹不应为空"); - System.Diagnostics.Debug.WriteLine($"测试开始 - 初始位置: {_missile.KState.Position}, 初始速度: {_missile.KState.Speed}"); + System.Diagnostics.Debug.WriteLine($"测试开始 - 初始位置: {_missile.KState.Position}, 初始速度: {_missile.KState.Speed:F2}m/s"); // 更新激光波束参数 _guidanceSystem.UpdateLaserBeamRider( diff --git a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs index 39dca9b..f589cdb 100644 --- a/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserBeamRiderGuidanceSystem.cs @@ -396,17 +396,17 @@ namespace ThreatSource.Guidance if (shortestDistance > config.ControlFieldDiameter / 2) { HasGuidance = false; - Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}"); + Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance:F2}m"); return; } - Debug.WriteLine($"激光驾束引导系统: 在控制场内, 距离: {shortestDistance}"); + Debug.WriteLine($"激光驾束引导系统: 在控制场内, 距离中心点: {shortestDistance:F2}m"); Vector3D missileToSource = LaserSourcePosition.Value - KState.Position; double distance = missileToSource.Magnitude(); double receivedPower = CalculateReceivedLaserPower(distance); - Debug.WriteLine($"激光驾束引导系统: 接收到的激光功率: {receivedPower:E} W"); + Debug.WriteLine($"激光驾束引导系统: 接收到的激光功率: {receivedPower:E2} W"); if(receivedPower >= config.MinDetectablePower) { @@ -415,7 +415,7 @@ namespace ThreatSource.Guidance else { HasGuidance = false; - Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W"); + Trace.TraceInformation($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E2} W/{receivedPower:E2} W"); } } diff --git a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs index 5ad2070..9164adb 100644 --- a/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/LaserSemiActiveGuidanceSystem.cs @@ -440,13 +440,13 @@ namespace ThreatSource.Guidance { // 计算接收功率 receivedPower = CalculateReceivedPower(target.Source.KState.Position, target.SpotPosition, decoy.config.Power, decoy.config.DivergenceAngle); - Debug.WriteLine($"处理激光信号: 诱偏目标接收功率={receivedPower:E}W, 诱偏目标ID: {target.Target.Id}, 诱偏目标位置: {target.SpotPosition}"); + Debug.WriteLine($"处理激光信号: 诱偏目标接收功率={receivedPower:E2}W, 诱偏目标ID: {target.Target.Id}, 诱偏目标位置: {target.SpotPosition}"); } else if (target.Source is LaserDesignator laserDesignator) { // 计算接收功率 receivedPower = CalculateReceivedPower(target.Source.KState.Position, target.SpotPosition, laserDesignator.config.Power, laserDesignator.config.DivergenceAngle); - Debug.WriteLine($"处理激光信号: 真实目标接收功率={receivedPower:E}W, 真实目标ID: {target.Target.Id}, 真实目标位置: {target.SpotPosition}"); + Debug.WriteLine($"处理激光信号: 真实目标接收功率={receivedPower:E2}W, 真实目标ID: {target.Target.Id}, 真实目标位置: {target.SpotPosition}"); } // 累加功率 @@ -454,7 +454,7 @@ namespace ThreatSource.Guidance // 加权位置 weightedPosition += target.SpotPosition * receivedPower; - Debug.WriteLine($"处理激光信号: 累加功率={ReceivedLaserPower:E}W, 加权位置={weightedPosition}"); + Debug.WriteLine($"处理激光信号: 累加功率={ReceivedLaserPower:E2}W, 加权位置={weightedPosition}"); } // 如果总功率为0,表示没有在视野范围内的激光源 @@ -467,7 +467,7 @@ namespace ThreatSource.Guidance // 计算加权平均位置 TargetPosition = weightedPosition / ReceivedLaserPower; - Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E}W, 加权平均目标位置={TargetPosition}"); + Debug.WriteLine($"处理激光信号: 总功率={ReceivedLaserPower:E2}W, 加权平均目标位置={TargetPosition}"); // 更新激光照射参数 LaserIlluminationOn = true; @@ -534,9 +534,9 @@ namespace ThreatSource.Guidance double lensArea = Math.PI * Math.Pow(config.LensDiameter / 2, 2); double finalReceivedPower = powerDensityAtMissileAperture * lensArea * config.ReceiverEfficiency; - Debug.WriteLine($"激光功率计算: S2T D={distanceSourceToTarget:F1}m (Path1 T={totalTransmittance_S2T:F3}), " + - $"T2M D={distanceTargetToMissile:F1}m (Path2 T={totalTransmittance_T2M:F3}), " + - $"最终功率={finalReceivedPower:E}W"); + Debug.WriteLine($"激光功率计算: 源到目标距离={distanceSourceToTarget:F1}m (路径1 透过率={totalTransmittance_S2T:F3}), " + + $"目标到导弹距离={distanceTargetToMissile:F1}m (路径2 透过率={totalTransmittance_T2M:F3}), " + + $"最终功率={finalReceivedPower:E2}W"); return finalReceivedPower; } diff --git a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs index 2c55972..7626ccb 100644 --- a/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs +++ b/ThreatSource/src/Guidance/MillimeterWaveGuidanceSystem.cs @@ -685,7 +685,7 @@ namespace ThreatSource.Guidance rcsLinear = swerlingRcsModel.GetRealtimeRcs(target.Id, target.Properties.Type, motionState, rcsLinear, isNewScanPeriodForRcs); double rcsDbSmAfterSwerling = 10.0 * Math.Log10(rcsLinear); double rcsVariationDb = rcsDbSmAfterSwerling - rcsDbSm; - Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:+F2} dB."); + Debug.WriteLine($"[MMW_GUIDANCE] 目标 {target.Id}: Swerling后RCS: {rcsDbSmAfterSwerling:F2} dBsm ({rcsLinear:F4} m²), 波动: {rcsVariationDb:F2} dB."); double localSnrDb = CalculateSNR(distance, rcsLinear, liveSmokeTransmittance); switch (currentMode) diff --git a/ThreatSource/src/Indicator/BaseIndicator.cs b/ThreatSource/src/Indicator/BaseIndicator.cs index 86373ff..166ba37 100644 --- a/ThreatSource/src/Indicator/BaseIndicator.cs +++ b/ThreatSource/src/Indicator/BaseIndicator.cs @@ -27,7 +27,7 @@ namespace ThreatSource.Indicator /// /// 干扰处理组件 /// - protected readonly JammableComponent _jammingComponent; + protected readonly JammableComponent JammingComponent; /// /// 获取目标是否被烟幕遮挡 (由任何烟幕引起) @@ -37,12 +37,12 @@ namespace ThreatSource.Indicator /// /// 最后一次成功获取的目标位置 /// - protected Vector3D? _lastKnownTargetPosition = null; + protected Vector3D? LastKnownTargetPosition = null; /// /// 最后一次成功获取的目标朝向 /// - protected Orientation? _lastKnownTargetOrientation = null; + protected Orientation? LastKnownTargetOrientation = null; /// /// 获取设备支持的干扰类型 @@ -65,12 +65,12 @@ namespace ThreatSource.Indicator /// true表示指示器当前受到干扰影响 /// false表示指示器正常工作 /// - public bool IsJammed => _jammingComponent.IsJammed; + public bool IsJammed => JammingComponent.IsJammed; /// /// 获取设备当前是否正受到有效的阻塞式干扰 /// - public bool IsBlockingJammed => _jammingComponent.IsBlockingJammed; + public bool IsBlockingJammed => JammingComponent.IsBlockingJammed; /// /// 获取或设置目标ID @@ -97,12 +97,12 @@ namespace ThreatSource.Indicator protected BaseIndicator(string id, KinematicState motionParameters, ISimulationManager manager) : base(id, motionParameters, manager) { - _jammingComponent = new JammableComponent( + JammingComponent = new JammableComponent( positionProvider: () => base.KState.Position ); - _jammingComponent.JammingApplied += HandleJammingApplied; - _jammingComponent.JammingCleared += HandleJammingCleared; + JammingComponent.JammingApplied += HandleJammingApplied; + JammingComponent.JammingCleared += HandleJammingCleared; } /// @@ -119,10 +119,10 @@ namespace ThreatSource.Indicator /// protected void InitializeJamming(double jammingResistanceThreshold, IEnumerable supportedTypes, IEnumerable supportedBlockingTypes) { - _jammingComponent.LoadJammingConfigFromThreshold(jammingResistanceThreshold, supportedBlockingTypes); + JammingComponent.LoadJammingConfigFromThreshold(jammingResistanceThreshold, supportedBlockingTypes); foreach (var type in supportedTypes) { - _jammingComponent.AddSupportedJammingType(type); + JammingComponent.AddSupportedJammingType(type); } } @@ -136,7 +136,7 @@ namespace ThreatSource.Indicator /// public virtual void ApplyJamming(JammingParameters parameters) { - _jammingComponent.ApplyJamming(parameters); + JammingComponent.ApplyJamming(parameters); } /// @@ -149,7 +149,7 @@ namespace ThreatSource.Indicator /// public virtual void ClearJamming(JammingParameters parameters) { - _jammingComponent.ClearJamming(parameters); + JammingComponent.ClearJamming(parameters); } /// @@ -197,8 +197,8 @@ namespace ThreatSource.Indicator } IsTargetObscured = false; // 重置最后目标状态 - _lastKnownTargetPosition = null; - _lastKnownTargetOrientation = null; + LastKnownTargetPosition = null; + LastKnownTargetOrientation = null; base.Deactivate(); } @@ -207,7 +207,7 @@ namespace ThreatSource.Indicator /// public override void Update(double deltaTime) { - _jammingComponent.UpdateJammingStatus(deltaTime); + JammingComponent.UpdateJammingStatus(deltaTime); if (IsActive) { @@ -254,8 +254,8 @@ namespace ThreatSource.Indicator // 仅当目标被看到 (未遮挡) 且目标有效时,才更新最后已知状态 if (!currentlyObscured && currentTarget != null) { - _lastKnownTargetPosition = currentTarget.KState.Position; - _lastKnownTargetOrientation = currentTarget.KState.Orientation; + LastKnownTargetPosition = currentTarget.KState.Position; + LastKnownTargetOrientation = currentTarget.KState.Orientation; } } @@ -282,7 +282,7 @@ namespace ThreatSource.Indicator } // 3. 获取活动的烟幕 - var activeJammerIds = _jammingComponent.GetActiveJammerIdsOfType(JammingType.SmokeGrenade); + var activeJammerIds = JammingComponent.GetActiveJammerIdsOfType(JammingType.SmokeGrenade); if (!activeJammerIds.Any()) { return false; // 没有活动的烟幕,视为未遮挡 @@ -404,8 +404,8 @@ namespace ThreatSource.Indicator // 添加指示器特有属性 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["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; diff --git a/ThreatSource/src/Indicator/InfraredTracker.cs b/ThreatSource/src/Indicator/InfraredTracker.cs index 4613578..588331c 100644 --- a/ThreatSource/src/Indicator/InfraredTracker.cs +++ b/ThreatSource/src/Indicator/InfraredTracker.cs @@ -128,9 +128,9 @@ namespace ThreatSource.Indicator if (IsTargetObscured) { // 目标被遮挡,尝试使用最后已知位置 - if (_lastKnownTargetPosition != null) + if (LastKnownTargetPosition != null) { - currentTargetPosition = _lastKnownTargetPosition.Value; + currentTargetPosition = LastKnownTargetPosition.Value; Debug.WriteLine($"红外测角仪 {Id}: 目标被遮挡,使用最后已知位置 {currentTargetPosition}"); } else @@ -157,7 +157,7 @@ namespace ThreatSource.Indicator return; } currentTargetPosition = targetElement.KState.Position; - _lastKnownTargetPosition = currentTargetPosition; // 记录最后已知的目标位置 + LastKnownTargetPosition = currentTargetPosition; // 记录最后已知的目标位置 } IsTracking = true; diff --git a/ThreatSource/src/Indicator/LaserBeamRider.cs b/ThreatSource/src/Indicator/LaserBeamRider.cs index a3d8b1a..d3e0c40 100644 --- a/ThreatSource/src/Indicator/LaserBeamRider.cs +++ b/ThreatSource/src/Indicator/LaserBeamRider.cs @@ -138,7 +138,7 @@ namespace ThreatSource.Indicator { LaserDirection = newDirection; Debug.WriteLine($"激光驾束仪 {Id} 更新激光指向: {LaserDirection}"); - _lastKnownTargetPosition = targetPosition; // 记录最后已知的目标位置 + LastKnownTargetPosition = targetPosition; // 记录最后已知的目标位置 PublishLaserBeamEvent(); } } @@ -188,7 +188,7 @@ namespace ThreatSource.Indicator StopBeamIllumination(); } Debug.WriteLine($"激光驾束仪 {Id} 已停用"); - base.Deactivate(); // Handles IsActive and unsubscribes HandleJammingEvent + base.Deactivate(); } } diff --git a/ThreatSource/src/Indicator/LaserDesignator.cs b/ThreatSource/src/Indicator/LaserDesignator.cs index de04307..cdd6788 100644 --- a/ThreatSource/src/Indicator/LaserDesignator.cs +++ b/ThreatSource/src/Indicator/LaserDesignator.cs @@ -129,9 +129,9 @@ namespace ThreatSource.Indicator double yaw = Math.PI + Math.Atan2(direction.Z, direction.X); double pitch = -Math.Asin(direction.Y); KState.Orientation = new Orientation(yaw, pitch, 0); - _lastKnownTargetPosition = target.KState.Position; + LastKnownTargetPosition = target.KState.Position; - Debug.WriteLine($"激光指示器 {Id} 更新朝向: {KState.Orientation}, _lastKnownTargetPosition: {_lastKnownTargetPosition}"); + Debug.WriteLine($"激光指示器 {Id} 更新朝向: {KState.Orientation}, 最后已知目标位置: {LastKnownTargetPosition}"); } } } @@ -283,7 +283,7 @@ namespace ThreatSource.Indicator { LaserDesignatorId = Id, TargetId = TargetId, - SpotPosition = _lastKnownTargetPosition, + SpotPosition = LastKnownTargetPosition, LaserCodeConfig = config.LaserCodeConfig }); } diff --git a/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs b/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs index d17bbc6..887ce21 100644 --- a/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs +++ b/ThreatSource/src/MIssile/TerminalSensitiveSubmunition.cs @@ -669,10 +669,10 @@ namespace ThreatSource.Missile public override string GetStatus() { return base.GetStatus() - + $"\n激光测距仪状态: {rangefinder.GetStatus()}" - + $"\n红外探测器状态: {infraredDetector.GetStatus()}" - + $"\n毫米波辐射计状态: {radiometer.GetStatus()}" - + $"\n测高仪状态: {altimeter.GetStatus()}"; + + $"\n激光测距仪: {rangefinder.GetStatus()}" + + $"\n红外探测器: {infraredDetector.GetStatus()}" + + $"\n毫米波辐射计: {radiometer.GetStatus()}" + + $"\n测高仪: {altimeter.GetStatus()}"; } /// diff --git a/ThreatSource/src/Sensor/QuadrantDetector.cs b/ThreatSource/src/Sensor/QuadrantDetector.cs index a46679c..98f2bb9 100644 --- a/ThreatSource/src/Sensor/QuadrantDetector.cs +++ b/ThreatSource/src/Sensor/QuadrantDetector.cs @@ -303,7 +303,7 @@ namespace ThreatSource.Sensor VerticalError = filteredVerticalError; // 增强调试输出,同时显示水平和垂直误差 - Debug.WriteLine($"原始误差: 水平={rawHorizontalError:F6}, 垂直={rawVerticalError:F6}, 滤波后: 水平={HorizontalError:F6}, 垂直={VerticalError:F6}"); + Debug.WriteLine($"原始误差: 水平={rawHorizontalError:E2}, 垂直={rawVerticalError:E2}, 滤波后: 水平={HorizontalError:E2}, 垂直={VerticalError:E2}"); } else { @@ -365,9 +365,9 @@ namespace ThreatSource.Sensor /// public string GetStatus() { - return $"锁定={IsTargetLocked}, 总功率={TotalReceivedPower:E} W, 最小可探测功率={MinDetectablePower:E} W," + - $" 水平误差={HorizontalError:F4}, 垂直误差={VerticalError:F4}," + - $" 象限信号=[{quadrantSignals[0]:E}, {quadrantSignals[1]:E}, {quadrantSignals[2]:E}, {quadrantSignals[3]:E}]"; + return $"锁定={IsTargetLocked}, 总功率={TotalReceivedPower:E2} W, 最小可探测功率={MinDetectablePower:E2} W," + + $" 水平误差={HorizontalError:E2}, 垂直误差={VerticalError:E2}," + + $" 象限信号=[{quadrantSignals[0]:E2}, {quadrantSignals[1]:E2}, {quadrantSignals[2]:E2}, {quadrantSignals[3]:E2}]"; } } } \ No newline at end of file diff --git a/ThreatSource/src/Simulation/ISimulationManager.cs b/ThreatSource/src/Simulation/ISimulationManager.cs index 6d07e02..67ad7c5 100644 --- a/ThreatSource/src/Simulation/ISimulationManager.cs +++ b/ThreatSource/src/Simulation/ISimulationManager.cs @@ -179,6 +179,15 @@ namespace ThreatSource.Simulation /// 事件类型 /// 要取消的事件处理函数 void UnsubscribeFromEvent(Action handler); + + /// + /// 清理所有事件处理器和待处理事件 + /// + /// + /// 用于导弹切换或仿真重置时清理事件系统状态 + /// 防止事件残留影响新的制导系统 + /// + void ClearAllEvents(); #endregion #region 实体管理 diff --git a/ThreatSource/src/Simulation/SimulationManager.cs b/ThreatSource/src/Simulation/SimulationManager.cs index 74386e4..6aeba71 100644 --- a/ThreatSource/src/Simulation/SimulationManager.cs +++ b/ThreatSource/src/Simulation/SimulationManager.cs @@ -186,7 +186,7 @@ namespace ThreatSource.Simulation foreach (var target in activeTargets) { double distance = Vector3D.Distance(missile.KState.Position, target.KState.Position); - Debug.WriteLine($"导弹 {missile.Id} 和目标 {target.Id} 之间的距离: {distance:F2}"); + Debug.WriteLine($"导弹 {missile.Id} 和目标 {target.Id} 之间的距离: {distance:F2}m"); if (distance <= missile.Properties.ExplosionRadius) { double damage = CalculateMissileDamage(missile); @@ -365,6 +365,23 @@ namespace ThreatSource.Simulation } } } + + /// + /// 清理所有事件处理器和待处理事件 + /// + /// + /// 用于导弹切换或仿真重置时清理事件系统状态 + /// 防止事件残留影响新的制导系统 + /// + public void ClearAllEvents() + { + Debug.WriteLine("[事件] 清理所有事件处理器和待处理事件"); + + // 清理所有事件处理器 + eventHandlers.Clear(); + + Debug.WriteLine("[事件] 事件系统已完全清理"); + } #endregion #region 实体管理 diff --git a/tools/ComprehensiveMissileSimulator.cs b/tools/ComprehensiveMissileSimulator.cs index 8b67d5c..316d040 100644 --- a/tools/ComprehensiveMissileSimulator.cs +++ b/tools/ComprehensiveMissileSimulator.cs @@ -96,8 +96,6 @@ namespace ThreatSource.Tools.MissileSimulation // 初始化导弹-干扰映射 InitializeMissileJammingMap(); - - InitializeSimulation(); } public SourceLevels CurrentLogLevel => logLevelFilter?.EventType ?? SourceLevels.Off; @@ -245,11 +243,14 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(0.0, 0.0, 0.0), Speed = 2.0 }; + string targetId = "Tank_1"; var target = _threatSourceFactory.CreateEquipment(targetId, "mbt_001", motionParameters); targets[targetId] = target; simulationManager.RegisterEntity(targetId, target); + target.Activate(); // 激活目标 Console.WriteLine($"添加目标 {targetId},位置:{motionParameters.Position}"); + Console.WriteLine($"目标创建后实际位置:{target.KState.Position}"); } /// @@ -337,11 +338,13 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, Math.PI/20, 0), Speed = 700 }; + string missileId = "LSGM_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "lsgm_001", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册激光半主动制导导弹 {missileId}"); + Console.WriteLine($"注册激光半主动制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -355,11 +358,13 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, 0.04, 0.0), Speed = 10 }; + string missileId = "LBRM_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "hj10", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册激光驾束制导导弹 {missileId}"); + Console.WriteLine($"注册激光驾束制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -375,11 +380,11 @@ namespace ThreatSource.Tools.MissileSimulation }; string missileId = "TSM_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "tsm_001", "Tank_1", motionParameters); - missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册末敏弹 {missileId}"); + Console.WriteLine($"注册末敏弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -395,10 +400,11 @@ namespace ThreatSource.Tools.MissileSimulation }; string missileId = "ICGM_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "irc_001", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册红外指令制导导弹 {missileId}"); + Console.WriteLine($"注册红外指令制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -412,11 +418,13 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, 0.12, 0), Speed = 10 }; + string missileId = "ITGM_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "itg_001", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册红外成像末制导导弹 {missileId}"); + Console.WriteLine($"注册红外成像末制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -430,11 +438,13 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, 0.05, 0), Speed = 10 }; + string missileId = "MMWG_1"; + var missile = _threatSourceFactory.CreateMissile(missileId, "mmw_001", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册毫米波末制导导弹 {missileId}"); + Console.WriteLine($"注册毫米波末制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -449,10 +459,11 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, 0.05, 0), Speed = 10 }; + var missile = _threatSourceFactory.CreateMissile(missileId, "cg_001", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册毫米波/红外复合制导导弹 {missileId}"); + Console.WriteLine($"注册毫米波/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}"); missileId = "CGGM_2"; motionParameters = new KinematicState @@ -461,10 +472,11 @@ namespace ThreatSource.Tools.MissileSimulation Orientation = new Orientation(Math.PI/2, 0.05, 0), Speed = 10 }; + missile = _threatSourceFactory.CreateMissile(missileId, "cg_002", "Tank_1", motionParameters); missiles[missileId] = missile; simulationManager.RegisterEntity(missileId, missile); - Console.WriteLine($"注册激光/红外复合制导导弹 {missileId}"); + Console.WriteLine($"注册激光/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}"); } /// @@ -668,56 +680,27 @@ namespace ThreatSource.Tools.MissileSimulation private Orientation CalculateOrientationToEntity(SimulationElement target) { // 使用CalculateDirectionToTarget获取归一化方向向量 - Vector3D direction = CalculateDirectionToTarget(new Vector3D(0, 0, 0), target.KState.Position); + Vector3D direction = target.KState.Position - new Vector3D(0, 0, 0); // 创建朝向目标的方向 - return Orientation.FromVector(direction); + return Orientation.FromVector(direction.Normalize()); } /// - /// 选择要激活的导弹 + /// 选择导弹 /// + /// 导弹ID public void SelectMissile(string missileId) { - if (!missiles.ContainsKey(missileId)) - { - Console.WriteLine($"错误:找不到导弹 {missileId}"); - return; - } - - // 先停用所有导弹、传感器、干扰器 - foreach (var id in missiles.Keys) - { - missileActiveStatus[id] = false; - missiles[id].Deactivate(); - } - foreach (var indicator in indicators.Values) - { - indicator.Deactivate(); - } - foreach (var jammer in jammers.Values) - { - jammer.Deactivate(); - } - - // 激活选中的导弹 - missileActiveStatus[missileId] = true; - missiles[missileId].Activate(); - SelectedMissileId = missileId; - Console.WriteLine($"已选择导弹:{missileId} ({SelectedMissileDisplayName})"); - - // 确保所有目标都处于激活状态 - foreach (var target in targets.Values) - { - target.Activate(); - Console.WriteLine($"确保目标 {target.Id} 处于激活状态"); - } - - // 激活相关的传感器和指示器 - ActivateRelatedIndicators(missileId); - - // 打印所有注册的组件 - PrintSimulationRegisteredComponents(); + Console.WriteLine($"=== 选择导弹: {missileId} ==="); + + // 新架构:完全销毁所有现有实体 + DestroyAllEntities(); + + // 重新创建选中的导弹及其相关实体 + CreateMissileAndRelatedEntities(missileId); + + Console.WriteLine($"=== 导弹选择完成: {missileId} ==="); } /// @@ -1085,12 +1068,25 @@ namespace ThreatSource.Tools.MissileSimulation { Console.WriteLine("开始综合导弹模拟..."); - // 确保所有激活的导弹和传感器都处于正确状态 - foreach (var missile in missiles.Values) + // 使用新架构:销毁重建模式,确保每次都是全新的实体和位置 + if (missiles.Count > 0 || targets.Count > 0) { - if (missileActiveStatus[missile.Id]) + Console.WriteLine("检测到现有实体,销毁并重新创建..."); + + // 保存当前选中的导弹ID,避免在销毁时被清空 + string currentSelectedMissileId = SelectedMissileId; + + DestroyAllEntities(); + + // 重新创建选中的导弹及其相关实体 + if (!string.IsNullOrEmpty(currentSelectedMissileId)) { - missile.Fire(); + CreateMissileAndRelatedEntities(currentSelectedMissileId); + } + else + { + Console.WriteLine("错误:没有选中的导弹"); + return; } } @@ -1113,7 +1109,7 @@ namespace ThreatSource.Tools.MissileSimulation { simulationManager.StopSimulation(); SimulationEnded?.Invoke(this, EventArgs.Empty); - ResetSimulation(); + Console.WriteLine("仿真结束,所有导弹已完成任务"); break; } @@ -1136,7 +1132,7 @@ namespace ThreatSource.Tools.MissileSimulation Console.WriteLine($"\n========== 模拟状态 (时间: {simulationTime:F3}s)=========="); // 天气状态 - Console.WriteLine("\n--- 天气状态 ---"); + Console.WriteLine("\n--- 天气环境 ---"); if (weather != null) { Console.WriteLine($"天气类型: {weather.Type}"); @@ -1147,7 +1143,7 @@ namespace ThreatSource.Tools.MissileSimulation } // 导弹状态 - Console.WriteLine("\n--- 导弹状态 ---"); + Console.WriteLine("\n--- 导弹 ---"); var activeMissiles = simulationManager.GetEntitiesByType() .Where(m => m.IsActive) .ToList(); @@ -1165,7 +1161,7 @@ namespace ThreatSource.Tools.MissileSimulation } // 目标状态 - Console.WriteLine("\n--- 目标状态 ---"); + Console.WriteLine("\n--- 目标 ---"); var activeTargets = targets.Values.Where(t => t.IsActive).ToList(); if (activeTargets.Any()) { @@ -1181,7 +1177,7 @@ namespace ThreatSource.Tools.MissileSimulation } // 传感器状态 - Console.WriteLine("\n--- 指示器状态 ---"); + Console.WriteLine("\n--- 指示器 ---"); var activeIndicators = indicators.Values.Where(i => i.IsActive).ToList(); if (activeIndicators.Any()) { @@ -1197,7 +1193,7 @@ namespace ThreatSource.Tools.MissileSimulation } // 干扰器状态 - Console.WriteLine("\n--- 干扰器状态 ---"); + Console.WriteLine("\n--- 干扰器 ---"); var activeJammers = jammers.Values.Where(j => j.IsActive).ToList(); if (activeJammers.Any()) { @@ -1275,52 +1271,25 @@ namespace ThreatSource.Tools.MissileSimulation /// /// 重置仿真状态 /// + /// + /// 新架构:由于采用销毁重建模式,此方法已简化 + /// 主要功能已移至DestroyAllEntities和CreateMissileAndRelatedEntities方法 + /// public void ResetSimulation() { - // 获取所有活跃的导弹 - var activeMissiles = simulationManager.GetEntitiesByType(); - foreach (var missile in activeMissiles) - { - // 获取导弹的初始属性 - var motionParameters = missile.GetType().GetField("motionParameters", - System.Reflection.BindingFlags.NonPublic | - System.Reflection.BindingFlags.Instance)?.GetValue(missile) as KinematicState; - - if (motionParameters != null) - { - // 重置导弹位置和状态 - missile.KState.Position = motionParameters.Position; - missile.KState.Velocity = Vector3D.Zero; - } - missile.Deactivate(); - } - - // 重置所有传感器状态 - var activeIndicators = simulationManager.GetEntitiesByType() - .Where(e => indicators.ContainsValue(e)); - foreach (var indicator in activeIndicators) - { - indicator.Deactivate(); - } - - // 重置所有目标状态 - var activeTargets = simulationManager.GetEntitiesByType(); - foreach (var target in activeTargets) - { - var initialPosition = target.KState.Position; - target.Deactivate(); - target.KState.Position = initialPosition; - target.Activate(); - } - + Console.WriteLine("=== 开始重置仿真状态 ==="); + + // 停止仿真并清理事件系统 + simulationManager.StopSimulation(); + simulationManager.ClearAllEvents(); + // 重置导弹激活状态 missileActiveStatus.Clear(); - foreach (var missile in missiles.Values) - { - missileActiveStatus[missile.Id] = false; - } - - Console.WriteLine("仿真状态已重置"); + + // 清理活跃干扰列表 + activeJammings.Clear(); + + Console.WriteLine("=== 仿真状态重置完成 ==="); } /// @@ -1421,5 +1390,285 @@ namespace ThreatSource.Tools.MissileSimulation // 返回一个新的列表,防止外部修改内部列表 return [.. activeJammings]; } + + /// + /// 销毁所有实体并从仿真管理器中注销 + /// + /// + /// 新架构:每次仿真结束后完全销毁所有实体,下次选择时重新创建 + /// 这样可以避免状态残留问题,确保每次都是全新的实体 + /// + private void DestroyAllEntities() + { + Console.WriteLine("=== 开始销毁所有实体 ==="); + + // 停止仿真并清理事件系统 + simulationManager.StopSimulation(); + simulationManager.ClearAllEvents(); + + // 销毁所有导弹 + foreach (var missile in missiles.Values) + { + missile.Deactivate(); + simulationManager.UnregisterEntity(missile.Id); + Console.WriteLine($"销毁导弹: {missile.Id}"); + } + missiles.Clear(); + + // 销毁所有目标 + foreach (var target in targets.Values) + { + target.Deactivate(); + simulationManager.UnregisterEntity(target.Id); + Console.WriteLine($"销毁目标: {target.Id}"); + } + targets.Clear(); + + // 销毁所有指示器 + foreach (var indicator in indicators.Values) + { + indicator.Deactivate(); + simulationManager.UnregisterEntity(indicator.Id); + Console.WriteLine($"销毁指示器: {indicator.Id}"); + } + indicators.Clear(); + + // 销毁所有干扰器 + foreach (var jammer in jammers.Values) + { + jammer.Deactivate(); + simulationManager.UnregisterEntity(jammer.Id); + Console.WriteLine($"销毁干扰器: {jammer.Id}"); + } + jammers.Clear(); + + // 清理状态 + missileActiveStatus.Clear(); + activeJammings.Clear(); + SelectedMissileId = ""; + + Console.WriteLine("=== 所有实体销毁完成 ==="); + } + + /// + /// 按需创建特定导弹及其相关实体 + /// + /// 要创建的导弹ID + /// + /// 新架构:每次选择导弹时重新创建所需的实体 + /// 包括目标、导弹、指示器、干扰器等 + /// + private void CreateMissileAndRelatedEntities(string missileId) + { + Console.WriteLine($"=== 开始创建导弹 {missileId} 及相关实体 ==="); + + // 首先添加天气(如果还没有) + if (simulationManager.CurrentWeather == null) + { + AddWeathers(); + } + + // 创建目标 + AddTankTarget(); + + // 根据导弹类型创建对应的导弹 + switch (missileId) + { + case "LSGM_1": + AddLaserSemiActiveMissile(); + break; + + case "LBRM_1": + AddLaserBeamRiderMissile(); + break; + + case "TSM_1": + AddTerminalSensitiveMissile(); + break; + + case "ICGM_1": + AddInfraredCommandMissile(); + break; + + case "ITGM_1": + AddInfraredImagingMissile(); + break; + + case "MMWG_1": + AddMillimeterWaveMissile(); + break; + + case "CGGM_1": + case "CGGM_2": + AddCompositeGuidanceMissile(); // 这个方法会添加两种复合制导导弹 + break; + + default: + Console.WriteLine($"未知的导弹类型: {missileId}"); + return; + } + + // 添加所有指示器、干扰器和烟幕弹 + AddIndicators(); + + // 根据导弹类型添加相应的干扰器 + AddJammersForMissile(missileId); + + // 添加烟幕弹和激光诱偏目标 + AddSmokeGrenade(); + AddLaserDecoy(); + + // 激活选中的导弹 + if (missiles.TryGetValue(missileId, out var selectedMissile)) + { + selectedMissile.Activate(); + SelectedMissileId = missileId; + missileActiveStatus[missileId] = true; + Console.WriteLine($"已激活导弹: {missileId}"); + + // 激活相关指示器 + ActivateRelatedIndicators(missileId); + } + + Console.WriteLine($"=== 导弹 {missileId} 及相关实体创建完成 ==="); + } + + private void AddJammersForMissile(string missileId) + { + Console.WriteLine($"为导弹 {missileId} 创建相应的干扰器"); + + // 利用现有的导弹-干扰器映射 + if (missileJammingMap.TryGetValue(missileId, out var jammingList)) + { + foreach (var (type, displayName, jammerId, mode, target) in jammingList) + { + CreateJammerById(jammerId, type, target); + } + } + else + { + Console.WriteLine($"未找到导弹 {missileId} 的干扰器映射"); + } + } + + /// + /// 根据干扰器ID创建干扰器实体 + /// + private void CreateJammerById(string jammerId, JammingType type, string target) + { + try + { + // 根据干扰器ID确定朝向 + Orientation orientation = GetJammerOrientation(jammerId, target); + + var jammerParams = new KinematicState + { + Position = new Vector3D(0, 0, 0), + Orientation = orientation, + Speed = 0.0 + }; + + // 根据干扰器ID确定类型配置 + string jammerConfig = GetJammerConfig(jammerId); + + var jammer = _threatSourceFactory.CreateJammer(jammerId, jammerConfig, jammerParams, "Tank_1"); + if (jammer is BaseJammer baseJammer) + { + simulationManager.RegisterEntity(jammerId, jammer); + jammers[jammerId] = baseJammer; + Console.WriteLine($"注册干扰器 {jammerId}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"创建干扰器 {jammerId} 时出错: {ex.Message}"); + } + } + + /// + /// 根据干扰器ID和目标确定朝向 + /// + private Orientation GetJammerOrientation(string jammerId, string target) + { + // 根据干扰器ID和目标类型确定朝向 + return jammerId switch + { + "LaserJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器 + "LaserJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹 + "InfraredJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器 + "InfraredJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹 + "MillimeterWaveJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹 + "LaserJammer_Submunition" or "InfraredJammer_Submunition" or "MillimeterWaveJammer_Submunition" or "MillimeterWaveCompensationJammer_Submunition" + => new Orientation(0, Math.PI/2, 0), // 垂直向上 + _ => new Orientation(0, 0, 0) // 默认朝向 + }; + } + + /// + /// 获取朝向与当前选中导弹相关的指示器的方向 + /// + private Orientation GetOrientationToRelatedIndicator() + { + // 根据当前选中的导弹确定相关的指示器 + string[] relatedIndicatorIds = SelectedMissileId switch + { + "LSGM_1" => ["LD_1"], // 激光半主动导弹 -> 激光指示器 + "LBRM_1" => ["LBR_1"], // 激光驾束导弹 -> 激光驾束仪 + "ICGM_1" => ["IT_1"], // 红外指令导弹 -> 红外测角仪 + "CGGM_2" => ["LD_1"], // 激光/红外复合导弹 -> 激光指示器 + _ => ["LD_1", "LBR_1", "IT_1"] // 默认尝试所有指示器 + }; + + return GetOrientationToIndicator(relatedIndicatorIds); + } + + /// + /// 获取朝向当前选中导弹的方向 + /// + private Orientation GetOrientationToCurrentMissile() + { + if (!string.IsNullOrEmpty(SelectedMissileId) && missiles.TryGetValue(SelectedMissileId, out var missile)) + { + return CalculateOrientationToEntity(missile); + } + return new Orientation(0, 0, 0); // 默认朝向 + } + + /// + /// 获取朝向指示器的方向 + /// + private Orientation GetOrientationToIndicator(params string[] indicatorIds) + { + foreach (var indicatorId in indicatorIds) + { + if (indicators.TryGetValue(indicatorId, out var indicator)) + { + return CalculateOrientationToEntity(indicator); + } + } + return new Orientation(0, 0, 0); // 默认朝向 + } + + /// + /// 根据干扰器ID确定配置类型 + /// + private string GetJammerConfig(string jammerId) + { + return jammerId switch + { + "LaserJammer_Designator" or "LaserJammer_Missile" => "laser_blocking", + "LaserJammer_Submunition" => "laser_top_blocking", + "InfraredJammer_Designator" or "InfraredJammer_Missile" => "infrared_blocking", + "InfraredJammer_Submunition" => "infrared_top_blocking", + "MillimeterWaveJammer_Missile" or "MillimeterWaveJammer_Submunition" => "mmw_blocking", + "MillimeterWaveCompensationJammer_Submunition" => "mmw_compensation", + "LDY_1" => "laser_decoy", + "SG_1" => "surround", + "SG_2" => "infrared", + "SG_3" => "mmw", + "SG_4" => "top", + _ => "laser_blocking" // 默认配置 + }; + } } } \ No newline at end of file