修改了末敏弹,增加了子弹模型,增加了传感器模型

This commit is contained in:
Tian jianyong 2024-10-21 01:24:51 +08:00
parent a292d0e03f
commit 2f692dffbd
11 changed files with 1016 additions and 286 deletions

View File

@ -0,0 +1,347 @@
using System;
using System.Collections.Generic;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class TerminalSensitiveMissile : MissileBase
{
// 定义末敏弹工作阶段的枚举
private enum TerminalSensitiveStage
{
Launch, // 发射阶段
Separation, // 分离阶段
Deceleration, // 减速阶段
SpiralScan, // 螺旋扫描阶段
Attack, // 攻击阶段
SelfDestruct // 自毁阶段
}
// 当前工作阶段
private TerminalSensitiveStage currentWorkingStage;
// 阶段策略字典,用于存储不同阶段的更新策略
private Dictionary<TerminalSensitiveStage, Action<double>> stageStrategies;
// 螺旋扫描相关参数
private double spiralAngle;
private const double SpiralRotationSpeed = 4 * Math.PI; // 2 rotations per second
private const double VerticalDescentSpeed = 10; // 10 m/s
private const double ScanAngle = 30 * Math.PI / 180; // 30 degrees in radians
// 各阶段的距离和高度参数
private const double SeparationDistance = 1000; // 分离距离 1000米
private const double SeparationHeight = 1000; // 分离高度 1000米
private const double DecelerationHeight = 400; // 减速高度 400米
private const double ScanningHeight = 200; // 扫描高度 200米
private const double SelfDestructHeight = 20; // 自毁高度 20米
// 扫描和目标检测相关参数
private Vector3D lastScanDirection;
private bool targetDetected;
private double detectionAngle;
// 目标位置和分离位置
private Vector3D TargetPosition;
private Vector3D SeparationPosition;
// 制导指令
public Vector3D GuidanceCommand { get; private set; }
// 传感器
private InfraredDetector infraredDetector;
private MillimeterWaveRadiometer radiometer;
private MillimeterWaveAltimeter altimeter;
private LaserRangefinder rangefinder;
// 构造函数
public TerminalSensitiveMissile(string id, MissileConfig missileConfig, string targetId, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
// 初始化参数
spiralAngle = 0;
lastScanDirection = Vector3D.Zero;
targetDetected = false;
detectionAngle = 0;
GuidanceCommand = Vector3D.Zero;
// 获取目标位置
TargetPosition = SimulationManager.GetEntityById(targetId).Position;
// 计算分离位置
SeparationPosition = CalculatePointOnTrajectory(Position, TargetPosition, SeparationDistance, SeparationHeight);
// 初始化阶段策略字典
stageStrategies = new Dictionary<TerminalSensitiveStage, Action<double>>
{
{ TerminalSensitiveStage.Launch, UpdateLaunchStage },
{ TerminalSensitiveStage.Separation, UpdateSeparationStage },
{ TerminalSensitiveStage.Deceleration, UpdateDecelerationStage },
{ TerminalSensitiveStage.SpiralScan, UpdateSpiralScanStage },
{ TerminalSensitiveStage.Attack, UpdateAttackStage },
{ TerminalSensitiveStage.SelfDestruct, UpdateSelfDestructStage }
};
// 设置初始阶段
currentWorkingStage = TerminalSensitiveStage.Launch;
// 初始化传感器
infraredDetector = new InfraredDetector(Position, Orientation, 1000, 30);
radiometer = new MillimeterWaveRadiometer(Position, Orientation, 94e9, 1e-6);
altimeter = new MillimeterWaveAltimeter(Position, Orientation, 1000, 0.1);
rangefinder = new LaserRangefinder(Position, Orientation, 5000, 1000);
}
// 更新方法,每帧调用
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
Console.WriteLine($"末敏弹 {Id} 当前位置: {Position}");
Console.WriteLine($"末敏弹 {Id} 分离位置: {SeparationPosition}");
// 更新传感器
infraredDetector.Update(deltaTime);
radiometer.Update(deltaTime);
altimeter.Update(deltaTime);
rangefinder.Update(deltaTime);
// 使用当前阶段的策略更新导弹状态
if (stageStrategies.TryGetValue(currentWorkingStage, out var updateStrategy))
{
updateStrategy(deltaTime);
}
}
// 发射阶段更新方法
private void UpdateLaunchStage(double deltaTime)
{
// 无动力抛物线飞行
ApplyGravity(deltaTime);
base.UpdateMotionState(deltaTime, GuidanceCommand);
if (Vector3D.Distance(Position, SeparationPosition) <= 200)
{
currentWorkingStage = TerminalSensitiveStage.Separation;
}
}
// 分离阶段更新方法
private void UpdateSeparationStage(double deltaTime)
{
Console.WriteLine($"末敏弹 {Id} 进入分离");
// 根据速度大小调整制导指令
switch(Velocity.Magnitude())
{
case >= 200:
GuidanceCommand = new Vector3D(400, -400, 0);
break;
case >= 100:
GuidanceCommand = new Vector3D(30, -30, 0);
break;
case >= 50:
GuidanceCommand = new Vector3D(20, -20, 0);
break;
case >= 20:
GuidanceCommand = new Vector3D(5, -10, 0);
break;
default:
GuidanceCommand = new Vector3D(0, -10, 0);
break;
}
base.UpdateMotionState(deltaTime, GuidanceCommand);
if (Position.Y <= DecelerationHeight)
{
currentWorkingStage = TerminalSensitiveStage.Deceleration;
}
}
// 减速阶段更新方法
private void UpdateDecelerationStage(double deltaTime)
{
Console.WriteLine($"末敏弹 {Id} 进入减速");
// 减速下降
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
Position += Velocity * deltaTime;
if (Position.Y <= ScanningHeight)
{
currentWorkingStage = TerminalSensitiveStage.SpiralScan;
}
}
// 螺旋扫描阶段更新方法
private void UpdateSpiralScanStage(double deltaTime)
{
Console.WriteLine($"末敏弹 {Id} 进入螺旋扫描");
spiralAngle += SpiralRotationSpeed * deltaTime;
// 计算水平速度分量
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new Vector3D(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度
Velocity = new Vector3D(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
// 计算扫描方向
Vector3D scanDirection = new Vector3D(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
if (DetectTarget(scanDirection))
{
if (!targetDetected)
{
targetDetected = true;
detectionAngle = spiralAngle;
}
else if (Math.Abs(spiralAngle - detectionAngle) < 0.1) // 允许一定的误差
{
currentWorkingStage = TerminalSensitiveStage.Attack;
}
}
lastScanDirection = scanDirection;
if (Position.Y <= SelfDestructHeight)
{
currentWorkingStage = TerminalSensitiveStage.SelfDestruct;
}
}
// 攻击阶段更新方法
private void UpdateAttackStage(double deltaTime)
{
// 攻击逻辑
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D direction = (targetPosition - Position).Normalize();
Velocity = direction * MaxSpeed;
if (Vector3D.Distance(Position, targetPosition) < 1)
{
Explode();
}
}
// 自毁阶段更新方法
private void UpdateSelfDestructStage(double deltaTime)
{
// 实现自毁逻辑
Explode();
}
// 目标检测方法
private bool DetectTarget(Vector3D scanDirection)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D toTarget = (targetPosition - Position).Normalize();
// 检查目标是否在扫描线上
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(0.5 * Math.PI / 180); // 允许0.5度的误差
}
// 应用重力
private void ApplyGravity(double deltaTime)
{
GuidanceCommand = new Vector3D(0, -9.81, 0);
}
// 获取导弹状态
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "末敏弹");
string additionalStatus = $"\n 扫描阶段: {(currentWorkingStage == TerminalSensitiveStage.SpiralScan ? "有效" : "无效")} \n";
return baseStatus + additionalStatus;
}
// 激活导弹
public override void Activate()
{
base.Activate();
// 可以在这里添加订阅事件的代码
}
// 停用导弹
public override void Deactivate()
{
base.Deactivate();
// 可以在这里添加取消订阅事件的代码
}
// 静态方法:计算发射参数
public static (double angle, double distance) CalculateLaunchParameters(double initialVelocity, double targetHeight, double targetDistance)
{
double g = 9.8; // 重力加速度
double v = initialVelocity;
double y = targetHeight;
double x = targetDistance;
// 计算发射角度(弧度)
double angle = Math.Atan((v * v + Math.Sqrt(Math.Pow(v, 4) - g * (g * x * x + 2 * y * v * v))) / (g * x));
// 计算水平飞行距离
double t = x / (v * Math.Cos(angle));
double totalDistance = v * Math.Cos(angle) * t;
return (angle, totalDistance);
}
// 静态方法:计算发射位置
public static Vector3D CalculateLaunchPosition(Vector3D knownPoint, Vector3D velocity)
{
double g = 9.8; // 重力加速度
double x = knownPoint.X;
double y = knownPoint.Y;
double vx = velocity.X;
double vy = velocity.Y;
// 计算时间 t
double t = (-vy - Math.Sqrt(vy * vy + 2 * g * y)) / -g;
// 计算发射点的 x 坐标
double launchX = x - vx * t;
// 发射点的 y 和 z 坐标为 0
return new Vector3D(launchX, 0, 0);
}
// 静态方法:计算轨迹上的点
public static Vector3D CalculatePointOnTrajectory(Vector3D launchPosition, Vector3D targetPosition, double distanceFromTarget, double height)
{
// 确保发射位置和目标位置的y坐标为0
launchPosition = new Vector3D(launchPosition.X, 0, launchPosition.Z);
targetPosition = new Vector3D(targetPosition.X, 0, targetPosition.Z);
// 计算发射方向向量
Vector3D direction = targetPosition - launchPosition;
// 计算总距离
double totalDistance = direction.Magnitude();
// 归一化方向向量
direction = direction.Normalize();
// 计算所需点的位置
Vector3D pointOnTrajectory = targetPosition - direction * distanceFromTarget;
// 返回结果y坐标设置为指定的高度
return new Vector3D(pointOnTrajectory.X, height, pointOnTrajectory.Z);
}
}
}

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class TerminalSensitiveMissile : SimulationElement
{
private TerminalSensitiveMotherMissile motherMissile;
private List<TerminalSensitiveSubmunition> submunitions;
public TerminalSensitiveMissile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, missileConfig.InitialSpeed, simulationManager)
{
motherMissile = new TerminalSensitiveMotherMissile($"{id}_Mother", missileConfig, simulationManager);
submunitions = new List<TerminalSensitiveSubmunition>();
SimulationManager.AddElement(motherMissile);
}
public override void Update(double deltaTime)
{
// 这个类现在主要用于管理和跟踪整个末敏弹系统的状态
// 实际的更新逻辑由母弹和子弹各自处理
}
public override string GetStatus()
{
string status = $"Terminal Sensitive Missile System {Id}:\n";
status += motherMissile.GetStatus() + "\n";
foreach (var submunition in submunitions)
{
status += submunition.GetStatus() + "\n";
}
return status;
}
}
}

