创建项目,添加基础类

This commit is contained in:
Tian jianyong 2024-10-06 09:09:32 +08:00
commit edfead8927
13 changed files with 1158 additions and 0 deletions

51
.gitignore vendored Normal file
View File

@ -0,0 +1,51 @@
# 构建结果
[Bb]in/
[Oo]bj/
[Ll]ib/
# Visual Studio 文件
.vs/
*.user
*.userosscache
*.suo
*.userprefs
# 编译文件
*.dll
*.exe
*.pdb
# 日志文件
*.log
# 临时文件
[Tt]emp/
[Tt]mp/
# 缓存文件
*.cache
*.bak
# 测试结果
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NuGet包
*.nupkg
**/packages/*
!**/packages/build/
# Visual Studio Code 设置
.vscode/
# Rider 设置
.idea/
# 操作系统文件
.DS_Store
Thumbs.db
# 其他
*.swp
*.*~
project.lock.json

10
ActiveProtect.csproj Normal file
View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

25
ActiveProtect.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActiveProtect", "ActiveProtect.csproj", "{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {73773200-50D4-40ED-803B-FC16B131FFD2}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,7 @@
using ActiveProtect.Models;
public interface ISimulationManager
{
Vector3D GetElementPosition(string elementId);
// 添加其他必要的方法
}

View File

@ -0,0 +1,71 @@
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
public class SimulationConfig
{
public List<TankConfig> TankConfigs { get; set; }
public List<MissileConfig> MissileConfigs { get; set; }
public double SimulationTimeStep { get; set; }
public SimulationConfig()
{
TankConfigs = [];
MissileConfigs = [];
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
}
}
public class TankConfig
{
public Vector3D InitialPosition { get; set; }
public Orientation InitialOrientation { get; set; }
public double InitialSpeed { get; set; }
public double MaxSpeed { get; set; }
public double MaxArmor { get; set; }
public TankConfig()
{
InitialPosition = new Vector3D(0, 0, 0);
InitialOrientation = new Orientation(0, 0, 0);
}
}
public class MissileConfig
{
public Vector3D InitialPosition { get; set; }
public Orientation InitialOrientation { get; set; }
public double InitialSpeed { get; set; }
public double MaxSpeed { get; set; }
public int TargetIndex { get; set; }
public double MaxFlightTime { get; set; }
public double MaxFlightDistance { get; set; }
public double MaxAcceleration { get; set; }
public double ProportionalNavigationCoefficient { get; set; }
public Missile.FlightStageConfig StageConfig { get; set; }
public MissileDistanceParams DistanceParams { get; set; }
public MissileType Type { get; set; }
// 新增属性
public double ThrustAcceleration { get; set; }
public double MaxEngineBurnTime { get; set; }
public MissileConfig()
{
InitialPosition = new Vector3D(0, 0, 0); // 初始位置
InitialOrientation = new Orientation(0, 0, 0); // 初始方向
InitialSpeed = 0; // 初始速度
MaxSpeed = 0; // 最大速度
TargetIndex = 0; // 目标索引
MaxFlightTime = 0; // 最大飞行时间
MaxFlightDistance = 0; // 最大飞行距离
StageConfig = Missile.FlightStageConfig.StandardMissile; // 飞行阶段配置
ThrustAcceleration = 0; // 推力加速度
MaxEngineBurnTime = 0; // 最大发动机燃烧时间
MaxAcceleration = 0; // 最大加速度
DistanceParams = new MissileDistanceParams(0, 0, 0); // 距离参数
ProportionalNavigationCoefficient = 0; // 比例导引系数
Type = MissileType.StandardMissile; // 导弹类型
}
}
}

View File

@ -0,0 +1,18 @@
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
public abstract class SimulationElement(string id, Vector3D position, Orientation orientation)
{
public string Id { get; set; } = id;
public Vector3D Position { get; set; } = position;
public Orientation Orientation { get; set; } = orientation;
public abstract void Update(double deltaTime);
public virtual string GetStatus()
{
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}";
}
}
}

View File

