611 lines
22 KiB
C#
611 lines
22 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|