View File

@ -99,6 +99,16 @@ namespace ActiveProtect.Models
return new Vector3D(-a.X, -a.Y, -a.Z);
}
public static bool operator ==(Vector3D left, Vector3D right)
{
return left.X == right.X && left.Y == right.Y && left.Z == right.Z;
}
public static bool operator !=(Vector3D left, Vector3D right)
{
return !(left == right);
}
/// <summary>
/// 计算向量的模长
/// </summary>
@ -166,6 +176,20 @@ namespace ActiveProtect.Models
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
/// <summary>
/// 计算AB两点之间距离 A 点一定距离的点的坐标
/// </summary>
/// <param name="a">直线起点</param>
/// <param name="b">直线终点</param>
/// <param name="distance">距离起点距离</param>
/// <returns>直线上的点</returns>
public static Vector3D PointOnLine(Vector3D a, Vector3D b, double distance)
{
Vector3D direction = b - a;
Vector3D unitDirection = direction.Normalize();
return a + unitDirection * distance;
}
}
/// <summary>

View File

@ -7,11 +7,10 @@ namespace ActiveProtect.Models
private LaserBeamRiderGuidanceSystem LaserBeamRiderGuidanceSystem;
public LaserBeamRiderMissile(string id, string targetId, MissileConfig missileConfig, ISimulationManager simulationManager)
public LaserBeamRiderMissile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
LaserBeamRiderGuidanceSystem = new LaserBeamRiderGuidanceSystem(missileConfig.ProportionalNavigationCoefficient);
TargetId = targetId;
}
protected override Vector3D GetGuidanceCommand()

