commit edfead8927b1dcd75cc55a2ef0ed1b7e94d89614
Author: Tian jianyong <11429339@qq.com>
Date: Sun Oct 6 09:09:32 2024 +0800
创建项目,添加基础类
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2b97d60
--- /dev/null
+++ b/.gitignore
@@ -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
\ No newline at end of file
diff --git a/ActiveProtect.csproj b/ActiveProtect.csproj
new file mode 100644
index 0000000..206b89a
--- /dev/null
+++ b/ActiveProtect.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/ActiveProtect.sln b/ActiveProtect.sln
new file mode 100644
index 0000000..414cdb7
--- /dev/null
+++ b/ActiveProtect.sln
@@ -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
diff --git a/Environment/ISimulatinManager.cs b/Environment/ISimulatinManager.cs
new file mode 100644
index 0000000..2daa4a3
--- /dev/null
+++ b/Environment/ISimulatinManager.cs
@@ -0,0 +1,7 @@
+using ActiveProtect.Models;
+
+public interface ISimulationManager
+{
+ Vector3D GetElementPosition(string elementId);
+ // 添加其他必要的方法
+}
diff --git a/Environment/SimulationConfig.cs b/Environment/SimulationConfig.cs
new file mode 100644
index 0000000..290d687
--- /dev/null
+++ b/Environment/SimulationConfig.cs
@@ -0,0 +1,71 @@
+using ActiveProtect.Models;
+
+namespace ActiveProtect.SimulationEnvironment
+{
+ public class SimulationConfig
+ {
+ public List TankConfigs { get; set; }
+ public List 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; // 导弹类型
+ }
+ }
+}
diff --git a/Environment/SimulationElement.cs b/Environment/SimulationElement.cs
new file mode 100644
index 0000000..f642c0b
--- /dev/null
+++ b/Environment/SimulationElement.cs
@@ -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}";
+ }
+ }
+}
diff --git a/Environment/SimulationManager.cs b/Environment/SimulationManager.cs
new file mode 100644
index 0000000..6929662
--- /dev/null
+++ b/Environment/SimulationManager.cs
@@ -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 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");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Models/Common.cs b/Models/Common.cs
new file mode 100644
index 0000000..c9ed4f8
--- /dev/null
+++ b/Models/Common.cs
@@ -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 // 毫米波终端制导
+ }
+
+}
diff --git a/Models/LaserSemiActiveGuidedMissile.cs b/Models/LaserSemiActiveGuidedMissile.cs
new file mode 100644
index 0000000..7337f64
--- /dev/null
+++ b/Models/LaserSemiActiveGuidedMissile.cs
@@ -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 ? "是" : "否")}";
+ }
+ }
+}
diff --git a/Models/Missile.cs b/Models/Missile.cs
new file mode 100644
index 0000000..2e87931
--- /dev/null
+++ b/Models/Missile.cs
@@ -0,0 +1,315 @@
+using System;
+using ActiveProtect.SimulationEnvironment;
+
+namespace ActiveProtect.Models
+{
+ ///
+ /// 表示仿真中的导弹
+ ///
+ public class Missile : SimulationElement
+ {
+ ///
+ /// 导弹类型
+ ///
+ public MissileType Type { get; protected set; }
+
+ ///
+ /// 导弹飞行的各个阶段
+ ///
+ public enum FlightStage
+ {
+ Launch, // 发射阶段
+ Acceleration, // 加速阶段
+ Cruise, // 巡航阶段
+ TerminalGuidance, // 终端制导阶段
+ Attack, // 攻击阶段
+ Explosion // 爆炸阶段
+ }
+
+ ///
+ /// 导弹飞行阶段的配置结构
+ ///
+ ///
+ /// 初始化飞行阶段配置
+ ///
+ 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;
+
+ ///
+ /// 标准导弹的预设配置, 所有阶段都启用
+ ///
+ public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true);
+
+ ///
+ /// 激光制导炮弹的预设配置, 没有加速阶段
+ ///
+ public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false);
+
+ ///
+ /// 短程导弹的预设配置,没有巡航阶段
+ ///
+ public static FlightStageConfig ShortRangeMissile => new(enableCruise: false);
+
+ ///
+ /// 激光半主动制导导弹的预设配置, 没有加速阶段
+ ///
+ 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 ? "超出最大飞行距���" :
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/Models/Tank.cs b/Models/Tank.cs
new file mode 100644
index 0000000..645fa8d
--- /dev/null
+++ b/Models/Tank.cs
@@ -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}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..8bb23e0
--- /dev/null
+++ b/Program.cs
@@ -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("仿真结束");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c866420
--- /dev/null
+++ b/README.md
@@ -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 值,观察其对导弹性能的影响,以找到最适合特定场景的设置。