修改了项目结构;增加了无制导状态下的运动算法;增加了末敏弹发射角度的自动计算。

This commit is contained in:
Tian jianyong 2024-10-29 17:43:17 +08:00
parent a5c0bfc3d9
commit 2f1ecf86cf
46 changed files with 1328 additions and 600 deletions

BIN
Models/.DS_Store vendored

Binary file not shown.

View File

@ -1,168 +0,0 @@
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 制导系统接口
/// </summary>
public interface IGuidanceSystem
{
bool HasGuidance { get; }
void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity);
Vector3D GetGuidanceAcceleration();
}
/// <summary>
/// 基础制导系统
/// </summary>
public class BasicGuidanceSystem : IGuidanceSystem
{
/// <summary>
/// 是否有制导
/// </summary>
public bool HasGuidance { get; protected set; }
/// <summary>
/// 最大加速度
/// </summary>
public double MaxAcceleration { get; set; }
/// <summary>
/// 制导系数
/// </summary>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 导弹位置
/// </summary>
protected Vector3D Position { get; set; }
/// <summary>
/// 导弹速度
/// </summary>
protected Vector3D Velocity { get; set; }
/// <summary>
/// 制导加速度
/// </summary>
protected Vector3D GuidanceAcceleration { get; set; }
public BasicGuidanceSystem(double maxAcceleration, double proportionalNavigationCoefficient)
{
HasGuidance = false;
GuidanceAcceleration = Vector3D.Zero;
Position = Vector3D.Zero;
Velocity = Vector3D.Zero;
MaxAcceleration = maxAcceleration;
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
}
/// <summary>
/// 更新制导系统
/// </summary>
/// <param name="deltaTime">时间步长</param>
/// <param name="missilePosition">导弹位置</param>
/// <param name="missileVelocity">导弹速度</param>
public virtual void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
Position = missilePosition;
Velocity = missileVelocity;
}
/// <summary>
/// 获取制导加速度
/// </summary>
/// <returns>制导加速度</returns>
public Vector3D GetGuidanceAcceleration()
{
return GuidanceAcceleration;
}
/// <summary>
/// 计算制导加速度
/// </summary>
/// <param name="deltaTime">时间步长</param>
protected virtual void CalculateGuidanceAcceleration(double deltaTime)
{
// 基础制导系统不计算制导指令
// 派生类应该重写这个方法来实现特定的制导逻辑
}
/// <summary>
/// 计算比例导引加速度
/// </summary>
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
/// <param name="missilePosition">导弹位置</param>
/// <param name="missileVelocity">导弹速度</param>
/// <param name="targetPosition">目标位置</param>
/// <param name="targetVelocity">目标速度</param>
/// <returns>比例导引加速度</returns>
protected static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient, Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
{
// 预测时间(预测目标前进方向该时间后到达的位置,可以调整)
double predictionTime = 0.01;
// 预测目标位置
Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime;
Vector3D r = predictedTargetPosition - missilePosition;
Vector3D v = targetVelocity - missileVelocity;
Vector3D LOS = r.Normalize();
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude();
Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * proportionalNavigationCoefficient * missileVelocity.Magnitude();
return acceleration;
}
/// <summary>
/// 四阶龙格库塔法计算导弹运动状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
/// <param name="position">导弹位置</param>
/// <param name="velocity">导弹速度</param>
/// <param name="acceleration">导弹加速度</param>
/// <returns>新的位置和速度</returns>
public static (Vector3D newPosition, Vector3D newVelocity) RungeKutta4(double deltaTime, Vector3D position, Vector3D velocity, Vector3D acceleration)
{
// 定义一个局部函数来计算加速度
Vector3D AccelerationFunction(Vector3D pos, Vector3D vel)
{
// 这里可以添加更复杂的加速度计算,比如考虑空气阻力等
return acceleration;
}
// 第一步
Vector3D k1v = AccelerationFunction(position, velocity) * deltaTime;
Vector3D k1r = velocity * deltaTime;
// 第二步
Vector3D k2v = AccelerationFunction(position + k1r * 0.5, velocity + k1v * 0.5) * deltaTime;
Vector3D k2r = (velocity + k1v * 0.5) * deltaTime;
// 第三步
Vector3D k3v = AccelerationFunction(position + k2r * 0.5, velocity + k2v * 0.5) * deltaTime;
Vector3D k3r = (velocity + k2v * 0.5) * deltaTime;
// 第四步
Vector3D k4v = AccelerationFunction(position + k3r, velocity + k3v) * deltaTime;
Vector3D k4r = (velocity + k3v) * deltaTime;
// 计算新的位置和速度
Vector3D newPosition = position + (k1r + k2r * 2 + k3r * 2 + k4r) / 6;
Vector3D newVelocity = velocity + (k1v + k2v * 2 + k3v * 2 + k4v) / 6;
return (newPosition, newVelocity);
}
/// <summary>
/// 获取制导系统状态
/// </summary>
/// <returns>制导系统状态</returns>
public virtual string GetStatus()
{
return $" 导引头状态: 有制导={HasGuidance}, 位置={Position}, 速度={Velocity}, 制导加速度={GuidanceAcceleration}";
}
}
}

View File