View File

@ -9,7 +9,7 @@ namespace ActiveProtect.Models
public class LaserSemiActiveGuidedMissile : MissileBase
{
private LaserSemiActiveGuidanceSystem LaserGuidanceSystem;
private string LaserDesignatorId;
public string LaserDesignatorId { get; set; } = "";
/// <summary>
/// 构造函数
@ -18,7 +18,7 @@ namespace ActiveProtect.Models
/// <param name="laserDesignatorId">激光指示器ID</param>
/// <param name="missileConfig">导弹配置</param>
/// <param name="simulationManager">仿真管理器</param>
public LaserSemiActiveGuidedMissile(string id, MissileConfig missileConfig, string laserDesignatorId, ISimulationManager simulationManager)
public LaserSemiActiveGuidedMissile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
Vector3D initialTargetPosition = simulationManager.GetEntityById($"Tank_{missileConfig.TargetIndex + 1}").Position;
@ -29,7 +29,6 @@ namespace ActiveProtect.Models
initialTargetPosition,
initialTargetVelocity
);
LaserDesignatorId = laserDesignatorId;
}
/// <summary>

355
Models/Sensors.cs Normal file
View File

@ -0,0 +1,355 @@
using System;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
/// <summary>
/// 定义传感器的基本接口
/// </summary>
public interface ISensor
{
/// <summary>
/// 获取或设置传感器是否处于激活状态
/// </summary>
bool IsActive { get; set; }
/// <summary>
/// 激活传感器
/// </summary>
void Activate();
/// <summary>
/// 停用传感器
/// </summary>
void Deactivate();
/// <summary>
/// 更新传感器状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
void Update(double deltaTime);
/// <summary>
/// 获取传感器数据
/// </summary>
/// <returns>传感器采集的数据</returns>
SensorData GetSensorData();
}
/// <summary>
/// 传感器的抽象基类实现了ISensor接口的基本功能
/// </summary>
public abstract class Sensor : ISensor
{
/// <summary>
/// 获取或设置传感器是否处于激活状态
/// </summary>
public bool IsActive { get; set; }
/// <summary>
/// 传感器的位置
/// </summary>
protected Vector3D Position { get; set; }
/// <summary>
/// 传感器的朝向
/// </summary>
protected Orientation Orientation { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">传感器的初始位置</param>
/// <param name="orientation">传感器的初始朝向</param>
protected Sensor(Vector3D position, Orientation orientation)
{
Position = position;
Orientation = orientation;
IsActive = false;
}
/// <summary>
/// 激活传感器
/// </summary>
public virtual void Activate()
{
IsActive = true;
}
/// <summary>
/// 停用传感器
/// </summary>
public virtual void Deactivate()
{
IsActive = false;
}
/// <summary>
/// 更新传感器状态(需要在子类中实现)
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public abstract void Update(double deltaTime);
/// <summary>
/// 获取传感器数据(需要在子类中实现)
/// </summary>
/// <returns>传感器采集的数据</returns>
public abstract SensorData GetSensorData();
}
/// <summary>
/// 红外探测器类
/// </summary>
public class InfraredDetector : Sensor
{
/// <summary>
/// 探测范围
/// </summary>
public double DetectionRange { get; set; }
/// <summary>
/// 视场角
/// </summary>
public double FieldOfView { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">探测器的位置</param>
/// <param name="orientation">探测器的朝向</param>
/// <param name="detectionRange">探测范围</param>
/// <param name="fieldOfView">视场角</param>
public InfraredDetector(Vector3D position, Orientation orientation, double detectionRange, double fieldOfView)
: base(position, orientation)
{
DetectionRange = detectionRange;
FieldOfView = fieldOfView;
}
/// <summary>
/// 更新红外探测器的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 实现红外探测器的更新逻辑
}
/// <summary>
/// 获取红外探测器的数据
/// </summary>
/// <returns>红外探测器采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回红外探测器的数据
return new InfraredSensorData();
}
}
/// <summary>
/// 毫米波辐射计类
/// </summary>
public class MillimeterWaveRadiometer : Sensor
{
/// <summary>
/// 工作频率
/// </summary>
public double Frequency { get; set; }
/// <summary>
/// 灵敏度
/// </summary>
public double Sensitivity { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">辐射计的位置</param>
/// <param name="orientation">辐射计的朝向</param>
/// <param name="frequency">工作频率</param>
/// <param name="sensitivity">灵敏度</param>
public MillimeterWaveRadiometer(Vector3D position, Orientation orientation, double frequency, double sensitivity)
: base(position, orientation)
{
Frequency = frequency;
Sensitivity = sensitivity;
}
/// <summary>
/// 更新毫米波辐射计的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 实现毫米波辐射计的更新逻辑
}
/// <summary>
/// 获取毫米波辐射计的数据
/// </summary>
/// <returns>毫米波辐射计采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回毫米波辐射计的数据
return new RadiometerSensorData();
}
}
/// <summary>
/// 毫米波测高雷达类
/// </summary>
public class MillimeterWaveAltimeter : Sensor
{
/// <summary>
/// 最大测量高度
/// </summary>
public double MaxAltitude { get; set; }
/// <summary>
/// 测量精度
/// </summary>
public double Accuracy { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">测高雷达的位置</param>
/// <param name="orientation">测高雷达的朝向</param>
/// <param name="maxAltitude">最大测量高度</param>
/// <param name="accuracy">测量精度</param>
public MillimeterWaveAltimeter(Vector3D position, Orientation orientation, double maxAltitude, double accuracy)
: base(position, orientation)
{
MaxAltitude = maxAltitude;
Accuracy = accuracy;
}
/// <summary>
/// 更新毫米波测高雷达的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 实现毫米波测高雷达的更新逻辑
}
/// <summary>
/// 获取毫米波测高雷达的数据
/// </summary>
/// <returns>毫米波测高雷达采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回毫米波测高雷达的数据
return new AltimeterSensorData();
}
}
/// <summary>
/// 激光测距仪类
/// </summary>
public class LaserRangefinder : Sensor
{
/// <summary>
/// 最大测量距离
/// </summary>
public double MaxRange { get; set; }
/// <summary>
/// 脉冲频率
/// </summary>
public double PulseRate { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">测距仪的位置</param>
/// <param name="orientation">测距仪的朝向</param>
/// <param name="maxRange">最大测量距离</param>
/// <param name="pulseRate">脉冲频率</param>
public LaserRangefinder(Vector3D position, Orientation orientation, double maxRange, double pulseRate)
: base(position, orientation)
{
MaxRange = maxRange;
PulseRate = pulseRate;
}
/// <summary>
/// 更新激光测距仪的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 实现激光测距仪的更新逻辑
}
/// <summary>
/// 获取激光测距仪的数据
/// </summary>
/// <returns>激光测距仪采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回激光测距仪的数据
return new RangefinderSensorData();
}
}
/// <summary>
/// 传感器数据的抽象基类
/// </summary>
public abstract class SensorData
{
/// <summary>
/// 数据采集的时间戳
/// </summary>
public DateTime Timestamp { get; set; }
}
/// <summary>
/// 红外传感器数据类
/// </summary>
public class InfraredSensorData : SensorData
{
/// <summary>
/// 探测到的温度
/// </summary>
public double Temperature { get; set; }
/// <summary>
/// 目标方向(如果检测到目标)
/// </summary>
public Vector3D? TargetDirection { get; set; }
}
/// <summary>
/// 辐射计传感器数据类
/// </summary>
public class RadiometerSensorData : SensorData
{
/// <summary>
/// 探测到的辐射强度
/// </summary>
public double RadiationIntensity { get; set; }
}
/// <summary>
/// 测高仪传感器数据类
/// </summary>
public class AltimeterSensorData : SensorData
{
/// <summary>
/// 测量的高度
/// </summary>
public double Altitude { get; set; }
}
/// <summary>
/// 测距仪传感器数据类
/// </summary>
public class RangefinderSensorData : SensorData
{
/// <summary>
/// 测量的距离
/// </summary>
public double Distance { get; set; }
}
}

