using ThreatSource.Utils; using ThreatSource.Equipment; using System.Diagnostics; using ThreatSource.Jammer; using ThreatSource.Simulation; using AirTransmission; namespace ThreatSource.Guidance { /// /// 毫米波导引头系统类,实现了基于毫米波雷达的目标探测和跟踪功能 /// /// /// 该类提供了毫米波导引头系统的核心功能: /// - 目标探测和识别 /// - 信噪比计算 /// - 抗干扰处理 /// - 比例导引控制 /// 用于实现全天候制导打击 /// public class MillimeterWaveGuidanceSystem : BasicGuidanceSystem { /// /// 工作模式枚举 /// private enum WorkMode { Search, // 搜索模式 Track, // 跟踪模式 Lock // 锁定模式 } /// /// 毫米波导引系统配置 /// /// /// 存储系统的所有可配置参数 /// 包括探测范围、视场角等 /// private readonly MillimeterWaveGuidanceConfig config; /// /// 随机数生成器实例 /// /// /// 用于生成随机扰动 /// 模拟系统噪声和识别概率 /// private readonly Random random = new(); /// /// 上一次探测到的目标位置 /// /// /// 记录目标的历史位置 /// 用于计算目标速度 /// private Vector3D lastTargetPosition; /// /// 上一次探测到的目标速度 /// /// /// 记录目标的历史速度 /// 用于计算目标速度 /// private Vector3D lastTargetVelocity; /// /// 目标丢失计时器 /// /// /// 记录目标丢失的时间 /// 用于切换到搜索模式 /// private double targetLostTimer = 0; /// /// 锁定确认计时器 /// /// /// 记录锁定确认的时间 /// 用于切换到锁定模式 /// private double lockConfirmationTimer = 0; /// /// 当前工作模式 /// private WorkMode currentMode = WorkMode.Search; /// /// 是否受到干扰 /// /// /// 指示当前是否受到电子干扰 /// 影响系统的工作状态 /// private bool isJammed = false; /// /// 干扰功率,单位:瓦特 /// /// /// 记录接收到的干扰信号功率 /// 用于评估干扰效果 /// private double jammingPower = 0; /// /// 是否有目标 /// public bool HasTarget { get; private set; } /// /// 是否在锁定模式 /// public bool IsInLockMode => currentMode == WorkMode.Lock; /// /// 当前扫描角度,单位:弧度 /// private double currentScanAngle = 0; /// /// 当前扫描半径,单位:弧度 /// private double currentScanRadius = 0; /// /// 最大扫描半径,单位:弧度 /// private double maxScanRadius => config.FieldOfViewAngle * Math.PI / 180.0 / 2; /// /// 初始化毫米波制导系统的新实例 /// /// 制导系统ID /// 最大加速度,单位:米/平方秒 /// 制导系数 /// 仿真管理器实例 /// 毫米波导引系统配置 /// /// 构造过程: /// - 初始化基类参数 /// - 设置仿真管理器 /// - 初始化目标位置 /// - 注册干扰事件处理 /// - 加载干扰阈值配置 /// public MillimeterWaveGuidanceSystem( string id, double maxAcceleration, double guidanceCoefficient, MillimeterWaveGuidanceConfig config, ISimulationManager simulationManager) : base(id, maxAcceleration, guidanceCoefficient, simulationManager) { this.config = config; lastTargetPosition = Vector3D.Zero; lastTargetVelocity = Vector3D.Zero; InitializeJamming(config.JammingResistanceThreshold, [JammingType.MillimeterWave]); SwitchToSearchMode(); // 初始化为搜索模式 } /// /// 切换到搜索模式 /// public void SwitchToSearchMode() { currentMode = WorkMode.Search; HasTarget = false; HasGuidance = false; targetLostTimer = 0; lockConfirmationTimer = 0; currentScanAngle = 0; currentScanRadius = config.SearchBeamWidth * Math.PI / 720.0; // 从半个波束宽度的一半开始 Trace.WriteLine($"切换到搜索模式,波束宽度: {config.SearchBeamWidth}度"); } /// /// 切换到跟踪模式 /// private void SwitchToTrackMode() { currentMode = WorkMode.Track; lockConfirmationTimer = 0; HasGuidance = true; Trace.WriteLine($"切换到跟踪模式,波束宽度: {config.TrackBeamWidth}度"); } /// /// 切换到锁定模式 /// private void SwitchToLockMode() { currentMode = WorkMode.Lock; HasGuidance = true; Trace.WriteLine("切换到锁定模式 - 目标锁定成功"); } /// /// 激活制导系统 /// public override void Activate() { if (!IsActive) { IsActive = true; // 在这里订阅事件,确保只订阅一次 SimulationManager.SubscribeToEvent(OnMillimeterWaveJamming); } base.Activate(); SwitchToSearchMode(); } /// /// 停用制导系统 /// public override void Deactivate() { if (IsActive) { IsActive = false; SimulationManager.UnsubscribeFromEvent(OnMillimeterWaveJamming); } base.Deactivate(); HasTarget = false; HasGuidance = false; GuidanceAcceleration = Vector3D.Zero; } /// /// 处理毫米波干扰事件 /// /// 干扰事件参数 /// /// 处理过程: /// - 更新干扰状态 /// - 记录干扰功率 /// private void OnMillimeterWaveJamming(MillimeterWaveJammingEvent evt) { if (evt == null) return; // 创建干扰参数 var parameters = new JammingParameters { Type = JammingType.MillimeterWave, Power = evt.JammingPower, Direction = evt.JammingDirection, SourcePosition = evt.JammingSourcePosition, AngleRange = evt.JammingAngleRange, Mode = evt.JammingMode, Duration = evt.Duration }; // 使用JammableComponent进行干扰判断 ApplyJamming(parameters); Debug.WriteLine($"毫米波导引头系统干扰状态 - IsJammed: {IsJammed}, 干扰功率: {evt.JammingPower}W, 抗性阈值: {config.JammingResistanceThreshold}W"); } /// /// 处理系统被干扰的事件 /// /// 干扰参数 protected override void HandleJammingApplied(JammingParameters parameters) { if (parameters.Type == JammingType.MillimeterWave) { Debug.WriteLine($"毫米波导引头系统受到毫米波干扰,功率:{parameters.Power}瓦特"); // 确保基类的处理逻辑被调用,设置HasGuidance = false base.HandleJammingApplied(parameters); } // 在强干扰下切换到搜索模式 if (currentMode != WorkMode.Search) { SwitchToSearchMode(); } } /// /// 处理系统干扰被清除的事件 /// /// 被清除的干扰类型 protected override void HandleJammingCleared(JammingType type) { if (type == JammingType.MillimeterWave) { Debug.WriteLine("毫米波导引头系统干扰被清除"); base.HandleJammingCleared(type); } } /// /// 更新圆锥扫描参数 /// private void UpdateConicalScan(double deltaTime) { if (currentMode == WorkMode.Search) { // 使用配置参数 currentScanAngle += config.ScanAngularSpeedDeg * Math.PI / 180.0 * deltaTime; currentScanRadius += config.ScanRadiusGrowthRateDeg * Math.PI / 180.0 * deltaTime; currentScanRadius = Math.Min(currentScanRadius, maxScanRadius); if (currentScanAngle >= 2 * Math.PI) { currentScanAngle -= 2 * Math.PI; } Console.WriteLine($"扫描参数 - 半径: {currentScanRadius * 180/Math.PI:F2}度, 角度: {currentScanAngle * 180/Math.PI:F2}度"); } else { currentScanAngle = 0; // 非搜索模式时重置扫描参数 currentScanRadius = config.SearchBeamWidth * Math.PI / 720.0; } } /// /// 单脉冲和差测角处理(仅用于跟踪/锁定模式) /// /// 弹目视线方向向量 /// 导弹速度向量 /// (方位误差弧度, 俯仰误差弧度) private (double azimuthError, double elevationError) ProcessMonopulse(Vector3D toTarget, Vector3D missileVelocity) { // 建立弹体坐标系(X轴为导弹速度方向) Vector3D xAxis = missileVelocity.Normalize(); // 使用地面垂直方向作为参考 Vector3D up = Vector3D.UnitY; // 计算水平方向 Vector3D yAxis = Vector3D.CrossProduct(up, xAxis).Normalize(); if (yAxis.Magnitude() < 1e-6) { // 如果导弹垂直飞行,使用北向作为参考 yAxis = Vector3D.CrossProduct(Vector3D.UnitZ, xAxis).Normalize(); } // 计算垂直方向 Vector3D zAxis = Vector3D.CrossProduct(xAxis, yAxis).Normalize(); // 将目标向量转换到弹体坐标系 Vector3D targetBodyFrame = new( Vector3D.DotProduct(toTarget, xAxis), Vector3D.DotProduct(toTarget, yAxis), Vector3D.DotProduct(toTarget, zAxis) ); // 计算方位角和俯仰角 double azimuthError = Math.Atan2(targetBodyFrame.Y, targetBodyFrame.X); double elevationError = Math.Atan2(targetBodyFrame.Z, Math.Sqrt(targetBodyFrame.X * targetBodyFrame.X + targetBodyFrame.Y * targetBodyFrame.Y)); // 应用灵敏度系数 return ( azimuthError * config.MonopulseSensitivity, elevationError * config.MonopulseSensitivity ); } /// /// 计算目标是否在当前扫描波束内 /// private bool IsTargetInBeam(Vector3D missileVelocity, Vector3D toTarget) { // 根据当前模式选择波束宽度 double currentBeamWidth = currentMode switch { WorkMode.Search => config.SearchBeamWidth * Math.PI / 180.0, WorkMode.Track => config.TrackBeamWidth * Math.PI / 180.0, WorkMode.Lock => config.LockBeamWidth * Math.PI / 180.0, _ => config.SearchBeamWidth * Math.PI / 180.0 }; if (currentMode == WorkMode.Search) { // 搜索模式使用圆锥扫描 // 建立以前进方向为X轴的右手坐标系 Vector3D xAxis = missileVelocity.Normalize(); Vector3D yAxis; Vector3D referenceAxis = Vector3D.UnitY; // 优先使用垂直轴作为参考 // 处理近乎垂直飞行的情况 if (Math.Abs(xAxis.Y) > 0.9) { referenceAxis = Vector3D.UnitZ; // 改用Z轴作为参考 } // 构建正交坐标系 yAxis = Vector3D.CrossProduct(Vector3D.CrossProduct(xAxis, referenceAxis), xAxis).Normalize(); Vector3D zAxis = Vector3D.CrossProduct(xAxis, yAxis).Normalize(); // 计算圆锥扫描方向 double offsetAngle = currentScanRadius; // X轴为主轴的圆锥扫描参数 double x = Math.Cos(offsetAngle); // 主轴分量 double y = Math.Sin(offsetAngle) * Math.Sin(currentScanAngle); // 垂直分量 double z = Math.Sin(offsetAngle) * Math.Cos(currentScanAngle); // 水平分量 // 合成扫描方向向量 Vector3D scanDirection = ( xAxis * x + yAxis * y + zAxis * z ).Normalize(); // 调试输出 Console.WriteLine($"导弹前进方向: {xAxis}"); Console.WriteLine($"目标方向: {toTarget.Normalize()}"); Console.WriteLine($"扫描方向: {scanDirection}"); // 计算目标夹角 double angle = Vector3D.AngleBetween(scanDirection, toTarget.Normalize()); Console.WriteLine($"目标夹角: {angle * 180/Math.PI:F2}度"); Console.WriteLine($"波束宽度: {currentBeamWidth * 180/Math.PI:F2}度,SNR阈值: {config.RecognitionSNRThreshold}dB"); return angle <= currentBeamWidth; } else { // 跟踪/锁定模式使用单脉冲测角 var (azError, elError) = ProcessMonopulse(toTarget.Normalize(), missileVelocity); Console.WriteLine($"[单脉冲测角] 方位误差: {azError * 180/Math.PI:F3}度, 俯仰误差: {elError * 180/Math.PI:F3}度"); Console.WriteLine($"[波束宽度检查] 当前阈值: {currentBeamWidth * 180/Math.PI:F3}度,实际误差: {Math.Sqrt(azError*azError + elError*elError) * 180/Math.PI:F3}度"); return Math.Sqrt(azError*azError + elError*elError) < currentBeamWidth; } } /// /// 更新制导系统的状态 /// /// 自上次更新以来的时间间隔,单位:秒 /// 导弹当前位置,单位:米 /// 导弹当前速度,单位:米/秒 /// /// 更新过程: /// - 探测目标位置 /// - 计算目标速度 /// - 生成制导指令 /// - 限制最大加速度 /// public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity) { // 更新扫描参数 UpdateConicalScan(deltaTime); base.Update(deltaTime, missilePosition, missileVelocity); if (!IsJammed) { if (TryDetectAndTrackTarget(missilePosition, missileVelocity, deltaTime, out Vector3D targetPosition)) { targetLostTimer = 0; Vector3D targetVelocity = (targetPosition - lastTargetPosition) / deltaTime; lastTargetPosition = targetPosition; lastTargetVelocity = targetVelocity; // 使用比例导引计算制导加速度 GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation( ProportionalNavigationCoefficient, missilePosition, missileVelocity, targetPosition, targetVelocity ); // 限制最大加速度 if (GuidanceAcceleration.Magnitude() > MaxAcceleration) { GuidanceAcceleration = GuidanceAcceleration.Normalize() * MaxAcceleration; } Console.WriteLine($"制导加速度: {GuidanceAcceleration}"); HasGuidance = true; } else { if (currentMode != WorkMode.Search) { targetLostTimer += deltaTime; // 如果目标丢失时间达到阈值,切换回搜索模式 if (targetLostTimer >= config.TargetLostTolerance) { HasGuidance = false; Trace.WriteLine($"目标丢失 {targetLostTimer:F3}秒,切换回搜索模式"); SwitchToSearchMode(); } } else { HasGuidance = false; } } } else { HasGuidance = false; GuidanceAcceleration = Vector3D.Zero; } } /// /// 尝试探测和跟踪目标 /// /// 导弹当前位置,单位:米 /// 导弹当前速度,单位:米/秒 /// 自上次更新以来的时间间隔,单位:秒 /// 输出探测到的目标位置,单位:米 /// 是否成功探测到目标 /// /// 探测过程: /// - 检查干扰状态 /// - 遍历场景中的目标 /// - 检查距离和角度 /// - 计算信噪比 /// - 判断目标有效性 /// private bool TryDetectAndTrackTarget(Vector3D missilePosition, Vector3D missileVelocity, double deltaTime, out Vector3D targetPosition) { targetPosition = Vector3D.Zero; double minDistance = double.MaxValue; bool foundTarget = false; double currentSNR = double.MinValue; // 如果被干扰,直接返回false if (isJammed) { Trace.WriteLine($"毫米波导引头受到干扰,干扰功率: {jammingPower:F2}W"); HasGuidance = false; return false; } foreach (var element in SimulationManager.GetEntitiesByType()) { if (element is BaseEquipment target) { Vector3D toTarget = target.Position - missilePosition; double distance = toTarget.Magnitude(); if (distance <= config.MaxDetectionRange) { // 计算信噪比 double snr = CalculateSNR(distance, target.Properties.RadarCrossSection); Console.WriteLine($"信噪比: {snr:F2}dB"); if (currentMode == WorkMode.Search) { // 在搜索模式下进行波束判断 if (IsTargetInBeam(missileVelocity, toTarget) && snr >= config.RecognitionSNRThreshold) { targetPosition = target.Position; minDistance = distance; foundTarget = true; currentSNR = snr; } } else if (currentMode == WorkMode.Track || currentMode == WorkMode.Lock) { // 波束内判断 if (IsTargetInBeam(missileVelocity, toTarget) && Vector3D.Distance(target.Position, lastTargetPosition) < 100.0) { // 在跟踪模式下,SNR至少要达到识别阈值 double requiredSNR = (currentMode == WorkMode.Track) ? config.RecognitionSNRThreshold : config.LockSNRThreshold; if (snr >= requiredSNR) { targetPosition = target.Position; foundTarget = true; currentSNR = snr; Console.WriteLine($"[目标跟踪] 距离: {distance:F1}米, SNR: {snr:F2}dB, 要求SNR: {requiredSNR:F2}dB"); break; } else { Console.WriteLine($"[目标丢失] 距离: {distance:F1}米, SNR: {snr:F2}dB, 要求SNR: {requiredSNR:F2}dB"); } } } } } } // 根据当前模式和探测结果更新系统状态 UpdateSystemState(foundTarget, currentSNR, deltaTime); HasTarget = foundTarget; return foundTarget; } /// /// 更新系统状态 /// private void UpdateSystemState(bool hasTarget, double snr, double deltaTime) { if (!hasTarget) { targetLostTimer += deltaTime; if (targetLostTimer >= config.TargetLostTolerance) { SwitchToSearchMode(); } return; } targetLostTimer = 0; switch (currentMode) { case WorkMode.Search: if (snr >= config.RecognitionSNRThreshold) { SwitchToTrackMode(); } break; case WorkMode.Track: if (snr >= config.LockSNRThreshold) { lockConfirmationTimer += deltaTime; if (lockConfirmationTimer >= config.LockConfirmationTime) { SwitchToLockMode(); } } else { lockConfirmationTimer = 0; } break; case WorkMode.Lock: if (snr < config.LockSNRThreshold) { SwitchToTrackMode(); } break; } } /// /// 获取制导系统的详细状态信息 /// /// 包含完整状态参数的字符串 /// /// 返回信息: /// - 基本状态信息 /// - 目标位置 /// 用于系统监控和调试 /// public override string GetStatus() { return base.GetStatus() + $"\n当前模式: {currentMode}" + $"\n目标位置: {lastTargetPosition}" + $"\n目标速度: {lastTargetVelocity}" + $"\n是否有目标: {HasTarget}"; } /// /// 计算目标的信噪比 /// /// 到目标的距离,单位:米 /// 目标雷达散射截面积,单位:平方米 /// 信噪比,单位:分贝 /// /// 计算过程: /// - 设置雷达参数 /// - 计算信号功率 /// - 计算噪声功率 /// - 计算信噪比 /// - 转换为分贝值 /// private double CalculateSNR(double distance, double radarCrossSection) { // 雷达参数 double transmitPower = config.TransmitPower; // 发射功率(W),典型值0.3W double antennaGain = Math.Pow(10, config.AntennaGainDB/10); // 天线增益(线性值) double wavelength = 3e8 / config.WaveFrequency; // 波长(m),94GHz -> 3.19mm double bandwidth = 1.0 / config.PulseDuration; // 带宽(Hz),由脉冲持续时间决定 double noiseFigure = Math.Pow(10, config.NoiseFigureDB/10); // 噪声系数(线性值) // 系统损耗,单位:dB double atmosphericLoss = 0.4 * distance / 1000.0; // 大气衰减,0.4dB/km double totalLoss = Math.Pow(10, (atmosphericLoss + config.SystemLossDB) / 10); // 转换为线性值 // 常量 double k = 1.38e-23; // 玻尔兹曼常数 double T0 = 290; // 标准噪声温度(K) // 计算接收信号功率 double signalPower = (transmitPower * Math.Pow(antennaGain, 2) * Math.Pow(wavelength, 2) * radarCrossSection) / (Math.Pow(4 * Math.PI, 3) * Math.Pow(distance, 4) * totalLoss); // 考虑大气透过率,如果当前天气为null,则认为大气透过率为1.0 double atmosphericTransmittance = 1.0; if(SimulationManager.CurrentWeather != null) { atmosphericTransmittance = AtmosphereDllWrapper.CalculateTransmittance( distance, RadiationType.MillimeterWave, wavelength, SimulationManager.CurrentWeather); } signalPower *= atmosphericTransmittance; // 计算噪声功率 double noisePower = k * T0 * bandwidth * noiseFigure; // 计算信噪比 double snr = signalPower / noisePower; // 转换为dB return 10 * Math.Log10(snr); } } }