@ -1,366 +0,0 @@
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>
/// 工作频率3mm 或 8mm
/// </summary>
public double Frequency { get; set; }
/// <summary>
/// 辐射温度差检测阈值辐射计高温物体与低温物体的检测温差单位K默认 50K
/// </summary>
public double DetectionTemperatureDifferenceThreshold { get; set; } = 50;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">辐射计的位置</param>
/// <param name="orientation">辐射计的朝向</param>
/// <param name="frequency">工作频率</param>
/// <param name="detectionTemperatureDifferenceThreshold">辐射温差检测阈值</param>
public MillimeterWaveRadiometer(Vector3D position, Orientation orientation, double frequency, double detectionTemperatureDifferenceThreshold)
: base(position, orientation)
{
Frequency = frequency;
DetectionTemperatureDifferenceThreshold = detectionTemperatureDifferenceThreshold;
}
/// <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
{
private double currentAltitude;
private readonly TerminalSensitiveSubmunition submunition;
/// <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(TerminalSensitiveSubmunition submunition, double maxAltitude, double accuracy)
: base(submunition.Position, submunition.Orientation)
{
MaxAltitude = maxAltitude;
Accuracy = accuracy;
currentAltitude = 0;
this.submunition = submunition;
}
/// <summary>
/// 更新毫米波测高雷达的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 更新当前高度,考虑测量精度
currentAltitude = submunition.Position.Y + Accuracy * new Random().NextDouble();
}
/// <summary>
/// 获取毫米波测高雷达的数据
/// </summary>
/// <returns>毫米波测高雷达采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回毫米波测高雷达的数据
AltimeterSensorData altimeterSensorData = new AltimeterSensorData
{
Altitude = currentAltitude
};
return 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

@ -1,8 +1,8 @@
using System;
using System.Threading;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Models;
using Model;
using ActiveProtect.Utility;
using System.Collections.Generic;
namespace ActiveProtect
@ -114,8 +114,8 @@ namespace ActiveProtect
// 末敏弹配置
new() {
Id = "TSM_1",
InitialPosition = new Vector3D(4000, 0, 100), // 发射位置
InitialOrientation = new Orientation(Math.PI, Math.PI/8, 0), // 使用计算得到的发射角度
InitialPosition = new Vector3D(3000, 0, 100), // 发射位置
InitialOrientation = new Orientation(Math.PI, 0, 0), // 使用计算得到的发射角度
InitialSpeed = 800,
MaxSpeed = 1000,
TargetIndex = 0,
@ -125,6 +125,7 @@ namespace ActiveProtect
MaxEngineBurnTime = 0,
MaxAcceleration = 10,
ProportionalNavigationCoefficient = 3,
ExplosionRadius = 5,
Mass = 50,
Type = MissileType.TerminalSensitiveMissile
},

View File