@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
public class SimulationManager : ISimulationManager
{
public List<SimulationElement> Elements { get; private set; }
public double CurrentTime { get; private set; }
public bool IsSimulationEnded { get; private set; }
private readonly SimulationConfig config;
public SimulationManager(SimulationConfig config)
{
this.config = config;
Elements = [];
CurrentTime = 0;
IsSimulationEnded = false;
InitializeSimulation();
}
private void InitializeSimulation()
{
// 创建坦克(保持不变)
for (int i = 0; i < config.TankConfigs.Count; i++)
{
var tankConfig = config.TankConfigs[i];
Elements.Add(new Tank(
$"Tank_{i + 1}",
tankConfig.InitialPosition,
tankConfig.InitialOrientation,
tankConfig.InitialSpeed,
tankConfig.MaxSpeed,
tankConfig.MaxArmor
));
}
// 创建导弹(修改这部分)
for (int i = 0; i < config.MissileConfigs.Count; i++)
{
var missileConfig = config.MissileConfigs[i];
Missile missile = missileConfig.Type switch
{
MissileType.SemiActiveLaserGuidance => new LaserSemiActiveGuidedMissile(
$"LSGM_{i + 1}",
missileConfig.InitialPosition,
missileConfig.InitialOrientation,
missileConfig.InitialSpeed,
missileConfig.MaxSpeed,
$"Tank_{missileConfig.TargetIndex + 1}",
missileConfig.MaxFlightTime,
missileConfig.MaxFlightDistance,
missileConfig.DistanceParams,
missileConfig.StageConfig,
this,
missileConfig.ThrustAcceleration,
missileConfig.MaxEngineBurnTime,
missileConfig.MaxAcceleration,
missileConfig.ProportionalNavigationCoefficient
),
_ => new Missile(
$"NM_{i + 1}",
missileConfig.InitialPosition,
missileConfig.InitialOrientation,
missileConfig.InitialSpeed,
missileConfig.MaxSpeed,
$"Tank_{missileConfig.TargetIndex + 1}",
missileConfig.MaxFlightTime,
missileConfig.MaxFlightDistance,
missileConfig.DistanceParams,
missileConfig.StageConfig,
this,
missileConfig.ThrustAcceleration,
missileConfig.MaxEngineBurnTime,
missileConfig.MaxAcceleration,
missileConfig.ProportionalNavigationCoefficient
),
};
Elements.Add(missile);
}
}
public void Update()
{
if (IsSimulationEnded) return;
CurrentTime += config.SimulationTimeStep;
foreach (var element in Elements.ToList())
{
element.Update(config.SimulationTimeStep);
}
// 移除不活跃的元素
Elements.RemoveAll(e => (e is Tank tank && !tank.IsActive) || (e is Missile missile && !missile.IsActive));
// 检查是否所有导弹都结束飞行
if (!Elements.Any(e => e is Missile))
{
EndSimulation();
}
}
public void PrintStatus()
{
Console.WriteLine($"仿真时间: {CurrentTime:F2}");
foreach (var element in Elements)
{
Console.WriteLine(element.GetStatus());
}
Console.WriteLine();
}
private void EndSimulation()
{
IsSimulationEnded = true;
Console.WriteLine("仿真结束");
Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒");
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
}
public Vector3D GetElementPosition(string elementId)
{
var element = Elements.FirstOrDefault(e => e.Id == elementId);
if (element != null)
{
return element.Position;
}
throw new ArgumentException($"Element with id {elementId} not found");
}
}
}

151
Models/Common.cs Normal file
View File

