ThreatSourceLibaray/ThreatSource/src/MIssile/BaseMissile.cs

611 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Diagnostics;
using ThreatSource.Simulation;
using ThreatSource.Utils;
using System.Reflection;
namespace ThreatSource.Missile
{
/// <summary>
/// 导弹基类,实现了导弹的基本功能和状态管理
/// </summary>
/// <remarks>
/// 该类提供了导弹的核心功能:
/// - 运动状态计算和更新
/// - 制导系统管理
/// - 发动机控制
/// - 自毁和爆炸处理
/// - 状态监控和事件处理
/// 所有具体的导弹类型都继承自此基类
/// </remarks>
public class BaseMissile : SimulationElement, IMissile
{
/// <summary>
/// 获取导弹的当前飞行时间
/// </summary>
/// <value>飞行时间,单位:秒</value>
/// <remarks>
/// 从发射时刻开始计时
/// 用于控制导弹的生命周期
/// </remarks>
public double FlightTime { get; protected set; }
/// <summary>
/// 获取导弹的当前飞行距离
/// </summary>
/// <value>飞行距离,单位:米</value>
/// <remarks>
/// 从发射点到当前位置的累计飞行距离
/// 用于判断是否超出最大射程
/// </remarks>
public double FlightDistance { get; protected set; }
/// <summary>
/// 获取发动机的当前燃烧时间
/// </summary>
/// <value>发动机燃烧时间,单位:秒</value>
/// <remarks>
/// 发动机工作的累计时间
/// 用于控制推力变化和燃料消耗
/// </remarks>
public double EngineBurnTime { get; protected set; }
/// <summary>
/// 获取导弹是否处于制导状态
/// </summary>
/// <value>true表示导弹当前在制导false表示导弹处于非制导状态</value>
/// <remarks>
/// 影响导弹的运动学计算方法
/// 制导状态下使用制导律计算加速度
/// 非制导状态下使用弹道方程计算运动
/// </remarks>
public bool IsGuidance { get; protected set; }
/// <summary>
/// 获取或设置导弹失去制导的持续时间
/// </summary>
/// <value>失去制导的时间,单位:秒</value>
/// <remarks>
/// 用于判断是否需要触发自毁
/// 超过阈值时可能导致导弹自毁
/// </remarks>
protected double LostGuidanceTime { get; set; } = 0;
/// <summary>
/// 获取或设置导弹的最后已知速度向量
/// </summary>
/// <value>三维速度向量</value>
/// <remarks>
/// 用于在失去制导时保持导弹的运动状态
/// 作为弹道计算的参考数据
/// </remarks>
protected Vector3D LastKnownVelocity = Vector3D.Zero;
/// <summary>
/// 获取或设置导弹的制导加速度
/// </summary>
/// <value>三维加速度向量,单位:米/秒²</value>
/// <remarks>
/// 由制导系统计算得出的期望加速度
/// 用于修正导弹的飞行路径
/// </remarks>
protected Vector3D GuidanceAcceleration { get; set; } = Vector3D.Zero;
/// <summary>
/// 获取或设置导弹的推力加速度
/// </summary>
/// <value>三维加速度向量,单位:米/秒²</value>
/// <remarks>
/// 由发动机产生的推进加速度
/// 影响导弹的速度变化
/// </remarks>
protected Vector3D ThrustAcceleration { get; set; }
/// <summary>
/// 获取或设置导弹的升力加速度
/// </summary>
/// <value>三维加速度向量,单位:米/秒²</value>
/// <remarks>
/// 由升力产生的加速度
/// 影响导弹的垂直运动
/// </remarks>
protected Vector3D LiftAcceleration { get; set; }
/// <summary>
/// 重力加速度(北京标准值)
/// </summary>
private static readonly Vector3D GravityAcceleration = new(0, -PhysicalConstants.BeijingGravity, 0);
/// <summary>
/// 获取导弹的固定配置参数
/// </summary>
/// <value>导弹属性配置对象</value>
/// <remarks>
/// 包含导弹的所有基本属性和性能限制
/// 在导弹创建时设置,运行期间保持不变
/// </remarks>
public readonly MissileProperties Properties;
/// <summary>
/// 标准导弹三段式飞行阶段
/// </summary>
public enum MissileFlightStage
{
/// <summary>
/// 发射阶段
/// </summary>
Launch,
/// <summary>
/// 巡航阶段
/// </summary>
Cruise,
/// <summary>
/// 制导阶段
/// </summary>
Guidance
}
/// <summary>
/// 当前飞行阶段
/// </summary>
protected MissileFlightStage currentStage = MissileFlightStage.Launch;
/// <summary>
/// 初始化导弹基类的新实例
/// </summary>
/// <param name="missileId">导弹ID</param>
/// <param name="properties">导弹属性配置</param>
/// <param name="kinematicState">发射参数</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
/// 构造过程:
/// - 初始化基本属性
/// - 设置性能限制
/// - 配置运动参数
/// - 建立仿真管理器关联
/// </remarks>
protected BaseMissile(
string missileId,
MissileProperties properties,
KinematicState kinematicState,
ISimulationManager manager)
: base(missileId, kinematicState, manager)
{
// 设置性能限制
Properties = properties;
// 初始化状态
EngineBurnTime = 0;
FlightTime = 0;
FlightDistance = 0;
IsActive = false;
IsGuidance = false;
GuidanceAcceleration = Vector3D.Zero;
LiftAcceleration = Vector3D.Zero;
// 计算初始推力加速度
Vector3D launchDirection = kinematicState.Orientation.ToVector().Normalize();
ThrustAcceleration = launchDirection * properties.LaunchAcceleration;
}
/// <summary>
/// 判断是否为末敏弹类型
/// </summary>
protected bool IsTerminalSensitiveType()
{
return Properties.Type == MissileType.TerminalSensitiveSubmunition;
}
/// <summary>
/// 供末敏弹等特殊导弹重写的自定义阶段更新方法
/// </summary>
protected virtual void UpdateCustomStages(double deltaTime) { }
/// <summary>
/// 更新导弹的状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 检查导弹是否处于活动状态
/// - 更新导弹的运动状态
/// - 更新计时器和计数器
/// </remarks>
public override void Update(double deltaTime)
{
if (!IsActive) return;
// 末敏弹等特殊类型走自定义流程
if (!IsTerminalSensitiveType())
{
// 标准三段式流程
switch (currentStage)
{
case MissileFlightStage.Launch:
OnLaunchStage(deltaTime);
break;
case MissileFlightStage.Cruise:
OnCruiseStage(deltaTime);
break;
case MissileFlightStage.Guidance:
OnGuidanceStage(deltaTime);
break;
}
}
// 公共运动学与生命周期管理
UpdateMotionState(deltaTime);
if (ShouldSelfDestruct())
{
SelfDestruct();
}
}
/// <summary>
/// 发射阶段默认实现
/// </summary>
protected virtual void OnLaunchStage(double deltaTime)
{
// 发射阶段不使用制导
GuidanceAcceleration = Vector3D.Zero;
// 计算升力加速度。在发射阶段,升力加速度和攻角相关
LiftAcceleration = LiftModel.CalculateLiftAcceleration(KState.Orientation.Pitch * 180 / Math.PI);
// 发射阶段结束,进入巡航阶段
if (FlightTime >= Properties.MaxEngineBurnTime)
{
currentStage = MissileFlightStage.Cruise;
}
}
/// <summary>
/// 巡航阶段默认实现
/// </summary>
protected virtual void OnCruiseStage(double deltaTime)
{
// 巡航阶段不使用制导
GuidanceAcceleration = Vector3D.Zero;
if(KState.Orientation.Pitch > 0)
{
KState.Orientation = new Orientation(KState.Orientation.Yaw, -0.01, KState.Orientation.Roll);
}
// 计算升力加速度。在巡航阶段,升力加速度与重力加速度抵消
LiftAcceleration = new Vector3D(0, PhysicalConstants.BeijingGravity, 0);
// 巡航阶段结束,进入制导阶段
if (FlightTime >= Properties.MaxEngineBurnTime + Properties.CruiseTime)
{
currentStage = MissileFlightStage.Guidance;
}
}
/// <summary>
/// 制导阶段默认实现
/// </summary>
protected virtual void OnGuidanceStage(double deltaTime)
{
// 计算升力加速度。在制导阶段,升力加速度和攻角相关;
LiftAcceleration = LiftModel.CalculateLiftAcceleration(KState.Orientation.Pitch * 180 / Math.PI);
}
/// <summary>
/// 更新导弹的运动状态
/// </summary>
/// <param name="deltaTime">时间步长,单位:秒</param>
/// <remarks>
/// 更新过程:
/// - 计算包含风影响的合加速度
/// - 根据制导状态选择运动更新方法
/// - 更新导弹的位置和速度
/// </remarks>
protected virtual void UpdateMotionState(double deltaTime)
{
// 检查发动机是否仍在提供推力
if (ThrustAcceleration != Vector3D.Zero)
{
EngineBurnTime += deltaTime; // 累加燃烧时间
if (EngineBurnTime >= Properties.MaxEngineBurnTime || KState.Speed >= Properties.MaxSpeed)
{
string reason = EngineBurnTime >= Properties.MaxEngineBurnTime ?
$"达到最大燃烧时间({Properties.MaxEngineBurnTime}s)" :
$"达到最大速度({KState.Speed:F2}m/s >= {Properties.MaxSpeed}m/s)";
Debug.WriteLine($"导弹 {Id}: 发动机推力已于飞行时间 {FlightTime:F2}s 关闭。原因: {reason}");
ThrustAcceleration = Vector3D.Zero; // 关闭推力
}
}
// 计算包含风影响的合加速度
Vector3D acceleration = CalculateAcceleration(KState.Velocity);
if (IsGuidance)
{
// 制导条件下,使用四阶龙格-库塔方法更新导弹的位置和速度
(KState.Position, KState.Velocity) = MotionAlgorithm.RungeKutta4(deltaTime, KState.Position, KState.Velocity, acceleration);
}
else
{
// 无制导条件下,使用运动学方程更新导弹的位置和速度
(KState.Position, KState.Velocity) = MotionAlgorithm.CalculateBallisticMotion(KState.Position, KState.Velocity, acceleration, deltaTime);
}
// 在制导阶段,导弹指向速度方向(便于搜索跟踪)
if(currentStage == MissileFlightStage.Guidance)
{
KState.Orientation = Orientation.FromVector(KState.Velocity);
}
// 限制速度不超过最大速度
if (KState.Speed > Properties.MaxSpeed)
{
KState.Speed = Properties.MaxSpeed;
}
// 添加高斯噪声(测试用,用于测试运动中概率的影响)
// Position = MotionAlgorithm.AddRandomPerturbation(Position);
// Velocity = MotionAlgorithm.AddRandomPerturbation(Velocity);
FlightTime += deltaTime;
FlightDistance += KState.Speed * deltaTime;
}
/// <summary>
/// 计算导弹的合加速度
/// </summary>
/// <param name="velocity">当前速度向量</param>
/// <returns>合加速度向量</returns>
/// <remarks>
/// 计算过程:
/// - 获取当前风速向量
/// - 计算空气阻力加速度(已考虑风)
/// - 合成总加速度(制导加速度 + 推力加速度 + 空气阻力加速度 + 重力加速度)
/// - 限制合加速度不超过最大值
/// </remarks>
private Vector3D CalculateAcceleration(Vector3D velocity)
{
// 获取当前风速向量
Vector3D windVector = GetWindVectorFromWeather();
// 计算空气阻力加速度(考虑风的影响)
Vector3D dragAcceleration = MotionAlgorithm.CalculateDragAcceleration(velocity, windVector, Properties.Mass);
// 合成总加速度(制导加速度 + 推力加速度 + 空气阻力加速度 + 升力加速度 + 重力加速度)
Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration + LiftAcceleration + GravityAcceleration;
Debug.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导: {GuidanceAcceleration}, " +
$"推力: {ThrustAcceleration}, 空阻(含风): {dragAcceleration}, 升力: {LiftAcceleration}, 重力: {GravityAcceleration}");
if (totalAcceleration.Magnitude() > Properties.MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * Properties.MaxAcceleration;
}
return totalAcceleration;
}
/// <summary>
/// 从天气系统获取当前的风速向量
/// </summary>
/// <returns>风速向量,单位:米/秒</returns>
protected Vector3D GetWindVectorFromWeather()
{
var weather = SimulationManager.CurrentWeather;
if (weather == null)
return Vector3D.Zero;
return MotionAlgorithm.CalculateWindVector(weather.WindSpeed, weather.WindDirection);
}
/// <summary>
/// 发射导弹
/// </summary>
/// <remarks>
/// 发射过程:
/// - 开始计时和计数
/// - 启动发动机
/// - 初始化运动状态
/// </remarks>
public virtual void Fire()
{
// 子类可以重写此方法来处理发射时的特殊逻辑
}
/// <summary>
/// 检查是否应该自毁
/// </summary>
/// <returns>true表示需要自毁false表示可以继续飞行</returns>
/// <remarks>
/// 自毁条件:
/// - 超出最大飞行时间
/// - 超出最大飞行距离
/// - 有制导时:高度低于负爆炸半径(考虑仿真步长)
/// - 无制导时:高度低于安全阈值
/// </remarks>
protected bool ShouldSelfDestruct()
{
// 基本条件判断
if (FlightTime >= Properties.MaxFlightTime
|| FlightDistance >= Properties.MaxFlightDistance)
{
return true;
}
// 根据制导状态判断自毁高度
if (IsGuidance)
{
// 有制导时,在负爆炸半径高度自毁(考虑仿真步长)
return KState.Position.Y <= -Properties.ExplosionRadius;
}
else
{
// 无制导时,在自毁高度自毁
return KState.Position.Y <= Properties.SelfDestructHeight;
}
}
/// <summary>
/// 导弹爆炸
/// </summary>
/// <remarks>
/// 爆炸过程:
/// - 停止导弹运动
/// - 触发爆炸效果
/// - 发布爆炸事件
/// - 结束导弹任务
/// </remarks>
public virtual void Explode()
{
OnExplode();
Deactivate();
}
/// <summary>
/// 爆炸后处理
/// </summary>
/// <remarks>
/// 爆炸后处理:
/// - 设置导弹状态为非活动
/// - 触发爆炸事件
/// </remarks>
protected virtual void OnExplode()
{
// 子类可以重写此方法来处理爆炸时的特殊逻辑
}
/// <summary>
/// 导弹自毁
/// </summary>
/// <remarks>
/// 自毁过程:
/// - 记录自毁原因
/// - 停止导弹运动
/// - 触发自毁效果
/// - 结束导弹任务
/// </remarks>
public void SelfDestruct()
{
string reason;
if (FlightTime >= Properties.MaxFlightTime)
{
reason = "超出最大飞行时间";
}
else if (FlightDistance >= Properties.MaxFlightDistance)
{
reason = "超出最大飞行距离";
}
else if (IsGuidance && KState.Position.Y <= -Properties.ExplosionRadius)
{
reason = "有制导状态下高度低于负爆炸半径";
}
else if (!IsGuidance && KState.Position.Y <= Properties.SelfDestructHeight)
{
reason = "无制导状态下高度低于自毁高度";
}
else
{
reason = "未知原因触发自毁";
}
Trace.TraceInformation($"导弹 {Id} 自毁。原因: {reason}");
OnSelfDestruct();
Deactivate();
}
/// <summary>
/// 自毁后处理
/// </summary>
/// <remarks>
/// 自毁后处理:
/// - 设置导弹状态为非活动
/// - 触发自毁事件
/// </remarks>
protected virtual void OnSelfDestruct()
{
// 子类可以重写此方法来处理自毁时的特殊逻辑
}
/// <summary>
/// 激活导弹
/// </summary>
/// <remarks>
/// 激活过程:
/// - 调用基类激活方法
/// - 订阅目标命中事件
/// </remarks>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<TargetHitEvent>(OnTargetHitEvent);
}
/// <summary>
/// 停用导弹
/// </summary>
/// <remarks>
/// 停用过程:
/// - 调用基类停用方法
/// - 取消订阅目标命中事件
/// </remarks>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<TargetHitEvent>(OnTargetHitEvent);
}
private void OnTargetHitEvent(TargetHitEvent eventData)
{
if (eventData.MissileId == Id)
{
Explode();
}
}
/// <summary>
/// 获取导弹状态信息
/// </summary>
/// <returns>导弹状态信息</returns>
/// <remarks>
/// 返回信息包括:
/// - 基本状态信息
/// - 导弹固有属性
/// - 导弹运行时状态
/// </remarks>
public override ElementStatusInfo GetStatusInfo()
{
// 获取基础状态信息
var statusInfo = base.GetStatusInfo();
// 使用反射动态添加来自 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)
{
object? propValue = prop.GetValue(Properties);
if (propValue != null)
{
statusInfo.ExtendedProperties[prop.Name] = propValue;
}
}
}
}
// 添加 BaseMissile 类的运行时状态参数
statusInfo.ExtendedProperties["FlightTime"] = FlightTime;
statusInfo.ExtendedProperties["FlightDistance"] = FlightDistance;
statusInfo.ExtendedProperties["EngineBurnTime"] = EngineBurnTime;
statusInfo.ExtendedProperties["CurrentStage"] = currentStage.ToString();
statusInfo.ExtendedProperties["IsGuidance"] = IsGuidance;
statusInfo.ExtendedProperties["LostGuidanceTime"] = LostGuidanceTime;
statusInfo.ExtendedProperties["GuidanceAcceleration"] = GuidanceAcceleration;
return statusInfo;
}
}
}