@ -1,5 +1,6 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -38,6 +39,11 @@ namespace ActiveProtect.Models
/// </summary>
public double RadarCrossSection { get; set; }
/// <summary>
/// 坦克配置
/// </summary>
public TankConfig TankConfig { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
@ -46,12 +52,13 @@ namespace ActiveProtect.Models
public Tank(TankConfig tankConfig, ISimulationManager simulationManager)
: base(tankConfig.Id, tankConfig.InitialPosition, tankConfig.InitialOrientation, tankConfig.InitialSpeed, simulationManager)
{
Speed = tankConfig.InitialSpeed;
MaxSpeed = tankConfig.MaxSpeed;
MaxArmor = tankConfig.MaxArmor;
CurrentArmor = tankConfig.MaxArmor;
InfraredRadiationIntensity = tankConfig.InfraredRadiationIntensity;
RadarCrossSection = tankConfig.RadarCrossSection;
TankConfig = tankConfig;
Speed = TankConfig.InitialSpeed;
MaxSpeed = TankConfig.MaxSpeed;
MaxArmor = TankConfig.MaxArmor;
CurrentArmor = TankConfig.MaxArmor;
InfraredRadiationIntensity = TankConfig.InfraredRadiationIntensity;
RadarCrossSection = TankConfig.RadarCrossSection;
IsActive = false;
}

View File

@ -0,0 +1,101 @@
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <summary>
/// 制导系统接口
/// </summary>
public interface IGuidanceSystem
{
bool HasGuidance { get; }
void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity);
Vector3D GetGuidanceAcceleration();
}
/// <summary>
/// 基础制导系统
/// </summary>
public class BasicGuidanceSystem : IGuidanceSystem
{
/// <summary>
/// 是否有制导
/// </summary>
public bool HasGuidance { get; protected set; }
/// <summary>
/// 最大加速度
/// </summary>
public double MaxAcceleration { get; set; }
/// <summary>
/// 制导系数
/// </summary>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 导弹位置
/// </summary>
protected Vector3D Position { get; set; }
/// <summary>
/// 导弹速度
/// </summary>
protected Vector3D Velocity { get; set; }
/// <summary>
/// 制导加速度
/// </summary>
protected Vector3D GuidanceAcceleration { get; set; }
public BasicGuidanceSystem(double maxAcceleration, double proportionalNavigationCoefficient)
{
HasGuidance = false;
GuidanceAcceleration = Vector3D.Zero;
Position = Vector3D.Zero;
Velocity = Vector3D.Zero;
MaxAcceleration = maxAcceleration;
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
}
/// <summary>
/// 更新制导系统
/// </summary>
/// <param name="deltaTime">时间步长</param>
/// <param name="missilePosition">导弹位置</param>
/// <param name="missileVelocity">导弹速度</param>
public virtual void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
Position = missilePosition;
Velocity = missileVelocity;
}
/// <summary>
/// 获取制导加速度
/// </summary>
/// <returns>制导加速度</returns>
public Vector3D GetGuidanceAcceleration()
{
return GuidanceAcceleration;
}
/// <summary>
/// 计算制导加速度
/// </summary>
/// <param name="deltaTime">时间步长</param>
protected virtual void CalculateGuidanceAcceleration(double deltaTime)
{
// 基础制导系统不计算制导指令
// 派生类应该重写这个方法来实现特定的制导逻辑
}
/// <summary>
/// 获取制导系统状态
/// </summary>
/// <returns>制导系统状态</returns>
public virtual string GetStatus()
{
return $" 导引头状态: 有制导={HasGuidance}, 位置={Position}, 速度={Velocity}, 制导加速度={GuidanceAcceleration}";
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -38,7 +39,7 @@ namespace ActiveProtect.Models
lastTargetPosition = tankPosition;
// 使用基类的比例控制算法
GuidanceAcceleration = CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
// 限制最大加速度
if (GuidanceAcceleration.Magnitude() > MaxAcceleration)
{

View File

@ -1,4 +1,5 @@
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,4 +1,5 @@
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -161,7 +162,7 @@ namespace ActiveProtect.Models
protected override void CalculateGuidanceAcceleration(double deltaTime)
{
// 计算比例导引加速度
GuidanceAcceleration = CalculateProportionalNavigation(ProportionalNavigationCoefficient, Position, Velocity, TargetPosition, TargetVelocity);
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, Position, Velocity, TargetPosition, TargetVelocity);
// 限制最大加速度
double maxAcceleration = 100; // 根据实际情况调整

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -17,6 +18,8 @@ namespace ActiveProtect.Models
private readonly Random random = new();
private Vector3D lastTargetPosition;
private bool isJammed = false;
private double jammingPower = 0;
public ISimulationManager SimulationManager { get; set; }
@ -27,6 +30,15 @@ namespace ActiveProtect.Models
{
SimulationManager = simulationManager;
lastTargetPosition = Vector3D.Zero;
// 订阅干扰事件
simulationManager.SubscribeToEvent<MillimeterWaveJammingEvent>(HandleJammingEvent);
}
private void HandleJammingEvent(MillimeterWaveJammingEvent evt)
{
isJammed = true;
jammingPower = evt.JammingPower;
}
/// <summary>
@ -43,7 +55,7 @@ namespace ActiveProtect.Models
lastTargetPosition = tankPosition;
// 使用基类的比例控制算法
GuidanceAcceleration = CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
GuidanceAcceleration = MotionAlgorithm.CalculateProportionalNavigation(ProportionalNavigationCoefficient, missilePosition, missileVelocity, tankPosition, targetVelocity);
if (GuidanceAcceleration.Magnitude() > MaxAcceleration)
{
@ -65,6 +77,13 @@ namespace ActiveProtect.Models
{
targetPosition = Vector3D.Zero;
// 如果被干扰直接返回false
if (isJammed)
{
Console.WriteLine($"毫米波导引头受到干扰,干扰功率: {jammingPower:F2}W");
return false;
}
foreach (var element in SimulationManager.GetElements())
{
if (element is Tank tank)

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,6 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,6 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -0,0 +1,34 @@
namespace ActiveProtect.Models
{
/// <summary>
/// 干扰设备接口
/// </summary>
public interface IJammer
{
/// <summary>
/// 是否正在干扰
/// </summary>
bool IsJamming { get; }
/// <summary>
/// 当前干扰功率
/// </summary>
double CurrentJammingPower { get; }
/// <summary>
/// 开始干扰
/// </summary>
void StartJamming();
/// <summary>
/// 停止干扰
/// </summary>
void StopJamming();
/// <summary>
/// 获取干扰状态
/// </summary>
string GetJammingStatus();
}
}

View File

@ -0,0 +1,120 @@
using System;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <summary>
/// 干扰设备基类
/// </summary>
public abstract class JammerBase : SimulationElement, IJammer
{
/// <summary>
/// 是否正在干扰
/// </summary>
public bool IsJamming { get; protected set; }
/// <summary>
/// 当前干扰功率
/// </summary>
public double CurrentJammingPower { get; protected set; }
/// <summary>
/// 最大干扰功率
/// </summary>
protected double MaxJammingPower { get; set; }
/// <summary>
/// 功率增长率
/// </summary>
protected double PowerIncreaseRate { get; set; }
/// <summary>
/// 最大冷却时间
/// </summary>
protected double MaxCooldownTime { get; set; }
/// <summary>
/// 当前冷却时间
/// </summary>
protected double CurrentCooldownTime { get; set; }
/// <summary>
/// 所属坦克ID
/// </summary>
protected string TankId { get; set; }
protected JammerBase(string id, Vector3D position, Orientation orientation,
ISimulationManager manager, string tankId, double maxJammingPower,
double initialJammingPower, double powerIncreaseRate, double maxCooldownTime)
: base(id, position, orientation, 0, manager)
{
TankId = tankId;
MaxJammingPower = maxJammingPower;
CurrentJammingPower = initialJammingPower;
PowerIncreaseRate = powerIncreaseRate;
MaxCooldownTime = maxCooldownTime;
CurrentCooldownTime = 0;
IsJamming = false;
}
public virtual void StartJamming()
{
if (CurrentCooldownTime <= 0 && !IsJamming)
{
IsJamming = true;
Console.WriteLine($"干扰器 {Id} 开始干扰");
}
}
public virtual void StopJamming()
{
if (IsJamming)
{
IsJamming = false;
CurrentCooldownTime = MaxCooldownTime;
CurrentJammingPower = MaxJammingPower * 0.4; // 重置为最大功率的40%
Console.WriteLine($"干扰器 {Id} 停止干扰,进入冷却");
}
}
public abstract string GetJammingStatus();
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (IsJamming)
{
UpdateJammingPower(deltaTime);
PublishJammingEvent();
}
else if (CurrentCooldownTime > 0)
{
CurrentCooldownTime = Math.Max(0, CurrentCooldownTime - deltaTime);
}
// 更新位置(跟随坦克)
if (SimulationManager.GetEntityById(TankId) is Tank tank)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
}
public override void Activate()
{
base.Activate();
StartJamming();
}
public override void Deactivate()
{
StopJamming();
base.Deactivate();
}
protected abstract void UpdateJammingPower(double deltaTime);
protected abstract void PublishJammingEvent();
}
}

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -0,0 +1,151 @@
using System;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <summary>
/// 毫米波干扰器
/// </summary>
public class MillimeterWaveJammer : SimulationElement
{
/// <summary>
/// 最大干扰功率(瓦特)
/// </summary>
private readonly double maxJammingPower;
/// <summary>
/// 当前干扰功率(瓦特)
/// </summary>
private double currentJammingPower;
/// <summary>
/// 干扰功率增长率(瓦特/秒)
/// </summary>
private readonly double powerIncreaseRate;
/// <summary>
/// 最大干扰冷却时间(秒)
/// </summary>
private readonly double maxJammingCooldown;
/// <summary>
/// 当前冷却时间(秒)
/// </summary>
private double currentCooldown;
/// <summary>
/// 是否正在干扰
/// </summary>
private bool isJamming;
/// <summary>
/// 所属坦克ID
/// </summary>
private readonly string tankId;
/// <summary>
/// 干扰器构造函数
/// </summary>
public MillimeterWaveJammer(string id, Vector3D position, Orientation orientation,
ISimulationManager manager, string tankId, MillimeterWaveJammerConfig config)
: base(id, position, orientation, 0, manager)
{
this.tankId = tankId;
maxJammingPower = config.MaxJammingPower;
currentJammingPower = config.InitialJammingPower;
powerIncreaseRate = config.PowerIncreaseRate;
maxJammingCooldown = config.MaxJammingCooldown;
currentCooldown = 0;
isJamming = false;
}
/// <summary>
/// 更新干扰器状态
/// </summary>
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (isJamming)
{
// 增加干扰功率
currentJammingPower = Math.Min(maxJammingPower,
currentJammingPower + powerIncreaseRate * deltaTime);
// 发布干扰事件
SimulationManager.PublishEvent(new MillimeterWaveJammingEvent
{
SenderId = Id,
Timestamp = SimulationManager.CurrentTime,
TargetId = tankId,
JammingPower = currentJammingPower
});
}
else if (currentCooldown > 0)
{
// 更新冷却时间
currentCooldown = Math.Max(0, currentCooldown - deltaTime);
}
// 更新位置(跟随坦克)
if (SimulationManager.GetEntityById(tankId) is Tank tank)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
}
/// <summary>
/// 开始干扰
/// </summary>
public void StartJamming()
{
if (currentCooldown <= 0 && !isJamming)
{
isJamming = true;
Console.WriteLine($"毫米波干扰器 {Id} 开始干扰");
}
}
/// <summary>
/// 停止干扰
/// </summary>
public void StopJamming()
{
if (isJamming)
{
isJamming = false;
currentCooldown = maxJammingCooldown;
currentJammingPower = maxJammingPower * 0.4; // 重置为最大功率的40%
Console.WriteLine($"毫米波干扰器 {Id} 停止干扰,进入冷却");
}
}
public override void Activate()
{
base.Activate();
StartJamming();
}
/// <summary>
/// 销毁干扰器
/// </summary>
public override void Deactivate()
{
StopJamming();
base.Deactivate();
}
/// <summary>
/// 获取干扰器状态
/// </summary>
public override string GetStatus()
{
return $"毫米波干扰器 {Id}:\n" +
$" 位置: {Position}\n" +
$" 干扰功率: {currentJammingPower:F2}/{maxJammingPower:F2}\n" +
$" 冷却时间: {currentCooldown:F2}/{maxJammingCooldown:F2}\n" +
$" 状态: {(isJamming ? "" : "")}";
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,5 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
public class LaserBeamRiderMissile : MissileBase

View File

@ -1,5 +1,6 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,5 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using ActiveProtect.SimulationEnvironment;
using Model;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -98,7 +98,7 @@ namespace ActiveProtect.Models
/// <summary>
/// 是否有制导
/// </summary>
public bool HasGuidance { get; protected set; } = false;
public bool HasGuidance { get; protected set; }
/// <summary>
/// 失去制导的时间(秒)
@ -109,16 +109,11 @@ namespace ActiveProtect.Models
/// 最后已知的速度向量
/// </summary>
protected Vector3D LastKnownVelocity = Vector3D.Zero;
/// <summary>
/// 发射速度(米/秒)
/// </summary>
public const double LAUNCH_SPEED = 10;
/// <summary>
/// 导弹质量(千克)
/// </summary>
public double Mass { get; protected set; } = 100;
public double Mass { get; protected set; }
/// <summary>
/// 制导加速度
@ -143,6 +138,7 @@ namespace ActiveProtect.Models
InitializeFromConfig();
IsActive = false;
HasGuidance = false;
FlightTime = 0;
FlightDistance = 0;
EngineBurnTime = 0;
@ -189,8 +185,19 @@ namespace ActiveProtect.Models
Vector3D acceleration = GuidanceAcceleration;
// 使用四阶龙格-库塔方法更新导弹的位置和速度
(Position, Velocity) = BasicGuidanceSystem.RungeKutta4(deltaTime, Position, Velocity, acceleration);
if (HasGuidance)
{
// 制导条件下,使用四阶龙格-库塔方法更新导弹的位置和速度
(Position, Velocity) = MotionAlgorithm.RungeKutta4(deltaTime, Position, Velocity, acceleration);
}
else
{
Console.WriteLine($"无制导条件下,使用运动学方程更新导弹的位置和速度");
// 无制导条件下,使用运动学方程更新导弹的位置和速度
(Position, Velocity) = MotionAlgorithm.CalculateBallisticMotion(Position, Velocity, acceleration, deltaTime);
}
// 限制速度不超过最大速度
if (Velocity.Magnitude() > MaxSpeed)

View File

@ -1,6 +1,6 @@
using System;
namespace Model
namespace ActiveProtect.Models
{
/// <summary>
/// 坦克消息结构

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
@ -11,9 +12,9 @@ namespace ActiveProtect.Models
// 分离点距离目标水平距离,默认 1000 米
private const double SeparationDistance = 1000;
// 分离时距离分离点的距离阈值,默认 50米
private const double SeparationRange = 50;
// 分离时距目标距离阈值,默认 1400 米
private const double SeparationTargetDistance = 1400;
private const double SeparationRange = 0.5;
// 分离时距目标距离阈值,默认 1200 米
private const double SeparationTargetDistance = 1200;
// 子弹数量, 155 口径母弹,默认 2 个
private const int SubmunitionCount = 1;
// 子弹数组
@ -28,6 +29,22 @@ namespace ActiveProtect.Models
//计算分离点坐标高度为SeparationHeight距离目标的距离为SeparationDistance
separationPoint = Vector3D.PointOnLine(base.SimulationManager.GetEntityById(TargetId).Position, base.Position, SeparationDistance) + new Vector3D(0, SeparationHeight, 0);
//计算导弹发射角度
(Orientation? launchOrientation, Vector3D? launchVelocity) = MotionAlgorithm.CalculateBestLaunchOrientation(Position, separationPoint, Speed);
if (!launchOrientation.HasValue || launchVelocity is null)
{
// 处理错误情况
throw new InvalidOperationException("无法计算发射方向");
}
else
{
Orientation = launchOrientation.Value;
Velocity = launchVelocity;
Console.WriteLine($"发射方向: {launchOrientation}");
}
GuidanceAcceleration = new Vector3D(0, -9.81, 0);
}
/// <summary>
@ -36,9 +53,8 @@ namespace ActiveProtect.Models
/// <param name="deltaTime">时间步长</param>
public override void Update(double deltaTime)
{
base.Update(deltaTime);
GuidanceAcceleration = new Vector3D(0, -9.8, 0);
base.Update(deltaTime);
Console.WriteLine($"分离点距离: {(separationPoint - Position).Magnitude()}");
@ -61,7 +77,7 @@ namespace ActiveProtect.Models
// 获取目标位置
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
// 创建并释子弹
// 创建并释子弹
for (int i = 0; i < SubmunitionCount; i++)
{
// 计算子弹朝向目标的方向
@ -82,7 +98,7 @@ namespace ActiveProtect.Models
MaxAcceleration = 50,
ProportionalNavigationCoefficient = 3,
Mass = 10,
ExplosionRadius = 10
ExplosionRadius = this.ExplosionRadius
},
SimulationManager);

View File

@ -1,6 +1,6 @@
using System;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
public class TerminalSensitiveSubmunition : MissileBase
@ -30,6 +30,9 @@ namespace ActiveProtect.Models
// 减速高度 400米
private const double DecelerationHeight = 400;
// 减速加速度 50 m/s^2
private const double DecelerationAcceleration = 50;
// 扫描高度 200米
private const double ScanningHeight = 200;
@ -141,14 +144,15 @@ namespace ActiveProtect.Models
/// </summary>
private void UpdateDecelerationStage(double deltaTime)
{
HasGuidance = true;
// 减速减旋,垂直速度减小
Vector3D deceleration = new Vector3D(0, 9.8, 0) - Velocity.Normalize() * 50; // 假设减速度为5m/s^2
Console.WriteLine($"降落伞打开,减速速度: {deceleration}");
Vector3D deceleration = - Velocity.Normalize() * DecelerationAcceleration;
Velocity += deceleration * deltaTime;
if (Velocity.Magnitude() <= VerticalDescentSpeed)
{
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
GuidanceAcceleration = Vector3D.Zero;
}
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= ScanningHeight)
@ -162,6 +166,7 @@ namespace ActiveProtect.Models
/// </summary>
private void UpdateSpiralScanStage(double deltaTime)
{
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
GuidanceAcceleration = Vector3D.Zero;
// 更新螺旋角度

View File

@ -0,0 +1,35 @@
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();
}
}

View File

@ -0,0 +1,54 @@
using ActiveProtect.Utility;
using System;
namespace ActiveProtect.Models
{
/// <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();
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <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();
}
}
}

View File

@ -0,0 +1,70 @@
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 毫米波测高雷达类
/// </summary>
public class MillimeterWaveAltimeter : Sensor
{
private double currentAltitude;
private readonly TerminalSensitiveSubmunition submunition;
/// <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(TerminalSensitiveSubmunition submunition, double maxAltitude, double accuracy)
: base(submunition.Position, submunition.Orientation)
{
MaxAltitude = maxAltitude;
Accuracy = accuracy;
currentAltitude = 0;
this.submunition = submunition;
}
/// <summary>
/// 更新毫米波测高雷达的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 更新当前高度,考虑测量精度
currentAltitude = submunition.Position.Y + Accuracy * new Random().NextDouble();
}
//监听毫米波干扰事件
public void OnMillimeterWaveJamming(object sender, EventArgs e)
{
Console.WriteLine("毫米波测高雷达受到干扰");
}
/// <summary>
/// 获取毫米波测高雷达的数据
/// </summary>
/// <returns>毫米波测高雷达采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回毫米波测高雷达的数据
AltimeterSensorData altimeterSensorData = new AltimeterSensorData
{
Altitude = currentAltitude
};
return altimeterSensorData;
}
}
}