@ -0,0 +1,151 @@
using System;
namespace ActiveProtect.Models
{
public class Vector3D(double x, double y, double z)
{
public double X { get; set; } = x;
public double Y { get; set; } = y;
public double Z { get; set; } = z;
public static double Distance(Vector3D v1, Vector3D v2)
{
return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2));
}
public static Vector3D Zero => new(0, 0, 0);
public override string ToString()
{
return $"({X:F2}, {Y:F2}, {Z:F2})";
}
public static Vector3D operator -(Vector3D a, Vector3D b)
{
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
public static Vector3D operator +(Vector3D a, Vector3D b)
{
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
public static Vector3D operator *(Vector3D a, double scalar)
{
return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar);
}
public static Vector3D operator /(Vector3D a, double scalar)
{
return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar);
}
public double Magnitude()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
public double MagnitudeSquared()
{
return X * X + Y * Y + Z * Z;
}
public Vector3D Normalize()
{
double mag = Magnitude();
if (mag > 0)
{
return new Vector3D(X / mag, Y / mag, Z / mag);
}
return new Vector3D(0, 0, 0);
}
public static Vector3D CrossProduct(Vector3D a, Vector3D b)
{
return new Vector3D(
a.Y * b.Z - a.Z * b.Y,
a.Z * b.X - a.X * b.Z,
a.X * b.Y - a.Y * b.X
);
}
public static double DotProduct(Vector3D a, Vector3D b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
}
public struct Orientation(double yaw, double pitch, double roll)
{
public double Yaw { get; set; } = yaw;
public double Pitch { get; set; } = pitch;
public double Roll { get; set; } = roll;
public override readonly string ToString()
{
return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})";
}
public void Normalize()
{
Yaw = NormalizeAngle(Yaw);
Pitch = NormalizeAngle(Pitch);
Roll = NormalizeAngle(Roll);
}
private static double NormalizeAngle(double angle)
{
while (angle > Math.PI) angle -= 2 * Math.PI;
while (angle <= -Math.PI) angle += 2 * Math.PI;
return angle;
}
public static Orientation LookAt(Vector3D direction)
{
double yaw = Math.Atan2(direction.Z, direction.X);
double pitch = Math.Atan2(direction.Y, Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z));
return new Orientation(yaw, pitch, 0);
}
public readonly Vector3D ToVector()
{
double cosYaw = Math.Cos(Yaw);
double sinYaw = Math.Sin(Yaw);
double cosPitch = Math.Cos(Pitch);
double sinPitch = Math.Sin(Pitch);
return new Vector3D(
cosYaw * cosPitch,
sinPitch,
sinYaw * cosPitch
);
}
public static Orientation FromVector(Vector3D vector)
{
Vector3D normalized = vector.Normalize();
double pitch = Math.Asin(normalized.Y);
double yaw;
if (Math.Abs(normalized.Y) > 0.9999) // 接近垂直
{
yaw = 0; // 或者保持之前的偏航角
}
else
{
yaw = Math.Atan2(normalized.Z, normalized.X);
}
return new Orientation(yaw, pitch, 0);
}
}
public enum MissileType
{
StandardMissile, // 标准导弹
SemiActiveLaserGuidance, // 半主动激光制导
LaserBeamRiderGuidance, // 激光束制导
InfraredCommandGuidance, // 红外指令制导
ImagingInfraredTerminalGuidance, // 成像红外终端制导
MillimeterWaveTerminalGuidance // 毫米波终端制导
}
}

View File

@ -0,0 +1,53 @@
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class LaserSemiActiveGuidedMissile : Missile
{
// 激光半主动制导导弹的特殊属性
public bool IsLaserLocked { get; private set; } = false;
public LaserSemiActiveGuidedMissile(
string id,
Vector3D position,
Orientation orientation,
double initialSpeed,
double maxSpeed,
string targetId,
double maxFlightTime,
double maxFlightDistance,
MissileDistanceParams distanceParams,
FlightStageConfig stageConfig,
ISimulationManager simulationManager,
double thrustAcceleration,
double maxEngineBurnTime,
double maxAcceleration,
double proportionalNavigationCoefficient)
: base(id, position, orientation, initialSpeed, maxSpeed, targetId, maxFlightTime, maxFlightDistance,
distanceParams, stageConfig, simulationManager, thrustAcceleration, maxEngineBurnTime, maxAcceleration, proportionalNavigationCoefficient)
{
Type = MissileType.SemiActiveLaserGuidance;
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
// 激光半主动制导导弹的特殊更新逻辑
UpdateLaserLock();
}
private void UpdateLaserLock()
{
// 这里实现激光锁定逻辑
// 例如,根据距离和其他因素来决定是否锁定目标
IsLaserLocked = DistanceToTarget < DistanceParams.TerminalGuidanceDistance;
}
public override string GetStatus()
{
return base.GetStatus().Replace("导弹", "激光半主动制导导弹") +
$"\n 激光锁定: {(IsLaserLocked ? "" : "")}";
}
}
}