View File

@ -6,316 +6,98 @@ namespace ActiveProtect.Models
{
public class TerminalSensitiveMissile : MissileBase
{
private enum TerminalSensitiveStage
{
Launch, // 发射阶段
Separation, // 分离阶段
Deceleration, // 减速阶段
SpiralScan, // 螺旋扫描阶段
Attack, // 攻击阶段
SelfDestruct // 自毁阶段
}
private TerminalSensitiveSubmunition[] submunitions;
private TerminalSensitiveStage currentWorkingStage;
private Dictionary<TerminalSensitiveStage, Action<double>> stageStrategies;
private double spiralAngle;
private const double SpiralRotationSpeed = 4 * Math.PI; // 2 rotations per second
private const double VerticalDescentSpeed = 10; // 10 m/s
private const double ScanAngle = 30 * Math.PI / 180; // 30 degrees in radians
// 分离距离 1000米
private const double SeparationDistance = 1000;
private Vector3D guidanceCommand;
// 分离高度 1000米
private const double SeparationHeight = 1000;
// 减速高度 400米
private const double DecelerationHeight = 400;
// 分离点距离目标水平距离
private const double SeparationDistance = 1000;
// 扫描高度 200米
private const double ScanningHeight = 200;
private Vector3D separationPoint;
// 子弹数量
private const int SubmunitionCount = 2;
// 自毁高度 20米
private const double SelfDestructHeight = 20;
private Vector3D lastScanDirection;
private bool targetDetected;
private double detectionAngle;
//目标位置
private Vector3D TargetPosition;
//末敏弹子母弹分离位置
private Vector3D SeparationPosition;
public Vector3D GuidanceCommand { get; private set; }
public TerminalSensitiveMissile(string id, MissileConfig missileConfig, string targetId, ISimulationManager simulationManager)
public TerminalSensitiveMissile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
spiralAngle = 0;
lastScanDirection = Vector3D.Zero;
targetDetected = false;
detectionAngle = 0;
GuidanceCommand = Vector3D.Zero;
submunitions = new TerminalSensitiveSubmunition[SubmunitionCount];
guidanceCommand = Vector3D.Zero;
TargetPosition = SimulationManager.GetEntityById(targetId).Position;
SeparationPosition = CalculatePointOnTrajectory(Position, TargetPosition, SeparationDistance, SeparationHeight);
// 初始化策略字典
stageStrategies = new Dictionary<TerminalSensitiveStage, Action<double>>
{
{ TerminalSensitiveStage.Launch, UpdateLaunchStage },
{ TerminalSensitiveStage.Separation, UpdateSeparationStage },
{ TerminalSensitiveStage.Deceleration, UpdateDecelerationStage },
{ TerminalSensitiveStage.SpiralScan, UpdateSpiralScanStage },
{ TerminalSensitiveStage.Attack, UpdateAttackStage },
{ TerminalSensitiveStage.SelfDestruct, UpdateSelfDestructStage }
};
currentWorkingStage = TerminalSensitiveStage.Launch;
//计算分离点坐标高度为SeparationHeight距离目标的距离为SeparationDistance
separationPoint = Vector3D.PointOnLine(SimulationManager.GetEntityById(TargetId).Position, Position, SeparationDistance) + new Vector3D(0, SeparationHeight, 0);
}
public override void Update(double deltaTime)
{
//base.Update(deltaTime);
if (!IsActive) return;
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
Console.WriteLine($"末敏弹 {Id} 当前位置: {Position}");
Console.WriteLine($"末敏弹 {Id} 分离位置: {SeparationPosition}");
// 使用当前阶段的策略更新导弹状态
if (stageStrategies.TryGetValue(currentWorkingStage, out var updateStrategy))
{
updateStrategy(deltaTime);
}
}
private void UpdateLaunchStage(double deltaTime)
{
base.Update(deltaTime);
// 无动力抛物线飞行
ApplyGravity(deltaTime);
base.UpdateMotionState(deltaTime, GuidanceCommand);
Console.WriteLine($"分离点距离: {(separationPoint - Position).Magnitude()}");
if (Vector3D.Distance(Position, SeparationPosition) <= 200)
//计算到目标的距离
double distanceToTarget = (SimulationManager.GetEntityById(TargetId).Position - Position).Magnitude();
//距离分离点距离小于50米或者距离目标小于1400米则分离
if ((separationPoint - Position).Magnitude() <= 50 || distanceToTarget <= 1400)
{
currentWorkingStage = TerminalSensitiveStage.Separation;
Console.WriteLine("分离");
PerformSeparation();
}
}
private void UpdateSeparationStage(double deltaTime)
private void PerformSeparation()
{
// 子母弹分离逻辑
// 这里可以添加分离的具体实现,比如创建子弹等
Console.WriteLine($"末敏弹 {Id} 进入分离");
switch(Velocity.Magnitude())
{
case >= 200:
GuidanceCommand = new Vector3D(400, -400, 0);
break;
case >= 100:
GuidanceCommand = new Vector3D(30, -30, 0);
break;
case >= 50:
GuidanceCommand = new Vector3D(20, -20, 0);
break;
case >= 20:
GuidanceCommand = new Vector3D(5, -10, 0);
break;
default:
GuidanceCommand = new Vector3D(0, -10, 0);
break;
}
base.UpdateMotionState(deltaTime, GuidanceCommand);
if (Position.Y <= DecelerationHeight)
{
currentWorkingStage = TerminalSensitiveStage.Deceleration;
}
}
private void UpdateDecelerationStage(double deltaTime)
{
Console.WriteLine($"末敏弹 {Id} 进入减速");
// 减速下降
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
Position += Velocity * deltaTime;
if (Position.Y <= ScanningHeight)
{
currentWorkingStage = TerminalSensitiveStage.SpiralScan;
}
}
private void UpdateSpiralScanStage(double deltaTime)
{
Console.WriteLine($"末敏弹 {Id} 进入螺旋扫描");
spiralAngle += SpiralRotationSpeed * deltaTime;
// 计算水平速度分量
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new Vector3D(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度
Velocity = new Vector3D(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
// 计算扫描方向
Vector3D scanDirection = new Vector3D(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
if (DetectTarget(scanDirection))
{
if (!targetDetected)
{
targetDetected = true;
detectionAngle = spiralAngle;
}
else if (Math.Abs(spiralAngle - detectionAngle) < 0.1) // 允许一定的误差
{
currentWorkingStage = TerminalSensitiveStage.Attack;
}
}
lastScanDirection = scanDirection;
if (Position.Y <= SelfDestructHeight)
{
currentWorkingStage = TerminalSensitiveStage.SelfDestruct;
}
}
private void UpdateAttackStage(double deltaTime)
{
// 攻击逻辑
// 获取目标位置
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D direction = (targetPosition - Position).Normalize();
Velocity = direction * MaxSpeed;
if (Vector3D.Distance(Position, targetPosition) < 1)
// 创建并释放子弹
for (int i = 0; i < SubmunitionCount; i++)
{
Explode();
// 计算子弹朝向目标的方向
Vector3D directionToTarget = (targetPosition - this.Position).Normalize();
Orientation orientationToTarget = Orientation.FromVector(directionToTarget);
submunitions[i] = new TerminalSensitiveSubmunition($"{Id}_Sub_{i}",
new MissileConfig
{
InitialPosition = this.Position,
InitialOrientation = orientationToTarget, // 设置为朝向目标的方向
InitialSpeed = 200, // 子弹初始速度
MaxSpeed = 300,
TargetIndex = 0,
MaxFlightTime = 10,
MaxFlightDistance = 1000,
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 0.1,
Mass = 10
},
SimulationManager);
SimulationManager.AddElement(submunitions[i]);
}
}
private void UpdateSelfDestructStage(double deltaTime)
{
// 实现自毁逻辑
Explode();
}
private bool DetectTarget(Vector3D scanDirection)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D toTarget = (targetPosition - Position).Normalize();
// 检查目标是否在扫描线上
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(0.5 * Math.PI / 180); // 允许0.5度的误差
// 母弹完成任务,可以被移除
IsActive = false;
}
private void ApplyGravity(double deltaTime)
{
GuidanceCommand = new Vector3D(0, -9.81, 0);
Velocity += new Vector3D(0, -9.8, 0) * deltaTime;
}
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "末敏弹");
string additionalStatus = $"\n 扫描阶段: {(currentWorkingStage == TerminalSensitiveStage.SpiralScan ? "" : "")} \n";
return baseStatus + additionalStatus;
return $"{base.GetStatus()}\nMother Missile Stage: {currentStage}, Separation Point: {separationPoint}";
}
public override void Activate()
protected override Vector3D GetGuidanceCommand()
{
base.Activate();
// SimulationManager.SubscribeToEvent<LaserBeamStartEvent>(OnLaserBeamStart);
// SimulationManager.SubscribeToEvent<LaserBeamStopEvent>(OnLaserBeamStop);
// SimulationManager.SubscribeToEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
return guidanceCommand;
}
public override void Deactivate()
{
base.Deactivate();
// SimulationManager.UnsubscribeFromEvent<LaserBeamStartEvent>(OnLaserBeamStart);
// SimulationManager.UnsubscribeFromEvent<LaserBeamStopEvent>(OnLaserBeamStop);
// SimulationManager.UnsubscribeFromEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
}
public static (double angle, double distance) CalculateLaunchParameters(double initialVelocity, double targetHeight, double targetDistance)
{
double g = 9.8; // 重力加速度
double v = initialVelocity;
double y = targetHeight;
double x = targetDistance;
// 计算发射角度(弧度)
double angle = Math.Atan((v * v + Math.Sqrt(Math.Pow(v, 4) - g * (g * x * x + 2 * y * v * v))) / (g * x));
// 计算水平飞行距离
double t = x / (v * Math.Cos(angle));
double totalDistance = v * Math.Cos(angle) * t;
return (angle, totalDistance);
}
public static Vector3D CalculateLaunchPosition(Vector3D knownPoint, Vector3D velocity)
{
double g = 9.8; // 重力加速度
double x = knownPoint.X;
double y = knownPoint.Y;
double vx = velocity.X;
double vy = velocity.Y;
// 计算时间 t
double t = (-vy - Math.Sqrt(vy * vy + 2 * g * y)) / -g;
// 计算发射点的 x 坐标
double launchX = x - vx * t;
// 发射点的 y 和 z 坐标为 0
return new Vector3D(launchX, 0, 0);
}
public static Vector3D CalculatePointOnTrajectory(Vector3D launchPosition, Vector3D targetPosition, double distanceFromTarget, double height)
{
// 确保发射位置和目标位置的y坐标为0
launchPosition = new Vector3D(launchPosition.X, 0, launchPosition.Z);
targetPosition = new Vector3D(targetPosition.X, 0, targetPosition.Z);
// 计算发射方向向量
Vector3D direction = targetPosition - launchPosition;
// 计算总距离
double totalDistance = direction.Magnitude();
// 归一化方向向量
direction = direction.Normalize();
// 计算所需点的位置
Vector3D pointOnTrajectory = targetPosition - direction * distanceFromTarget;
// 返回结果y坐标设置为指定的高度
return new Vector3D(pointOnTrajectory.X, height, pointOnTrajectory.Z);
}
}
}

