重新提交全部代码, 去掉无用文件

This commit is contained in:
Tian jianyong 2024-10-19 14:26:26 +08:00
parent 813700e6b0
commit 47849abf9e
30 changed files with 5043 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

65
.cursorrules Normal file
View File

@ -0,0 +1,65 @@
# Cursor Rules
You are an expert in C#, Unity, and scalable game development.
Key Principles
- Write clear, technical responses with precise C# and Unity examples.
- Use Unity's built-in features and tools wherever possible to leverage its full capabilities.
- Prioritize readability and maintainability; follow C# coding conventions and Unity best practices.
- Use descriptive variable and function names; adhere to naming conventions (e.g., PascalCase for public members, camelCase for private members).
- Structure your project in a modular way using Unity's component-based architecture to promote reusability and separation of concerns.
C#/Unity
- Use MonoBehaviour for script components attached to GameObjects; prefer ScriptableObjects for data containers and shared resources.
- Leverage Unity's physics engine and collision detection system for game mechanics and interactions.
- Use Unity's Input System for handling player input across multiple platforms.
- Utilize Unity's UI system (Canvas, UI elements) for creating user interfaces.
- Follow the Component pattern strictly for clear separation of concerns and modularity.
- Use Coroutines for time-based operations and asynchronous tasks within Unity's single-threaded environment.
- Use System.Console for logging and debugging in the console.
- Using C# 9.0 features.
Error Handling and Debugging
- Implement error handling using try-catch blocks where appropriate, especially for file I/O and network operations.
- Use Unity's Debug class for logging and debugging (e.g., Debug.Log, Debug.LogWarning, Debug.LogError).
- Utilize Unity's profiler and frame debugger to identify and resolve performance issues.
- Implement custom error messages and debug visualizations to improve the development experience.
- Use Unity's assertion system (Debug.Assert) to catch logical errors during development.
Dependencies
- Unity Engine
- .NET Framework (version compatible with your Unity version)
- Unity Asset Store packages (as needed for specific functionality)
- Third-party plugins (carefully vetted for compatibility and performance)
Unity-Specific Guidelines
- Use Prefabs for reusable game objects and UI elements.
- Keep game logic in scripts; use the Unity Editor for scene composition and initial setup.
- Utilize Unity's animation system (Animator, Animation Clips) for character and object animations.
- Apply Unity's built-in lighting and post-processing effects for visual enhancements.
- Use Unity's built-in testing framework for unit testing and integration testing.
- Leverage Unity's asset bundle system for efficient resource management and loading.
- Use Unity's tag and layer system for object categorization and collision filtering.
Performance Optimization
- Use object pooling for frequently instantiated and destroyed objects.
- Optimize draw calls by batching materials and using atlases for sprites and UI elements.
- Implement level of detail (LOD) systems for complex 3D models to improve rendering performance.
- Use Unity's Job System and Burst Compiler for CPU-intensive operations.
- Optimize physics performance by using simplified collision meshes and adjusting fixed timestep.
Key Conventions
1. Follow Unity's component-based architecture for modular and reusable game elements.
2. Prioritize performance optimization and memory management in every stage of development.
3. Maintain a clear and logical project structure to enhance readability and asset management.
Refer to Unity documentation and C# programming guides for best practices in scripting, game architecture, and performance optimization.

237
.gitignore vendored Normal file
View File

@ -0,0 +1,237 @@
# Visual Studio files
.vs/
*.user
*.userosscache
*.suo
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# ReSharper
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# Visual Studio Code
.vscode/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Rider
.idea/
*.sln.iml
# User-specific files
*.rsuser

11
ActiveProtect.csproj Normal file
View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>9.0</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

29
ActiveProtect.sln Normal file
View File

@ -0,0 +1,29 @@

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
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.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

150
Design.md Normal file
View File

@ -0,0 +1,150 @@
# 导弹仿真系统设计文档
## 系统架构设计思路
在处理导弹、坦克、告警设备、干扰设备等复杂交互关系时,我们采用了以下几种程序架构和设计模式的组合:
### 1. 事件驱动架构Event-Driven Architecture
事件驱动架构非常适合处理复杂的交互关系。每个实体(如导弹、坦克等)可以发布事件,其他实体可以订阅这些事件并作出反应。
``csharp
public class EventManager
{
private Dictionary<string, List<Action<object>>> eventSubscribers = new Dictionary<string, List<Action<object>>>();
public void Subscribe(string eventName, Action<object> listener) { ... }
public void Publish(string eventName, object eventData) { ... }
}
``
### 2. 组件系统Component System
将每个实体分解为多个组件,每个组件负责特定的功能。这样可以更灵活地组合不同的功能。
``csharp
public class Entity
{
public PositionComponent Position { get; set; }
public VelocityComponent Velocity { get; set; }
public HealthComponent Health { get; set; }
}
``
### 3. 观察者模式Observer Pattern
类似于事件驱动架构,但更加面向对象。每个实体可以作为观察者或被观察者。
``csharp
public interface IObserver
{
void Update(ISubject subject);
}
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
``
### 4. 状态机State Machine
对于有明确状态转换的实体(如导弹的飞行阶段),使用状态机可以更清晰地管理状态转换。
``csharp
public enum MissileState
{
Idle,
Tracking,
Locking,
Firing,
Exploding
}
public class Missile
{
public MissileState State { get; set; }
public void ChangeState(MissileState newState) { ... }
}
``csharp
public interface IState
{
void Enter();
void Update();
void Exit();
}
public class MissileStateMachine
{
private IState currentState;
public void ChangeState(IState newState) { ... }
public void Update() { ... }
}
``
### 5. 命令模式Command Pattern
用于封装各种操作,使得可以轻松地添加新的交互行为。
``csharp
public interface ICommand
{
void Execute();
}
public class FireMissileCommand : ICommand
{
public void Execute() { ... }
}
``
## 架构组合使用
在实际应用中,我们将这些模式组合使用:
1. 使用事件驱动架构作为整体框架,处理系统中的各种事件。
2. 采用组件系统来构建各个实体(如导弹、坦克、告警设备等)。
3. 使用状态机来管理导弹的飞行阶段。
4. 应用观察者模式来处理告警设备的通知机制。
5. 使用命令模式来封装各种交互操作,如发射导弹、激活干扰设备等。
这种组合架构允许我们灵活地处理复杂的交互关系,同时保持代码的可维护性和可扩展性。
## 下一步计划
- 实现核心实体(导弹、坦克、告警设备、干扰设备)的基本功能。
- 设计并实现事件系统,处理实体间的交互。
- 开发状态机,管理导弹的飞行阶段。
- 实现观察者模式,处理告警通知。
- 使用命令模式封装关键操作。
- 进行单元测试和集成测试,确保系统的正确性和稳定性。
## 数据库访问架构
在Unity3D环境中考虑到兼容性和易用性我推荐使用第二种方法值对象模式。这种方式有以下几个优点
1. 分离关注点数据库实体MissileConfigEntity和游戏中使用的配置对象MissileConfig是分开的这样可以避免 ORM 相关的属性和特性污染游戏逻辑。
2. 灵活性:可以轻松地在数据库实体和游戏配置对象之间进行转换,而不影响现有的游戏逻辑。
3. 序列化友好Unity 经常需要序列化对象,使用纯粹的 C# 对象(如 MissileConfig更容易进行序列化和反序列化。
4. 兼容性好:这种方法不依赖于特定的 ORM 框架,如果将来需要更换数据库或 ORM 系统,影响会较小。
数据访问层使用了 Dapper一个轻量级的 ORM它在 Unity 中使用较为简单。
数据库设计
### 1. 导弹数据库设计
导弹数据库设计需要考虑导弹的属性、状态、行为等。
#### 1.1 导弹属性
导弹属性包括导弹的初始位置、初始速度、最大速度、目标索引、最大飞行时间、最大飞行距离、飞行阶段配置、推力加速度、最大发动机燃烧时间、最大加速度、距离参数、比例导引系数、类型等。
#### 1.2 导弹状态
导弹状态包括导弹的当前位置、当前速度、当前加速度、当前飞行阶段、当前目标索引、当前最大速度、当前最大加速度、当前最大飞行距离、当前最大飞行时间、当前比例导引系数等。
#### 1.3 导弹行为
导弹行为包括导弹的飞行行为、攻击行为、躲避行为、跟踪行为、锁定行为、发射行为、爆炸行为等。

105
DesignMissile.md Normal file
View File

@ -0,0 +1,105 @@
# 实体设计
在仿真环境中,每个实体(如导弹)有几类参数:
1. 固有属性参数:如弹长、弹径、质量,最大速度、最大飞行距离、发动机推力等
2. 运行时状态参数:如当前位置、速度、朝向、加速度,接收的辐射能量、导引头视野中目标角度等
为了设计一个结构清晰的实体类,我们采用组合模式和接口分离原则。这样可以将不同类型的参数和状态分开管理,同时保持良好的扩展性。
## 基础接口
首先,我们定义几个基础接口来表示不同类型的参数:
```csharp
public interface IProperties
{
double Length { get; }
double Diameter { get; }
double Mass { get; }
}
public interface IState
{
Vector3 Position { get; set; }
Vector3 Velocity { get; set; }
Vector3 Acceleration { get; set; }
double Heading { get; set; }
double ReceivedRadiation { get; set; }
double TargetDeviation { get; set; }
}
```
## 实现类
然后,我们为每个接口创建实现类:
public class MissileProperties : IProperties
{
public double Length { get; }
public double Diameter { get; }
public double Mass { get; }
}
public class MissileState : IState
{
public Vector3 Position { get; set; }
public Vector3 Velocity { get; set; }
public Vector3 Acceleration { get; set; }
public double Heading { get; set; }
public double ReceivedRadiation { get; set; }
public double TargetDeviation { get; set; }
}
## 导弹实体类
接下来,我们创建一个导弹实体类,它将实现上述接口:
```csharp
public class Missile : IProperties, IState
{
public MissileProperties Properties { get; set; }
public MissileState State { get; set; }
public Missile()
{
Properties = new MissileProperties();
State = new MissileState();
}
// 其他方法,如更新状态、执行导航等
public void Update(double deltaTime)
{
// 更新运行时状态和导引参数
}
public void Navigate()
{
// 执行导航逻辑
}
}
```
## 设计优点
1. 清晰的结构:每种类型的参数或状态都有自己的接口和实现类,使得结构非常清晰。
2. 高度的模块化:可以轻松地替换或修改某一类参数,而不影响其他部分。
3. 易于扩展:如果需要添加新的参数类型,只需创建新的接口和实现类,然后在 Missile 类中添加相应的属性。
4. 符合单一职责原则:每个类都只负责一种类型的参数。
5. 便于测试:可以轻松地为每种参数类型创建模拟对象,便于单元测试。
6. 灵活性:可以为不同类型的导弹创建不同的参数实现,而保持相同的接口。
## 在激光驾束制导中, 为了实现更平滑的控制同时将加速度控制在25 m/s²以下并保持偏移在1.5米以内,我们可以采用以下几种方法
1. 使用PID控制器
PID比例-积分-微分)控制器可以提供更平滑和精确的控制。它考虑了误差的历史、当前值和变化率。
2. 非线性增益:
使用非线性函数来计算增益,使得在接近目标时增益减小,远离目标时增益增大。
3. 低通滤波:
对计算出的加速度进行低通滤波,以减少高频振荡。
4. 预测控制:
基于当前状态预测未来的位置,提前做出调整。

BIN
Models/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,10 @@
{
"folders": [
{
"path": "../../ActiveProtect.Tests"
},
{
"path": ".."
}
]
}

View File

@ -0,0 +1,90 @@
using System;
namespace ActiveProtect.Models
{
public class BasicGuidanceSystem : IGuidanceSystem
{
public bool HasGuidance { get; protected set; }
protected double ProportionalNavigationCoefficient { get; set; }
protected Vector3D Position { get; set; }
protected Vector3D Velocity { get; set; }
protected Vector3D GuidanceCommand { get; set; }
public BasicGuidanceSystem(double proportionalNavigationCoefficient)
{
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
HasGuidance = false;
GuidanceCommand = Vector3D.Zero;
Position = Vector3D.Zero;
Velocity = Vector3D.Zero;
}
public virtual void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
Position = missilePosition;
Velocity = missileVelocity;
}
public Vector3D GetGuidanceCommand()
{
return GuidanceCommand;
}
protected virtual void CalculateGuidanceCommand(double deltaTime)
{
// 基础制导系统不计算制导指令
// 派生类应该重写这个方法来实现特定的制导逻辑
}
protected Vector3D CalculateProportionalNavigation(Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
{
// 预测时间(可以根据实际情况调整)
double predictionTime = 2.0;
// 预测目标位置
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;
}
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);
}
}
}

297
Models/Common.cs Normal file
View File