315
Models/Missile.cs Normal file
View File

@ -0,0 +1,315 @@
using System;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
/// <summary>
/// 表示仿真中的导弹
/// </summary>
public class Missile : SimulationElement
{
/// <summary>
/// 导弹类型
/// </summary>
public MissileType Type { get; protected set; }
/// <summary>
/// 导弹飞行的各个阶段
/// </summary>
public enum FlightStage
{
Launch, // 发射阶段
Acceleration, // 加速阶段
Cruise, // 巡航阶段
TerminalGuidance, // 终端制导阶段
Attack, // 攻击阶段
Explosion // 爆炸阶段
}
/// <summary>
/// 导弹飞行阶段的配置结构
/// </summary>
/// <remarks>
/// 初始化飞行阶段配置
/// </remarks>
public struct FlightStageConfig(bool enableLaunch = true, bool enableAcceleration = true, bool enableCruise = true,
bool enableTerminalGuidance = true, bool enableAttack = true)
{
public bool EnableLaunch = enableLaunch;
public bool EnableAcceleration = enableAcceleration;
public bool EnableCruise = enableCruise;
public bool EnableTerminalGuidance = enableTerminalGuidance;
public bool EnableAttack = enableAttack;
/// <summary>
/// 标准导弹的预设配置, 所有阶段都启用
/// </summary>
public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true);
/// <summary>
/// 激光制导炮弹的预设配置, 没有加速阶段
/// </summary>
public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false);
/// <summary>
/// 短程导弹的预设配置,没有巡航阶段
/// </summary>
public static FlightStageConfig ShortRangeMissile => new(enableCruise: false);
/// <summary>
/// 激光半主动制导导弹的预设配置, 没有加速阶段
/// </summary>
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
}
public double Speed { get; protected set; }
public double MaxSpeed { get; protected set; }
public string TargetId { get; protected set; }
public double MaxFlightTime { get; protected set; }
public double MaxFlightDistance { get; protected set; }
public double FlightTime { get; protected set; }
public double FlightDistance { get; protected set; }
public double DistanceToTarget { get; protected set; }
public MissileDistanceParams DistanceParams { get; protected set; }
public FlightStageConfig StageConfig { get; protected set; }
public FlightStage CurrentStage { get; protected set; }
public bool IsActive { get; protected set; }
protected Vector3D Velocity;
private Vector3D LastTargetPosition;
private const double N = 3; // 比例导引系数
private readonly ISimulationManager _simulationManager;
public double ThrustAcceleration { get; protected set; }
public double EngineBurnTime { get; protected set; }
public double MaxEngineBurnTime { get; protected set; }
public double MaxAcceleration { get; protected set; } = 100; // m/s^2
public double ProportionalNavigationCoefficient { get; set; }
public Missile(string id, Vector3D position, Orientation orientation, double initialSpeed, double maxSpeed,
string targetId, double maxFlightTime, double maxFlightDistance,
MissileDistanceParams distanceParams,
FlightStageConfig stageConfig,
ISimulationManager simulationManager,
double thrustAcceleration, double maxEngineBurnTime, double maxAcceleration,
double proportionalNavigationCoefficient)
: base(id, position, orientation)
{
Speed = initialSpeed;
MaxSpeed = maxSpeed;
TargetId = targetId;
MaxFlightTime = maxFlightTime;
MaxFlightDistance = maxFlightDistance;
DistanceParams = distanceParams;
StageConfig = stageConfig;
IsActive = true;
FlightTime = 0;
FlightDistance = 0;
_simulationManager = simulationManager;
ThrustAcceleration = thrustAcceleration;
EngineBurnTime = 0;
MaxEngineBurnTime = maxEngineBurnTime;
MaxAcceleration = maxAcceleration;
Vector3D horizontalDirection = new Vector3D(orientation.ToVector().X, 0, orientation.ToVector().Z).Normalize();
Velocity = horizontalDirection * initialSpeed;
// 设置初始阶段
CurrentStage = StageConfig.EnableLaunch ? FlightStage.Launch :
StageConfig.EnableAcceleration ? FlightStage.Acceleration :
StageConfig.EnableCruise ? FlightStage.Cruise :
StageConfig.EnableTerminalGuidance ? FlightStage.TerminalGuidance :
StageConfig.EnableAttack ? FlightStage.Attack : FlightStage.Cruise;
Console.WriteLine($"导弹 {Id} 的初始阶: {CurrentStage}");
LastTargetPosition = position; // 初始化 LastTargetPosition
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
}
public override void Update(double deltaTime)
{
if (!IsActive) return;
// 更新发动机燃烧时间
UpdateEngineBurnTime(deltaTime);
// 使用 RK4 方法更新导弹状态
Vector3D k1, k2, k3, k4;
Vector3D v1, v2, v3, v4;
(k1, v1) = CalculateDerivatives(Position, Velocity, deltaTime);
(k2, v2) = CalculateDerivatives(Position + k1 * (deltaTime / 2), Velocity + v1 * (deltaTime / 2), deltaTime / 2);
(k3, v3) = CalculateDerivatives(Position + k2 * (deltaTime / 2), Velocity + v2 * (deltaTime / 2), deltaTime / 2);
(k4, v4) = CalculateDerivatives(Position + k3 * deltaTime, Velocity + v3 * deltaTime, deltaTime);
Position += (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6);
Velocity += (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6);
// 更新其他状态
Speed = Velocity.Magnitude();
if (Speed > MaxSpeed)
{
Speed = MaxSpeed;
Velocity = Velocity.Normalize() * MaxSpeed;
}
Orientation = Orientation.FromVector(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
UpdateDistanceToTarget(Vector3D.Distance(Position, _simulationManager.GetElementPosition(TargetId)));
// 首先检查是否命中目标
if (CheckHit())
{
Explode();
return;
}
// 然后检查是否应该自毁
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
// 更新飞行阶段
UpdateFlightStage();
}
private bool CheckHit()
{
return DistanceToTarget <= DistanceParams.ExplosionDistance;
}
private bool ShouldSelfDestruct()
{
return FlightTime >= MaxFlightTime || FlightDistance >= MaxFlightDistance || Position.Y <= 0;
}
private void UpdateEngineBurnTime(double deltaTime)
{
if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
{
EngineBurnTime += deltaTime;
}
}
private (Vector3D, Vector3D) CalculateDerivatives(Vector3D position, Vector3D velocity, double deltaTime)
{
Vector3D targetPosition = _simulationManager.GetElementPosition(TargetId);
Vector3D LOS = targetPosition - position;
Vector3D LOSRate = (targetPosition - LastTargetPosition) / deltaTime - velocity;
Vector3D guidanceAcceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
* ProportionalNavigationCoefficient * velocity.Magnitude();
LastTargetPosition = targetPosition;
// 添加推力加速度
Vector3D thrustAcceleration = (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
? Orientation.ToVector() * ThrustAcceleration
: Orientation.ToVector() * (ThrustAcceleration * 0.1); // 小的持续推力
// 添加重力补偿
Vector3D gravityCompensation = new Vector3D(0, 9.81, 0);
guidanceAcceleration += gravityCompensation;
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration;
// 添加重力加速度
Vector3D gravityAcceleration = new(0, -9.81, 0);
totalAcceleration += gravityAcceleration;
// 限制最大加速度
if (totalAcceleration.Magnitude() > MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
}
return (velocity, totalAcceleration);
}
private void UpdateFlightStage()
{
switch (CurrentStage)
{
case FlightStage.Launch:
if (StageConfig.EnableAcceleration) CurrentStage = FlightStage.Acceleration;
else if (StageConfig.EnableCruise) CurrentStage = FlightStage.Cruise;
else if (StageConfig.EnableTerminalGuidance) CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack) CurrentStage = FlightStage.Attack;
break;
case FlightStage.Acceleration:
if (EngineBurnTime >= MaxEngineBurnTime || Speed >= MaxSpeed * 0.95)
{
if (StageConfig.EnableCruise) CurrentStage = FlightStage.Cruise;
else if (StageConfig.EnableTerminalGuidance) CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack) CurrentStage = FlightStage.Attack;
}
break;
case FlightStage.Cruise:
if (StageConfig.EnableTerminalGuidance && DistanceToTarget <= DistanceParams.TerminalGuidanceDistance)
CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack && DistanceToTarget <= DistanceParams.AttackDistance)
CurrentStage = FlightStage.Attack;
break;
case FlightStage.TerminalGuidance:
if (StageConfig.EnableAttack && DistanceToTarget <= DistanceParams.AttackDistance)
CurrentStage = FlightStage.Attack;
break;
case FlightStage.Attack:
if (DistanceToTarget <= DistanceParams.ExplosionDistance)
Explode();
break;
}
}
public void UpdateDistanceToTarget(double distance)
{
DistanceToTarget = distance;
}
public void Explode()
{
IsActive = false;
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
}
public void SelfDestruct()
{
IsActive = false;
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MaxFlightDistance ? "超出最大飞行距<E8A18C><E8B79D><EFBFBD>" :
Position.Y <= 0 ? "高度小于等于0" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
}
public override string GetStatus()
{
return $"导弹 {Id}:\n" +
$" 位置: {Position}\n" +
$" 速度: {Speed:F2} m/s\n" +
$" 当前阶段: {CurrentStage}\n" +
$" 飞行时间: {FlightTime:F2}/{MaxFlightTime:F2}\n" +
$" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {DistanceToTarget:F2}\n" +
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}";
}
public void SetProportionalNavigationCoefficient(double newCoefficient)
{
ProportionalNavigationCoefficient = newCoefficient;
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
}
}
public struct MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance)
{
public double TerminalGuidanceDistance { get; set; } = terminalGuidanceDistance;
public double AttackDistance { get; set; } = attackDistance;
public double ExplosionDistance { get; set; } = explosionDistance;
}
}