View File

@ -0,0 +1,179 @@
using System;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class TerminalSensitiveSubmunition : MissileBase
{
private enum SubmunitionStage
{
Deceleration,
SpiralScan,
Attack,
SelfDestruct
}
private SubmunitionStage runningStage;
private Vector3D guidanceCommand;
private double spiralAngle;
private const double SpiralRotationSpeed = 4 * Math.PI; // 2 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;
private Vector3D lastScanDirection;
private bool targetDetected;
private double detectionAngle;
// 添加传感器
private InfraredDetector infraredDetector;
private MillimeterWaveRadiometer radiometer;
private MillimeterWaveAltimeter altimeter;
private LaserRangefinder rangefinder;
public TerminalSensitiveSubmunition(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
runningStage = SubmunitionStage.Deceleration;
spiralAngle = 0;
lastScanDirection = Vector3D.Zero;
targetDetected = false;
detectionAngle = 0;
guidanceCommand = Vector3D.Zero;
// 初始化传感器
infraredDetector = new InfraredDetector(Position, Orientation, 1000, 30);
radiometer = new MillimeterWaveRadiometer(Position, Orientation, 94e9, 1e-6);
altimeter = new MillimeterWaveAltimeter(Position, Orientation, 1000, 0.1);
rangefinder = new LaserRangefinder(Position, Orientation, 5000, 1000);
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
// 更新传感器
infraredDetector.Update(deltaTime);
radiometer.Update(deltaTime);
altimeter.Update(deltaTime);
rangefinder.Update(deltaTime);
switch (runningStage)
{
case SubmunitionStage.Deceleration:
UpdateDecelerationStage(deltaTime);
break;
case SubmunitionStage.SpiralScan:
UpdateSpiralScanStage(deltaTime);
break;
case SubmunitionStage.Attack:
UpdateAttackStage(deltaTime);
break;
case SubmunitionStage.SelfDestruct:
SelfDestruct();
break;
}
}
private void UpdateDecelerationStage(double deltaTime)
{
// 减速下降
Vector3D deceleration = new Vector3D(0, 9.8, 0) - Velocity.Normalize() * 5; // 假设减速度为5m/s^2
Velocity += deceleration * deltaTime;
if (Velocity.Y >= -VerticalDescentSpeed)
{
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
}
if (Position.Y <= ScanningHeight)
{
runningStage = SubmunitionStage.SpiralScan;
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
}
}
private void UpdateSpiralScanStage(double deltaTime)
{
spiralAngle += SpiralRotationSpeed * deltaTime;
// 计算水平速度分量
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
Vector3D horizontalVelocity = new Vector3D(
Math.Cos(spiralAngle) * horizontalSpeed,
0,
Math.Sin(spiralAngle) * horizontalSpeed
);
// 更新速度
Velocity = new Vector3D(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
// 计算扫描方向
Vector3D scanDirection = new Vector3D(
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
-Math.Cos(ScanAngle),
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
);
if (DetectTarget(scanDirection))
{
if (!targetDetected)
{
targetDetected = true;
detectionAngle = spiralAngle;
}
else if (Math.Abs(spiralAngle - detectionAngle) < 0.1) // 允许一定的误差
{
runningStage = SubmunitionStage.Attack;
}
}
lastScanDirection = scanDirection;
if (Position.Y <= SelfDestructHeight)
{
runningStage = SubmunitionStage.SelfDestruct;
}
}
private void UpdateAttackStage(double deltaTime)
{
// 攻击逻辑
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D direction = (targetPosition - Position).Normalize();
Velocity = direction * MaxSpeed;
if (Vector3D.Distance(Position, targetPosition) < 1)
{
Explode();
}
}
private bool DetectTarget(Vector3D scanDirection)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D toTarget = (targetPosition - Position).Normalize();
// 检查目标是否在扫描线上
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(0.5 * Math.PI / 180); // 允许0.5度的误差
}
public override string GetStatus()
{
return $"{base.GetStatus()}\nSubmunition Stage: {runningStage}\nSpiral Angle: {spiralAngle * 180 / Math.PI:F2}°\nTarget Detected: {targetDetected}";
}
protected override Vector3D GetGuidanceCommand()
{
return guidanceCommand;
}
}
}

