504 lines
17 KiB
C#
504 lines
17 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using ActiveProtect.SimulationEnvironment;
|
||
using Model;
|
||
|
||
namespace ActiveProtect.Models
|
||
{
|
||
/// <summary>
|
||
/// 表示仿真中的导弹
|
||
/// </summary>
|
||
public class MissileBase : SimulationElement
|
||
{
|
||
/// <summary>
|
||
/// 导弹类型
|
||
/// </summary>
|
||
public MissileType Type { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前速度(米/秒)
|
||
/// </summary>
|
||
public double Speed { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 最大速度(米/秒)
|
||
/// </summary>
|
||
public double MaxSpeed { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 目标ID
|
||
/// </summary>
|
||
public string TargetId { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 最大飞行时间(秒)
|
||
/// </summary>
|
||
public double MaxFlightTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 最大飞行距离(米)
|
||
/// </summary>
|
||
public double MaxFlightDistance { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行时间(秒)
|
||
/// </summary>
|
||
public double FlightTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行距离(米)
|
||
/// </summary>
|
||
public double FlightDistance { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 与目标的距离(米)
|
||
/// </summary>
|
||
public double DistanceToTarget { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 导弹距离参数
|
||
/// </summary>
|
||
public MissileDistanceParams DistanceParams { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 上一帧目标位置
|
||
/// </summary>
|
||
private Vector3D LastTargetPosition;
|
||
|
||
/// <summary>
|
||
/// 比例导引系数
|
||
/// </summary>
|
||
private const double N = 3;
|
||
|
||
/// <summary>
|
||
/// 推力加速度(米/秒²)
|
||
/// </summary>
|
||
public double LaunchAcceleration { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前发动机燃烧时间(秒)
|
||
/// </summary>
|
||
public double EngineBurnTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 最大发动机燃烧时间(秒)
|
||
/// </summary>
|
||
public double MaxEngineBurnTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 最大加速度(米/秒²)
|
||
/// </summary>
|
||
public double MaxAcceleration { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 比例导引系数
|
||
/// </summary>
|
||
public double ProportionalNavigationCoefficient { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否有制导
|
||
/// </summary>
|
||
public bool HasGuidance { get; protected set; } = false;
|
||
|
||
/// <summary>
|
||
/// 失去制导的时间(秒)
|
||
/// </summary>
|
||
protected double LostGuidanceTime { get; set; } = 0;
|
||
|
||
/// <summary>
|
||
/// 最后已知的速度向量
|
||
/// </summary>
|
||
protected Vector3D LastKnownVelocity = Vector3D.Zero;
|
||
|
||
/// <summary>
|
||
/// 发射速度(米/秒)
|
||
/// </summary>
|
||
public const double LAUNCH_SPEED = 10;
|
||
|
||
/// <summary>
|
||
/// 导弹质量(千克)
|
||
/// </summary>
|
||
public double Mass { get; protected set; } = 100;
|
||
|
||
/// <summary>
|
||
/// 制导加速度
|
||
/// </summary>
|
||
protected Vector3D GuidanceAcceleration { get; set; }
|
||
|
||
/// <summary>
|
||
/// 推力加速度
|
||
/// </summary>
|
||
protected Vector3D ThrustAcceleration { get; set; }
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
public MissileBase(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
|
||
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, missileConfig.InitialSpeed, simulationManager)
|
||
{
|
||
// 初始化导弹属性
|
||
Speed = missileConfig.InitialSpeed;
|
||
MaxSpeed = missileConfig.MaxSpeed;
|
||
MaxFlightTime = missileConfig.MaxFlightTime;
|
||
MaxFlightDistance = missileConfig.MaxFlightDistance;
|
||
DistanceParams = missileConfig.DistanceParams;
|
||
IsActive = false;
|
||
FlightTime = 0;
|
||
FlightDistance = 0;
|
||
SimulationManager = simulationManager;
|
||
LaunchAcceleration = missileConfig.LaunchAcceleration;
|
||
EngineBurnTime = 0;
|
||
MaxEngineBurnTime = missileConfig.MaxEngineBurnTime;
|
||
MaxAcceleration = missileConfig.MaxAcceleration;
|
||
ProportionalNavigationCoefficient = missileConfig.ProportionalNavigationCoefficient;
|
||
TargetId = $"Tank_{missileConfig.TargetIndex + 1}";
|
||
GuidanceAcceleration = Vector3D.Zero;
|
||
ThrustAcceleration = Vector3D.Zero;
|
||
LastTargetPosition = Vector3D.Zero;
|
||
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新导弹状态
|
||
/// </summary>
|
||
public override void Update(double deltaTime)
|
||
{
|
||
if (!IsActive) return;
|
||
|
||
if (ShouldSelfDestruct())
|
||
{
|
||
SelfDestruct();
|
||
return;
|
||
}
|
||
|
||
|
||
UpdateMotionState(deltaTime);
|
||
|
||
if (CheckHit())
|
||
{
|
||
Explode();
|
||
return;
|
||
}
|
||
}
|
||
|
||
protected virtual void UpdateMotionState(double deltaTime)
|
||
{
|
||
|
||
//Vector3D acceleration = CalculateAcceleration(Velocity);
|
||
|
||
Vector3D acceleration = GuidanceAcceleration;
|
||
|
||
// 使用四阶龙格-库塔方法更新导弹的位置和速度
|
||
(Position, Velocity) = BasicGuidanceSystem.RungeKutta4(deltaTime, Position, Velocity, acceleration);
|
||
|
||
// 限制速度不超过最大速度
|
||
if (Velocity.Magnitude() > MaxSpeed)
|
||
{
|
||
Velocity = Velocity.Normalize() * MaxSpeed;
|
||
}
|
||
|
||
Speed = Velocity.Magnitude();
|
||
Orientation = Orientation.FromVector(Velocity);
|
||
FlightTime += deltaTime;
|
||
FlightDistance += Speed * deltaTime;
|
||
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算导弹的加速度
|
||
/// </summary>
|
||
private Vector3D CalculateAcceleration(Vector3D velocity)
|
||
{
|
||
// Vector3D thrustAcceleration = Vector3D.Zero;
|
||
// Vector3D guidanceAcceleration = Vector3D.Zero;
|
||
|
||
// switch (CurrentStage)
|
||
// {
|
||
// case FlightStage.Launch:
|
||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||
// break;
|
||
// case FlightStage.Acceleration:
|
||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||
// guidanceAcceleration = guidanceCommand;
|
||
// break;
|
||
// case FlightStage.Cruise:
|
||
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
|
||
// guidanceAcceleration = guidanceCommand * 1;
|
||
// break;
|
||
// case FlightStage.TerminalGuidance:
|
||
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
|
||
// guidanceAcceleration = guidanceCommand * 1;
|
||
// break;
|
||
// case FlightStage.Attack:
|
||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration*0.05;
|
||
// guidanceAcceleration = guidanceCommand * 1;
|
||
// break;
|
||
// }
|
||
|
||
// if (!HasGuidance)
|
||
// {
|
||
// if (velocity.Magnitude() > 0)
|
||
// {
|
||
// ThrustAcceleration = LaunchAcceleration * velocity.Normalize();
|
||
// }
|
||
// else
|
||
// {
|
||
// ThrustAcceleration = LaunchAcceleration * velocity.Normalize();
|
||
// }
|
||
// }
|
||
|
||
//计算重力加速度(反坦克导弹一般升力很小, 主要依靠初始发射动能和持续的推力来维持飞行)
|
||
//Vector3D gravityCompensation = new(0, 9.81, 0);
|
||
//Vector3D gravityAcceleration = new(0, -9.81, 0);
|
||
|
||
// 计算空气阻力的影响
|
||
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
|
||
//Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + gravityAcceleration +dragAcceleration;
|
||
//Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration;
|
||
Vector3D totalAcceleration = GuidanceAcceleration;
|
||
|
||
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, 推力加速度: {ThrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
|
||
if (totalAcceleration.Magnitude() > MaxAcceleration)
|
||
{
|
||
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
|
||
}
|
||
|
||
return totalAcceleration;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算空气阻力
|
||
/// </summary>
|
||
private static double CalculateDrag(double speed)
|
||
{
|
||
const double dragCoefficient = 0.1; // 减小阻力系数
|
||
const double airDensity = 1.225; // 海平面空气密度,kg/m^3
|
||
const double referenceArea = 0.01; // 减小导弹的参考面积,m^2
|
||
|
||
return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否命中目标
|
||
/// </summary>
|
||
protected bool CheckHit()
|
||
{
|
||
return DistanceToTarget <= DistanceParams.ExplosionDistance;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否应该自毁
|
||
/// </summary>
|
||
protected bool ShouldSelfDestruct()
|
||
{
|
||
if (FlightTime >= MaxFlightTime)
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
if (FlightDistance >= MaxFlightDistance)
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
if (Position.Y <= -1.0) // 数字略小于0
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新发动机燃烧时间
|
||
/// </summary>
|
||
// private void UpdateEngineBurnTime(double deltaTime)
|
||
// {
|
||
// if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
|
||
// {
|
||
// EngineBurnTime += deltaTime;
|
||
// }
|
||
// }
|
||
|
||
/// <summary>
|
||
/// 计算比例导引加速度
|
||
/// </summary>
|
||
// private Vector3D CalculateProportionalNavigation(Vector3D position)
|
||
// {
|
||
// Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||
// Vector3D LOS = targetPosition - position;
|
||
// Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
|
||
// LastTargetPosition = targetPosition;
|
||
|
||
// return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
|
||
// * ProportionalNavigationCoefficient * Velocity.Magnitude();
|
||
// }
|
||
|
||
/// <summary>
|
||
/// 导弹爆炸
|
||
/// </summary>
|
||
protected virtual void Explode()
|
||
{
|
||
Deactivate();
|
||
SimulationManager.HandleTargetHit(TargetId, Id);
|
||
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导弹自毁
|
||
/// </summary>
|
||
public void SelfDestruct()
|
||
{
|
||
if (IsActive)
|
||
{
|
||
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
|
||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
|
||
Position.Y <= 0 ? "高度小于等于0" :
|
||
!HasGuidance ? "失去引导" : "未知原因";
|
||
|
||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||
Deactivate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置比例导引系数
|
||
/// </summary>
|
||
public void SetProportionalNavigationCoefficient(double newCoefficient)
|
||
{
|
||
ProportionalNavigationCoefficient = newCoefficient;
|
||
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取导弹状态
|
||
/// </summary>
|
||
public override string GetStatus()
|
||
{
|
||
MissileRunningState missileRunningState = GetState();
|
||
return $"导弹 {missileRunningState.Id}:\n" +
|
||
$" 位置: {missileRunningState.Position}\n" +
|
||
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
|
||
$" 速度分量: {missileRunningState.Velocity}\n" +
|
||
$" 朝向: {missileRunningState.Orientation}\n" +
|
||
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MaxFlightTime:F2}\n" +
|
||
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
|
||
$" 距离目标: {missileRunningState.DistanceToTarget:F2}\n" +
|
||
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
|
||
$" 有引导: {(missileRunningState.HasGuidance ? "是" : "否")}\n" +
|
||
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新导弹的制导状态
|
||
/// </summary>
|
||
protected virtual void UpdateGuidanceStatus()
|
||
{
|
||
// 基类中的默认实现
|
||
}
|
||
|
||
public MissileRunningState GetState()
|
||
{
|
||
return new MissileRunningState
|
||
{
|
||
Id = Id,
|
||
Type = Type,
|
||
Position = Position,
|
||
Velocity = Velocity,
|
||
Orientation = Orientation,
|
||
Speed = Speed,
|
||
TargetId = TargetId,
|
||
FlightTime = FlightTime,
|
||
FlightDistance = FlightDistance,
|
||
DistanceToTarget = DistanceToTarget,
|
||
//CurrentStage = CurrentStage,
|
||
HasGuidance = HasGuidance,
|
||
LostGuidanceTime = LostGuidanceTime,
|
||
EngineBurnTime = EngineBurnTime,
|
||
IsActive = IsActive
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表示导弹的运行状态信息
|
||
/// </summary>
|
||
public struct MissileRunningState
|
||
{
|
||
/// <summary>
|
||
/// 导弹ID
|
||
/// </summary>
|
||
public string Id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导弹类型
|
||
/// </summary>
|
||
public MissileType Type { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前位置
|
||
/// </summary>
|
||
public Vector3D Position { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前速度向量
|
||
/// </summary>
|
||
public Vector3D Velocity { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前朝向
|
||
/// </summary>
|
||
public Orientation Orientation { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前速度(米/秒)
|
||
/// </summary>
|
||
public double Speed { get; set; }
|
||
|
||
/// <summary>
|
||
/// 目标ID
|
||
/// </summary>
|
||
public string TargetId { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行时间(秒)
|
||
/// </summary>
|
||
public double FlightTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行距离(米)
|
||
/// </summary>
|
||
public double FlightDistance { get; set; }
|
||
|
||
/// <summary>
|
||
/// 与目标的距离(米)
|
||
/// </summary>
|
||
public double DistanceToTarget { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行阶段
|
||
/// </summary>
|
||
//public FlightStage CurrentStage { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否有制导
|
||
/// </summary>
|
||
public bool HasGuidance { get; set; }
|
||
|
||
/// <summary>
|
||
/// 失去制导时间(秒)
|
||
/// </summary>
|
||
public double LostGuidanceTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前发动机燃烧时间(秒)
|
||
/// </summary>
|
||
public double EngineBurnTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否处于活动状态
|
||
/// </summary>
|
||
public bool IsActive { get; set; }
|
||
}
|
||
}
|