@ -0,0 +1,297 @@
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 表示三维空间中的向量
/// </summary>
public class Vector3D
{
// 添加静态单位向量属性
public static Vector3D UnitX => new Vector3D(1, 0, 0);
public static Vector3D UnitY => new Vector3D(0, 1, 0);
public static Vector3D UnitZ => new Vector3D(0, 0, 1);
public static Vector3D Zero => new Vector3D(0, 0, 0);
/// <summary>
/// X 坐标
/// </summary>
public double X { get; set; }
/// <summary>
/// Y 坐标
/// </summary>
public double Y { get; set; }
/// <summary>
/// Z 坐标
/// </summary>
public double Z { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public Vector3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
/// <summary>
/// 计算两个向量之间的距离
/// </summary>
/// <param name="v1">第一个向量</param>
/// <param name="v2">第二个向量</param>
/// <returns>两个向量之间的距离</returns>
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));
}
/// <summary>
/// 将向量转换为字符串表示
/// </summary>
/// <returns>向量的字符串表示</returns>
public override string ToString()
{
return $"({X:F2}, {Y:F2}, {Z:F2})";
}
/// <summary>
/// 向量减法运算符重载
/// </summary>
public static Vector3D operator -(Vector3D a, Vector3D b)
{
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
/// <summary>
/// 向量加法运算符重载
/// </summary>
public static Vector3D operator +(Vector3D a, Vector3D b)
{
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
/// <summary>
/// 向量与标量乘法运算符重载
/// </summary>
public static Vector3D operator *(Vector3D a, double scalar)
{
return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar);
}
/// <summary>
/// 向量与标量除法运算符重载
/// </summary>
public static Vector3D operator /(Vector3D a, double scalar)
{
return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar);
}
/// <summary>
/// 向量反向
/// </summary>
public static Vector3D operator -(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
/// <summary>
/// 计算向量的模长
/// </summary>
/// <returns>向量的模长</returns>
public double Magnitude()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
/// <summary>
/// 计算向量模长的平方
/// </summary>
/// <returns>向量模长的平方</returns>
public double MagnitudeSquared()
{
return X * X + Y * Y + Z * Z;
}
/// <summary>
/// 向量归一化
/// </summary>
/// <returns>归一化后的向量</returns>
public Vector3D Normalize()
{
double mag = Magnitude();
if (mag > 0)
{
return new Vector3D(X / mag, Y / mag, Z / mag);
}
return new Vector3D(0, 0, 0);
}
/// <summary>
/// 计算两个向量的叉积
/// </summary>
/// <param name="a">第一个向量</param>
/// <param name="b">第二个向量</param>
/// <returns>叉积结果</returns>
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
);
}
/// <summary>
/// 计算两个向量的点积
/// </summary>
/// <param name="a">第一个向量</param>
/// <param name="b">第二个向量</param>
/// <returns>点积结果</returns>
public static double DotProduct(Vector3D a, Vector3D b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
/// <summary>
/// 向量取反
/// </summary>
/// <param name="a">输入向量</param>
/// <returns>取反后的向量</returns>
public static Vector3D Negate(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
}
/// <summary>
/// 表示三维空间中的方向
/// </summary>
public struct Orientation
{
/// <summary>
/// 偏航角绕Y轴旋转
/// </summary>
public double Yaw { get; set; }
/// <summary>
/// 俯仰角绕X轴旋转
/// </summary>
public double Pitch { get; set; }
/// <summary>
/// 滚转角绕Z轴旋转
/// </summary>
public double Roll { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public Orientation(double yaw, double pitch, double roll)
{
Yaw = yaw;
Pitch = pitch;
Roll = roll;
}
/// <summary>
/// 将方向转换为字符串表示
/// </summary>
/// <returns>方向的字符串表示</returns>
public override readonly string ToString()
{
return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})";
}
/// <summary>
/// 将角度归一化到 [-π, π] 范围内
/// </summary>
public void Normalize()
{
Yaw = NormalizeAngle(Yaw);
Pitch = NormalizeAngle(Pitch);
Roll = NormalizeAngle(Roll);
}
/// <summary>
/// 将单个角度归一化到 [-π, π] 范围内
/// </summary>
/// <param name="angle">输入角度</param>
/// <returns>归一化后的角度</returns>
private static double NormalizeAngle(double angle)
{
while (angle > Math.PI) angle -= 2 * Math.PI;
while (angle <= -Math.PI) angle += 2 * Math.PI;
return angle;
}
/// <summary>
/// 根据给定的方向向量创建方向
/// </summary>
/// <param name="direction">方向向量</param>
/// <returns>对应的方向</returns>
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);
}
/// <summary>
/// 将方向转换为单位向量
/// </summary>
/// <returns>对应的单位向量</returns>
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
);
}
/// <summary>
/// 从向量创建方向
/// </summary>
/// <param name="vector">输入向量</param>
/// <returns>对应的方向</returns>
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 struct Vector2D
{
public double X { get; set; }
public double Y { get; set; }
public Vector2D(double x, double y)
{
X = x;
Y = y;
}
public static Vector2D Zero => new Vector2D(0, 0);
}
}

View File

@ -0,0 +1,9 @@
namespace ActiveProtect.Models
{
public interface IGuidanceSystem
{
bool HasGuidance { get; }
void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity);
Vector3D GetGuidanceCommand();
}
}

157
Models/LaserBeamRider.cs Normal file
View File

@ -0,0 +1,157 @@
using ActiveProtect.SimulationEnvironment;
using System;
namespace ActiveProtect.Models
{
public class LaserBeamRider : SimulationElement
{
// 激光功率(瓦特)
public double LaserPower { get; private set; }
// 激光发散角(毫弧度)
public double BeamDivergence { get; private set; } = 0.0;
// 控制场直径(米)
public double ControlFieldDiameter { get; private set; }
// 激光方向
public Vector3D LaserDirection { get; private set; }
// 最大导引距离(米)
public double MaxGuidanceDistance { get; private set; }
// 激光束是否开启
public bool IsBeamOn { get; private set; }
// 导弹
public string MissileId { get; private set; }
// 目标
public string TargetId { get; private set; }
public LaserBeamRider(string id, string missileId, string targetId, LaserBeamRiderConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(0, 0, 0), simulationManager)
{
LaserPower = config.LaserPower;
ControlFieldDiameter = config.ControlFieldDiameter;
LaserDirection = Vector3D.Zero;
MaxGuidanceDistance = config.MaxGuidanceDistance;
IsActive = false; // 初始状态为非激活
IsBeamOn = false;
MissileId = missileId;
TargetId = targetId;
SimulationManager = simulationManager;
}
public override void Update(double deltaTime)
{
if (IsActive && IsBeamOn)
{
// 更新驾束仪的激光指向
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
LaserDirection = (targetPosition - Position).Normalize();
Console.WriteLine($"激光驾束仪 {Id} 更新激光指向: {LaserDirection}");
PublishLaserBeamUpdateEvent();
}
}
/// <summary>
/// 激活激光驾束仪
/// </summary>
public override void Activate()
{
if (!IsActive)
{
IsActive = true;
Console.WriteLine($"激光驾束仪 {Id} 已激活");
}
base.Activate();
}
/// <summary>
/// 停用激光驾束仪
/// </summary>
public override void Deactivate()
{
if (IsActive)
{
IsActive = false;
if (IsBeamOn)
{
StopBeamIllumination();
}
Console.WriteLine($"激光驾束仪 {Id} 已停用");
}
base.Deactivate();
}
public void StartBeamIllumination()
{
if (!IsBeamOn)
{
LaserDirection = (SimulationManager.GetEntityById(TargetId).Position - Position).Normalize();
IsBeamOn = true;
PublishLaserBeamStartEvent();
}
}
public void StopBeamIllumination()
{
if (IsBeamOn)
{
IsBeamOn = false;
LaserDirection = Vector3D.Zero;
PublishLaserBeamStopEvent();
}
}
/// <summary>
/// 发布激光束开始事件
/// </summary>
private void PublishLaserBeamStartEvent()
{
PublishEvent(new LaserBeamStartEvent
{
LaserBeamRider = this
});
}
/// <summary>
/// 发布激光束更新事件
/// </summary>
private void PublishLaserBeamUpdateEvent()
{
PublishEvent(new LaserBeamUpdateEvent
{
LaserBeamRider = this
});
}
/// <summary>
/// 发布激光束停止事件
/// </summary>
private void PublishLaserBeamStopEvent()
{
PublishEvent(new LaserBeamStopEvent
{
LaserBeamRider = this
});
}
public override string GetStatus()
{
return $"激光驾束仪 {Id}:\n" +
$" 位置: {Position}\n" +
$" 方向: {LaserDirection}\n" +
$" 激活状态: {(IsActive ? "" : "")}\n" +
$" 激光功率: {LaserPower} W\n" +
$" 发散角: {BeamDivergence} rad\n" +
$" 控制场直径: {ControlFieldDiameter} m\n" +
$" 最大导引距离: {MaxGuidanceDistance} m\n" +
$" 激光束状态: {(IsBeamOn ? "" : "")}";
}
}
}

View File

@ -0,0 +1,193 @@
using System;
namespace ActiveProtect.Models
{
public class LaserBeamRiderGuidanceSystem : BasicGuidanceSystem
{
private Vector3D LaserSourcePosition { get; set; }
private Vector3D LaserDirection { get; set; }
public double LaserPower { get; set; }
private const double MinDetectablePower = 1e-3; // 假设最小可探测功率为1毫瓦
private const double DetectorDiameter = 0.1; // 假设探测器直径为10厘米
private const double ControlFieldDiameter = 20.0; // 控制场直径(米)
private Vector3D LastError = Vector3D.Zero;
public Vector3D LastGuidanceCommand { get; private set; }
private Vector3D IntegralError = Vector3D.Zero;
public LaserBeamRiderGuidanceSystem(double proportionalNavigationCoefficient)
: base(proportionalNavigationCoefficient)
{
LaserSourcePosition = Vector3D.Zero;
LaserDirection = Vector3D.Zero;
LaserPower = 0;
HasGuidance = false;
LastGuidanceCommand = Vector3D.Zero;
}
public void ActivateLaserBeam(Vector3D sourcePosition, Vector3D direction, double laserPower)
{
LaserSourcePosition = sourcePosition;
LaserDirection = direction.Normalize();
LaserPower = laserPower;
HasGuidance = true;
}
public void UpdateLaserBeamRider(Vector3D sourcePosition, Vector3D direction, double laserPower)
{
LaserSourcePosition = sourcePosition;
LaserDirection = direction.Normalize();
LaserPower = laserPower;
}
public void DeactivateLaserBeam(Vector3D sourcePosition, Vector3D direction)
{
LaserSourcePosition = Vector3D.Zero;
LaserDirection = Vector3D.Zero;
LaserPower = 0;
HasGuidance = false;
}
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
UpdateGuidanceStatus();
if (HasGuidance)
{
CalculateGuidanceCommand(deltaTime);
}
else
{
GuidanceCommand = Vector3D.Zero;
}
}
private void UpdateGuidanceStatus()
{
// 计算导弹到激光束的最短距离
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
double shortestDistance = shortestDistanceVector.Magnitude();
// 检查导弹是否在控制场内
if (shortestDistance > ControlFieldDiameter / 2)
{
HasGuidance = false;
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
return;
}
Console.WriteLine($"激光驾束引导系统: 在控制场内, 距离: {shortestDistance}");
// 计算接收到的激光功率
double beamArea = Math.PI * Math.Pow(ControlFieldDiameter / 2, 2);
double powerDensity = LaserPower / beamArea;
double receivedPower = powerDensity * (Math.PI * Math.Pow(DetectorDiameter / 2, 2));
if(HasGuidance = receivedPower >= MinDetectablePower)
{
HasGuidance = true;
}
else
{
HasGuidance = false;
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W");
}
}
protected override void CalculateGuidanceCommand(double deltaTime)
{
if (!HasGuidance)
{
GuidanceCommand = Vector3D.Zero;
return;
}
// 计算导弹到激光束的最短距离
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
// PID控制
double Kp = 30; // 增加比例系数,使系统对误差更敏感,反应更快 30
double Ki = 0.05; // 减小积分系数,减少长期误差累积的影响 0.05
double Kd = 5; // 增加微分系数,减少系统的超调量,提高稳定性 5
double Kc = 0.5; // 减小非线性增益系数, 控制偏移量, 使得在更小的误差范围内有更大的修正 0.5
// 计算误差
Vector3D error = shortestDistanceVector;
// 积分项
IntegralError += error * deltaTime;
// 微分项
Vector3D derivativeError = (error - LastError) / deltaTime;
// 计算PID输出
Vector3D pidOutput = error * Kp + IntegralError * Ki + derivativeError * Kd;
// 非线性增益
double distance = shortestDistanceVector.Magnitude();
double nonLinearGain = Math.Tanh(distance / Kc);
// 计算横向加速度
Vector3D lateralAcceleration = pidOutput * nonLinearGain;
// 限制最大加速度
double maxAcceleration = 50; // 稍微增加最大加速度 50
if (lateralAcceleration.Magnitude() > maxAcceleration)
{
lateralAcceleration = lateralAcceleration.Normalize() * maxAcceleration;
}
// 计算前向加速度
Vector3D forwardDirection = LaserDirection;
Vector3D currentDirection = Velocity.Normalize();
Vector3D rotationAxis = Vector3D.CrossProduct(currentDirection, forwardDirection);
double rotationAngle = Math.Acos(Vector3D.DotProduct(currentDirection, forwardDirection));
Vector3D forwardAcceleration = Vector3D.CrossProduct(rotationAxis, Velocity) * rotationAngle * ProportionalNavigationCoefficient;
// 合并横向和前向加速度
GuidanceCommand = lateralAcceleration + forwardAcceleration;
// 低通滤波
const double alpha = 0.2;
GuidanceCommand = GuidanceCommand * alpha + LastGuidanceCommand * (1 - alpha);
// 更新上一次的误差和制导命令
LastError = error;
LastGuidanceCommand = GuidanceCommand;
Console.WriteLine($"Current Position: {Position}");
Console.WriteLine($"Laser Source Position: {LaserSourcePosition}");
Console.WriteLine($"Laser Direction: {LaserDirection}");
Console.WriteLine($"Shortest Distance Vector: {shortestDistanceVector}");
//Console.WriteLine($"Guidance Command: {GuidanceCommand.Magnitude()}, Lateral Error: {shortestDistanceVector.Magnitude()}, Lateral Acceleration: {lateralAcceleration.Magnitude()}, Forward Acceleration: {forwardAcceleration.Magnitude()}");
}
public override string ToString()
{
return $"LaserBeamRiderGuidanceSystem: HasGuidance={HasGuidance}, LaserSourcePosition={LaserSourcePosition}, LaserDirection={LaserDirection}, GuidanceCommand={GuidanceCommand}";
}
private Vector3D CalculateShortestDistanceToLaserBeam()
{
// 计算导弹到激光源的向量
Vector3D missileToSource = LaserSourcePosition - Position;
// 计算导弹在激光方向上的投影长度
double projectionLength = Vector3D.DotProduct(missileToSource, LaserDirection);
// 计算激光束上最接近导弹的点
Vector3D closestPointOnBeam = LaserSourcePosition - LaserDirection * projectionLength;
// 计算导弹到激光束最近点的向量(即最短距离向量)
Vector3D shortestDistanceVector = closestPointOnBeam - Position;
return shortestDistanceVector;
}
}
}