View File

@ -116,20 +116,20 @@ namespace ActiveProtect
// 末敏弹配置
new MissileConfig
{
InitialPosition = new Vector3D(3500, 0, 100), // 发射位置
InitialPosition = new Vector3D(4000, 0, 100), // 发射位置
InitialOrientation = new Orientation(Math.PI, Math.PI/8, 0), // 使用计算得到的发射角度
InitialSpeed = 800,
MaxSpeed = 1000,
TargetIndex = 0,
MaxFlightTime = 10, // 增加最大飞行时间
MaxFlightDistance = 5000, // 增加最大飞行距离
ThrustAcceleration = 0, // 推力加速度
MaxEngineBurnTime = 0, // 发动机燃烧时间
MaxFlightTime = 30, // 增加最大飞行时间
MaxFlightDistance = 5000, // 增加最大飞行距离
ThrustAcceleration = 0, // 母弹的推力加速度
MaxEngineBurnTime = 0, // 母弹的发动机燃烧时间
MaxAcceleration = 1000,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.StandardMissile,
StageConfig = FlightStageConfig.TerminalSensitiveMissile, // 使用新的枚举值
DistanceParams = new MissileDistanceParams(1000, 400, 20),
Mass = 100,
Mass = 50, // 增加质量以反映母弹的重量
Type = MissileType.TerminalSensitiveMissile
}
},

