431 lines
16 KiB
C#
431 lines
16 KiB
C#
using ThreatSource.Simulation;
|
||
using ThreatSource.Utils;
|
||
using ThreatSource.Missile;
|
||
using ThreatSource.Jammer;
|
||
using System.Diagnostics;
|
||
using System; // Added for Action
|
||
|
||
namespace ThreatSource.Indicator
|
||
{
|
||
/// <summary>
|
||
/// 红外测角仪类,实现了红外制导导弹的跟踪和制导功能
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 该类提供了红外测角仪的核心功能:
|
||
/// - 红外目标跟踪
|
||
/// - 角度测量和计算
|
||
/// - 制导指令生成
|
||
/// - 事件处理和状态管理
|
||
/// - 干扰防护处理
|
||
/// 通过测量目标的红外辐射实现对导弹的制导控制
|
||
/// </remarks>
|
||
public class InfraredTracker : BaseIndicator
|
||
{
|
||
/// <summary>
|
||
/// 定义设备支持的干扰类型
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 红外测角仪支持的干扰类型:
|
||
/// - 红外干扰
|
||
/// </remarks>
|
||
public override IEnumerable<JammingType> SupportedJammingTypes => [JammingType.Infrared, JammingType.SmokeGrenade];
|
||
|
||
/// <summary>
|
||
/// 红外测角仪配置参数
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 包含测角仪的工作参数:
|
||
/// - 初始位置和姿态
|
||
/// - 最大跟踪距离
|
||
/// - 视场角等性能参数
|
||
/// </remarks>
|
||
private readonly InfraredTrackerConfig config;
|
||
|
||
/// <summary>
|
||
/// 获取或设置红外测角仪是否正在跟踪目标
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// true表示正在跟踪目标
|
||
/// false表示未在跟踪状态
|
||
/// 用于控制测角仪的工作状态
|
||
/// </remarks>
|
||
public bool IsTracking { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 初始化红外测角仪的新实例
|
||
/// </summary>
|
||
/// <param name="id">测角仪ID</param>
|
||
/// <param name="targetId">目标ID</param>
|
||
/// <param name="config">配置参数</param>
|
||
/// <param name="motionParameters">初始运动参数</param>
|
||
/// <param name="manager">仿真管理器实例</param>
|
||
/// <remarks>
|
||
/// 构造过程:
|
||
/// - 初始化基本属性
|
||
/// - 设置目标关联
|
||
/// - 配置工作参数
|
||
/// - 设置初始状态
|
||
/// </remarks>
|
||
public InfraredTracker(string id, string targetId, InfraredTrackerConfig config, MotionParameters motionParameters, ISimulationManager manager)
|
||
: base(id, motionParameters, manager)
|
||
{
|
||
TargetId = targetId;
|
||
MissileId = null;
|
||
this.config = config;
|
||
IsTracking = false;
|
||
|
||
// 初始化干扰处理
|
||
InitializeJamming(config.JammingResistanceThreshold, SupportedJammingTypes);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新指示器特定功能
|
||
/// </summary>
|
||
/// <param name="deltaTime">时间步长,单位:秒</param>
|
||
/// <remarks>
|
||
/// 实现红外测角仪特定的更新逻辑:
|
||
/// - 基类 Update 会检查 IsJammed (电子干扰)
|
||
/// - UpdateTracking 方法内部会处理 IsTargetObscured (烟幕遮挡)
|
||
/// - 更新跟踪状态
|
||
/// </remarks>
|
||
protected override void UpdateIndicator(double deltaTime)
|
||
{
|
||
// 基类 Update 已经检查了 IsJammed
|
||
// if (IsJammed)
|
||
// {
|
||
// StopTracking(); // Logic moved to HandleJammingApplied
|
||
// Console.WriteLine($"InfraredTracker {Id} 受到红外干扰,停止跟踪。");
|
||
// return;
|
||
// }
|
||
|
||
// 无论是否被遮挡,都尝试更新跟踪状态
|
||
// IsTargetObscured is handled within UpdateTracking
|
||
UpdateTracking();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新跟踪状态
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 跟踪过程:
|
||
/// - 获取目标和导弹实体
|
||
/// - 如果被遮挡,使用最后已知目标位置;否则获取当前位置
|
||
/// - 计算相对位置和距离
|
||
/// - 检查跟踪条件
|
||
/// - 生成制导指令
|
||
/// </remarks>
|
||
private void UpdateTracking()
|
||
{
|
||
if (MissileId == null)
|
||
{
|
||
IsTracking = false;
|
||
return; // 没有导弹需要制导
|
||
}
|
||
|
||
var missile = SimulationManager.GetEntityById(MissileId);
|
||
if (missile is not InfraredCommandGuidedMissile missileElement)
|
||
{
|
||
StopTracking(); // 导弹无效
|
||
return;
|
||
}
|
||
|
||
Vector3D currentTargetPosition;
|
||
|
||
if (IsTargetObscured)
|
||
{
|
||
// 目标被遮挡,尝试使用最后已知位置
|
||
if (_lastKnownTargetPosition != null)
|
||
{
|
||
currentTargetPosition = _lastKnownTargetPosition;
|
||
Console.WriteLine($"InfraredTracker {Id}: 目标被遮挡,使用最后已知位置 {currentTargetPosition}");
|
||
}
|
||
else
|
||
{
|
||
// 没有最后已知位置 (例如首次观测前就被遮挡)
|
||
StopTracking();
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 目标未被遮挡,获取当前目标状态
|
||
if (string.IsNullOrEmpty(TargetId))
|
||
{
|
||
// 没有目标ID,无法跟踪
|
||
StopTracking();
|
||
return;
|
||
}
|
||
var target = SimulationManager.GetEntityById(TargetId);
|
||
if (target is not SimulationElement targetElement)
|
||
{
|
||
// 目标无效
|
||
StopTracking();
|
||
return;
|
||
}
|
||
currentTargetPosition = targetElement.Position;
|
||
}
|
||
|
||
IsTracking = true;
|
||
|
||
// 计算导弹到测角仪的距离
|
||
double distanceToMissile = Vector3D.Distance(Position, missileElement.Position);
|
||
|
||
// 检查导弹是否在跟踪范围内
|
||
if (distanceToMissile <= config.MaxTrackingRange)
|
||
{
|
||
// 计算测角仪到导弹的向量
|
||
Vector3D trackerToMissile = missileElement.Position - Position;
|
||
// 计算测角仪到目标的向量 (使用确定的目标位置)
|
||
Vector3D trackerToTarget = currentTargetPosition - Position;
|
||
|
||
// 发送制导指令事件
|
||
PublishGuidanceCommandEvent(missileElement.Id, trackerToMissile, trackerToTarget, Id);
|
||
}
|
||
else
|
||
{
|
||
// 导弹超出跟踪范围,停止跟踪
|
||
StopTracking();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止跟踪目标
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 停止过程:
|
||
/// - 清除导弹关联
|
||
/// - 重置跟踪状态
|
||
/// (不再清除 TargetId)
|
||
/// </remarks>
|
||
public void StopTracking()
|
||
{
|
||
if (!IsTracking && MissileId == null) return; // 避免重复操作和日志
|
||
MissileId = null;
|
||
IsTracking = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布制导指令事件
|
||
/// </summary>
|
||
/// <param name="missileId">导弹ID</param>
|
||
/// <param name="trackerToMissileVector">测角仪到导弹的向量</param>
|
||
/// <param name="trackerToTargetVector">测角仪到目标的向量</param>
|
||
/// <param name="senderId">发送者ID</param>
|
||
/// <remarks>
|
||
/// 发布过程:
|
||
/// - 创建制导指令事件
|
||
/// - 设置事件参数
|
||
/// - 发布到事件系统
|
||
/// </remarks>
|
||
private void PublishGuidanceCommandEvent(string missileId, Vector3D trackerToMissileVector, Vector3D trackerToTargetVector, string senderId)
|
||
{
|
||
var evt = new InfraredGuidanceCommandEvent
|
||
{
|
||
TargetMissileId = missileId,
|
||
TrackerToMissileVector = trackerToMissileVector,
|
||
TrackerToTargetVector = trackerToTargetVector,
|
||
SenderId = senderId
|
||
};
|
||
SimulationManager.PublishEvent(evt);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理红外指令制导导弹点亮红外热源事件
|
||
/// </summary>
|
||
/// <param name="evt">红外热源点亮事件数据</param>
|
||
/// <remarks>
|
||
/// 处理过程:
|
||
/// - 记录导弹ID
|
||
/// - 准备开始跟踪
|
||
/// </remarks>
|
||
private void OnInfraredGuidanceMissileLight(InfraredGuidanceMissileLightEvent evt)
|
||
{
|
||
// 处理导弹点亮红外热源事件
|
||
MissileId = evt.SenderId ?? "";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理红外指令制导导弹熄灭红外热源事件
|
||
/// </summary>
|
||
/// <param name="evt">红外热源熄灭事件数据</param>
|
||
/// <remarks>
|
||
/// 处理过程:
|
||
/// - 验证导弹ID
|
||
/// - 停止跟踪
|
||
/// </remarks>
|
||
private void OnInfraredGuidanceMissileLightOff(InfraredGuidanceMissileLightOffEvent evt)
|
||
{
|
||
// 处理导弹熄灭红外热源事件
|
||
if (evt.SenderId == MissileId) StopTracking();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活红外测角仪
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 激活过程:
|
||
/// - 调用基类激活方法
|
||
/// - 订阅红外事件
|
||
/// - 准备开始工作
|
||
/// </remarks>
|
||
public override void Activate()
|
||
{
|
||
if (!IsActive)
|
||
{
|
||
base.Activate(); // Handles IsActive and subscribes HandleJammingEvent
|
||
// Removed JammingEvent subscriptions for OnInfraredJamming and HandleSmokeEvent
|
||
|
||
// Subscribe to missile-specific events (KEEP THESE)
|
||
SimulationManager.SubscribeToEvent<InfraredGuidanceMissileLightEvent>(OnInfraredGuidanceMissileLight);
|
||
SimulationManager.SubscribeToEvent<InfraredGuidanceMissileLightOffEvent>(OnInfraredGuidanceMissileLightOff);
|
||
|
||
// 子类特定的激活逻辑
|
||
Debug.WriteLine($"红外测角仪 {Id} 已激活");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停用红外测角仪
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 停用过程:
|
||
/// - 调用基类停用方法
|
||
/// - 取消事件订阅
|
||
/// - 清理工作状态
|
||
/// </remarks>
|
||
public override void Deactivate()
|
||
{
|
||
if (IsActive)
|
||
{
|
||
// 子类特定的停用逻辑
|
||
StopTracking(); // 停止跟踪
|
||
|
||
// Unsubscribe from missile-specific events (KEEP THESE)
|
||
SimulationManager.UnsubscribeFromEvent<InfraredGuidanceMissileLightEvent>(OnInfraredGuidanceMissileLight);
|
||
SimulationManager.UnsubscribeFromEvent<InfraredGuidanceMissileLightOffEvent>(OnInfraredGuidanceMissileLightOff);
|
||
|
||
// Removed JammingEvent subscriptions for OnInfraredJamming and HandleSmokeEvent
|
||
Debug.WriteLine($"红外测角仪 {Id} 已停用");
|
||
base.Deactivate(); // Handles IsActive and unsubscribes HandleJammingEvent
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断是否应该处理传入的干扰参数
|
||
/// </summary>
|
||
/// <param name="parameters">干扰参数</param>
|
||
/// <returns>如果应该处理则返回 true,否则返回 false</returns>
|
||
protected override bool ShouldHandleJamming(JammingParameters parameters)
|
||
{
|
||
// 首先调用基类检查是否支持该干扰类型 (包括 SmokeScreen)
|
||
if (!base.ShouldHandleJamming(parameters))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 对红外干扰添加波长检查
|
||
if (parameters.Type == JammingType.Infrared)
|
||
{
|
||
double wavelength = parameters.Wavelength ?? 0;
|
||
// 检查波长是否在中波红外 (3-5 微米) 或长波红外 (8-12 微米) 范围内
|
||
bool isCompatible = (wavelength >= 3 && wavelength <= 5) || (wavelength >= 8 && wavelength <= 12);
|
||
|
||
if (!isCompatible)
|
||
{
|
||
Debug.WriteLine($"[InfraredTracker] {Id} 忽略红外干扰:波长 {wavelength}um 不在兼容范围 (3-5um 或 8-12um) 内。", "Jamming");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 如果是支持的非红外干扰 (例如烟幕) 或通过了红外波长检查,则返回 true
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取红外测角仪运行状态
|
||
/// </summary>
|
||
/// <returns>包含测角仪完整状态信息的结构体</returns>
|
||
/// <remarks>
|
||
/// 返回信息包括:
|
||
/// - 目标和导弹关联状态
|
||
/// - 工作类型和状态
|
||
/// - 位置和姿态信息
|
||
/// - 激活状态
|
||
/// - 干扰状态 (包括电子干扰和烟幕遮挡)
|
||
/// </remarks>
|
||
public override IndicatorRunningState GetRunningState()
|
||
{
|
||
return new IndicatorRunningState
|
||
{
|
||
TargetId = TargetId ?? "",
|
||
MissileId = MissileId ?? "",
|
||
Type = IndicatorType.InfraredTracker,
|
||
State = IsTracking ? IndicatorState.Indicating : IndicatorState.Idle,
|
||
Position = Position,
|
||
Orientation = Orientation,
|
||
IsActive = IsActive,
|
||
JammingState = (IsJammed || IsTargetObscured) ? JammingState.Jammed : JammingState.Normal
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取红外测角仪状态信息
|
||
/// </summary>
|
||
/// <returns>包含测角仪状态的详细描述</returns>
|
||
/// <remarks>
|
||
/// 返回信息包括:
|
||
/// - 基本标识信息
|
||
/// - 位置信息
|
||
/// - 目标关联状态
|
||
/// - 工作状态
|
||
/// - 跟踪状态
|
||
/// - 干扰/遮挡状态
|
||
/// </remarks>
|
||
public override string GetStatus()
|
||
{
|
||
string jammingStatusString = "正常";
|
||
if (IsJammed) jammingStatusString = "受红外干扰";
|
||
if (IsTargetObscured) jammingStatusString = IsJammed ? "受红外干扰和烟幕遮挡" : "目标被烟幕遮挡";
|
||
|
||
return base.GetStatus() + "\n" +
|
||
$" 位置: {Position}\n" +
|
||
$" 跟踪导弹: {MissileId ?? "无"}\n" +
|
||
$" 目标: {TargetId ?? "无"}\n" +
|
||
$" 状态: {(IsActive ? "活动" : "已销毁")}\n" +
|
||
$" 跟踪状态: {(IsTracking ? "跟踪中" : "未跟踪")}\n" +
|
||
$" 干扰/遮挡状态: {jammingStatusString}\n";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理指示器被干扰的事件
|
||
/// </summary>
|
||
/// <param name="parameters">干扰参数</param>
|
||
protected override void HandleJammingApplied(JammingParameters parameters)
|
||
{
|
||
base.HandleJammingApplied(parameters); // Calls RecalculateObscurationStatus for smoke
|
||
|
||
// 添加子类特定响应:如果是红外干扰,停止跟踪
|
||
if (parameters.Type == JammingType.Infrared)
|
||
{
|
||
Debug.WriteLine($"[InfraredTracker] {Id} 受到红外干扰,停止跟踪。", "Jamming");
|
||
StopTracking();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理指示器干扰被清除的事件
|
||
/// </summary>
|
||
/// <param name="parameters">干扰参数</param>
|
||
protected override void HandleJammingCleared(JammingParameters parameters)
|
||
{
|
||
base.HandleJammingCleared(parameters); // Calls RecalculateObscurationStatus for smoke
|
||
|
||
// 红外干扰清除后,不需要特殊操作,UpdateIndicator 会重新评估跟踪状态
|
||
if (parameters.Type == JammingType.Infrared)
|
||
{
|
||
Debug.WriteLine($"[InfraredTracker] {Id} 红外干扰已清除。", "Jamming");
|
||
}
|
||
}
|
||
}
|
||
}
|