View File

@ -0,0 +1,84 @@
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class LaserBeamRiderMissile : MissileBase
{
private LaserBeamRiderGuidanceSystem LaserBeamRiderGuidanceSystem;
public LaserBeamRiderMissile(string id, string targetId, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
LaserBeamRiderGuidanceSystem = new LaserBeamRiderGuidanceSystem(missileConfig.ProportionalNavigationCoefficient);
TargetId = targetId;
}
protected override Vector3D GetGuidanceCommand()
{
return LaserBeamRiderGuidanceSystem.GetGuidanceCommand();
}
private void OnLaserBeamStart(LaserBeamStartEvent evt)
{
if (evt?.LaserBeamRider != null)
{
LaserBeamRiderGuidanceSystem?.ActivateLaserBeam(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection, evt.LaserBeamRider.LaserPower);
}
}
private void OnLaserBeamUpdate(LaserBeamUpdateEvent evt)
{
if (evt?.LaserBeamRider != null)
{
LaserBeamRiderGuidanceSystem?.UpdateLaserBeamRider(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection, evt.LaserBeamRider.LaserPower);
}
}
private void OnLaserBeamStop(LaserBeamStopEvent evt)
{
if (evt?.LaserBeamRider != null)
{
LaserBeamRiderGuidanceSystem?.DeactivateLaserBeam(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection);
}
}
public override void Update(double deltaTime)
{
if (LaserBeamRiderGuidanceSystem.HasGuidance)
{
LaserBeamRiderGuidanceSystem.Update(deltaTime, Position, Velocity);
this.HasGuidance = true;
}
else
{
this.HasGuidance = false;
}
base.Update(deltaTime);
}
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "激光驾束制导导弹");
string additionalStatus = $"\n 激光引导: {(LaserBeamRiderGuidanceSystem.HasGuidance ? "" : "")}";
return baseStatus + additionalStatus;
}
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserBeamStartEvent>(OnLaserBeamStart);
SimulationManager.SubscribeToEvent<LaserBeamStopEvent>(OnLaserBeamStop);
SimulationManager.SubscribeToEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
}
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserBeamStartEvent>(OnLaserBeamStart);
SimulationManager.UnsubscribeFromEvent<LaserBeamStopEvent>(OnLaserBeamStop);
SimulationManager.UnsubscribeFromEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
}
}
}

235
Models/LaserDesignator.cs Normal file
View File

@ -0,0 +1,235 @@
using ActiveProtect.SimulationEnvironment;
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 激光指示器类,用于对目标进行激光照射
/// </summary>
public class LaserDesignator : SimulationElement
{
/// <summary>
/// 目标ID
/// </summary>
public string TargetId { get; private set; }
/// <summary>
/// 导弹ID
/// </summary>
public string MissileId { get; private set; }
/// <summary>
/// 干扰阈值(分贝)
/// </summary>
public double JammingThreshold { get; private set; } = 0.0;
/// <summary>
/// 是否被干扰
/// </summary>
public bool IsJammed { get; private set; } = false;
/// <summary>
/// 是否正在照射
/// </summary>
public bool IlluminationOn { get; private set; } = false;
/// <summary>
/// 激光功率
/// </summary>
public double LaserPower { get; private set; } = 0;
/// <summary>
/// 激光发散角
/// </summary>
public double LaserDivergenceAngle { get; private set; } = 0;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">激光指示器ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="missileId">导弹ID</param>
/// <param name="config">激光指示器配置</param>
/// <param name="simulationManager">仿真管理器</param>
public LaserDesignator(string id, string targetId, string missileId, LaserDesignatorConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(), simulationManager)
{
TargetId = targetId;
MissileId = missileId;
IsActive = false;
IlluminationOn = false;
LaserPower = config.LaserPower;
LaserDivergenceAngle = config.LaserDivergenceAngle;
}
/// <summary>
/// 更新激光指示器状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
public override void Update(double deltaTime)
{
if (IsActive && !IsJammed)
{
if (IlluminationOn)
{
PublishIlluminationUpdateEvent();
}
}
}
/// <summary>
/// 开始激光照射
/// </summary>
private void StartLaserIllumination()
{
if (!IlluminationOn)
{
IlluminationOn = true;
Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}");
PublishIlluminationStartEvent();
}
}
/// <summary>
/// 停止激光照射
/// </summary>
private void StopLaserIllumination()
{
if (IlluminationOn)
{
IlluminationOn = false;
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
PublishIlluminationStopEvent();
}
}
/// <summary>
/// 处理激光干扰事件
/// </summary>
/// <param name="evt">激光干扰事件</param>
private void OnLaserJamming(LaserJammingEvent evt)
{
if (evt.TargetId == TargetId)
{
var tank = SimulationManager.GetEntityById(TargetId) as Tank;
if (tank != null)
{
double distanceToTarget = Vector3D.Distance(Position, tank.Position);
double jammingEffectiveness = 20 * Math.Log10(evt.JammingPower) - 20 * Math.Log10(distanceToTarget) - 20 * Math.Log10(4 * Math.PI);
Console.WriteLine($"激光目标指示器 {Id} 收到干扰事件,干扰功率: {evt.JammingPower:F2}, 距离: {distanceToTarget:F2}, 干扰效果: {jammingEffectiveness:F2} dB, 阈值: {JammingThreshold:F2} dB");
if (jammingEffectiveness > JammingThreshold)
{
if (!IsJammed)
{
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
IsJammed = true;
StopLaserIllumination();
}
}
else
{
if (IsJammed)
{
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
IsJammed = false;
}
}
}
}
}
/// <summary>
/// 激活激光指示器
/// </summary>
public override void Activate()
{
if (!IsActive)
{
IsActive = true;
IsJammed = false;
Console.WriteLine($"激光目标指示器 {Id} 已激活");
StartLaserIllumination();
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
}
base.Activate();
}
/// <summary>
/// 停用激光指示器
/// </summary>
public override void Deactivate()
{
if (IsActive)
{
IsActive = false;
StopLaserIllumination();
Console.WriteLine($"激光目标指示器 {Id} 已停用");
SimulationManager.UnsubscribeFromEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.UnsubscribeFromEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
}
base.Deactivate();
}
/// <summary>
/// 发布激光照射事件
/// </summary>
private void PublishIlluminationStartEvent()
{
var evt = new LaserIlluminationStartEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射事件");
}
/// <summary>
/// 发布激光照射更新事件
/// </summary>
private void PublishIlluminationUpdateEvent()
{
var evt = new LaserIlluminationUpdateEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射更新事件");
}
/// <summary>
/// 发布激光照射停止事件
/// </summary>
private void PublishIlluminationStopEvent()
{
var evt = new LaserIlluminationStopEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
PublishEvent(evt);
Console.WriteLine($"激光指示器 {Id} 发布激光照射停止事件");
}
/// <summary>
/// 处理实体停用事件
/// </summary>
/// <param name="evt">实体停用事件</param>
private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt)
{
if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId)
{
StopLaserIllumination();
}
}
/// <summary>
/// 获取激光指示器状态信息
/// </summary>
/// <returns>状态信息字符串</returns>
public override string GetStatus()
{
return $"激光目标指示器 {Id}:\n" +
$" 位置: {Position}\n" +
$" 目标: {TargetId}\n" +
$" 导弹: {MissileId}\n" +
$" 激活状态: {(IsActive ? "" : "")}\n" +
$" 照射状态: {(IlluminationOn ? "" : "")}\n" +
$" 干扰状态: {(IsJammed ? "" : "")}\n" +
$" 激光功率: {LaserPower:E} W";
}
}
}

196
Models/LaserJammer.cs Normal file
View File

@ -0,0 +1,196 @@
using System;
using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
/// <summary>
/// 激光干扰器类,用于对抗激光制导武器
/// </summary>
public class LaserJammer : SimulationElement
{
/// <summary>
/// 是否正在进行干扰
/// </summary>
public bool IsJamming { get; private set; }
/// <summary>
/// 当前干扰功率(瓦特)
/// </summary>
public double JammingPower { get; private set; }
/// <summary>
/// 当前冷却时间(秒)
/// </summary>
private double jammingCooldown = 0;
/// <summary>
/// 最大冷却时间(秒)
/// </summary>
private readonly double maxJammingCooldown;
/// <summary>
/// 最大干扰功率(瓦特)
/// </summary>
private readonly double maxJammingPower;
/// <summary>
/// 初始干扰功率(瓦特)
/// </summary>
private readonly double initialJammingPower;
/// <summary>
/// 功率增加速率(瓦特/秒)
/// </summary>
private readonly double powerIncreaseRate;
/// <summary>
/// 被监视实体的ID
/// </summary>
public string MonitoredEntityId { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">激光干扰器ID</param>
/// <param name="position">初始位置</param>
/// <param name="orientation">初始朝向</param>
/// <param name="simulationManager">仿真管理器</param>
/// <param name="monitoredEntityId">被监视实体的ID</param>
/// <param name="config">激光干扰器配置</param>
public LaserJammer(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserJammerConfig config)
: base(id, position, orientation, simulationManager)
{
MonitoredEntityId = monitoredEntityId;
IsJamming = false;
JammingPower = 0;
maxJammingCooldown = config.MaxJammingCooldown;
maxJammingPower = config.MaxJammingPower;
initialJammingPower = config.InitialJammingPower;
powerIncreaseRate = config.PowerIncreaseRate;
SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
}
/// <summary>
/// 更新激光干扰器状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (SimulationManager.GetEntityById(MonitoredEntityId) is Tank tank)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
if (IsJamming)
{
JammingPower = Math.Min(JammingPower + powerIncreaseRate * deltaTime, maxJammingPower);
jammingCooldown += deltaTime;
if (jammingCooldown >= maxJammingCooldown)
{
StopJamming();
}
else
{
// 发布干扰事件
PublishEvent(new LaserJammingEvent
{
TargetId = MonitoredEntityId,
JammingPower = JammingPower
});
}
Console.WriteLine($"激光干扰器 {Id} 正在工作,当前功率: {JammingPower:F2}");
}
}
/// <summary>
/// 处理激光告警器警报事件
/// </summary>
/// <param name="evt">激光告警器警报事件</param>
private void OnLaserWarnerAlarmEvent(LaserWarnerAlarmEvent evt)
{
if (evt.TargetId == MonitoredEntityId)
{
StartJamming();
}
}
/// <summary>
/// 处理激光告警器警报停止事件
/// </summary>
/// <param name="evt">激光告警器警报停止事件</param>
private void OnLaserWarnerAlarmStopEvent(LaserWarnerAlarmStopEvent evt)
{
if (evt.TargetId == MonitoredEntityId)
{
StopJamming();
}
}
/// <summary>
/// 开始干扰
/// </summary>
private void StartJamming()
{
if (!IsJamming)
{
IsJamming = true;
JammingPower = initialJammingPower;
jammingCooldown = 0;
Console.WriteLine($"激光干扰器 {Id} 开始工作,初始功率: {JammingPower:F2}");
}
}
/// <summary>
/// 停止干扰
/// </summary>
private void StopJamming()
{
if (IsJamming)
{
IsJamming = false;
JammingPower = 0;
jammingCooldown = 0;
Console.WriteLine($"激光干扰器 {Id} 停止工作");
}
}
/// <summary>
/// 获取激光干扰器状态信息
/// </summary>
/// <returns>状态信息字符串</returns>
public override string GetStatus()
{
return $"激光干扰器 {Id}:\n" +
$" 监视实体: {MonitoredEntityId}\n" +
$" 干扰状态: {(IsJamming ? "" : "")}\n" +
$" 当前功率: {JammingPower:F2}/{maxJammingPower:F2}\n" +
$" 冷却时间: {jammingCooldown:F2}/{maxJammingCooldown:F2}";
}
/// <summary>
/// 激活激光干扰器
/// </summary>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
}
/// <summary>
/// 停用激光干扰器
/// </summary>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
}
}
}

View File