View File

@ -0,0 +1,52 @@
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <summary>
/// 毫米波辐射计类
/// </summary>
public class MillimeterWaveRadiometer : Sensor
{
/// <summary>
/// 工作频率3mm 或 8mm
/// </summary>
public double Frequency { get; set; }
/// <summary>
/// 辐射温度差检测阈值辐射计高温物体与低温物体的检测温差单位K默认 50K
/// </summary>
public double DetectionTemperatureDifferenceThreshold { get; set; } = 50;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="position">辐射计的位置</param>
/// <param name="orientation">辐射计的朝向</param>
/// <param name="frequency">工作频率</param>
/// <param name="detectionTemperatureDifferenceThreshold">辐射温差检测阈值</param>
public MillimeterWaveRadiometer(Vector3D position, Orientation orientation, double frequency, double detectionTemperatureDifferenceThreshold)
: base(position, orientation)
{
Frequency = frequency;
DetectionTemperatureDifferenceThreshold = detectionTemperatureDifferenceThreshold;
}
/// <summary>
/// 更新毫米波辐射计的状态
/// </summary>
/// <param name="deltaTime">自上次更新以来的时间间隔</param>
public override void Update(double deltaTime)
{
// 实现毫米波辐射计的更新逻辑
}
/// <summary>
/// 获取毫米波辐射计的数据
/// </summary>
/// <returns>毫米波辐射计采集的数据</returns>
public override SensorData GetSensorData()
{
// 返回毫米波辐射计的数据
return new RadiometerSensorData();
}
}
}