40
Models/Tank.cs Normal file
View File

@ -0,0 +1,40 @@
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class Tank(string id, Vector3D position, Orientation orientation, double initialSpeed, double maxSpeed, double maxArmor) : SimulationElement(id, position, orientation)
{
public double Speed { get; set; } = initialSpeed;
public bool IsActive { get; private set; } = true;
public double MaxSpeed { get; private set; } = maxSpeed;
public double MaxArmor { get; private set; } = maxArmor;
public double Armor { get; private set; } = maxArmor;
public double CurrentArmor { get; private set; } = maxArmor;
public override void Update(double deltaTime)
{
if (!IsActive) return;
Position.X += Speed * Math.Cos(Orientation.Yaw) * Math.Cos(Orientation.Pitch) * deltaTime;
Position.Y += Speed * Math.Sin(Orientation.Pitch) * deltaTime;
Position.Z += Speed * Math.Sin(Orientation.Yaw) * Math.Cos(Orientation.Pitch) * deltaTime;
}
public void TakeDamage(double damage)
{
CurrentArmor -= damage;
if (CurrentArmor <= 0)
{
CurrentArmor = 0;
IsActive = false;
}
}
public override string GetStatus()
{
return $"坦克 {Id}:\n" +
$" 位置: X={Position.X:F2}, Y={Position.Y:F2}, Z={Position.Z:F2}\n" +
$" 装甲: {CurrentArmor:F2}";
}
}
}