@ -0,0 +1,142 @@
using System;
namespace ActiveProtect.Models
{
public class LaserSemiActiveGuidanceSystem : BasicGuidanceSystem
{
private const double FieldOfViewAngle = Math.PI / 6; // 30度视场角
private const double DetectorDiameter = 0.1; // 探测器直径(米)
private const double FocusedSpotDiameter = 0.003; // 聚焦后光斑直径(米)
private const double ReflectionCoefficient = 0.2; // 反射系数
private const double LockThreshold = 1e-12; // 锁定阈值(瓦特)
private const double TargetReflectiveArea = 1.0; // 目标有效反射面积(平方米)
private Vector3D TargetPosition { get; set; }
private Vector3D TargetVelocity { get; set; }
private Vector3D LaserDesignatorPosition { get; set; }
private double LaserPower { get; set; }
private double LaserDivergenceAngle { get; set; }
public LaserSemiActiveGuidanceSystem(double proportionalNavigationCoefficient, Vector3D initialMissilePosition, Vector3D initialTargetPosition, Vector3D initialTargetVelocity)
: base(proportionalNavigationCoefficient)
{
Position = initialMissilePosition;
TargetPosition = initialTargetPosition;
TargetVelocity = initialTargetVelocity;
LaserDesignatorPosition = Vector3D.Zero;
LaserPower = 0;
}
public void ActivateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
{
HasGuidance = true;
LaserDesignatorPosition = sourcePosition;
TargetPosition = targetPosition;
TargetVelocity = targetVelocity;
LaserPower = laserPower;
LaserDivergenceAngle = laserDivergenceAngle;
}
public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
{
LaserDesignatorPosition = sourcePosition;
TargetPosition = targetPosition;
TargetVelocity = targetVelocity;
LaserPower = laserPower;
LaserDivergenceAngle = laserDivergenceAngle;
}
public void DeactivateLaserDesignator()
{
HasGuidance = false;
LaserDesignatorPosition = Vector3D.Zero;
TargetPosition = Vector3D.Zero;
TargetVelocity = Vector3D.Zero;
LaserPower = 0;
LaserDivergenceAngle = 0;
}
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
{
base.Update(deltaTime, missilePosition, missileVelocity);
HasGuidance = CalculateReceivedLaserPower() > LockThreshold;
if (HasGuidance)
{
CalculateGuidanceCommand(deltaTime);
}
else
{
GuidanceCommand = Vector3D.Zero;
}
PrintGuidanceInfo();
}
private double CalculateReceivedLaserPower()
{
double distanceToTarget = (TargetPosition - LaserDesignatorPosition).Magnitude();
double distanceToMissile = (Position - TargetPosition).Magnitude();
// 计算目标处的光斑面积
double spotAreaAtTarget = Math.PI * Math.Pow(distanceToTarget * Math.Tan(LaserDivergenceAngle), 2);
// 计算目标处的激光功率密度
double powerDensityAtTarget = LaserPower / spotAreaAtTarget;
// 计算从目标反射的总功率
double reflectedPower = powerDensityAtTarget * TargetReflectiveArea * ReflectionCoefficient;
// 计算反射光在导弹处的扩散面积(假设漫反射)
double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceToMissile, 2);
// 计算导弹接收到的功率
double receivedPower = reflectedPower / reflectedSpotArea;
// 计算探测器接收到的功率比例
double detectorArea = Math.PI * Math.Pow(DetectorDiameter / 2, 2);
double illuminatedArea = Math.PI * Math.Pow(distanceToMissile * Math.Tan(FieldOfViewAngle / 2), 2);
double powerRatio = Math.Min(1, detectorArea / illuminatedArea);
// 计算聚焦后的功率密度增加
double focusedArea = Math.PI * Math.Pow(FocusedSpotDiameter / 2, 2);
double focusingFactor = detectorArea / focusedArea;
// 计算最终接收到的功率
double finalReceivedPower = receivedPower * powerRatio * focusingFactor;
return finalReceivedPower;
}
protected override void CalculateGuidanceCommand(double deltaTime)
{
if (!HasGuidance)
{
GuidanceCommand = Vector3D.Zero;
return;
}
// 计算比例导引加速度
GuidanceCommand = CalculateProportionalNavigation(Position, Velocity, TargetPosition, TargetVelocity);
// 限制最大加速度
double maxAcceleration = 100; // 根据实际情况调整
if (GuidanceCommand.Magnitude() > maxAcceleration)
{
GuidanceCommand = GuidanceCommand.Normalize() * maxAcceleration;
}
}
private void PrintGuidanceInfo()
{
Console.WriteLine($"激光半主动导弹引导信息:");
Console.WriteLine($" 位置: {Position}");
Console.WriteLine($" 速度: {Velocity}");
Console.WriteLine($" 速度大小: {Velocity.Magnitude():F2} m/s");
Console.WriteLine($" 是否有引导: {HasGuidance}");
Console.WriteLine($" 目标位置: {TargetPosition}");
Console.WriteLine($" 制导指令: {GuidanceCommand}");
Console.WriteLine($" 接收到的激光功率: {CalculateReceivedLaserPower():E} W");
Console.WriteLine($" 锁定阈值: {LockThreshold:E} W");
Console.WriteLine();
}
}
}

View File

@ -0,0 +1,126 @@
using ActiveProtect.SimulationEnvironment;
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 激光半主动制导导弹类,继承自基础导弹类
/// </summary>
public class LaserSemiActiveGuidedMissile : MissileBase
{
private LaserSemiActiveGuidanceSystem LaserGuidanceSystem;
private string LaserDesignatorId;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">导弹ID</param>
/// <param name="laserDesignatorId">激光指示器ID</param>
/// <param name="missileConfig">导弹配置</param>
/// <param name="simulationManager">仿真管理器</param>
public LaserSemiActiveGuidedMissile(string id, MissileConfig missileConfig, string laserDesignatorId, ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager)
{
Vector3D initialTargetPosition = simulationManager.GetEntityById($"Tank_{missileConfig.TargetIndex + 1}").Position;
Vector3D initialTargetVelocity = simulationManager.GetEntityById($"Tank_{missileConfig.TargetIndex + 1}").Velocity;
LaserGuidanceSystem = new LaserSemiActiveGuidanceSystem(
missileConfig.ProportionalNavigationCoefficient,
missileConfig.InitialPosition,
initialTargetPosition,
initialTargetVelocity
);
LaserDesignatorId = laserDesignatorId;
}
/// <summary>
/// 处理激光照射事件
/// </summary>
/// <param name="evt">激光照射事件</param>
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
{
if (evt?.LaserDesignator != null && evt?.Target != null)
{
LaserGuidanceSystem.ActivateLaserDesignator(evt.LaserDesignator.Position, evt.Target.Position, evt.Target.Velocity,
evt.LaserDesignator.LaserPower, evt.LaserDesignator.LaserDivergenceAngle);
}
}
/// <summary>
/// 处理激光照射更新事件
/// </summary>
/// <param name="evt">激光照射更新事件</param>
private void OnLaserIlluminationUpdate(LaserIlluminationUpdateEvent evt)
{
if (evt?.LaserDesignator != null && evt?.Target != null)
{
LaserGuidanceSystem.UpdateLaserDesignator(evt.LaserDesignator.Position, evt.Target.Position, evt.Target.Velocity,
evt.LaserDesignator.LaserPower, evt.LaserDesignator.LaserDivergenceAngle);
}
}
/// <summary>
/// 处理激光照射停止事件
/// </summary>
/// <param name="evt">激光照射停止事件</param>
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
LaserGuidanceSystem.DeactivateLaserDesignator();
}
/// <summary>
/// 获取导弹状态信息
/// </summary>
/// <returns>状态信息字符串</returns>
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
string additionalStatus = $"\n 激光引导: {(LaserGuidanceSystem.HasGuidance ? "" : "")}";
return baseStatus + additionalStatus;
}
/// <summary>
/// 激活导弹
/// </summary>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.SubscribeToEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
/// <summary>
/// 停用导弹
/// </summary>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
public override void Update(double deltaTime)
{
if (LaserGuidanceSystem.HasGuidance)
{
LaserGuidanceSystem.Update(deltaTime, Position, Velocity);
this.HasGuidance = true;
}
else
{
this.HasGuidance = false;
}
base.Update(deltaTime);
}
/// <summary>
/// 获取制导命令
/// </summary>
/// <returns>制导命令</returns>
protected override Vector3D GetGuidanceCommand()
{
return LaserGuidanceSystem.GetGuidanceCommand();
}
}
}

159
Models/LaserWarner.cs Normal file
View File

@ -0,0 +1,159 @@
using ActiveProtect.SimulationEnvironment;
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 激光告警器类,用于检测激光照射并发出警报
/// </summary>
public class LaserWarner : SimulationElement
{
/// <summary>
/// 是否正在发出警报
/// </summary>
public bool IsAlarming { get; private set; }
/// <summary>
/// 警报持续时间(秒)
/// </summary>
private readonly double alarmDuration;
/// <summary>
/// 当前警报计时器
/// </summary>
private double alarmTimer = 0;
/// <summary>
/// 被监视实体的ID
/// </summary>
public string MonitoredEntityId { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">激光告警器ID</param>
/// <param name="position">初始位置</param>
/// <param name="orientation">初始朝向</param>
/// <param name="simulationManager">仿真管理器</param>
/// <param name="monitoredEntityId">被监视实体的ID</param>
/// <param name="config">激光告警器配置</param>
public LaserWarner(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserWarnerConfig config)
: base(id, position, orientation, simulationManager)
{
MonitoredEntityId = monitoredEntityId;
IsAlarming = false;
alarmDuration = config.AlarmDuration;
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
/// <summary>
/// 更新激光告警器状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
public override void Update(double deltaTime)
{
if (!IsActive) return;
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
if (tank != null)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
if (IsAlarming)
{
alarmTimer += deltaTime;
if (alarmTimer >= alarmDuration)
{
StopAlarm();
}
}
}
/// <summary>
/// 处理激光照射事件
/// </summary>
/// <param name="evt">激光照射事件</param>
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
{
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
{
TriggerAlarm();
}
}
/// <summary>
/// 处理激光照射停止事件
/// </summary>
/// <param name="evt">激光照射停止事件</param>
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
{
StopAlarm();
}
}
/// <summary>
/// 触发警报
/// </summary>
public void TriggerAlarm()
{
if (!IsAlarming)
{
IsAlarming = true;
alarmTimer = 0;
PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId });
Console.WriteLine($"激光告警器 {Id} 发出警报!");
}
}
/// <summary>
/// 停止警报
/// </summary>
public void StopAlarm()
{
if (IsAlarming)
{
IsAlarming = false;
alarmTimer = 0;
PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId });
Console.WriteLine($"激光告警器 {Id} 停止警报");
}
}
/// <summary>
/// 获取激光告警器状态信息
/// </summary>
/// <returns>状态信息字符串</returns>
public override string GetStatus()
{
return $"激光告警器 {Id}:\n" +
$" 监视实体: {MonitoredEntityId}\n" +
$" 警报状态: {(IsAlarming ? "" : "")}\n" +
$" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}";
}
/// <summary>
/// 激活激光告警器
/// </summary>
public override void Activate()
{
base.Activate();
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
/// <summary>
/// 停用激光告警器
/// </summary>
public override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
}
}

675
Models/MissileBase.cs Normal file
View File