View File

@ -0,0 +1,65 @@
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <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

@ -0,0 +1,67 @@
using System;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <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();
}
}

View File

@ -0,0 +1,28 @@
namespace ActiveProtect.Models
{
/// <summary>
/// 告警设备接口
/// </summary>
public interface IWarner
{
/// <summary>
/// 是否处于告警状态
/// </summary>
bool IsWarning { get; }
/// <summary>
/// 开始告警
/// </summary>
void StartWarning();
/// <summary>
/// 停止告警
/// </summary>
void StopWarning();
/// <summary>
/// 获取告警状态
/// </summary>
string GetWarningStatus();
}
}

View File

@ -1,5 +1,6 @@
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Simulation;
using System;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{

View File

@ -0,0 +1,98 @@
using System;
using ActiveProtect.Simulation;
using ActiveProtect.Utility;
namespace ActiveProtect.Models
{
/// <summary>
/// 告警设备基类
/// </summary>
public abstract class WarnerBase : SimulationElement, IWarner
{
/// <summary>
/// 是否处于告警状态
/// </summary>
public bool IsWarning { get; protected set; }
/// <summary>
/// 告警持续时间(秒)
/// </summary>
protected double WarningDuration { get; set; }
/// <summary>
/// 当前告警时间(秒)
/// </summary>
protected double CurrentWarningTime { get; set; }
/// <summary>
/// 所属坦克ID
/// </summary>
protected string TankId { get; set; }
protected WarnerBase(string id, Vector3D position, Orientation orientation,
ISimulationManager manager, string tankId, double warningDuration)
: base(id, position, orientation, 0, manager)
{
TankId = tankId;
WarningDuration = warningDuration;
CurrentWarningTime = 0;
IsWarning = false;
}
public virtual void StartWarning()
{
if (!IsWarning)
{
IsWarning = true;
CurrentWarningTime = 0;
Console.WriteLine($"告警器 {Id} 开始告警");
}
}
public virtual void StopWarning()
{
if (IsWarning)
{
IsWarning = false;
CurrentWarningTime = 0;
Console.WriteLine($"告警器 {Id} 停止告警");
}
}
public abstract string GetWarningStatus();
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (IsWarning)
{
CurrentWarningTime += deltaTime;
if (CurrentWarningTime >= WarningDuration)
{
StopWarning();
}
}
// 更新位置(跟随坦克)
if (SimulationManager.GetEntityById(TankId) is Tank tank)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
}
public override void Activate()
{
base.Activate();
Console.WriteLine($"告警器 {Id} 已激活");
}
public override void Deactivate()
{
StopWarning();
base.Deactivate();
Console.WriteLine($"告警器 {Id} 已停用");
}
}
}