114
Program.cs Normal file
View File

@ -0,0 +1,114 @@
using System;
using System.Threading;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Models;
namespace ActiveProtect
{
class Program
{
static void Main(string[] args)
{
// 创建仿真配置
var config = new SimulationConfig
{
TankConfigs =
[
new() {
InitialPosition = new Vector3D(100, 0, 100),
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 0,
MaxSpeed = 20,
MaxArmor = 100
}
],
MissileConfigs =
[
// 标准导弹配置
new() {
InitialPosition = new Vector3D(1500, 200, 100),
InitialOrientation = new Orientation(Math.PI, -0.1, 0),
InitialSpeed = 10,
MaxSpeed = 400,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightDistance = 5000,
ThrustAcceleration = 80,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = Missile.FlightStageConfig.StandardMissile,
DistanceParams = new MissileDistanceParams(500, 100, 20),
Type = MissileType.StandardMissile
},
// 激光制导炮弹配置
new() {
InitialPosition = new Vector3D(2000, 150, 100),
InitialOrientation = new Orientation(Math.PI, -0.15, 0),
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightDistance = 5000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = Missile.FlightStageConfig.LaserGuidedShell,
DistanceParams = new MissileDistanceParams(300, 100, 20),
Type = MissileType.InfraredCommandGuidance
},
// 短程导弹配置
new() {
InitialPosition = new Vector3D(1000, 50, 100),
InitialOrientation = new Orientation(Math.PI, -0.05, 0),
InitialSpeed = 10,
MaxSpeed = 300,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightDistance = 3000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = Missile.FlightStageConfig.ShortRangeMissile,
DistanceParams = new MissileDistanceParams(400, 100, 20),
Type = MissileType.MillimeterWaveTerminalGuidance
},
// 新增激光半主动制导导弹配置
new() {
InitialPosition = new Vector3D(2000, 150, 100),
InitialOrientation = new Orientation(Math.PI, -0.12, 0),
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 20,
MaxFlightDistance = 4500,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = Missile.FlightStageConfig.LaserSemiActiveGuidedMissile,
DistanceParams = new MissileDistanceParams(500, 200, 20),
Type = MissileType.SemiActiveLaserGuidance
}
],
SimulationTimeStep = 0.05
};
// 创建仿真管理器
var simulationManager = new SimulationManager(config);
// 运行仿真
while (!simulationManager.IsSimulationEnded)
{
simulationManager.Update();
simulationManager.PrintStatus();
Thread.Sleep(100); // 暂停100毫秒使输出更易读
}
Console.WriteLine("仿真结束");
}
}
}