@ -0,0 +1,675 @@
using System;
using System.Collections.Generic;
using ActiveProtect.SimulationEnvironment;
using Model;
namespace ActiveProtect.Models
{
/// <summary>
/// 表示仿真中的导弹
/// </summary>
public class MissileBase : SimulationElement
{
/// <summary>
/// 导弹类型
/// </summary>
public MissileType Type { get; protected set; }
/// <summary>
/// 当前速度(米/秒)
/// </summary>
public double Speed { get; protected set; }
/// <summary>
/// 最大速度(米/秒)
/// </summary>
public double MaxSpeed { get; protected set; }
/// <summary>
/// 目标ID
/// </summary>
public string TargetId { get; protected set; }
/// <summary>
/// 最大飞行时间(秒)
/// </summary>
public double MaxFlightTime { get; protected set; }
/// <summary>
/// 最大飞行距离(米)
/// </summary>
public double MaxFlightDistance { get; protected set; }
/// <summary>
/// 当前飞行时间(秒)
/// </summary>
public double FlightTime { get; protected set; }
/// <summary>
/// 当前飞行距离(米)
/// </summary>
public double FlightDistance { get; protected set; }
/// <summary>
/// 与目标的距离(米)
/// </summary>
public double DistanceToTarget { get; protected set; }
/// <summary>
/// 导弹距离参数
/// </summary>
public MissileDistanceParams DistanceParams { get; protected set; }
/// <summary>
/// 飞行阶段配置
/// </summary>
public FlightStageConfig StageConfig { get; protected set; }
/// <summary>
/// 当前飞行阶段
/// </summary>
public FlightStage CurrentStage { get; protected set; }
/// <summary>
/// 上一帧目标位置
/// </summary>
private Vector3D LastTargetPosition;
/// <summary>
/// 比例导引系数
/// </summary>
private const double N = 3;
/// <summary>
/// 推力加速度(米/秒²)
/// </summary>
public double ThrustAcceleration { get; protected set; }
/// <summary>
/// 当前发动机燃烧时间(秒)
/// </summary>
public double EngineBurnTime { get; protected set; }
/// <summary>
/// 最大发动机燃烧时间(秒)
/// </summary>
public double MaxEngineBurnTime { get; protected set; }
/// <summary>
/// 最大加速度(米/秒²)
/// </summary>
public double MaxAcceleration { get; protected set; } = 100;
/// <summary>
/// 比例导引系数
/// </summary>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 是否有制导
/// </summary>
public bool HasGuidance { get; protected set; } = false;
/// <summary>
/// 失去制导的时间(秒)
/// </summary>
protected double LostGuidanceTime { get; set; } = 0;
/// <summary>
/// 最后已知的速度向量
/// </summary>
protected Vector3D LastKnownVelocity = Vector3D.Zero;
/// <summary>
/// 发射速度(米/秒)
/// </summary>
public const double LAUNCH_SPEED = 10;
/// <summary>
/// 发射阶段持续时间(秒)
/// </summary>
public const double LAUNCH_DURATION = 0.5;
protected IMissileStageStrategy currentStage;
private Dictionary<FlightStage, IMissileStageStrategy> stageStrategies;
/// <summary>
/// 导弹质量(千克)
/// </summary>
public double Mass { get; protected set; } = 100;
/// <summary>
/// 构造函数
/// </summary>
public MissileBase(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager)
{
// 初始化导弹属性
Speed = missileConfig.InitialSpeed;
MaxSpeed = missileConfig.MaxSpeed;
MaxFlightTime = missileConfig.MaxFlightTime;
MaxFlightDistance = missileConfig.MaxFlightDistance;
DistanceParams = missileConfig.DistanceParams;
StageConfig = missileConfig.StageConfig;
IsActive = true;
FlightTime = 0;
FlightDistance = 0;
SimulationManager = simulationManager;
ThrustAcceleration = missileConfig.ThrustAcceleration;
EngineBurnTime = 0;
MaxEngineBurnTime = missileConfig.MaxEngineBurnTime;
MaxAcceleration = missileConfig.MaxAcceleration;
ProportionalNavigationCoefficient = missileConfig.ProportionalNavigationCoefficient;
TargetId = $"Tank_{missileConfig.TargetIndex + 1}";
Vector3D horizontalDirection = new Vector3D(Orientation.ToVector().X, 0, Orientation.ToVector().Z).Normalize();
Velocity = horizontalDirection * missileConfig.InitialSpeed;
// 初始化策略字典
stageStrategies = new Dictionary<FlightStage, IMissileStageStrategy>
{
{ FlightStage.Launch, new LaunchStageStrategy(this) },
{ FlightStage.Acceleration, new AccelerationStageStrategy(this) },
{ FlightStage.Cruise, new CruiseStageStrategy(this) },
{ FlightStage.TerminalGuidance, new TerminalGuidanceStageStrategy(this) },
{ FlightStage.Attack, new AttackStageStrategy(this) }
};
// 设置初始阶段
SetInitialStage();
currentStage = stageStrategies[CurrentStage];
LastTargetPosition = Position;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
}
/// <summary>
/// 设置导弹的初始飞行阶段
/// </summary>
private void SetInitialStage()
{
if (StageConfig.EnableLaunch) CurrentStage = FlightStage.Launch;
else 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;
Console.WriteLine($"导弹 {Id} 的初始阶段: {CurrentStage}");
}
/// <summary>
/// 更新导弹状态
/// </summary>
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
UpdateEngineBurnTime(deltaTime);
Vector3D guidanceCommand = GetGuidanceCommand();
UpdateMotionState(deltaTime, guidanceCommand);
if (CheckHit())
{
Explode();
return;
}
currentStage.Update(deltaTime);
}
protected virtual Vector3D GetGuidanceCommand()
{
throw new NotImplementedException();
}
private void UpdateMotionState(double deltaTime, Vector3D guidanceCommand)
{
Vector3D acceleration = CalculateAcceleration(Velocity, guidanceCommand);
// 使用四阶龙格-库塔方法更新导弹的位置和速度
(Position, Velocity) = BasicGuidanceSystem.RungeKutta4(deltaTime, Position, Velocity, acceleration);
// 限制速度不超过最大速度
if (Velocity.Magnitude() > MaxSpeed)
{
Velocity = Velocity.Normalize() * MaxSpeed;
}
UpdateMotionStatus(deltaTime);
}
protected virtual void UpdateMotionStatus(double deltaTime)
{
Speed = Velocity.Magnitude();
Orientation = Orientation.FromVector(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
}
/// <summary>
/// 计算导弹的加速度
/// </summary>
private Vector3D CalculateAcceleration(Vector3D velocity, Vector3D guidanceCommand)
{
Vector3D thrustAcceleration = Vector3D.Zero;
Vector3D guidanceAcceleration = Vector3D.Zero;
switch (CurrentStage)
{
case FlightStage.Launch:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
break;
case FlightStage.Acceleration:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
guidanceAcceleration = guidanceCommand;
break;
case FlightStage.Cruise:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
guidanceAcceleration = guidanceCommand * 1;
break;
case FlightStage.TerminalGuidance:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
guidanceAcceleration = guidanceCommand * 1;
break;
case FlightStage.Attack:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration*0.05;
guidanceAcceleration = guidanceCommand * 1;
break;
}
if (!HasGuidance)
{
if (velocity.Magnitude() > 0)
{
thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
}
else
{
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
}
}
//计算重力加速度(反坦克导弹一般升力很小, 主要依靠初始发射动能和持续的推力来维持飞行)
//Vector3D gravityCompensation = new(0, 9.81, 0);
Vector3D gravityAcceleration = new(0, -9.81, 0);
// 计算空气阻力的影响
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + gravityAcceleration +dragAcceleration;
//Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration +dragAcceleration;
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {guidanceAcceleration}, 推力加速度: {thrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
if (totalAcceleration.Magnitude() > MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
}
return totalAcceleration;
}
/// <summary>
/// 切换导弹飞行阶段
/// </summary>
public void ChangeStage(FlightStage newStage)
{
if (stageStrategies.TryGetValue(newStage, out var strategy))
{
if (IsStageEnabled(newStage))
{
CurrentStage = newStage;
currentStage = strategy;
Console.WriteLine($"导弹 {Id} 切换到 {newStage} 阶段");
}
else
{
// 如果目标阶段不可用,尝试切换到下一个可用阶段
TryChangeToNextAvailableStage(newStage);
}
}
else
{
Console.WriteLine($"导弹 {Id} 无法切换到未知阶段 {newStage}");
}
}
/// <summary>
/// 检查指定飞行阶段是否启用
/// </summary>
private bool IsStageEnabled(FlightStage stage)
{
return stage switch
{
FlightStage.Launch => StageConfig.EnableLaunch,
FlightStage.Acceleration => StageConfig.EnableAcceleration,
FlightStage.Cruise => StageConfig.EnableCruise,
FlightStage.TerminalGuidance => StageConfig.EnableTerminalGuidance,
FlightStage.Attack => StageConfig.EnableAttack,
_ => false
};
}
/// <summary>
/// 尝试切换到下一个可用的飞行阶段
/// </summary>
private void TryChangeToNextAvailableStage(FlightStage startStage)
{
FlightStage[] stageOrder = new FlightStage[] {FlightStage.Launch, FlightStage.Acceleration, FlightStage.Cruise, FlightStage.TerminalGuidance, FlightStage.Attack};
int startIndex = Array.IndexOf(stageOrder, startStage);
for (int i = startIndex + 1; i < stageOrder.Length; i++)
{
if (IsStageEnabled(stageOrder[i]))
{
ChangeStage(stageOrder[i]);
return;
}
}
// 如果没有可用的下一个阶段,导弹自毁
Console.WriteLine($"导弹 {Id} 没有可用的下一个阶段,准备自毁");
SelfDestruct();
}
/// <summary>
/// 计算导弹的加速度
/// </summary>
// private (Vector3D, Vector3D) CalculateDerivatives_RK4(Vector3D position, Vector3D velocity, double deltaTime)
// {
// Vector3D guidanceAcceleration = Vector3D.Zero;
// Vector3D thrustAcceleration = Vector3D.Zero;
// switch (CurrentStage)
// {
// case FlightStage.Launch:
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
// break;
// case FlightStage.Acceleration:
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
// guidanceAcceleration = CalculateProportionalNavigation(position);
// break;
// case FlightStage.Cruise:
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
// guidanceAcceleration = CalculateProportionalNavigation(position) * 0.5;
// break;
// case FlightStage.TerminalGuidance:
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
// guidanceAcceleration = CalculateProportionalNavigation(position) * 1.5;
// break;
// case FlightStage.Attack:
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
// guidanceAcceleration = CalculateProportionalNavigation(position) * 2;
// break;
// }
// if (!HasGuidance)
// {
// guidanceAcceleration = Vector3D.Zero;
// if (velocity.Magnitude() > 0)
// {
// thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
// }
// else
// {
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
// }
// }
// // 计算空气阻力的影响
// Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
// // 计算重力加速度(反坦克导弹一般升力很小, 主要依靠初始发射动能和持续的推力来维持飞行)
// //Vector3D gravityCompensation = new(0, 9.81, 0);
// Vector3D gravityAcceleration = new(0, -9.81, 0);
// Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + gravityAcceleration + dragAcceleration;
// if (totalAcceleration.Magnitude() > MaxAcceleration)
// {
// totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
// }
// return (velocity, totalAcceleration);
// }
/// <summary>
/// 计算空气阻力
/// </summary>
private static double CalculateDrag(double speed)
{
const double dragCoefficient = 0.1; // 减小阻力系数
const double airDensity = 1.225; // 海平面空气密度kg/m^3
const double referenceArea = 0.01; // 减小导弹的参考面积m^2
return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed;
}
/// <summary>
/// 检查是否命中目标
/// </summary>
protected bool CheckHit()
{
return DistanceToTarget <= DistanceParams.ExplosionDistance;
}
/// <summary>
/// 检查是否应该自毁
/// </summary>
protected bool ShouldSelfDestruct()
{
if (FlightTime >= MaxFlightTime)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
return true;
}
if (FlightDistance >= MaxFlightDistance)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
return true;
}
if (Position.Y <= -1.0) // 数字略小于0
{
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
return true;
}
return false;
}
/// <summary>
/// 更新发动机燃烧时间
/// </summary>
private void UpdateEngineBurnTime(double deltaTime)
{
if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
{
EngineBurnTime += deltaTime;
}
}
/// <summary>
/// 计算比例导引加速度
/// </summary>
private Vector3D CalculateProportionalNavigation(Vector3D position)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D LOS = targetPosition - position;
Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
LastTargetPosition = targetPosition;
return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
* ProportionalNavigationCoefficient * Velocity.Magnitude();
}
/// <summary>
/// 导弹爆炸
/// </summary>
public void Explode()
{
Deactivate();
SimulationManager.HandleTargetHit(TargetId, Id);
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
}
/// <summary>
/// 导弹自毁
/// </summary>
public void SelfDestruct()
{
if (IsActive)
{
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
Position.Y <= 0 ? "高度小于等于0" :
!HasGuidance ? "失去引导" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
Deactivate();
}
}
/// <summary>
/// 设置比例导引系数
/// </summary>
public void SetProportionalNavigationCoefficient(double newCoefficient)
{
ProportionalNavigationCoefficient = newCoefficient;
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
}
/// <summary>
/// 获取导弹状态
/// </summary>
public override string GetStatus()
{
MissileRunningState missileRunningState = GetState();
return $"导弹 {missileRunningState.Id}:\n" +
$" 位置: {missileRunningState.Position}\n" +
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
$" 当前状态: {missileRunningState.CurrentStage}\n" +
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MaxFlightTime:F2}\n" +
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {missileRunningState.DistanceToTarget:F2}\n" +
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
$" 有引导: {(missileRunningState.HasGuidance ? "" : "")}\n" +
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}";
}
/// <summary>
/// 更新导弹的制导状态
/// </summary>
protected virtual void UpdateGuidanceStatus()
{
// 基类中的默认实现
}
public MissileRunningState GetState()
{
return new MissileRunningState
{
Id = Id,
Type = Type,
Position = Position,
Velocity = Velocity,
Orientation = Orientation,
Speed = Speed,
TargetId = TargetId,
FlightTime = FlightTime,
FlightDistance = FlightDistance,
DistanceToTarget = DistanceToTarget,
CurrentStage = CurrentStage,
HasGuidance = HasGuidance,
LostGuidanceTime = LostGuidanceTime,
EngineBurnTime = EngineBurnTime,
IsActive = IsActive
};
}
}
/// <summary>
/// 表示导弹的运行状态信息
/// </summary>
public struct MissileRunningState
{
/// <summary>
/// 导弹ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 导弹类型
/// </summary>
public MissileType Type { get; set; }
/// <summary>
/// 当前位置
/// </summary>
public Vector3D Position { get; set; }
/// <summary>
/// 当前速度向量
/// </summary>
public Vector3D Velocity { get; set; }
/// <summary>
/// 当前朝向
/// </summary>
public Orientation Orientation { get; set; }
/// <summary>
/// 当前速度(米/秒)
/// </summary>
public double Speed { get; set; }
/// <summary>
/// 目标ID
/// </summary>
public string TargetId { get; set; }
/// <summary>
/// 当前飞行时间(秒)
/// </summary>
public double FlightTime { get; set; }
/// <summary>
/// 当前飞行距离(米)
/// </summary>
public double FlightDistance { get; set; }
/// <summary>
/// 与目标的距离(米)
/// </summary>
public double DistanceToTarget { get; set; }
/// <summary>
/// 当前飞行阶段
/// </summary>
public FlightStage CurrentStage { get; set; }
/// <summary>
/// 是否有制导
/// </summary>
public bool HasGuidance { get; set; }
/// <summary>
/// 失去制导时间(秒)
/// </summary>
public double LostGuidanceTime { get; set; }
/// <summary>
/// 当前发动机燃烧时间(秒)
/// </summary>
public double EngineBurnTime { get; set; }
/// <summary>
/// 是否处于活动状态
/// </summary>
public bool IsActive { get; set; }
}
}

351
Models/MissileClass.cs Normal file
View File