View File

@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using ActiveProtect.Utility;
using ActiveProtect.Models;
using Model;
namespace ActiveProtect.SimulationEnvironment
namespace ActiveProtect.Simulation
{
/// <summary>
/// 仿真配置类,包含整个仿真所需的所有配置信息
@ -40,6 +40,11 @@ namespace ActiveProtect.SimulationEnvironment
/// </summary>
public LaserJammerConfig LaserJammerConfig { get; set; }
/// <summary>
/// 毫米波干扰器配置
/// </summary>
public MillimeterWaveJammerConfig MillimeterWaveJammerConfig { get; set; }
/// <summary>
/// 仿真时间步长(秒)
/// </summary>
@ -61,6 +66,7 @@ namespace ActiveProtect.SimulationEnvironment
LaserBeamRiderConfig = new LaserBeamRiderConfig();
LaserWarnerConfig = new LaserWarnerConfig();
LaserJammerConfig = new LaserJammerConfig();
MillimeterWaveJammerConfig = new MillimeterWaveJammerConfig();
InfraredTrackerConfig = new InfraredTrackerConfig();
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
}
@ -121,6 +127,11 @@ namespace ActiveProtect.SimulationEnvironment
/// </summary>
public bool HasLaserJammer { get; set; }
/// <summary>
/// 是否装备毫米波干扰器
/// </summary>
public bool HasMillimeterWaveJammer { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
@ -147,6 +158,7 @@ namespace ActiveProtect.SimulationEnvironment
MaxArmor = 0;
HasLaserWarner = false;
HasLaserJammer = false;
HasMillimeterWaveJammer = false;
InfraredRadiationIntensity = 0;
}
@ -521,4 +533,47 @@ namespace ActiveProtect.SimulationEnvironment
UpdateFrequency = 10; // 10赫兹
}
}
/// <summary>
/// 毫米波干扰器配置类
/// </summary>
public class MillimeterWaveJammerConfig
{
/// <summary>
/// 干扰器ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 最大干扰功率(瓦特)
/// </summary>
public double MaxJammingPower { get; set; }
/// <summary>
/// 初始干扰功率(瓦特)
/// </summary>
public double InitialJammingPower { get; set; }
/// <summary>
/// 功率增长率(瓦特/秒)
/// </summary>
public double PowerIncreaseRate { get; set; }
/// <summary>
/// 最大冷却时间(秒)
/// </summary>
public double MaxJammingCooldown { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public MillimeterWaveJammerConfig()
{
Id = "";
MaxJammingPower = 1000;
InitialJammingPower = 400;
PowerIncreaseRate = 200;
MaxJammingCooldown = 5;
}
}
}

