ActiveProtect/Models/TerminalSensitiveSubmunition.cs

286 lines
9.9 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;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class TerminalSensitiveSubmunition : MissileBase
{
/// <summary>
/// 子弹阶段
/// </summary>
private enum SubmunitionStage
{
Separation,
Deceleration,
SpiralScan,
Attack,
Explode,
SelfDestruct
}
/// <summary>
/// 当前阶段
/// </summary>
private SubmunitionStage currentStage;
private const double SpiralRotationSpeed = 8 * Math.PI; // 4 rotations per second
private const double VerticalDescentSpeed = 10; // 10 m/s
private const double ScanAngle = 20 * Math.PI / 180; // 20 degrees in radians
// 减速高度 400米
private const double DecelerationHeight = 400;
// 扫描高度 200米
private const double ScanningHeight = 200;
// 自毁高度 20米
private const double SelfDestructHeight = 20;
// 攻击速度 500 m/s
private const double AttackSpeed = 500;
// 检测到目标的时间
private double? lastDetectionTime = null;
/// <summary>
/// 螺旋角度
/// </summary>
private double spiralAngle;
// 检测到目标的角度
private double detectionAngle;
// 弹载传感器
private readonly InfraredDetector infraredDetector;
private readonly MillimeterWaveRadiometer radiometer;
private readonly MillimeterWaveAltimeter altimeter;
private readonly LaserRangefinder rangefinder;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="config">导弹配置</param>
/// <param name="manager">模拟管理器</param>
public TerminalSensitiveSubmunition(MissileConfig config, ISimulationManager manager)
: base(config, manager)
{
currentStage = SubmunitionStage.Separation;
spiralAngle = 0;
detectionAngle = 0;
// 初始化传感器
infraredDetector = new InfraredDetector(Position, Orientation, 100, 30);
radiometer = new MillimeterWaveRadiometer(Position, Orientation, 94e9, 1e-6);
altimeter = new MillimeterWaveAltimeter(this, 1000, 0.1); // 毫米波测高仪测量精度0.1米
rangefinder = new LaserRangefinder(Position, Orientation, 1000, 1000);
}
/// <summary>
/// 更新子弹的状态
/// </summary>
/// <param name="deltaTime">时间增量</param>
public override void Update(double deltaTime)
{
base.Update(deltaTime);
// 更新传感器
infraredDetector.Update(deltaTime);
radiometer.Update(deltaTime);
altimeter.Update(deltaTime);
rangefinder.Update(deltaTime);
switch (currentStage)
{
case SubmunitionStage.Separation:
UpdateSeparationStage(deltaTime);
break;
case SubmunitionStage.Deceleration:
UpdateDecelerationStage(deltaTime);
break;
case SubmunitionStage.SpiralScan:
UpdateSpiralScanStage(deltaTime);
break;
case SubmunitionStage.Attack:
UpdateAttackStage(deltaTime);
break;
case SubmunitionStage.Explode:
UpdateExplodeStage(deltaTime);
break;
case SubmunitionStage.SelfDestruct:
UpdateSelfDestructStage(deltaTime);
break;
}
}
/// <summary>
/// 分离阶段
/// </summary>
private void UpdateSeparationStage(double deltaTime)
{
// 分离阶段
Vector3D deceleration = new(0, 9.8, 0);
Velocity += deceleration * deltaTime;
Position += Velocity * deltaTime;
if(!altimeter.IsActive)
{
// 激活毫米波测高雷达
altimeter.Activate();
}
// 检查高度是否小于等于减速高度
if(((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= DecelerationHeight)
{
// 如果是,则进入减速阶段
currentStage = SubmunitionStage.Deceleration;
}
}
/// <summary>
/// 减速阶段
/// </summary>
private void UpdateDecelerationStage(double deltaTime)
{
// 减速减旋,垂直速度减小
Vector3D deceleration = new Vector3D(0, 9.8, 0) - Velocity.Normalize() * 50; // 假设减速度为5m/s^2
Console.WriteLine($"降落伞打开,减速速度: {deceleration}");
Velocity += deceleration * deltaTime;
if (Velocity.Magnitude() <= VerticalDescentSpeed)
{
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
}
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= ScanningHeight)
{
currentStage = SubmunitionStage.SpiralScan;
}
}
/// <summary>
/// 扫描阶段
/// </summary>
private void UpdateSpiralScanStage(double deltaTime)
{
GuidanceAcceleration = Vector3D.Zero;
// 更新螺旋角度
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime) % (2 * Math.PI);
// 计算水平速度分量
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度
Velocity = new(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
// 计算扫描方向
Vector3D scanDirection = new(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
if (DetectTarget(scanDirection))
{
Console.WriteLine("检测到目标");
double currentTime = SimulationManager.CurrentTime;
if (lastDetectionTime == null)
{
lastDetectionTime = currentTime;
}
else
{
double timeSinceLastDetection = currentTime - lastDetectionTime.Value;
// 重新检测到目标的时间大于等于螺旋周期的90%,则二次确认目标
if (timeSinceLastDetection >= 0.9 * 2 * Math.PI / SpiralRotationSpeed)
{
Console.WriteLine($"目标确认,进入攻击阶段。距离上次检测时间:{timeSinceLastDetection:F2}秒");
currentStage = SubmunitionStage.Attack;
return;
}
}
}
// 使用模式匹配简化类型转换
if (altimeter.GetSensorData() is AltimeterSensorData altimeterData &&
altimeterData.Altitude <= SelfDestructHeight)
{
currentStage = SubmunitionStage.SelfDestruct;
}
}
/// <summary>
/// 攻击阶段
/// </summary>
private void UpdateAttackStage(double deltaTime)
{
Console.WriteLine("攻击阶段");
// 攻击逻辑
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D direction = (targetPosition - Position).Normalize();
Velocity = direction * AttackSpeed;
Console.WriteLine($"导弹ID: {Id}, 距离目标: {DistanceToTarget}, 爆炸半径: {ExplosionRadius}");
if (DistanceToTarget <= ExplosionRadius)
{
currentStage = SubmunitionStage.Explode;
}
}
/// <summary>
/// 爆炸阶段
/// </summary>
private void UpdateExplodeStage(double deltaTime)
{
Explode();
}
/// <summary>
/// 自毁阶段
/// </summary>
private void UpdateSelfDestructStage(double deltaTime)
{
SelfDestruct();
}
/// <summary>
/// 检测目标
/// </summary>
/// <param name="scanDirection">扫描方向</param>
/// <returns>是否检测到目标</returns>
private bool DetectTarget(Vector3D scanDirection)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D toTarget = (targetPosition - Position).Normalize();
// 检查目标是否在扫描线上
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(5 * Math.PI / 180); // 允许5度的误差
}
/// <summary>
/// 销毁子弹
/// </summary>
public override void Deactivate()
{
base.Deactivate();
infraredDetector.Deactivate();
radiometer.Deactivate();
altimeter.Deactivate();
rangefinder.Deactivate();
}
/// <summary>
/// 获取子弹状态
/// </summary>
/// <returns>子弹状态</returns>
public override string GetStatus()
{
return $"{base.GetStatus()}\n运行状态: {currentStage}\n检测角度: {detectionAngle * 180 / Math.PI:F2}°\n螺旋角度: {spiralAngle * 180 / Math.PI:F2}°\n目标检测: {lastDetectionTime != null}";
}
}
}