@ -0,0 +1,351 @@
using System;
namespace Model
{
/// <summary>
/// 坦克消息结构
/// </summary>
public struct TankInfo
{
/// <summary>
/// 坦克编号
/// </summary>
public int TankID { get; set; }
/// <summary>
/// 坦克类型编号
/// </summary>
public int TankType { get; set; }
/// <summary>
/// 坦克X坐标
/// </summary>
public double xp { get; set; }
/// <summary>
/// 坦克Y坐标
/// </summary>
public double yp { get; set; }
/// <summary>
/// 坦克Z坐标
/// </summary>
public double zp { get; set; }
/// <summary>
/// 烟幕标记
/// </summary>
public double fYMFlag { get; set; }
/// <summary>
/// 烟幕SNR
/// </summary>
public double fYMSNR { get; set; }
/// <summary>
/// 激光致盲标记,1-导弹2-制导站3-两者都不是
/// </summary>
public double fZMJGFlag { get; set; }
/// <summary>
/// 致盲能量
/// </summary>
public double fZMJGPower { get; set; }
/// <summary>
/// 激光诱骗假目标X坐标
/// </summary>
public double fFalseX { get; set; }
/// <summary>
/// 激光诱骗假目标Y坐标
/// </summary>
public double fFalseY { get; set; }
/// <summary>
/// 激光诱骗假目标Z坐标
/// </summary>
public double fFalseZ { get; set; }
/// <summary>
/// 红外诱骗能量值
/// </summary>
public double fFalseIRPower { get; set; }
/// <summary>
/// 激光诱骗能量值
/// </summary>
public double fFalseJGPower { get; set; }
/// <summary>
/// 毫米波补偿//1为开启
/// </summary>
public double fHMBBCFlag { get; set; }
/// <summary>
/// 毫米波干扰能量
/// </summary>
public double fHMBGRPower { get; set; }
/// <summary>
/// 红外干扰能量
/// </summary>
public double fHWGRPower { get; set; }
/// <summary>
/// 坦克辐射红外能量
/// </summary>
public double fTankIRPower { get; set; }
/// <summary>
/// 坦克辐射激光能量
/// </summary>
public double fTankJGPower { get; set; }
/// <summary>
/// 坦克辐射毫米波能量
/// </summary>
public double fTankHMBPower { get; set; }
/// <summary>
/// 毫米波补偿特征值//大于导弹补偿成功,末敏弹子弹爆炸
/// </summary>
public double fFeature { get; set; }
};
/// <summary>
/// 威胁源初始化信息结构
/// </summary>
public struct MIniInfo
{
/// <summary>
/// 导弹ID
/// </summary>
public int nMisID;
/// <summary>
/// 导弹X坐标
/// </summary>
public double xm;
/// <summary>
/// 导弹Y坐标
/// </summary>
public double ym;
/// <summary>
/// 导弹Z坐标
/// </summary>
public double zm;
/// <summary>
/// 导弹方位角
/// </summary>
public double psi_m;
/// <summary>
/// 导弹俯仰角
/// </summary>
public double theta_m;
/// <summary>
/// 导弹飞行速度
/// </summary>
public double vm;
/// <summary>
/// 坦克X坐标
/// </summary>
public double xt;
/// <summary>
/// 坦克Y坐标
/// </summary>
public double yt;
/// <summary>
/// 坦克Z坐标
/// </summary>
public double zt;
/// <summary>
/// 光斑X坐标
/// </summary>
public double xd;
/// <summary>
/// 光斑Y坐标
/// </summary>
public double yd;
/// <summary>
/// 光斑Z坐标
/// </summary>
public double zd;
};
/// <summary>
/// 威胁源运行信息结构
/// </summary>
public struct MRunInfo
{
/// <summary>
/// 杀伤半径
/// </summary>
public double Rx;
/// <summary>
/// 仿真时间
/// </summary>
public double fSimTime;
/// <summary>
/// x坐标
/// </summary>
public double fMisX;
/// <summary>
/// y坐标
/// </summary>
public double fMisY;
/// <summary>
/// z坐标
/// </summary>
public double fMisZ;
/// <summary>
/// 导弹弹道倾角
/// </summary>
public double fMisDeltCw;
/// <summary>
/// 滚转角
/// </summary>
public double fMisRoll;
/// <summary>
/// 导弹弹道偏角
/// </summary>
public double fMisPitch;
/// <summary>
/// 导弹速度
/// </summary>
public double fMisV;
/// <summary>
/// 导弹辐射红外能量
/// </summary>
public double fIRPower;
/// <summary>
/// 导弹辐射红外波长
/// </summary>
public double fIRWaveLen;
/// <summary>
/// 导弹紫外能量
/// </summary>
public double fUVPower;
/// <summary>
/// 导弹紫外波长
/// </summary>
public double fUVWaveLen;
/// <summary>
/// 导弹激光能量
/// </summary>
public double fJGPower;
// 导弹激光波长
public double fJGWaveLen;
/// <summary>
/// 导弹毫米波能量
/// </summary>
public double fHMBPower;
/// <summary>
/// 导弹毫米波波长
/// </summary>
public double fHMBWaveLen;
/// <summary>
/// 制导站批号
/// </summary>
public double nZDZID;
/// <summary>
/// 架束仪位置x
/// </summary>
public double fZDZX;
/// <summary>
/// 架束仪位置Y
/// </summary>
public double fZDZY;
/// <summary>
/// 架束仪位置Z
/// </summary>
public double fZDZZ;
/// <summary>
/// 制导站辐射激光能量
/// </summary>
public double fZDZJGPower;
/// <summary>
/// 制导站辐射激光波长
/// </summary>
public double fZDZJGWaveLen;
/// <summary>
/// 编码
/// </summary>
public double nZDZCode;
/// <summary>
/// 脉冲重复频率
/// </summary>
public double fZDZReFre;
/// <summary>
/// 脉宽
/// </summary>
public double fZDZPulse;
/// <summary>
/// 末敏弹状态 1母弹2子弹3子弹扫描状态
/// </summary>
public double nMMDState;
/// <summary>
/// 子弹数量
/// </summary>
public double nSubNum;
/// <summary>
/// 子弹1批号
/// </summary>
public double nSub1ID;
/// <summary>
/// 子弹1坐标X
/// </summary>
public double fSub1X;
// 子弹1坐标Y
public double fSub1Y;
/// <summary>
/// 子弹1坐标Z
/// </summary>
public double fSub1Z;
/// <summary>
/// 子弹1辐射毫米波能量
/// </summary>
public double fSub1HMBPower;
/// <summary>
/// 子弹1辐射毫米波波长
/// </summary>
public double fSub1HMBWaveLen;
/// <summary>
/// 子弹1扫描坐标X
/// </summary>
public double fSub1ScanX;
/// <summary>
/// 子弹1扫描坐标Y
/// </summary>
public double fSub1ScanY;
/// <summary>
/// 子弹1扫描坐标Z
/// </summary>
public double fSub1ScanZ;
/// <summary>
/// 防护手段 1:激光致盲2激光诱骗3红外干扰4:红外诱骗5毫米波干扰6毫米波补偿7:烟幕防护;8:致盲制导站
/// </summary>
public double nDisType;
/// <summary>
/// 0代表失败 1代表成功
/// </summary>
public double nDisRes;
/// <summary>
/// 后续进一步处理
/// </summary>
public double k1;
/// <summary>
/// 弹道偏角和倾角改变角度当亲步骤数
/// </summary>
public int Xi;
public int JG_GR_success;
/// <summary>
/// 炮弹状态标志0:正常1炸毁目标2自爆
/// </summary>
public int bombFlag;
///// <summary>
///// 激光诱骗假目标X坐标
///// </summary>
//public double fFalseX;
///// <summary>
///// 激光诱骗假目标Y坐标
///// </summary>
//public double fFalseY;
///// <summary>
///// 激光诱骗假目标Z坐标
///// </summary>
//public double fFalseZ;
};
};

View File

@ -0,0 +1,168 @@
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 导弹飞行阶段枚举
/// </summary>
public enum FlightStage
{
Launch, // 发射阶段
Acceleration, // 加速阶段
Cruise, // 巡航阶段
TerminalGuidance, // 终端制导阶段
Attack, // 攻击阶段
Explosion, // 爆炸阶段
}
/// <summary>
/// 导弹飞行阶段策略接口
/// </summary>
public interface IMissileStageStrategy
{
void Update(double deltaTime);
}
/// <summary>
/// 发射阶段策略
/// </summary>
public class LaunchStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
private double launchTime = 0;
public LaunchStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
launchTime += deltaTime;
if (launchTime >= MissileBase.LAUNCH_DURATION || missile.Speed >= missile.MaxSpeed * 0.1)
{
missile.ChangeStage(FlightStage.Acceleration);
}
}
}
/// <summary>
/// <summary>
/// 加速阶段策略
/// </summary>
public class AccelerationStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
public AccelerationStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
if (missile.EngineBurnTime >= missile.MaxEngineBurnTime || missile.Speed >= missile.MaxSpeed)
{
missile.ChangeStage(FlightStage.Cruise);
}
}
}
/// <summary>
/// 巡航阶段策略
/// </summary>
public class CruiseStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
public CruiseStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
{
missile.ChangeStage(FlightStage.TerminalGuidance);
}
}
}
/// <summary>
/// 终端制导阶段策略
/// </summary>
public class TerminalGuidanceStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
public TerminalGuidanceStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
{
missile.ChangeStage(FlightStage.Attack);
}
}
}
/// <summary>
/// 攻击阶段策略
/// </summary>
public class AttackStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
public AttackStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.ExplosionDistance)
{
missile.Explode();
}
}
}
/// <summary>
/// 无制导阶段策略
/// </summary>
public class UnguidedStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
public UnguidedStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
// 检查是否重新获得引导
if (missile.HasGuidance)
{
Console.WriteLine($"导弹 {missile.Id} 重新获得引导,退出无制导阶段");
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
{
missile.ChangeStage(FlightStage.Attack);
}
else if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
{
missile.ChangeStage(FlightStage.TerminalGuidance);
}
else
{
missile.ChangeStage(FlightStage.Cruise);
}
}
}
}
}

100
Models/Tank.cs Normal file
View File