View File

@ -1,7 +1,7 @@
using System;
using ActiveProtect.Models;
using ActiveProtect.Utility;
namespace ActiveProtect.SimulationEnvironment
namespace ActiveProtect.Simulation
{
/// <summary>
/// 仿真元素的抽象基类,所有仿真中的实体都继承自此类

View File

@ -1,6 +1,7 @@
using ActiveProtect.Utility;
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
namespace ActiveProtect.Simulation
{
/// <summary>
/// 仿真事件的基类
@ -61,7 +62,7 @@ namespace ActiveProtect.SimulationEnvironment
public SimulationElement? Target { get; set; }
}
/// <summary
/// <summary>
/// 激光照射停止事件
/// </summary>
public class LaserIlluminationStopEvent : SimulationEvent
@ -205,4 +206,20 @@ namespace ActiveProtect.SimulationEnvironment
public class InfraredGuidanceMissileLightOffEvent : SimulationEvent
{
}
/// <summary>
/// 毫米波干扰事件
/// </summary>
public class MillimeterWaveJammingEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 干扰功率(瓦特)
/// </summary>
public double JammingPower { get; set; }
}
}

View File

@ -2,8 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using ActiveProtect.Models;
using ActiveProtect.Utility;
namespace ActiveProtect.SimulationEnvironment
namespace ActiveProtect.Simulation
{
/// <summary>
/// 仿真管理器接口,定义了仿真管理器的基本功能
@ -131,6 +132,20 @@ namespace ActiveProtect.SimulationEnvironment
);
Elements.Add(laserJammer);
}
// 为坦克创建毫米波干扰器
if (tankConfig.HasMillimeterWaveJammer)
{
var millimeterWaveJammer = new MillimeterWaveJammer(
$"MMWJ_{i}",
tank.Position,
tank.Orientation,
this,
tank.Id,
config.MillimeterWaveJammerConfig
);
Elements.Add(millimeterWaveJammer);
}
}
@ -208,10 +223,10 @@ namespace ActiveProtect.SimulationEnvironment
Elements.Add(infraredTracker);
// 激活所有元素
ActivateAllElements();
//ActivateAllElements();
// 激活部分元素
//ActivateSomeElements();
ActivateSomeElements();
}
//激活所有元素
@ -245,18 +260,21 @@ namespace ActiveProtect.SimulationEnvironment
//Elements.FindAll(e => e.Id == "LBR_1").ForEach(e => e.Activate());
// 激活红外指令制导导弹
Elements.FindAll(e => e.Id == "ICGM_1").ForEach(e => e.Activate());
//Elements.FindAll(e => e.Id == "ICGM_1").ForEach(e => e.Activate());
// 激活红外测角仪
Elements.FindAll(e => e.Id == "IT_1").ForEach(e => e.Activate());
//Elements.FindAll(e => e.Id == "IT_1").ForEach(e => e.Activate());
// 激活红外成像末制导导弹
Elements.FindAll(e => e.Id == "ITGM_1").ForEach(e => e.Activate());
//Elements.FindAll(e => e.Id == "ITGM_1").ForEach(e => e.Activate());
// 激活毫米波末制导导弹
//Elements.FindAll(e => e.Id == "MMWG_1").ForEach(e => e.Activate());
// 激活末敏弹
//Elements.FindAll(e => e.Id == "TSM_1").ForEach(e => e.Activate());
Elements.FindAll(e => e.Id == "TSM_1").ForEach(e => e.Activate());
// 激活毫米波干扰器
//Elements.FindAll(e => e.Id == "MMWJ_1").ForEach(e => e.Activate());
}
/// <summary>

View File

@ -1,7 +1,7 @@
using System;
using System.Numerics;
namespace ActiveProtect.Models
namespace ActiveProtect.Utility
{
/// <summary>
/// 表示三维空间中的向量
@ -392,4 +392,6 @@ namespace ActiveProtect.Models
/// </summary>
public static Vector2D Zero => new Vector2D(0, 0);
}
}

View File