169
README.md Normal file
View File

@ -0,0 +1,169 @@
# ActiveProtect 仿真系统
## 项目概述
ActiveProtect 是一个复杂的军事仿真系统,旨在模拟导弹和坦克之间的交互。该系统能够模拟三维空间中的运动,考虑天气、地形等环境因素,并评估防御系统的有效性。
## 主要功能
1. 三维空间仿真:使用 Vector3D 和 Orientation 结构精确模拟物体在三维空间中的位置和方向。
2. 导弹和坦克模拟:包括运动、攻击和防御逻辑。
3. 环境因素:考虑天气和地形对仿真的影响。
4. 数据收集与分析:实时收集仿真数据,并进行后续分析。
5. 评估模型:评估仿真结果,计算各种性能指标。
6. 可视化和报告:生成数据可视化和评估报告。
## 核心组件
1. SimulationElement: 所有仿真元素的基类。
2. Tank 和 Missile: 继承自 SimulationElement,实现具体的坦克和导弹逻辑。
3. SimulationManager: 管理整个仿真过程。
4. SimulationConfig: 用于配置仿真参数。
5. DataCollector: 收集仿真数据。
6. EvaluationModel: 评估仿真结果。
7. Weather 和 Terrain: 模拟环境因素。
## 使用方法
1. 配置仿真参数:
```csharp
var config = new SimulationConfig
{
// 设置坦克、导弹、环境等参数
};
```
2. 创建并运行仿真:
```csharp
var simulationManager = new SimulationManager(config);
simulationManager.RunSimulation();
```
3. 分析结果:
```csharp
var evaluationResult = simulationManager.EvaluateSimulation();
var report = ReportGenerator.GenerateReport(evaluationResult);
```
## 未来改进
1. 实现更复杂的导弹追踪算法。
2. 添加更多类型的防御系统。
3. 改进环境模拟的真实性。
4. 开发图形用户界面以便更直观地配置和运行仿真。
## 贡献
欢迎提交 Pull Requests 来改进这个项目。在提交之前,请确保您的代码符合项目的编码规范,并且通过了所有的单元测试。
## 许可证
本项目采用 MIT 许可证。详情请见 [LICENSE](LICENSE) 文件。
## 仿真运行流程(这个 Mermaid 图表会在支持 Mermaid 的 Markdown 查看器中渲染为一个流程图)
```mermaid
graph TD
A[开始仿真] --> B[初始化SimulationManager]
B --> C[加载SimulationConfig]
C --> D[创建仿真元素]
D --> E[开始仿真循环]
E --> F{是否结束仿真?}
F -->|否| G[更新所有元素]
G --> H[收集数据]
H --> I[处理事件]
I --> E
F -->|是| J[结束仿真]
J --> K[评估结果]
K --> L[生成报告]
L --> M[结束]
```
# 反坦克导弹仿真系统
本项目旨在模拟反坦克导弹的飞行过程和攻击效果。
## 反坦克导弹飞行阶段
反坦克导弹的飞行过程通常可以分为以下几个主要阶段:
1. 发射阶段
- 导弹从发射装置或发射管中被推出
- 火箭发动机点火,提供初始推力
2. 加速阶段
- 导弹迅速加速到巡航速度
- 可能会抛掉一些辅助推进装置(如有)
3. 巡航阶段
- 导弹保持相对稳定的速度飞向目标
- 根据导引系统类型,可能会进行中途修正
4. 终端制导阶段
- 导弹接近目标,进入最后的制导阶段
- 可能会启动终端制导系统,如毫米波雷达或红外成像系统
5. 攻击阶段
- 导弹进行最后的机动,以最佳角度接近目标
- 可能会启动穿甲弹头或预制破片
6. 爆炸阶段
- 导弹击中目标并引爆
- 根据弹头类型,可能是穿甲、破片或破片-燃烧等效果
在仿真中,这些阶段被纳入计算,每个阶段可能有不同的物理特性和行为模式。例如,加速阶段可能有较大的加速度,而巡航阶段则保持恒定速度。终端制导阶段可能会有更频繁的方向调整。
## 项目结构
```
ActiveProtect/
├── Program.cs # 主程序入口
├── SimulationEnvironment/ # 仿真环境相关类
│ ├── SimulationManager.cs # 仿真管理器
│ └── SimulationConfig.cs # 仿真配置
├── Models/ # 模型类
│ ├── Tank.cs # 坦克模型
│ ├── Missile.cs # 导弹模型
│ ├── Vector3D.cs # 3D向量
│ └── Orientation.cs # 方向类
└── ActiveProtect.csproj # 项目文件
```
## 如何运行
1. 确保你的系统已安装 .NET 8.0 或更高版本。
2. 在终端中导航到项目根目录。
3. 运行以下命令来构建项目:
```
dotnet build
```
4. 运行以下命令来启动仿真:
```
dotnet run
```
## 注意事项
- 当前仿真使用简化模型,可能无法完全反映真实世界的复杂性。
- 仿真结果仅供参考,不应用于实际军事决策。
## 比例导引系数N的选择
在导弹制导系统中比例导引系数N是一个关键参数它直接影响导弹的性能和行为。在我们的仿真系统中用户可以根据不同的场景需求调整这个参数。
### N 值的影响
- **N = 3**:这是一个较为保守的选择,适合大多数情况。它提供了良好的稳定性和能源效率,但可能在应对高机动性目标时表现不佳。
- **N = 4**:这个值提供了更积极的制导,适合需要更高机动性的场景。它能更快地响应目标的变化,但可能会增加能源消耗。
- **N = 5**:这是一个更激进的选择,提供最高的机动性,但也带来了更大的能源消耗和可能的过度修正。
### 选择 N 值的考虑因素
1. **导弹类型**:大型、长程导弹通常使用较小的 N 值,而小型、短程导弹可以使用较大的 N 值。
2. **目标特性**:对付高速、高机动性目标时,可能需要较大的 N 值。
3. **作战环境**:在复杂环境中,可能需要更大的 N 值来应对突发情况。
4. **能源限制**:如果导弹燃料有限,较小的 N 值可以帮助节省能源。
5. **制导系统精度**:精度较高的系统可以使用较小的 N 值,而精度较低的系统可能需要较大的 N 值来补偿误差。
6. **任务要求**:精确打击任务可能需要较大的 N 值,而区域防御任务可能使用较小的 N 值。
在我们的仿真系统中,用户可以通过调整 `ProportionalNavigationCoefficient` 参数来设置不同的 N 值,以模拟各种实际情况下的导弹行为。我们建议用户尝试不同的 N 值,观察其对导弹性能的影响,以找到最适合特定场景的设置。