@ -0,0 +1,100 @@
using ActiveProtect.SimulationEnvironment;
using System;
namespace ActiveProtect.Models
{
/// <summary>
/// 表示仿真中的坦克
/// </summary>
public class Tank : SimulationElement
{
/// <summary>
/// 当前速度(米/秒)
/// </summary>
public double Speed { get; set; }
/// <summary>
/// 最大速度(米/秒)
/// </summary>
public double MaxSpeed { get; private set; }
/// <summary>
/// 最大装甲值
/// </summary>
public double MaxArmor { get; private set; }
/// <summary>
/// 当前装甲值
/// </summary>
public double CurrentArmor { get; private set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">坦克ID</param>
/// <param name="tankConfig">坦克配置</param>
/// <param name="simulationManager">仿真管理器</param>
public Tank(string id, TankConfig tankConfig, ISimulationManager simulationManager)
: base(id, tankConfig.InitialPosition, tankConfig.InitialOrientation, simulationManager)
{
Speed = tankConfig.InitialSpeed;
MaxSpeed = tankConfig.MaxSpeed;
MaxArmor = tankConfig.MaxArmor;
CurrentArmor = tankConfig.MaxArmor;
}
/// <summary>
/// 更新坦克状态
/// </summary>
/// <param name="deltaTime">时间步长(秒)</param>
public override void Update(double deltaTime)
{
if (!IsActive) return;
UpdatePosition(deltaTime);
}
/// <summary>
/// 更新坦克位置
/// </summary>
/// <param name="deltaTime">时间步长(秒)</param>
private void UpdatePosition(double deltaTime)
{
Vector3D direction = Orientation.ToVector();
Vector3D movement = direction * Speed * deltaTime;
Position += movement;
}
/// <summary>
/// 坦克受到伤害
/// </summary>
/// <param name="damage">伤害值</param>
/// <param name="isMissileDamage">是否为导弹造成的伤害</param>
public void TakeDamage(double damage, bool isMissileDamage = false)
{
if (isMissileDamage)
{
damage = CurrentArmor * 0.5;
}
CurrentArmor = Math.Max(0, CurrentArmor - damage);
if (CurrentArmor <= 0)
{
Deactivate();
}
}
/// <summary>
/// 获取坦克状态信息
/// </summary>
/// <returns>坦克状态字符串</returns>
public override string GetStatus()
{
return $"坦克 {Id}:\n" +
$" 位置: {Position}\n" +
$" 速度: {Speed:F2}/{MaxSpeed:F2}\n" +
$" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" +
$" 状态: {(IsActive ? "" : "")}\n";
}
}
}

138
Program.cs Normal file
View File

@ -0,0 +1,138 @@
using System;
using System.Threading;
using ActiveProtect.SimulationEnvironment;
using ActiveProtect.Models;
using Model;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Generic;
namespace ActiveProtect
{
class Program
{
static void Main(string[] args)
{
TankInfo tankinfo = new()
{
xp = 100,
yp = 0,
zp = 100
};
MIniInfo mIniInfo = new()
{
xm = 1500,
ym = 200,
zm = 100,
psi_m = Math.PI,
theta_m = -0.1,
vm = 0
};
// 创建仿真配置
var config = new SimulationConfig
{
// 配置坦克
TankConfigs = new List<TankConfig>
{
new TankConfig(tankinfo)
{
InitialOrientation = new Orientation(Math.PI/4, 0, 0),
InitialSpeed = 15,
MaxSpeed = 20,
MaxArmor = 100,
HasLaserWarner = false,
HasLaserJammer = true
}
},
// 配置激光指示器
LaserDesignatorConfig = new LaserDesignatorConfig
{
InitialPosition = new Vector3D(2000, 150, 100),
LaserPower = 1e6,
LaserDivergenceAngle = 0.01
},
// 配置激光告警器
LaserWarnerConfig = new LaserWarnerConfig
{
AlarmDuration = 5.0
},
// 配置激光干扰器
LaserJammerConfig = new LaserJammerConfig
{
MaxJammingCooldown = 5.0,
MaxJammingPower = 10000.0,
InitialJammingPower = 4000.0,
PowerIncreaseRate = 2000.0
},
// 配置激光驾束仪
LaserBeamRiderConfig = new LaserBeamRiderConfig
{
InitialPosition = new Vector3D(2000, 10, 100),
LaserPower = 1000,
ControlFieldDiameter = 6
},
// 配置导弹
MissileConfigs = new List<MissileConfig>
{
// 激光半主动制导导弹配置
new MissileConfig
{
InitialPosition = new Vector3D(2000, 100, 100),
InitialOrientation = new Orientation(Math.PI, -0.1, 0),
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 0.05,
MaxFlightDistance = 5000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 10,
MaxAcceleration = 400,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile,
DistanceParams = new MissileDistanceParams(500, 200, 20),
Mass = 50,
Type = MissileType.LaserSemiActiveGuidance
},
// 激光驾束制导导弹配置
new MissileConfig
{
InitialPosition = new Vector3D(2000, 10, 100),
InitialOrientation = new Orientation(Math.PI, 0.1, 0.0),
InitialSpeed = 300,
MaxSpeed = 400,
TargetIndex = 0,
MaxFlightTime = 0.05,
MaxFlightDistance = 3000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 10,
MaxAcceleration = 400,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.LaserBeamRiderGuidance,
DistanceParams = new MissileDistanceParams(500, 200, 10),
Mass = 50,
Type = MissileType.LaserBeamRiderGuidance
}
},
SimulationTimeStep = 0.025
};
// 创建仿真管理器
var simulationManager = new SimulationManager(config);
// 运行仿真
int maxIterations = 1000;
int iteration = 0;
while (!simulationManager.IsSimulationEnded && iteration < maxIterations)
{
simulationManager.Update();
simulationManager.PrintStatus();
Thread.Sleep(100); // 暂停100毫秒使输出更易读
iteration++;
}
Console.WriteLine("仿真结束");
}
}
}

171
README.md Normal file
View File

@ -0,0 +1,171 @@
# ActiveProtect 仿真系统
ActiveProtect 是一个用于模拟激光制导导弹和防御系统的仿真环境。
## 功能特性
- 激光半主动制导导弹仿真
- 激光驾束制导导弹仿真
- 坦克和激光告警器仿真
- 激光干扰器仿真
- 可扩展的仿真框架
## Unity 兼容性
本项目设计时考虑了与 Unity 游戏引擎的兼容性, 使用C# 9.0 语法。以下是在 Unity 中使用本项目的注意事项:
1. 向量和数学运算:本项目使用自定义的 `Vector3D` 类。在 Unity 中,您可以将其替换为 Unity 的 `Vector3` 类。
2. 仿真更新Unity 使用 `MonoBehaviour``Update` 方法进行每帧更新。您可以创建一个 `SimulationManager` 脚本,并在其 `Update` 方法中调用仿真系统的更新逻辑。
3. 可视化Unity 提供了强大的 3D 渲染能力。您可以为每个仿真元素(如导弹、坦克等)创建相应的 Unity 游戏对象,并在每帧更新其位置和旋转。
4. 输入处理:将键盘/鼠标输入处理逻辑替换为 Unity 的输入系统(如 `Input.GetKey()` 等)。
5. 协程Unity 支持协程,可用于实现某些异步操作或时间相关的功能。
6. 物理系统:如果需要更复杂的物理模拟,可以考虑使用 Unity 的物理引擎替代当前的简化物理模型。
7. 事件系统Unity 有自己的事件系统,您可能需要调整当前的事件处理机制以更好地与 Unity 集成。
8. 性能优化:在 Unity 中,您可以使用 Unity Profiler 来监控和优化性能。
通过这些调整,您应该能够将 ActiveProtect 仿真系统顺利集成到 Unity 项目中,从而获得更好的可视化效果和交互体验。
## 使用说明
1. 克隆仓库到本地
2. 使用 Visual Studio 或其他 C# IDE 打开解决方案
3. 编译并运行项目
## 贡献指南
欢迎提交 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. 巡航阶段
- 导弹保持相对稳定的速度飞向<E9A39E><E59091>
- 根据导引系统类型,可能会进行中途修正
4. 终端制导阶段
- 导弹接近目标,进入最后的制导阶段
- 可能会启动终端制导系统,如毫米波雷达或红外成像系统
5. 攻击阶段
- 导弹进行最后的机动,以最佳角度接近目标
- 可能会启动穿甲弹头或预制破片
6. 爆炸阶段
- 导弹击中目标并引爆
- 根据弹头类型,可能是穿甲、破片或破片-燃烧等效果
在仿真中,这些阶段被纳入计算,每个阶段可能有不同的物理特性和行为模式。例如,加速阶段可能有较大的加速度,而巡航阶段则保持恒定速度。终端制导阶段可能会有更频繁的方向调整。
## 项目结构
```csharp
ActiveProtect/
├── Models/ # 仿真模型目录
│ ├── BasicGuidanceSystem.cs # 基础制导系统类
│ ├── ILaserIlluminatable.cs # 可被激光照射的接口定义
│ ├── LaserBeamRider.cs # 激光驾束仪类
│ ├── LaserBeamRiderGuidanceSystem.cs # 激光驾束制导系统类
│ ├── LaserBeamRiderMissile.cs # 激光驾束导弹类
│ ├── LaserDesignator.cs # 激光指示器类
│ ├── LaserJammer.cs # 激光干扰器类
│ ├── LaserSemiActiveGuidedMissile.cs # 激光半主动制导导弹类
│ ├── LaserWarner.cs # 激光告警器类
│ ├── MissileClass.cs # 导弹基类
│ └── Tank.cs # 坦克模型类
├── SimulationEnvironment/ # 仿真环境目录
│ ├── SimulationConfig.cs # 仿真配置类
│ ├── SimulationElement.cs # 仿真元素基类
│ ├── SimulationEvents.cs # 仿真事件定义类
│ └── SimulationManager.cs # 仿真管理器类
├── Program.cs # 程序入口点
├── README.md # 项目说明文档
└── Design.md # 设计文档
```
## 如何运行
1. 确保你的系统已安装 .NET 6.0。
2. 在终端中导航到项目根目录。
3. 运行以下命令来构建项目:
```shell
dotnet build
```
4. 运行以下命令来启动仿真:
```shell
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 值,观察其对导弹性能的影响,以找到最适合特定场景的设置。

View File

@ -0,0 +1,474 @@
using System.Collections.Generic;
using System.ComponentModel;
using ActiveProtect.Models;
using Model;
namespace ActiveProtect.SimulationEnvironment
{
/// <summary>
/// 仿真配置类,包含整个仿真所需的所有配置信息
/// </summary>
public class SimulationConfig
{
/// <summary>
/// 坦克配置列表
/// </summary>
public List<TankConfig> TankConfigs { get; set; }
/// <summary>
/// 导弹配置列表
/// </summary>
public List<MissileConfig> MissileConfigs { get; set; }
/// <summary>
/// 激光指示器配置列表
/// </summary>
public LaserDesignatorConfig LaserDesignatorConfig { get; set; }
/// <summary>
/// 激光驾束仪配置列表
/// </summary>
public LaserBeamRiderConfig LaserBeamRiderConfig { get; set; }
/// <summary>
/// 激光告警器配置
/// </summary>
public LaserWarnerConfig LaserWarnerConfig { get; set; }
/// <summary>
/// 激光干扰器配置
/// </summary>
public LaserJammerConfig LaserJammerConfig { get; set; }
/// <summary>
/// 仿真时间步长(秒)
/// </summary>
public double SimulationTimeStep { get; set; }
/// <summary>
/// 构造函数,初始化默认配置
/// </summary>
public SimulationConfig()
{
TankConfigs = new List<TankConfig>();
MissileConfigs = new List<MissileConfig>();
LaserDesignatorConfig = new LaserDesignatorConfig();
LaserBeamRiderConfig = new LaserBeamRiderConfig();
LaserWarnerConfig = new LaserWarnerConfig();
LaserJammerConfig = new LaserJammerConfig();
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
}
}
/// <summary>
/// 坦克配置类
/// </summary>
public class TankConfig
{
/// <summary>
/// 初始位置
/// </summary>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 初始朝向
/// </summary>
public Orientation InitialOrientation { get; set; }
/// <summary>
/// 初始速度(米/秒)
/// </summary>
public double InitialSpeed { get; set; }
/// <summary>
/// 最大速度(米/秒)
/// </summary>
public double MaxSpeed { get; set; }
/// <summary>
/// 最大装甲值
/// </summary>
public double MaxArmor { get; set; }
/// <summary>
/// 是否装备激光告警器
/// </summary>
public bool HasLaserWarner { get; set; }
/// <summary>
/// 是否装备激光干扰器
/// </summary>
public bool HasLaserJammer { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public TankConfig()
{
SetDefaultValues();
InitialPosition = new Vector3D(0, 0, 0);
InitialOrientation = new Orientation(0, 0, 0);
}
public TankConfig(TankInfo tankInfo){
SetDefaultValues();
InitialPosition = new Vector3D(tankInfo.xp, tankInfo.yp, tankInfo.zp);
InitialOrientation = new Orientation(0, 0, 0);
}
public void SetDefaultValues(){
InitialSpeed = 0;
MaxSpeed = 0;
MaxArmor = 0;
HasLaserWarner = false;
HasLaserJammer = false;
}
}
/// <summary>
/// 导弹配置类
/// </summary>
public class MissileConfig
{
/// <summary>
/// 初始位置
/// </summary>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 初始朝向
/// </summary>
public Orientation InitialOrientation { get; set; }
/// <summary>
/// 初始速度(米/秒)
/// </summary>
public double InitialSpeed { get; set; }
/// <summary>
/// 最大速度(米/秒)
/// </summary>
public double MaxSpeed { get; set; }
/// <summary>
/// 目标索引
/// </summary>
public int TargetIndex { get; set; }
/// <summary>
/// 最大飞行时间(秒)
/// </summary>
public double MaxFlightTime { get; set; }
/// <summary>
/// 最大飞行距离(米)
/// </summary>
public double MaxFlightDistance { get; set; }
/// <summary>
/// 最大加速度(米/秒²)
/// </summary>
public double MaxAcceleration { get; set; }
/// <summary>
/// 比例导引系数
/// </summary>
public double ProportionalNavigationCoefficient { get; set; }
/// <summary>
/// 飞行阶段配置
/// </summary>
public FlightStageConfig StageConfig { get; set; }
/// <summary>
/// 距离参数
/// </summary>
public MissileDistanceParams DistanceParams { get; set; }
/// <summary>
/// 推力加速度(米/秒²)
/// </summary>
public double ThrustAcceleration { get; set; }
/// <summary>
/// 最大发动机燃烧时间(秒)
/// </summary>
public double MaxEngineBurnTime { get; set; }
/// <summary>
/// 导弹质量(千克)
/// </summary>
public double Mass { get; set; }
/// <summary>
/// 导弹类型
/// </summary>
public MissileType Type { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public MissileConfig()
{
SetDefaultValues();
InitialPosition = new Vector3D(0, 0, 0);
InitialOrientation = new Orientation(0, 0, 0);
}
public MissileConfig(MIniInfo mIniInfo){
SetDefaultValues();
InitialPosition = new Vector3D(mIniInfo.xm, mIniInfo.ym, mIniInfo.zm);
InitialOrientation = new Orientation(mIniInfo.psi_m, mIniInfo.theta_m, 0);
InitialSpeed = mIniInfo.vm;
}
public void SetDefaultValues(){
InitialSpeed = 0;
MaxSpeed = 0;
TargetIndex = 0;
MaxFlightTime = 0;
MaxFlightDistance = 0;
StageConfig = FlightStageConfig.StandardMissile;
ThrustAcceleration = 0;
MaxEngineBurnTime = 0;
MaxAcceleration = 0;
DistanceParams = new MissileDistanceParams(0, 0, 0);
ProportionalNavigationCoefficient = 0;
Type = MissileType.StandardMissile;
}
}
/// <summary>
/// 激光指示器配置类
/// </summary>
public class LaserDesignatorConfig
{
/// <summary>
/// 初始位置
/// </summary>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 激光功率(瓦特)
/// </summary>
public double LaserPower { get; set; }
/// <summary>
/// 激光发散角
/// </summary>
public double LaserDivergenceAngle { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public LaserDesignatorConfig()
{
InitialPosition = new Vector3D(0, 0, 0);
LaserPower = 0;
LaserDivergenceAngle = 0;
}
}
/// <summary>
/// 激光驾束仪配置类
/// </summary>
public class LaserBeamRiderConfig
{
/// <summary>
/// 初始位置
/// </summary>
public Vector3D InitialPosition { get; set; }
/// <summary>
/// 激光功率(瓦特)
/// </summary>
public double LaserPower { get; set; }
/// <summary>
/// 控制场直径(米)
/// </summary>
public double ControlFieldDiameter { get; set; }
/// <summary>
/// 最大导引距离(米)
/// </summary>
public double MaxGuidanceDistance { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public LaserBeamRiderConfig()
{
InitialPosition = new Vector3D(0, 0, 0);
LaserPower = 0;
ControlFieldDiameter = 0;
}
}
/// <summary>
/// 导弹类型枚举
/// </summary>
public enum MissileType
{
StandardMissile, // 标准导弹
LaserSemiActiveGuidance, // 激光半主动制导
LaserBeamRiderGuidance, // 激光驾束制导
InfraredCommandGuidance, // 红外指令制导
InfraredImagingTerminalGuidance, // 红外成像末制导
MillimeterWaveTerminalGuidance // 毫米波末制导
}
/// <summary>
/// 导弹距离参数结构
/// </summary>
public struct MissileDistanceParams
{
/// <summary>
/// 终端制导距离(米)
/// </summary>
public double TerminalGuidanceDistance;
/// <summary>
/// 攻击距离(米)
/// </summary>
public double AttackDistance;
/// <summary>
/// 爆炸距离(米)
/// </summary>
public double ExplosionDistance;
public MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance)
{
TerminalGuidanceDistance = terminalGuidanceDistance;
AttackDistance = attackDistance;
ExplosionDistance = explosionDistance;
}
}
/// <summary>
/// <summary>
/// 导弹飞行阶段配置结构
/// </summary>
public struct FlightStageConfig
{
/// <summary>
/// 启用发射阶段
/// </summary>
public bool EnableLaunch;
/// <summary>
/// 启用加速阶段
/// </summary>
public bool EnableAcceleration;
/// <summary>
/// 启用巡航阶段
/// </summary>
public bool EnableCruise;
/// <summary>
/// 启用终端制导阶段
/// </summary>
public bool EnableTerminalGuidance;
/// <summary>
/// 启用攻击阶段
/// </summary>
public bool EnableAttack;
/// <summary>
/// 标准导弹的预设配置, 所有阶段都启用
/// </summary>
public static FlightStageConfig StandardMissile => new(true, true, true, true, true);
/// <summary>
/// 激光半主动制导导弹的预设配置, 没有加速阶段
/// </summary>
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(true, false, true, true, true);
/// <summary>
/// 激光驾束制导导弹的预设配置,没有巡航阶段
/// </summary>
public static FlightStageConfig LaserBeamRiderGuidance => new(true, true, false, true, true);
/// <summary>
/// 红外指令制导导弹的预设配置,没有巡航阶段
/// </summary>
public static FlightStageConfig InfraredCommandGuidance => new(true, true, false, true, true);
/// <summary>
/// 红外成像末制导导弹的预设配置
/// </summary>
public static FlightStageConfig InfraredImagingTerminalGuidance => new(true, true, true, true, true);
/// <summary>
/// 毫米波末制导导弹的预设配置
/// </summary>
public static FlightStageConfig MillimeterWaveTerminalGuidance => new(true, true, true, true, true);
public FlightStageConfig(bool enableLaunch, bool enableAcceleration, bool enableCruise, bool enableTerminalGuidance, bool enableAttack)
{
EnableLaunch = enableLaunch;
EnableAcceleration = enableAcceleration;
EnableCruise = enableCruise;
EnableTerminalGuidance = enableTerminalGuidance;
EnableAttack = enableAttack;
}
}
/// <summary>
/// 激光告警器配置类
/// </summary>
public class LaserWarnerConfig
{
/// <summary>
/// 警报持续时间(秒)
/// </summary>
public double AlarmDuration { get; set; }
/// <summary>
/// 构造函数,设置默认值
/// </summary>
public LaserWarnerConfig()
{
AlarmDuration = 5.0; // 默认警报持续5秒
}
}
/// <summary>
/// 激光干扰器配置类
/// </summary>
public class LaserJammerConfig
{
/// <summary>
/// 最大干扰冷却时间(秒)
/// </summary>
public double MaxJammingCooldown { 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 LaserJammerConfig()
{
MaxJammingCooldown = 5.0;
MaxJammingPower = 10000.0;
InitialJammingPower = 4000.0;
PowerIncreaseRate = 2000.0; // 每秒增加的功率
}
}
}

View File

@ -0,0 +1,101 @@
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
/// <summary>
/// 仿真元素的抽象基类,所有仿真中的实体都继承自此类
/// </summary>
public abstract class SimulationElement
{
/// <summary>
/// 仿真元素的唯一标识符
/// </summary>
public virtual string Id { get; set; }
/// <summary>
/// 仿真元素的当前位置
/// </summary>
public virtual Vector3D Position { get; set; }
/// <summary>
/// 仿真元素的当前速度
/// </summary>
public virtual Vector3D Velocity { get; set; }
/// <summary>
/// 仿真元素的当前朝向
/// </summary>
public virtual Orientation Orientation { get; set; }
/// <summary>
/// 仿真元素是否处于活动状态
/// </summary>
public virtual bool IsActive { get; protected set; }
/// <summary>
/// 仿真管理器的引用
/// </summary>
public ISimulationManager SimulationManager { get; set; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="id">仿真元素的唯一标识符</param>
/// <param name="position">初始位置</param>
/// <param name="orientation">初始朝向</param>
/// <param name="simulationManager">仿真管理器</param>
protected SimulationElement(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager)
{
Id = id;
Position = position;
Orientation = orientation;
SimulationManager = simulationManager;
Velocity = Vector3D.Zero;
IsActive = true;
}
/// <summary>
/// 更新仿真元素的状态
/// </summary>
/// <param name="deltaTime">时间步长</param>
public abstract void Update(double deltaTime);
/// <summary>
/// 获取仿真元素的状态信息
/// </summary>
/// <returns>状态信息字符串</returns>
public virtual string GetStatus()
{
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}";
}
/// <summary>
/// 发布仿真事件
/// </summary>
/// <param name="evt">要发布的事件</param>
protected void PublishEvent(SimulationEvent evt)
{
evt.SenderId = Id;
evt.Timestamp = SimulationManager.CurrentTime;
SimulationManager.PublishEvent(evt);
}
/// <summary>
/// 激活仿真元素
/// </summary>
public virtual void Activate()
{
IsActive = true;
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
}
/// <summary>
/// 停用仿真元素
/// </summary>
public virtual void Deactivate()
{
IsActive = false;
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
}
}
}

View File

@ -0,0 +1,171 @@
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
/// <summary>
/// 仿真事件的基类
/// </summary>
public class SimulationEvent
{
/// <summary>
/// 事件发送者的ID
/// </summary>
public string? SenderId { get; set; }
/// <summary>
/// 事件发生的时间戳
/// </summary>
public double Timestamp { get; set; }
}
/// <summary>
/// 导弹发射事件
/// </summary>
public class MissileFireEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光照射事件
/// </summary>
public class LaserIlluminationStartEvent : SimulationEvent
{
/// <summary>
/// 激光定位器
/// </summary>
public LaserDesignator? LaserDesignator { get; set; }
/// <summary>
/// 目标元素
/// </summary>
public SimulationElement? Target { get; set; }
}
/// <summary
/// <summary>
/// 激光照射更新事件
/// </summary>
public class LaserIlluminationUpdateEvent : SimulationEvent
{
/// <summary>
/// 激光定位器
/// </summary>
public LaserDesignator? LaserDesignator { get; set; }
/// <summary>
/// 目标元素
/// </summary>
public SimulationElement? Target { get; set; }
}
/// <summary
/// 激光照射停止事件
/// </summary>
public class LaserIlluminationStopEvent : SimulationEvent
{
public LaserDesignator? LaserDesignator { get; set; }
public SimulationElement? Target { get; set; }
}
/// <summary>
/// 激光干扰事件
/// </summary>
public class LaserJammingEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
/// <summary>
/// 干扰功率
/// </summary>
public double JammingPower { get; set; }
}
/// <summary>
/// 实体销毁事件
/// </summary>
public class EntityDestroyedEvent : SimulationEvent
{
/// <summary>
/// 被销毁实体的ID
/// </summary>
public string? DestroyedEntityId { get; set; }
}
/// <summary>
/// 激光告警器警报事件
/// </summary>
public class LaserWarnerAlarmEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 激光告警器警报停止事件
/// </summary>
public class LaserWarnerAlarmStopEvent : SimulationEvent
{
/// <summary>
/// 目标ID
/// </summary>
public string? TargetId { get; set; }
}
/// <summary>
/// 实体激活事件
/// </summary>
public class EntityActivatedEvent : SimulationEvent
{
/// <summary>
/// 被激活实体的ID
/// </summary>
public string? ActivatedEntityId { get; set; }
}
/// <summary>
/// 实体停用事件
/// </summary>
public class EntityDeactivatedEvent : SimulationEvent
{
/// <summary>
/// 被停用实体的ID
/// </summary>
public string? DeactivatedEntityId { get; set; }
}
/// <summary>
/// 激光开始事件
/// </summary>
public class LaserBeamStartEvent : SimulationEvent
{
public LaserBeamRider? LaserBeamRider { get; set; }
}
/// <summary>
/// 激光更新事件
/// </summary>
public class LaserBeamUpdateEvent : SimulationEvent
{
public LaserBeamRider? LaserBeamRider { get; set; }
}
/// <summary>
/// 激光停止事件
/// </summary>
public class LaserBeamStopEvent : SimulationEvent
{
public LaserBeamRider? LaserBeamRider { get; set; }
}
}

View File

@ -0,0 +1,399 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment
{
/// <summary>
/// 仿真管理器接口,定义了仿真管理器的基本功能
/// </summary>
public interface ISimulationManager
{
/// <summary>
/// 当前仿真时间
/// </summary>
double CurrentTime { get; }
/// <summary>
/// 添加仿真元素
/// </summary>
void AddElement(SimulationElement element);
/// <summary>
/// 根据ID获取仿真实体
/// </summary>
SimulationElement GetEntityById(string id);
/// <summary>
/// 处理目标被击中事件
/// </summary>
void HandleTargetHit(string targetId, string missileId);
/// <summary>
/// 发布仿真事件
/// </summary>
void PublishEvent(SimulationEvent evt);
/// <summary>
/// 订阅仿真事件
/// </summary>
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
/// <summary>
/// 取消订阅仿真事件
/// </summary>
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
/// <summary>
/// 取消所有事件订阅
/// </summary>
void UnsubscribeAllEvents(SimulationElement element);
}
/// <summary>
/// 仿真管理器类,负责管理整个仿真过程
/// </summary>
public class SimulationManager : ISimulationManager
{
/// <summary>
/// 仿真元素列表
/// </summary>
public List<SimulationElement> Elements { get; private set; }
/// <summary>
/// 当前仿真时间
/// </summary>
public double CurrentTime { get; private set; }
/// <summary>
/// 仿真是否结束
/// </summary>
public bool IsSimulationEnded { get; private set; }
private readonly SimulationConfig config;
private Dictionary<Type, List<Delegate>> eventHandlers = new Dictionary<Type, List<Delegate>>();
private Dictionary<SimulationElement, List<(Type, Delegate)>> elementSubscriptions = new Dictionary<SimulationElement, List<(Type, Delegate)>>();
/// <summary>
/// 构造函数
/// </summary>
public SimulationManager(SimulationConfig config)
{
this.config = config;
Elements = new List<SimulationElement>();
CurrentTime = 0;
IsSimulationEnded = false;
InitializeSimulation();
}
/// <summary>
/// 初始化仿真
/// </summary>
private void InitializeSimulation()
{
// 创建坦克
for (int i = 0; i < config.TankConfigs.Count; i++)
{
var tankConfig = config.TankConfigs[i];
var tank = new Tank($"Tank_{i + 1}", tankConfig, this);
Elements.Add(tank);
// // 为坦克创建激光告警器
// if (tankConfig.HasLaserWarner)
// {
// var laserWarner = new LaserWarner(
// $"LaserWarner_{tank.Id}",
// tank.Position,
// tank.Orientation,
// this,
// tank.Id,
// config.LaserWarnerConfig
// );
// Elements.Add(laserWarner);
// }
// // 为坦克创建激光干扰机
// if (tankConfig.HasLaserJammer)
// {
// var laserJammer = new LaserJammer(
// $"LaserJammer_{tank.Id}",
// tank.Position,
// tank.Orientation,
// this,
// tank.Id,
// config.LaserJammerConfig
// );
// Elements.Add(laserJammer);
// }
}
// 创建导弹
for (int i = 0; i < config.MissileConfigs.Count; i++)
{
var missileConfig = config.MissileConfigs[i];
// 确保 MaxFlightTime 设置合理
if (missileConfig.MaxFlightTime <= 0)
{
missileConfig.MaxFlightTime = 300; // 设置一个默认值,比如 300 秒
Console.WriteLine($"警告:导弹配置 {i} 的 MaxFlightTime 无效,已设置为默认值 300 秒");
}
MissileBase missile = missileConfig.Type switch
{
MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
$"LSGM_{i + 1}",
missileConfig,
"LD_1",
this
),
MissileType.LaserBeamRiderGuidance => new LaserBeamRiderMissile(
$"LBRM_{i + 1}",
"Tank_1",
missileConfig,
this
),
_ => new MissileBase(
$"NM_{i + 1}",
missileConfig,
this
),
};
Elements.Add(missile);
}
// 创建激光目标指示器
var laserDesignatorConfig = config.LaserDesignatorConfig;
var laserDesignator = new LaserDesignator(
$"LD_1",
"Tank_1",
"LSGM_1",
laserDesignatorConfig,
this
);
Elements.Add(laserDesignator);
// 创建激光驾束仪
var laserBeamRiderConfig = config.LaserBeamRiderConfig;
var laserBeamRider = new LaserBeamRider(
"LBR_1",
"LBRM_2",
"Tank_1",
laserBeamRiderConfig,
this
);
Elements.Add(laserBeamRider);
// 激活所有元素
ActivateAllElements();
// 启动激光驾束仪
laserBeamRider.StartBeamIllumination();
}
//激活所有元素
private void ActivateAllElements()
{
foreach (var element in Elements)
{
element.Activate();
}
}
/// <summary>
/// 发布仿真事件
/// </summary>
public void PublishEvent(SimulationEvent evt)
{
var eventType = evt.GetType();
//Console.WriteLine($"发布事件: {eventType.Name}, 发送者: {evt.SenderId}");
if (eventHandlers.TryGetValue(eventType, out var handlers))
{
foreach (var handler in handlers)
{
handler.DynamicInvoke(evt);
}
}
else
{
Console.WriteLine($"没有找到事件 {eventType.Name} 的处理程序");
}
}
/// <summary>
/// 订阅仿真事件
/// </summary>
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
{
var eventType = typeof(T);
if (!eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
{
value = new List<Delegate>();
eventHandlers[eventType] = value;
}
value.Add(handler);
// 记录订阅关系
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null)
{
if (!elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{
subscriptions = new List<(Type, Delegate)>();
elementSubscriptions[element] = subscriptions;
}
subscriptions.Add((eventType, handler as Delegate));
}
}
/// <summary>
/// 取消订阅仿真事件
/// </summary>
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
{
var eventType = typeof(T);
if (eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
{
value.Remove(handler);
}
// 移除订阅关系记录
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null && elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{
subscriptions.RemoveAll(s => Delegate.Equals(s.Item2, handler));
}
}
/// <summary>
/// 取消所有事件订阅
/// </summary>
public void UnsubscribeAllEvents(SimulationElement element)
{
if (elementSubscriptions.ContainsKey(element))
{
foreach (var subscription in elementSubscriptions[element])
{
if (eventHandlers.TryGetValue(subscription.Item1, out List<Delegate>? value))
{
value.Remove(subscription.Item2);
}
}
elementSubscriptions.Remove(element);
}
}
/// <summary>
/// 更新仿真状态
/// </summary>
public void Update()
{
if (IsSimulationEnded) return;
CurrentTime += config.SimulationTimeStep;
foreach (var element in Elements.ToList())
{
if (element.IsActive)
{
element.Update(config.SimulationTimeStep);
}
else
{
UnsubscribeAllEvents(element);
}
}
// 移除不活跃的元素
Elements.RemoveAll(e => !e.IsActive);
// 检查是否所有导弹都结束飞行
if (!Elements.Any(e => e is MissileBase && e.IsActive))
{
EndSimulation();
}
}
/// <summary>
/// 打印仿真状态
/// </summary>
public void PrintStatus()
{
Console.WriteLine($"仿真时间: {CurrentTime:F2}");
foreach (var element in Elements)
{
Console.WriteLine(element.GetStatus());
}
Console.WriteLine();
}
/// <summary>
/// 结束仿真
/// </summary>
private void EndSimulation()
{
IsSimulationEnded = true;
Console.WriteLine("仿真结束");
Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒");
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
}
/// <summary>
/// 根据ID获取仿真实体
/// </summary>
public SimulationElement GetEntityById(string id)
{
return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found");
}
/// <summary>
/// 处理目标被击中事件
/// </summary>
public void HandleTargetHit(string targetId, string missileId)
{
if (GetEntityById(targetId) is Tank tank && GetEntityById(missileId) is MissileBase missile)
{
// 计算导弹造成的伤害
double damage = CalculateMissileDamage(missile);
// 对坦克造成伤害
tank.TakeDamage(damage, true);
// 记录击中事件
LogHitEvent(targetId, missileId, damage);
}
}
/// <summary>
/// 计算导弹造成的伤害
/// </summary>
private double CalculateMissileDamage(MissileBase missile)
{
// 这里可以根据导弹类型、速度等因素计算伤害
// 现在我们简单地返回一个固定值
return 50;
}
/// <summary>
/// 记录击中事件
/// </summary>
private static void LogHitEvent(string targetId, string missileId, double damage)
{
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
}
/// <summary>
/// 添加仿真元素
/// </summary>
public void AddElement(SimulationElement element)
{
Elements.Add(element);
}
}
}