@ -0,0 +1,173 @@
using System;
using System.Numerics;
namespace ActiveProtect.Utility
{
public static class MotionAlgorithm
{
/// <summary>
/// 计算抛物线弹道最佳发射方向(选择较小的仰角)
/// </summary>
/// <param name="startPos">发射位置</param>
/// <param name="targetPos">目标位置</param>
/// <param name="initialSpeed">初始速度</param>
/// <returns>最佳发射方向如果无解则返回null</returns>
public static (Orientation? orientation, Vector3D? velocity) CalculateBestLaunchOrientation(Vector3D startPos, Vector3D targetPos, double initialSpeed)
{
// 计算水平距离
double dx = targetPos.X - startPos.X;
double dz = targetPos.Z - startPos.Z;
double horizontalDistance = Math.Sqrt(dx * dx + dz * dz);
// 计算高度差
double dy = targetPos.Y - startPos.Y;
double[]? angles = CalculateLaunchAngles(initialSpeed, horizontalDistance, dy);
if (angles == null)
{
Console.WriteLine("无法计算发射角度");
return (null, null);
}
double bestAngle = Math.Min(angles[0], angles[1]);
double azimuth = Math.Atan2(dz, dx);
// 计算初始速度分量
double vx = initialSpeed * Math.Cos(bestAngle) * Math.Cos(azimuth);
double vy = initialSpeed * Math.Sin(bestAngle);
double vz = initialSpeed * Math.Cos(bestAngle) * Math.Sin(azimuth);
// 返回方向和速度
return (new Orientation(bestAngle, azimuth, 0), new Vector3D(vx, vy, vz));
}
/// <summary>
/// 计算抛物线弹道发射角度
/// </summary>
/// <param name="v0">初始速度(m/s)</param>
/// <param name="x">目标点x坐标(m)</param>
/// <param name="y">目标点y坐标(m)</param>
/// <param name="g">重力加速度(m/s²)</param>
/// <returns>两个可能的发射角度(弧度)如果无解则返回null</returns>
public static double[]? CalculateLaunchAngles(double v0, double x, double y, double g = 9.81)
{
double v0_2 = v0 * v0;
double v0_4 = v0_2 * v0_2;
double discriminant = v0_4 - g * (g * x * x + 2 * y * v0_2);
Console.WriteLine($"判别式: {discriminant}");
if (discriminant < 0)
{
Console.WriteLine("无实数解 - 目标不可达");
return null;
}
double angle1 = Math.Atan((v0_2 + Math.Sqrt(discriminant)) / (g * x));
double angle2 = Math.Atan((v0_2 - Math.Sqrt(discriminant)) / (g * x));
//Console.WriteLine($"计算得到的两个角度: {angle1 * 180 / Math.PI:F2}° 和 {angle2 * 180 / Math.PI:F2}°");
return new[] { angle1, angle2 };
}
/// <summary>
/// 使用运动学定律计算导弹运动状态,用于无制导状态(无制导时,使用该方法可以降低计算量)
/// </summary>
/// <param name="currentPosition">当前位置</param>
/// <param name="currentVelocity">当前速度</param>
/// <param name="acceleration">加速度(通常包含重力加速度)</param>
/// <param name="deltaTime">时间步长</param>
/// <returns>包含新位置和新速度的元组</returns>
public static (Vector3D newPosition, Vector3D newVelocity) CalculateBallisticMotion(
Vector3D currentPosition,
Vector3D currentVelocity,
Vector3D acceleration,
double deltaTime)
{
// 使用标准运动学方程
Vector3D newPosition = new(
currentPosition.X + currentVelocity.X * deltaTime + 0.5 * acceleration.X * deltaTime * deltaTime,
currentPosition.Y + currentVelocity.Y * deltaTime + 0.5 * acceleration.Y * deltaTime * deltaTime,
currentPosition.Z + currentVelocity.Z * deltaTime + 0.5 * acceleration.Z * deltaTime * deltaTime
);
Vector3D newVelocity = new(
currentVelocity.X + acceleration.X * deltaTime,
currentVelocity.Y + acceleration.Y * deltaTime,
currentVelocity.Z + acceleration.Z * deltaTime
);
return (newPosition, newVelocity);
}
/// <summary>
/// 使用四阶龙格库塔法计算物体运动状态,用于有制导状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
/// <param name="position">导弹位置</param>
/// <param name="velocity">导弹速度</param>
/// <param name="acceleration">导弹加速度</param>
/// <returns>新的位置和速度</returns>
public static (Vector3D newPosition, Vector3D newVelocity) RungeKutta4(double deltaTime, Vector3D position, Vector3D velocity, Vector3D acceleration)
{
// 定义一个局部函数来计算加速度
Vector3D AccelerationFunction(Vector3D pos, Vector3D vel)
{
// 这里可以添加更复杂的加速度计算,比如考虑空气阻力等
return acceleration;
}
// 第一步
Vector3D k1v = AccelerationFunction(position, velocity) * deltaTime;
Vector3D k1r = velocity * deltaTime;
// 第二步
Vector3D k2v = AccelerationFunction(position + k1r * 0.5, velocity + k1v * 0.5) * deltaTime;
Vector3D k2r = (velocity + k1v * 0.5) * deltaTime;
// 第三步
Vector3D k3v = AccelerationFunction(position + k2r * 0.5, velocity + k2v * 0.5) * deltaTime;
Vector3D k3r = (velocity + k2v * 0.5) * deltaTime;
// 第四步
Vector3D k4v = AccelerationFunction(position + k3r, velocity + k3v) * deltaTime;
Vector3D k4r = (velocity + k3v) * deltaTime;
// 计算新的位置和速度
Vector3D newPosition = position + (k1r + k2r * 2 + k3r * 2 + k4r) / 6;
Vector3D newVelocity = velocity + (k1v + k2v * 2 + k3v * 2 + k4v) / 6;
return (newPosition, newVelocity);
}
/// <summary>
/// 计算比例导引加速度
/// </summary>
/// <param name="proportionalNavigationCoefficient">比例导引系数</param>
/// <param name="missilePosition">导弹位置</param>
/// <param name="missileVelocity">导弹速度</param>
/// <param name="targetPosition">目标位置</param>
/// <param name="targetVelocity">目标速度</param>
/// <returns>比例导引加速度</returns>
public static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient, Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
{
// 预测时间(预测目标前进方向该时间后到达的位置,可以调整)
double predictionTime = 0.01;
// 预测目标位置
Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime;
Vector3D r = predictedTargetPosition - missilePosition;
Vector3D v = targetVelocity - missileVelocity;
Vector3D LOS = r.Normalize();
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude();
Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * proportionalNavigationCoefficient * missileVelocity.Magnitude();
return acceleration;
}
}
}