View File

@ -407,6 +407,11 @@ namespace ActiveProtect.SimulationEnvironment
/// </summary>
public static FlightStageConfig MillimeterWaveTerminalGuidance => new(true, true, true, true, true);
/// <summary>
/// 末敏弹的预设配置
/// </summary>
public static FlightStageConfig TerminalSensitiveMissile => new(false, false, true, false, false);
public FlightStageConfig(bool enableLaunch, bool enableAcceleration, bool enableCruise, bool enableTerminalGuidance, bool enableAttack)
{
EnableLaunch = enableLaunch;

View File

@ -139,13 +139,13 @@ namespace ActiveProtect.SimulationEnvironment
switch (missileConfig.Type)
{
case MissileType.LaserSemiActiveGuidance:
missile = new LaserSemiActiveGuidedMissile($"LSGM_{i + 1}", missileConfig, "Tank_1", this);
missile = new LaserSemiActiveGuidedMissile($"LSGM_{i + 1}", missileConfig, this);
break;
case MissileType.LaserBeamRiderGuidance:
missile = new LaserBeamRiderMissile($"LBRM_{i + 1}", "LBR_1", missileConfig, this);
missile = new LaserBeamRiderMissile($"LBRM_{i + 1}", missileConfig, this);
break;
case MissileType.TerminalSensitiveMissile:
missile = new TerminalSensitiveMissile($"TSM_{i + 1}", missileConfig, "Tank_1", this);
missile = new TerminalSensitiveMissile($"TSM_{i + 1}", missileConfig, this);
break;
default:
missile = new MissileBase($"M_{i + 1}", missileConfig, this);
@ -166,6 +166,10 @@ namespace ActiveProtect.SimulationEnvironment
this
);
Elements.Add(laserDesignator);
if (Elements.FirstOrDefault(e => e.Id == "LSGM_1") is LaserSemiActiveGuidedMissile lsGM)
{
lsGM.LaserDesignatorId = "LD_1";
}
// 创建激光驾束仪
var laserBeamRiderConfig = config.LaserBeamRiderConfig;
@ -212,7 +216,7 @@ namespace ActiveProtect.SimulationEnvironment
}
else
{
Console.WriteLine($"没找到事件 {eventType.Name} 的处理程序");
Console.WriteLine($"没<EFBFBD><EFBFBD>找到事件 {eventType.Name} 的处理程序");
}
}