using System; using System.Collections.Generic; using ActiveProtect.SimulationEnvironment; using Model; namespace ActiveProtect.Models { /// /// 表示仿真中的导弹 /// public class MissileBase : SimulationElement { /// /// 导弹类型 /// public MissileType Type { get; protected set; } /// /// 当前速度(米/秒) /// public double Speed { get; protected set; } /// /// 最大速度(米/秒) /// public double MaxSpeed { get; protected set; } /// /// 目标ID /// public string TargetId { get; protected set; } /// /// 最大飞行时间(秒) /// public double MaxFlightTime { get; protected set; } /// /// 最大飞行距离(米) /// public double MaxFlightDistance { get; protected set; } /// /// 当前飞行时间(秒) /// public double FlightTime { get; protected set; } /// /// 当前飞行距离(米) /// public double FlightDistance { get; protected set; } /// /// 与目标的距离(米) /// public double DistanceToTarget { get; protected set; } /// /// 导弹距离参数 /// public MissileDistanceParams DistanceParams { get; protected set; } /// /// 上一帧目标位置 /// private Vector3D LastTargetPosition; /// /// 比例导引系数 /// private const double N = 3; /// /// 推力加速度(米/秒²) /// public double LaunchAcceleration { get; protected set; } /// /// 当前发动机燃烧时间(秒) /// public double EngineBurnTime { get; protected set; } /// /// 最大发动机燃烧时间(秒) /// public double MaxEngineBurnTime { get; protected set; } /// /// 最大加速度(米/秒²) /// public double MaxAcceleration { get; protected set; } /// /// 比例导引系数 /// public double ProportionalNavigationCoefficient { get; set; } /// /// 是否有制导 /// public bool HasGuidance { get; protected set; } = false; /// /// 失去制导的时间(秒) /// protected double LostGuidanceTime { get; set; } = 0; /// /// 最后已知的速度向量 /// protected Vector3D LastKnownVelocity = Vector3D.Zero; /// /// 发射速度(米/秒) /// public const double LAUNCH_SPEED = 10; /// /// 导弹质量(千克) /// public double Mass { get; protected set; } = 100; /// /// 制导加速度 /// protected Vector3D GuidanceAcceleration { get; set; } /// /// 推力加速度 /// protected Vector3D ThrustAcceleration { get; set; } /// /// 构造函数 /// 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); } /// /// 更新导弹状态 /// 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); } /// /// 计算导弹的加速度 /// 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; } /// /// 计算空气阻力 /// 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; } /// /// 检查是否命中目标 /// protected bool CheckHit() { return DistanceToTarget <= DistanceParams.ExplosionDistance; } /// /// 检查是否应该自毁 /// 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; } /// /// 更新发动机燃烧时间 /// // private void UpdateEngineBurnTime(double deltaTime) // { // if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime) // { // EngineBurnTime += deltaTime; // } // } /// /// 计算比例导引加速度 /// // 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(); // } /// /// 导弹爆炸 /// protected virtual void Explode() { Deactivate(); SimulationManager.HandleTargetHit(TargetId, Id); Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!"); } /// /// 导弹自毁 /// public void SelfDestruct() { if (IsActive) { string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" : FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" : Position.Y <= 0 ? "高度小于等于0" : !HasGuidance ? "失去引导" : "未知原因"; Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}"); Deactivate(); } } /// /// 设置比例导引系数 /// public void SetProportionalNavigationCoefficient(double newCoefficient) { ProportionalNavigationCoefficient = newCoefficient; Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}"); } /// /// 获取导弹状态 /// 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}"; } /// /// 更新导弹的制导状态 /// 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 }; } } /// /// 表示导弹的运行状态信息 /// public struct MissileRunningState { /// /// 导弹ID /// public string Id { get; set; } /// /// 导弹类型 /// public MissileType Type { get; set; } /// /// 当前位置 /// public Vector3D Position { get; set; } /// /// 当前速度向量 /// public Vector3D Velocity { get; set; } /// /// 当前朝向 /// public Orientation Orientation { get; set; } /// /// 当前速度(米/秒) /// public double Speed { get; set; } /// /// 目标ID /// public string TargetId { get; set; } /// /// 当前飞行时间(秒) /// public double FlightTime { get; set; } /// /// 当前飞行距离(米) /// public double FlightDistance { get; set; } /// /// 与目标的距离(米) /// public double DistanceToTarget { get; set; } /// /// 当前飞行阶段 /// //public FlightStage CurrentStage { get; set; } /// /// 是否有制导 /// public bool HasGuidance { get; set; } /// /// 失去制导时间(秒) /// public double LostGuidanceTime { get; set; } /// /// 当前发动机燃烧时间(秒) /// public double EngineBurnTime { get; set; } /// /// 是否处于活动状态 /// public bool IsActive { get; set; } } }