From 47849abf9e9b7dc64ed11b82ed1f39261fcd4dea Mon Sep 17 00:00:00 2001 From: Tian jianyong <11429339@qq.com> Date: Sat, 19 Oct 2024 14:26:26 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=8F=90=E4=BA=A4=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E4=BB=A3=E7=A0=81,=20=E5=8E=BB=E6=8E=89=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes .cursorrules | 65 ++ .gitignore | 237 ++++++++ ActiveProtect.csproj | 11 + ActiveProtect.sln | 29 + Design.md | 150 +++++ DesignMissile.md | 105 ++++ Models/.DS_Store | Bin 0 -> 6148 bytes Models/ActiveProtect.code-workspace | 10 + Models/BasicGuidanceSystem.cs | 90 +++ Models/Common.cs | 297 +++++++++ Models/IGuidanceSystem.cs | 9 + Models/LaserBeamRider.cs | 157 +++++ Models/LaserBeamRiderGuidanceSystem.cs | 193 ++++++ Models/LaserBeamRiderMissile.cs | 84 +++ Models/LaserDesignator.cs | 235 +++++++ Models/LaserJammer.cs | 196 ++++++ Models/LaserSemiActiveGuidanceSystem.cs | 142 +++++ Models/LaserSemiActiveGuidedMissile.cs | 126 ++++ Models/LaserWarner.cs | 159 +++++ Models/MissileBase.cs | 675 +++++++++++++++++++++ Models/MissileClass.cs | 351 +++++++++++ Models/MissileStageStrategy.cs | 168 +++++ Models/Tank.cs | 100 +++ Program.cs | 138 +++++ README.md | 171 ++++++ SimulationEnvironment/SimulationConfig.cs | 474 +++++++++++++++ SimulationEnvironment/SimulationElement.cs | 101 +++ SimulationEnvironment/SimulationEvents.cs | 171 ++++++ SimulationEnvironment/SimulationManager.cs | 399 ++++++++++++ 30 files changed, 5043 insertions(+) create mode 100644 .DS_Store create mode 100644 .cursorrules create mode 100644 .gitignore create mode 100644 ActiveProtect.csproj create mode 100644 ActiveProtect.sln create mode 100644 Design.md create mode 100644 DesignMissile.md create mode 100644 Models/.DS_Store create mode 100644 Models/ActiveProtect.code-workspace create mode 100644 Models/BasicGuidanceSystem.cs create mode 100644 Models/Common.cs create mode 100644 Models/IGuidanceSystem.cs create mode 100644 Models/LaserBeamRider.cs create mode 100644 Models/LaserBeamRiderGuidanceSystem.cs create mode 100644 Models/LaserBeamRiderMissile.cs create mode 100644 Models/LaserDesignator.cs create mode 100644 Models/LaserJammer.cs create mode 100644 Models/LaserSemiActiveGuidanceSystem.cs create mode 100644 Models/LaserSemiActiveGuidedMissile.cs create mode 100644 Models/LaserWarner.cs create mode 100644 Models/MissileBase.cs create mode 100644 Models/MissileClass.cs create mode 100644 Models/MissileStageStrategy.cs create mode 100644 Models/Tank.cs create mode 100644 Program.cs create mode 100644 README.md create mode 100644 SimulationEnvironment/SimulationConfig.cs create mode 100644 SimulationEnvironment/SimulationElement.cs create mode 100644 SimulationEnvironment/SimulationEvents.cs create mode 100644 SimulationEnvironment/SimulationManager.cs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f121b4c2b3d84c8948fa1c98f0c93d9277a7c44b GIT binary patch literal 6148 zcmeHK%}T>S5Z-NTyQK&@DD)WcTCkNO1TP`#(Tfp1sMLf64aRI~QhO+cob`o#5}(JJ z-OV8w@FrqsVE3DypWVy{*&oIj_m4xyhp7x3 zCi;se{Pr%pV3I{FX7%s?2N1dNTL`*?rxGSk}FRxvnW@&zIKSd=+CU-dOdL_BYWyNn~}YC zj>e!LPdA&s*grTtxtu+xFPVJPL~`I<$*#c)-a)C=^y)9NRA!H0uX3tbLSldzAO?tm z?PI{41!Ay$rBlVk05R|b1Gqof&=6gNrAD=NK!?|7^mhPi2-7u&OloaEj<6v;g@NA z@Z$`^Zo^wckb^;#`BJ VMw|uhDjkq60*Vmoh=E^V;0sT1OZxx- literal 0 HcmV?d00001 diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..ec908e3 --- /dev/null +++ b/.cursorrules @@ -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. + \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d91b085 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/ActiveProtect.csproj b/ActiveProtect.csproj new file mode 100644 index 0000000..d579445 --- /dev/null +++ b/ActiveProtect.csproj @@ -0,0 +1,11 @@ + + + + Exe + net6.0 + 9.0 + disable + enable + + + diff --git a/ActiveProtect.sln b/ActiveProtect.sln new file mode 100644 index 0000000..99af9fe --- /dev/null +++ b/ActiveProtect.sln @@ -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 diff --git a/Design.md b/Design.md new file mode 100644 index 0000000..d2001ed --- /dev/null +++ b/Design.md @@ -0,0 +1,150 @@ +# 导弹仿真系统设计文档 + +## 系统架构设计思路 + +在处理导弹、坦克、告警设备、干扰设备等复杂交互关系时,我们采用了以下几种程序架构和设计模式的组合: + +### 1. 事件驱动架构(Event-Driven Architecture) + +事件驱动架构非常适合处理复杂的交互关系。每个实体(如导弹、坦克等)可以发布事件,其他实体可以订阅这些事件并作出反应。 + +``csharp +public class EventManager +{ +private Dictionary>> eventSubscribers = new Dictionary>>(); +public void Subscribe(string eventName, Action 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 导弹行为 + +导弹行为包括导弹的飞行行为、攻击行为、躲避行为、跟踪行为、锁定行为、发射行为、爆炸行为等。 diff --git a/DesignMissile.md b/DesignMissile.md new file mode 100644 index 0000000..28c34aa --- /dev/null +++ b/DesignMissile.md @@ -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. 预测控制: + 基于当前状态预测未来的位置,提前做出调整。 diff --git a/Models/.DS_Store b/Models/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1212d97df883ecbfe1d7498f8aa505b13e4ce782 GIT binary patch literal 6148 zcmeHK%Sr<=6g|;`1vg!~%nxYs4`Qi16+zuwZ4n>X(wPz5&8K_rLveK0(#pL6 znFEtd0HjGXKL$nshHQdKIz1xp-q4OG3nm@o2=}N~_1#%h^$fI$E?N5?t}(+ap7Cw{ z^_r1G+@Qh&Yw9s-JZj#P<2#nDdSGOR6(7ktAp?^4#;Qx!Eom*(H^w=wIjtAX?3?$Z zsdU~SE80ZjVokw7Fc1s`16#`g&uo$5zG3KKAQ%V+z8H}GA+re<$JS7{4l2C@5C?Rt zurGHBsmYGTu{C6blB|?yrOB@t$;#=^o>v@OLn}wpnK_Qn{CRmvIy?PY(~*i{=wKii z=rXWt=19)}Q+_hNm;7!?SiwLr@Xr`XgXz_D!k6;1_1EjkS)18z*+e9-l@5jd&QAah g*+&jEXz?t4<`u`*P(~5ImJ{PgKnV#I4EzBDA1+rd=>Px# literal 0 HcmV?d00001 diff --git a/Models/ActiveProtect.code-workspace b/Models/ActiveProtect.code-workspace new file mode 100644 index 0000000..f371420 --- /dev/null +++ b/Models/ActiveProtect.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "../../ActiveProtect.Tests" + }, + { + "path": ".." + } + ] +} \ No newline at end of file diff --git a/Models/BasicGuidanceSystem.cs b/Models/BasicGuidanceSystem.cs new file mode 100644 index 0000000..5f1e147 --- /dev/null +++ b/Models/BasicGuidanceSystem.cs @@ -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); + } + } +} diff --git a/Models/Common.cs b/Models/Common.cs new file mode 100644 index 0000000..01b946a --- /dev/null +++ b/Models/Common.cs @@ -0,0 +1,297 @@ +using System; + +namespace ActiveProtect.Models +{ + /// + /// 表示三维空间中的向量 + /// + 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); + + /// + /// X 坐标 + /// + public double X { get; set; } + + /// + /// Y 坐标 + /// + public double Y { get; set; } + + /// + /// Z 坐标 + /// + public double Z { get; set; } + + /// + /// 构造函数 + /// + public Vector3D(double x, double y, double z) + { + X = x; + Y = y; + Z = z; + } + + /// + /// 计算两个向量之间的距离 + /// + /// 第一个向量 + /// 第二个向量 + /// 两个向量之间的距离 + public static double Distance(Vector3D v1, Vector3D v2) + { + return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2)); + } + + + /// + /// 将向量转换为字符串表示 + /// + /// 向量的字符串表示 + public override string ToString() + { + return $"({X:F2}, {Y:F2}, {Z:F2})"; + } + + /// + /// 向量减法运算符重载 + /// + public static Vector3D operator -(Vector3D a, Vector3D b) + { + return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z); + } + + /// + /// 向量加法运算符重载 + /// + public static Vector3D operator +(Vector3D a, Vector3D b) + { + return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z); + } + + /// + /// 向量与标量乘法运算符重载 + /// + public static Vector3D operator *(Vector3D a, double scalar) + { + return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar); + } + + /// + /// 向量与标量除法运算符重载 + /// + public static Vector3D operator /(Vector3D a, double scalar) + { + return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar); + } + + /// + /// 向量反向 + /// + public static Vector3D operator -(Vector3D a) + { + return new Vector3D(-a.X, -a.Y, -a.Z); + } + + /// + /// 计算向量的模长 + /// + /// 向量的模长 + public double Magnitude() + { + return Math.Sqrt(X * X + Y * Y + Z * Z); + } + + /// + /// 计算向量模长的平方 + /// + /// 向量模长的平方 + public double MagnitudeSquared() + { + return X * X + Y * Y + Z * Z; + } + + /// + /// 向量归一化 + /// + /// 归一化后的向量 + public Vector3D Normalize() + { + double mag = Magnitude(); + if (mag > 0) + { + return new Vector3D(X / mag, Y / mag, Z / mag); + } + return new Vector3D(0, 0, 0); + } + + /// + /// 计算两个向量的叉积 + /// + /// 第一个向量 + /// 第二个向量 + /// 叉积结果 + public static Vector3D CrossProduct(Vector3D a, Vector3D b) + { + return new Vector3D( + a.Y * b.Z - a.Z * b.Y, + a.Z * b.X - a.X * b.Z, + a.X * b.Y - a.Y * b.X + ); + } + + /// + /// 计算两个向量的点积 + /// + /// 第一个向量 + /// 第二个向量 + /// 点积结果 + public static double DotProduct(Vector3D a, Vector3D b) + { + return a.X * b.X + a.Y * b.Y + a.Z * b.Z; + } + + /// + /// 向量取反 + /// + /// 输入向量 + /// 取反后的向量 + public static Vector3D Negate(Vector3D a) + { + return new Vector3D(-a.X, -a.Y, -a.Z); + } + } + + /// + /// 表示三维空间中的方向 + /// + public struct Orientation + { + /// + /// 偏航角(绕Y轴旋转) + /// + public double Yaw { get; set; } + + /// + /// 俯仰角(绕X轴旋转) + /// + public double Pitch { get; set; } + + /// + /// 滚转角(绕Z轴旋转) + /// + public double Roll { get; set; } + + /// + /// 构造函数 + /// + public Orientation(double yaw, double pitch, double roll) + { + Yaw = yaw; + Pitch = pitch; + Roll = roll; + } + + /// + /// 将方向转换为字符串表示 + /// + /// 方向的字符串表示 + public override readonly string ToString() + { + return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})"; + } + + /// + /// 将角度归一化到 [-π, π] 范围内 + /// + public void Normalize() + { + Yaw = NormalizeAngle(Yaw); + Pitch = NormalizeAngle(Pitch); + Roll = NormalizeAngle(Roll); + } + + /// + /// 将单个角度归一化到 [-π, π] 范围内 + /// + /// 输入角度 + /// 归一化后的角度 + private static double NormalizeAngle(double angle) + { + while (angle > Math.PI) angle -= 2 * Math.PI; + while (angle <= -Math.PI) angle += 2 * Math.PI; + return angle; + } + + /// + /// 根据给定的方向向量创建方向 + /// + /// 方向向量 + /// 对应的方向 + public static Orientation LookAt(Vector3D direction) + { + double yaw = Math.Atan2(direction.Z, direction.X); + double pitch = Math.Atan2(direction.Y, Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z)); + return new Orientation(yaw, pitch, 0); + } + + /// + /// 将方向转换为单位向量 + /// + /// 对应的单位向量 + public readonly Vector3D ToVector() + { + double cosYaw = Math.Cos(Yaw); + double sinYaw = Math.Sin(Yaw); + double cosPitch = Math.Cos(Pitch); + double sinPitch = Math.Sin(Pitch); + + return new Vector3D( + cosYaw * cosPitch, + sinPitch, + sinYaw * cosPitch + ); + } + + /// + /// 从向量创建方向 + /// + /// 输入向量 + /// 对应的方向 + public static Orientation FromVector(Vector3D vector) + { + Vector3D normalized = vector.Normalize(); + double pitch = Math.Asin(normalized.Y); + double yaw; + if (Math.Abs(normalized.Y) > 0.9999) // 接近垂直 + { + yaw = 0; // 或者保持之前的偏航角 + } + else + { + yaw = Math.Atan2(normalized.Z, normalized.X); + } + return new Orientation(yaw, pitch, 0); + } + } + + public 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); + } +} diff --git a/Models/IGuidanceSystem.cs b/Models/IGuidanceSystem.cs new file mode 100644 index 0000000..171ac22 --- /dev/null +++ b/Models/IGuidanceSystem.cs @@ -0,0 +1,9 @@ +namespace ActiveProtect.Models +{ + public interface IGuidanceSystem + { + bool HasGuidance { get; } + void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity); + Vector3D GetGuidanceCommand(); + } +} diff --git a/Models/LaserBeamRider.cs b/Models/LaserBeamRider.cs new file mode 100644 index 0000000..6bb77cd --- /dev/null +++ b/Models/LaserBeamRider.cs @@ -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(); + } + } + + + /// + /// 激活激光驾束仪 + /// + public override void Activate() + { + if (!IsActive) + { + IsActive = true; + Console.WriteLine($"激光驾束仪 {Id} 已激活"); + } + base.Activate(); + } + + /// + /// 停用激光驾束仪 + /// + 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(); + } + } + + /// + /// 发布激光束开始事件 + /// + private void PublishLaserBeamStartEvent() + { + PublishEvent(new LaserBeamStartEvent + { + LaserBeamRider = this + }); + } + + /// + /// 发布激光束更新事件 + /// + private void PublishLaserBeamUpdateEvent() + { + PublishEvent(new LaserBeamUpdateEvent + { + LaserBeamRider = this + }); + } + + /// + /// 发布激光束停止事件 + /// + 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 ? "开启" : "关闭")}"; + } + } +} diff --git a/Models/LaserBeamRiderGuidanceSystem.cs b/Models/LaserBeamRiderGuidanceSystem.cs new file mode 100644 index 0000000..155f984 --- /dev/null +++ b/Models/LaserBeamRiderGuidanceSystem.cs @@ -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; + } + } +} diff --git a/Models/LaserBeamRiderMissile.cs b/Models/LaserBeamRiderMissile.cs new file mode 100644 index 0000000..f2b4027 --- /dev/null +++ b/Models/LaserBeamRiderMissile.cs @@ -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(OnLaserBeamStart); + SimulationManager.SubscribeToEvent(OnLaserBeamStop); + SimulationManager.SubscribeToEvent(OnLaserBeamUpdate); + } + + public override void Deactivate() + { + base.Deactivate(); + SimulationManager.UnsubscribeFromEvent(OnLaserBeamStart); + SimulationManager.UnsubscribeFromEvent(OnLaserBeamStop); + SimulationManager.UnsubscribeFromEvent(OnLaserBeamUpdate); + } + } +} diff --git a/Models/LaserDesignator.cs b/Models/LaserDesignator.cs new file mode 100644 index 0000000..b6b583e --- /dev/null +++ b/Models/LaserDesignator.cs @@ -0,0 +1,235 @@ +using ActiveProtect.SimulationEnvironment; +using System; + +namespace ActiveProtect.Models +{ + /// + /// 激光指示器类,用于对目标进行激光照射 + /// + public class LaserDesignator : SimulationElement + { + /// + /// 目标ID + /// + public string TargetId { get; private set; } + + /// + /// 导弹ID + /// + public string MissileId { get; private set; } + + /// + /// 干扰阈值(分贝) + /// + public double JammingThreshold { get; private set; } = 0.0; + + /// + /// 是否被干扰 + /// + public bool IsJammed { get; private set; } = false; + + /// + /// 是否正在照射 + /// + public bool IlluminationOn { get; private set; } = false; + + + /// + /// 激光功率 + /// + public double LaserPower { get; private set; } = 0; + + /// + /// 激光发散角 + /// + public double LaserDivergenceAngle { get; private set; } = 0; + + /// + /// 构造函数 + /// + /// 激光指示器ID + /// 目标ID + /// 导弹ID + /// 激光指示器配置 + /// 仿真管理器 + 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; + } + + /// + /// 更新激光指示器状态 + /// + /// 时间步长 + public override void Update(double deltaTime) + { + if (IsActive && !IsJammed) + { + if (IlluminationOn) + { + PublishIlluminationUpdateEvent(); + } + } + } + + /// + /// 开始激光照射 + /// + private void StartLaserIllumination() + { + if (!IlluminationOn) + { + IlluminationOn = true; + Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}"); + PublishIlluminationStartEvent(); + } + } + + /// + /// 停止激光照射 + /// + private void StopLaserIllumination() + { + if (IlluminationOn) + { + IlluminationOn = false; + Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}"); + PublishIlluminationStopEvent(); + } + } + + /// + /// 处理激光干扰事件 + /// + /// 激光干扰事件 + 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; + } + } + } + } + } + + /// + /// 激活激光指示器 + /// + public override void Activate() + { + if (!IsActive) + { + IsActive = true; + IsJammed = false; + Console.WriteLine($"激光目标指示器 {Id} 已激活"); + StartLaserIllumination(); + SimulationManager.SubscribeToEvent(OnLaserJamming); + SimulationManager.SubscribeToEvent(OnEntityDeactivatedEvent); + } + base.Activate(); + } + + /// + /// 停用激光指示器 + /// + public override void Deactivate() + { + if (IsActive) + { + IsActive = false; + StopLaserIllumination(); + Console.WriteLine($"激光目标指示器 {Id} 已停用"); + SimulationManager.UnsubscribeFromEvent(OnLaserJamming); + SimulationManager.UnsubscribeFromEvent(OnEntityDeactivatedEvent); + } + base.Deactivate(); + } + + /// + /// 发布激光照射事件 + /// + private void PublishIlluminationStartEvent() + { + var evt = new LaserIlluminationStartEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement }; + PublishEvent(evt); + Console.WriteLine($"激光指示器 {Id} 发布激光照射事件"); + } + + /// + /// 发布激光照射更新事件 + /// + private void PublishIlluminationUpdateEvent() + { + var evt = new LaserIlluminationUpdateEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement }; + PublishEvent(evt); + Console.WriteLine($"激光指示器 {Id} 发布激光照射更新事件"); + } + + /// + /// 发布激光照射停止事件 + /// + private void PublishIlluminationStopEvent() + { + var evt = new LaserIlluminationStopEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement }; + PublishEvent(evt); + Console.WriteLine($"激光指示器 {Id} 发布激光照射停止事件"); + } + + /// + /// 处理实体停用事件 + /// + /// 实体停用事件 + private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt) + { + if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId) + { + StopLaserIllumination(); + } + } + + /// + /// 获取激光指示器状态信息 + /// + /// 状态信息字符串 + public override string GetStatus() + { + return $"激光目标指示器 {Id}:\n" + + $" 位置: {Position}\n" + + $" 目标: {TargetId}\n" + + $" 导弹: {MissileId}\n" + + $" 激活状态: {(IsActive ? "激活" : "未激活")}\n" + + $" 照射状态: {(IlluminationOn ? "正在照射" : "未照射")}\n" + + $" 干扰状态: {(IsJammed ? "被干扰" : "正常")}\n" + + $" 激光功率: {LaserPower:E} W"; + } + } +} diff --git a/Models/LaserJammer.cs b/Models/LaserJammer.cs new file mode 100644 index 0000000..89ebe1d --- /dev/null +++ b/Models/LaserJammer.cs @@ -0,0 +1,196 @@ +using System; +using ActiveProtect.SimulationEnvironment; + +namespace ActiveProtect.Models +{ + /// + /// 激光干扰器类,用于对抗激光制导武器 + /// + public class LaserJammer : SimulationElement + { + /// + /// 是否正在进行干扰 + /// + public bool IsJamming { get; private set; } + + /// + /// 当前干扰功率(瓦特) + /// + public double JammingPower { get; private set; } + + /// + /// 当前冷却时间(秒) + /// + private double jammingCooldown = 0; + + /// + /// 最大冷却时间(秒) + /// + private readonly double maxJammingCooldown; + + /// + /// 最大干扰功率(瓦特) + /// + private readonly double maxJammingPower; + + /// + /// 初始干扰功率(瓦特) + /// + private readonly double initialJammingPower; + + /// + /// 功率增加速率(瓦特/秒) + /// + private readonly double powerIncreaseRate; + + /// + /// 被监视实体的ID + /// + public string MonitoredEntityId { get; private set; } + + /// + /// 构造函数 + /// + /// 激光干扰器ID + /// 初始位置 + /// 初始朝向 + /// 仿真管理器 + /// 被监视实体的ID + /// 激光干扰器配置 + 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(OnLaserWarnerAlarmEvent); + SimulationManager.SubscribeToEvent(OnLaserWarnerAlarmStopEvent); + } + + /// + /// 更新激光干扰器状态 + /// + /// 时间步长 + 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}"); + } + } + + /// + /// 处理激光告警器警报事件 + /// + /// 激光告警器警报事件 + private void OnLaserWarnerAlarmEvent(LaserWarnerAlarmEvent evt) + { + if (evt.TargetId == MonitoredEntityId) + { + StartJamming(); + } + } + + /// + /// 处理激光告警器警报停止事件 + /// + /// 激光告警器警报停止事件 + private void OnLaserWarnerAlarmStopEvent(LaserWarnerAlarmStopEvent evt) + { + if (evt.TargetId == MonitoredEntityId) + { + StopJamming(); + } + } + + /// + /// 开始干扰 + /// + private void StartJamming() + { + if (!IsJamming) + { + IsJamming = true; + JammingPower = initialJammingPower; + jammingCooldown = 0; + Console.WriteLine($"激光干扰器 {Id} 开始工作,初始功率: {JammingPower:F2}"); + } + } + + /// + /// 停止干扰 + /// + private void StopJamming() + { + if (IsJamming) + { + IsJamming = false; + JammingPower = 0; + jammingCooldown = 0; + Console.WriteLine($"激光干扰器 {Id} 停止工作"); + } + } + + /// + /// 获取激光干扰器状态信息 + /// + /// 状态信息字符串 + public override string GetStatus() + { + return $"激光干扰器 {Id}:\n" + + $" 监视实体: {MonitoredEntityId}\n" + + $" 干扰状态: {(IsJamming ? "干扰中" : "未干扰")}\n" + + $" 当前功率: {JammingPower:F2}/{maxJammingPower:F2}\n" + + $" 冷却时间: {jammingCooldown:F2}/{maxJammingCooldown:F2}"; + } + + /// + /// 激活激光干扰器 + /// + public override void Activate() + { + base.Activate(); + SimulationManager.SubscribeToEvent(OnLaserWarnerAlarmEvent); + SimulationManager.SubscribeToEvent(OnLaserWarnerAlarmStopEvent); + } + + /// + /// 停用激光干扰器 + /// + public override void Deactivate() + { + base.Deactivate(); + SimulationManager.UnsubscribeFromEvent(OnLaserWarnerAlarmEvent); + SimulationManager.UnsubscribeFromEvent(OnLaserWarnerAlarmStopEvent); + } + } +} diff --git a/Models/LaserSemiActiveGuidanceSystem.cs b/Models/LaserSemiActiveGuidanceSystem.cs new file mode 100644 index 0000000..e7a040d --- /dev/null +++ b/Models/LaserSemiActiveGuidanceSystem.cs @@ -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(); + } + } +} diff --git a/Models/LaserSemiActiveGuidedMissile.cs b/Models/LaserSemiActiveGuidedMissile.cs new file mode 100644 index 0000000..50036e2 --- /dev/null +++ b/Models/LaserSemiActiveGuidedMissile.cs @@ -0,0 +1,126 @@ +using ActiveProtect.SimulationEnvironment; +using System; + +namespace ActiveProtect.Models +{ + /// + /// 激光半主动制导导弹类,继承自基础导弹类 + /// + public class LaserSemiActiveGuidedMissile : MissileBase + { + private LaserSemiActiveGuidanceSystem LaserGuidanceSystem; + private string LaserDesignatorId; + + /// + /// 构造函数 + /// + /// 导弹ID + /// 激光指示器ID + /// 导弹配置 + /// 仿真管理器 + 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; + } + + /// + /// 处理激光照射事件 + /// + /// 激光照射事件 + 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); + } + } + + /// + /// 处理激光照射更新事件 + /// + /// 激光照射更新事件 + 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); + } + } + + /// + /// 处理激光照射停止事件 + /// + /// 激光照射停止事件 + private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt) + { + LaserGuidanceSystem.DeactivateLaserDesignator(); + } + + /// + /// 获取导弹状态信息 + /// + /// 状态信息字符串 + public override string GetStatus() + { + string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹"); + string additionalStatus = $"\n 激光引导: {(LaserGuidanceSystem.HasGuidance ? "有效" : "无效")}"; + return baseStatus + additionalStatus; + } + + /// + /// 激活导弹 + /// + public override void Activate() + { + base.Activate(); + SimulationManager.SubscribeToEvent(OnLaserIlluminationStart); + SimulationManager.SubscribeToEvent(OnLaserIlluminationUpdate); + SimulationManager.SubscribeToEvent(OnLaserIlluminationStop); + } + + /// + /// 停用导弹 + /// + public override void Deactivate() + { + base.Deactivate(); + SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStart); + SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationUpdate); + SimulationManager.UnsubscribeFromEvent(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); + } + + /// + /// 获取制导命令 + /// + /// 制导命令 + protected override Vector3D GetGuidanceCommand() + { + return LaserGuidanceSystem.GetGuidanceCommand(); + } + } +} diff --git a/Models/LaserWarner.cs b/Models/LaserWarner.cs new file mode 100644 index 0000000..04b1082 --- /dev/null +++ b/Models/LaserWarner.cs @@ -0,0 +1,159 @@ +using ActiveProtect.SimulationEnvironment; +using System; + +namespace ActiveProtect.Models +{ + /// + /// 激光告警器类,用于检测激光照射并发出警报 + /// + public class LaserWarner : SimulationElement + { + /// + /// 是否正在发出警报 + /// + public bool IsAlarming { get; private set; } + + /// + /// 警报持续时间(秒) + /// + private readonly double alarmDuration; + + /// + /// 当前警报计时器 + /// + private double alarmTimer = 0; + + /// + /// 被监视实体的ID + /// + public string MonitoredEntityId { get; private set; } + + /// + /// 构造函数 + /// + /// 激光告警器ID + /// 初始位置 + /// 初始朝向 + /// 仿真管理器 + /// 被监视实体的ID + /// 激光告警器配置 + 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(OnLaserIlluminationStart); + SimulationManager.SubscribeToEvent(OnLaserIlluminationStop); + } + + /// + /// 更新激光告警器状态 + /// + /// 时间步长 + 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(); + } + } + } + + /// + /// 处理激光照射事件 + /// + /// 激光照射事件 + private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt) + { + if (evt?.Target != null && evt.Target.Id == MonitoredEntityId) + { + TriggerAlarm(); + } + } + + /// + /// 处理激光照射停止事件 + /// + /// 激光照射停止事件 + private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt) + { + if (evt?.Target != null && evt.Target.Id == MonitoredEntityId) + { + StopAlarm(); + } + } + + /// + /// 触发警报 + /// + public void TriggerAlarm() + { + if (!IsAlarming) + { + IsAlarming = true; + alarmTimer = 0; + PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId }); + Console.WriteLine($"激光告警器 {Id} 发出警报!"); + } + } + + /// + /// 停止警报 + /// + public void StopAlarm() + { + if (IsAlarming) + { + IsAlarming = false; + alarmTimer = 0; + PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId }); + Console.WriteLine($"激光告警器 {Id} 停止警报"); + } + } + + /// + /// 获取激光告警器状态信息 + /// + /// 状态信息字符串 + public override string GetStatus() + { + return $"激光告警器 {Id}:\n" + + $" 监视实体: {MonitoredEntityId}\n" + + $" 警报状态: {(IsAlarming ? "警报中" : "正常")}\n" + + $" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}"; + } + + /// + /// 激活激光告警器 + /// + public override void Activate() + { + base.Activate(); + SimulationManager.SubscribeToEvent(OnLaserIlluminationStart); + SimulationManager.SubscribeToEvent(OnLaserIlluminationStop); + } + + /// + /// 停用激光告警器 + /// + public override void Deactivate() + { + base.Deactivate(); + SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStart); + SimulationManager.UnsubscribeFromEvent(OnLaserIlluminationStop); + } + } +} diff --git a/Models/MissileBase.cs b/Models/MissileBase.cs new file mode 100644 index 0000000..5ba575e --- /dev/null +++ b/Models/MissileBase.cs @@ -0,0 +1,675 @@ +using System; +using System.Collections.Generic; +using ActiveProtect.SimulationEnvironment; +using Model; + +namespace ActiveProtect.Models +{ + /// + /// 表示仿真中的导弹 + /// + public class MissileBase : SimulationElement + { + /// + /// 导弹类型 + /// + public MissileType Type { get; protected set; } + + /// + /// 当前速度(米/秒) + /// + public double Speed { get; protected set; } + + /// + /// 最大速度(米/秒) + /// + public double MaxSpeed { get; protected set; } + + /// + /// 目标ID + /// + public string TargetId { get; protected set; } + + /// + /// 最大飞行时间(秒) + /// + public double MaxFlightTime { get; protected set; } + + /// + /// 最大飞行距离(米) + /// + public double MaxFlightDistance { get; protected set; } + + /// + /// 当前飞行时间(秒) + /// + public double FlightTime { get; protected set; } + + /// + /// 当前飞行距离(米) + /// + public double FlightDistance { get; protected set; } + + /// + /// 与目标的距离(米) + /// + public double DistanceToTarget { get; protected set; } + + /// + /// 导弹距离参数 + /// + public MissileDistanceParams DistanceParams { get; protected set; } + + /// + /// 飞行阶段配置 + /// + public FlightStageConfig StageConfig { get; protected set; } + + /// + /// 当前飞行阶段 + /// + public FlightStage CurrentStage { get; protected set; } + + /// + /// 上一帧目标位置 + /// + private Vector3D LastTargetPosition; + + /// + /// 比例导引系数 + /// + private const double N = 3; + + /// + /// 推力加速度(米/秒²) + /// + public double ThrustAcceleration { get; protected set; } + + /// + /// 当前发动机燃烧时间(秒) + /// + public double EngineBurnTime { get; protected set; } + + /// + /// 最大发动机燃烧时间(秒) + /// + public double MaxEngineBurnTime { get; protected set; } + + /// + /// 最大加速度(米/秒²) + /// + public double MaxAcceleration { get; protected set; } = 100; + + /// + /// 比例导引系数 + /// + public double ProportionalNavigationCoefficient { get; set; } + + /// + /// 是否有制导 + /// + public bool HasGuidance { get; protected set; } = false; + + /// + /// 失去制导的时间(秒) + /// + protected double LostGuidanceTime { get; set; } = 0; + + /// + /// 最后已知的速度向量 + /// + protected Vector3D LastKnownVelocity = Vector3D.Zero; + + /// + /// 发射速度(米/秒) + /// + public const double LAUNCH_SPEED = 10; + + /// + /// 发射阶段持续时间(秒) + /// + public const double LAUNCH_DURATION = 0.5; + + protected IMissileStageStrategy currentStage; + private Dictionary stageStrategies; + + /// + /// 导弹质量(千克) + /// + public double Mass { get; protected set; } = 100; + + /// + /// 构造函数 + /// + 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.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); + } + + /// + /// 设置导弹的初始飞行阶段 + /// + 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}"); + } + + /// + /// 更新导弹状态 + /// + 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); + } + /// + /// 计算导弹的加速度 + /// + 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; + } + /// + /// 切换导弹飞行阶段 + /// + 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}"); + } + } + + /// + /// 检查指定飞行阶段是否启用 + /// + 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 + }; + } + + /// + /// 尝试切换到下一个可用的飞行阶段 + /// + 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(); + } + + /// + /// 计算导弹的加速度 + /// + // 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); + // } + + /// + /// 计算空气阻力 + /// + 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; + } + + /// + /// 检查是否命中目标 + /// + protected bool CheckHit() + { + return DistanceToTarget <= DistanceParams.ExplosionDistance; + } + + /// + /// 检查是否应该自毁 + /// + 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; + } + + /// + /// 更新发动机燃烧时间 + /// + private void UpdateEngineBurnTime(double deltaTime) + { + if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime) + { + EngineBurnTime += deltaTime; + } + } + + /// + /// 计算比例导引加速度 + /// + 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(); + } + + /// + /// 导弹爆炸 + /// + public void Explode() + { + Deactivate(); + SimulationManager.HandleTargetHit(TargetId, Id); + Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!"); + } + + /// + /// 导弹自毁 + /// + public void SelfDestruct() + { + if (IsActive) + { + string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" : + FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" : + Position.Y <= 0 ? "高度小于等于0" : + !HasGuidance ? "失去引导" : "未知原因"; + + Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}"); + Deactivate(); + } + } + + /// + /// 设置比例导引系数 + /// + public void SetProportionalNavigationCoefficient(double newCoefficient) + { + ProportionalNavigationCoefficient = newCoefficient; + Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}"); + } + + /// + /// 获取导弹状态 + /// + 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}"; + } + + /// + /// 更新导弹的制导状态 + /// + 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 + }; + } + } + + /// + /// 表示导弹的运行状态信息 + /// + public struct MissileRunningState + { + /// + /// 导弹ID + /// + public string Id { get; set; } + + /// + /// 导弹类型 + /// + public MissileType Type { get; set; } + + /// + /// 当前位置 + /// + public Vector3D Position { get; set; } + + /// + /// 当前速度向量 + /// + public Vector3D Velocity { get; set; } + + /// + /// 当前朝向 + /// + public Orientation Orientation { get; set; } + + /// + /// 当前速度(米/秒) + /// + public double Speed { get; set; } + + /// + /// 目标ID + /// + public string TargetId { get; set; } + + /// + /// 当前飞行时间(秒) + /// + public double FlightTime { get; set; } + + /// + /// 当前飞行距离(米) + /// + public double FlightDistance { get; set; } + + /// + /// 与目标的距离(米) + /// + public double DistanceToTarget { get; set; } + + /// + /// 当前飞行阶段 + /// + public FlightStage CurrentStage { get; set; } + + /// + /// 是否有制导 + /// + public bool HasGuidance { get; set; } + + /// + /// 失去制导时间(秒) + /// + public double LostGuidanceTime { get; set; } + + /// + /// 当前发动机燃烧时间(秒) + /// + public double EngineBurnTime { get; set; } + + /// + /// 是否处于活动状态 + /// + public bool IsActive { get; set; } + } +} diff --git a/Models/MissileClass.cs b/Models/MissileClass.cs new file mode 100644 index 0000000..410f13e --- /dev/null +++ b/Models/MissileClass.cs @@ -0,0 +1,351 @@ +using System; + +namespace Model +{ + /// + /// 坦克消息结构 + /// + public struct TankInfo + { + /// + /// 坦克编号 + /// + public int TankID { get; set; } + /// + /// 坦克类型编号 + /// + public int TankType { get; set; } + /// + /// 坦克X坐标 + /// + public double xp { get; set; } + /// + /// 坦克Y坐标 + /// + public double yp { get; set; } + /// + /// 坦克Z坐标 + /// + public double zp { get; set; } + + /// + /// 烟幕标记 + /// + public double fYMFlag { get; set; } + /// + /// 烟幕SNR + /// + public double fYMSNR { get; set; } + + /// + /// 激光致盲标记,1-导弹;2-制导站;3-两者都不是 + /// + public double fZMJGFlag { get; set; } + /// + /// 致盲能量 + /// + public double fZMJGPower { get; set; } + + /// + /// 激光诱骗假目标X坐标 + /// + public double fFalseX { get; set; } + /// + /// 激光诱骗假目标Y坐标 + /// + public double fFalseY { get; set; } + /// + /// 激光诱骗假目标Z坐标 + /// + public double fFalseZ { get; set; } + /// + /// 红外诱骗能量值 + /// + public double fFalseIRPower { get; set; } + /// + /// 激光诱骗能量值 + /// + public double fFalseJGPower { get; set; } + /// + /// 毫米波补偿//1为开启 + /// + public double fHMBBCFlag { get; set; } + /// + /// 毫米波干扰能量 + /// + public double fHMBGRPower { get; set; } + /// + /// 红外干扰能量 + /// + public double fHWGRPower { get; set; } + /// + /// 坦克辐射红外能量 + /// + public double fTankIRPower { get; set; } + /// + /// 坦克辐射激光能量 + /// + public double fTankJGPower { get; set; } + + /// + /// 坦克辐射毫米波能量 + /// + public double fTankHMBPower { get; set; } + /// + /// 毫米波补偿特征值//大于导弹补偿成功,末敏弹子弹爆炸 + /// + public double fFeature { get; set; } + + }; + + /// + /// 威胁源初始化信息结构 + /// + public struct MIniInfo + { + /// + /// 导弹ID + /// + public int nMisID; + /// + /// 导弹X坐标 + /// + public double xm; + /// + /// 导弹Y坐标 + /// + public double ym; + /// + /// 导弹Z坐标 + /// + public double zm; + /// + /// 导弹方位角 + /// + public double psi_m; + /// + /// 导弹俯仰角 + /// + public double theta_m; + /// + /// 导弹飞行速度 + /// + public double vm; + /// + /// 坦克X坐标 + /// + public double xt; + /// + /// 坦克Y坐标 + /// + public double yt; + /// + /// 坦克Z坐标 + /// + public double zt; + /// + /// 光斑X坐标 + /// + public double xd; + /// + /// 光斑Y坐标 + /// + public double yd; + /// + /// 光斑Z坐标 + /// + public double zd; + + }; + + /// + /// 威胁源运行信息结构 + /// + public struct MRunInfo + { + /// + /// 杀伤半径 + /// + public double Rx; + /// + /// 仿真时间 + /// + public double fSimTime; + /// + /// x坐标 + /// + public double fMisX; + /// + /// y坐标 + /// + public double fMisY; + /// + /// z坐标 + /// + public double fMisZ; + /// + /// 导弹弹道倾角 + /// + public double fMisDeltCw; + /// + /// 滚转角 + /// + public double fMisRoll; + /// + /// 导弹弹道偏角 + /// + public double fMisPitch; + /// + /// 导弹速度 + /// + public double fMisV; + /// + /// 导弹辐射红外能量 + /// + public double fIRPower; + /// + /// 导弹辐射红外波长 + /// + public double fIRWaveLen; + /// + /// 导弹紫外能量 + /// + public double fUVPower; + /// + /// 导弹紫外波长 + /// + public double fUVWaveLen; + /// + /// 导弹激光能量 + /// + public double fJGPower; + // 导弹激光波长 + public double fJGWaveLen; + /// + /// 导弹毫米波能量 + /// + public double fHMBPower; + /// + /// 导弹毫米波波长 + /// + public double fHMBWaveLen; + /// + /// 制导站批号 + /// + public double nZDZID; + /// + /// 架束仪位置x + /// + public double fZDZX; + /// + /// 架束仪位置Y + /// + public double fZDZY; + /// + /// 架束仪位置Z + /// + public double fZDZZ; + /// + /// 制导站辐射激光能量 + /// + public double fZDZJGPower; + /// + /// 制导站辐射激光波长 + /// + public double fZDZJGWaveLen; + /// + /// 编码 + /// + public double nZDZCode; + /// + /// 脉冲重复频率 + /// + public double fZDZReFre; + /// + /// 脉宽 + /// + public double fZDZPulse; + /// + /// 末敏弹状态 1:母弹,2:子弹,3:子弹扫描状态 + /// + public double nMMDState; + /// + /// 子弹数量 + /// + public double nSubNum; + /// + /// 子弹1批号 + /// + public double nSub1ID; + /// + /// 子弹1坐标X + /// + public double fSub1X; + // 子弹1坐标Y + public double fSub1Y; + /// + /// 子弹1坐标Z + /// + public double fSub1Z; + /// + /// 子弹1辐射毫米波能量 + /// + public double fSub1HMBPower; + /// + /// 子弹1辐射毫米波波长 + /// + public double fSub1HMBWaveLen; + /// + /// 子弹1扫描坐标X + /// + public double fSub1ScanX; + /// + /// 子弹1扫描坐标Y + /// + public double fSub1ScanY; + /// + /// 子弹1扫描坐标Z + /// + public double fSub1ScanZ; + /// + /// 防护手段 1:激光致盲;2:激光诱骗;3:红外干扰;4:红外诱骗;5:毫米波干扰;6:毫米波补偿;7:烟幕防护;8:致盲制导站 + /// + public double nDisType; + /// + /// 0代表失败 1代表成功 + /// + public double nDisRes; + /// + /// 后续进一步处理 + /// + public double k1; + /// + /// 弹道偏角和倾角改变角度当亲步骤数 + /// + public int Xi; + + public int JG_GR_success; + + + /// + /// 炮弹状态标志,0:正常,1:炸毁目标,2:自爆 + /// + public int bombFlag; + + + ///// + ///// 激光诱骗假目标X坐标 + ///// + //public double fFalseX; + ///// + ///// 激光诱骗假目标Y坐标 + ///// + //public double fFalseY; + ///// + ///// 激光诱骗假目标Z坐标 + ///// + //public double fFalseZ; + }; + + +}; diff --git a/Models/MissileStageStrategy.cs b/Models/MissileStageStrategy.cs new file mode 100644 index 0000000..5b2a05d --- /dev/null +++ b/Models/MissileStageStrategy.cs @@ -0,0 +1,168 @@ + +using System; + +namespace ActiveProtect.Models +{ + /// + /// 导弹飞行阶段枚举 + /// + public enum FlightStage + { + Launch, // 发射阶段 + Acceleration, // 加速阶段 + Cruise, // 巡航阶段 + TerminalGuidance, // 终端制导阶段 + Attack, // 攻击阶段 + Explosion, // 爆炸阶段 + } + + /// + /// 导弹飞行阶段策略接口 + /// + public interface IMissileStageStrategy + { + void Update(double deltaTime); + } + + /// + /// 发射阶段策略 + /// + 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); + } + } + } + + /// + /// + /// 加速阶段策略 + /// + 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); + } + } + } + + /// + /// 巡航阶段策略 + /// + 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); + } + } + } + + /// + /// 终端制导阶段策略 + /// + 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); + } + } + } + + /// + /// 攻击阶段策略 + /// + 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(); + } + } + } + + /// + /// 无制导阶段策略 + /// + 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); + } + } + } + } +} \ No newline at end of file diff --git a/Models/Tank.cs b/Models/Tank.cs new file mode 100644 index 0000000..71ff327 --- /dev/null +++ b/Models/Tank.cs @@ -0,0 +1,100 @@ +using ActiveProtect.SimulationEnvironment; +using System; + +namespace ActiveProtect.Models +{ + /// + /// 表示仿真中的坦克 + /// + public class Tank : SimulationElement + { + /// + /// 当前速度(米/秒) + /// + public double Speed { get; set; } + + /// + /// 最大速度(米/秒) + /// + public double MaxSpeed { get; private set; } + + /// + /// 最大装甲值 + /// + public double MaxArmor { get; private set; } + + /// + /// 当前装甲值 + /// + public double CurrentArmor { get; private set; } + + /// + /// 构造函数 + /// + /// 坦克ID + /// 坦克配置 + /// 仿真管理器 + 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; + } + + /// + /// 更新坦克状态 + /// + /// 时间步长(秒) + public override void Update(double deltaTime) + { + if (!IsActive) return; + + UpdatePosition(deltaTime); + } + + /// + /// 更新坦克位置 + /// + /// 时间步长(秒) + private void UpdatePosition(double deltaTime) + { + Vector3D direction = Orientation.ToVector(); + Vector3D movement = direction * Speed * deltaTime; + Position += movement; + } + + /// + /// 坦克受到伤害 + /// + /// 伤害值 + /// 是否为导弹造成的伤害 + public void TakeDamage(double damage, bool isMissileDamage = false) + { + if (isMissileDamage) + { + damage = CurrentArmor * 0.5; + } + + CurrentArmor = Math.Max(0, CurrentArmor - damage); + if (CurrentArmor <= 0) + { + Deactivate(); + } + } + + /// + /// 获取坦克状态信息 + /// + /// 坦克状态字符串 + public override string GetStatus() + { + return $"坦克 {Id}:\n" + + $" 位置: {Position}\n" + + $" 速度: {Speed:F2}/{MaxSpeed:F2}\n" + + $" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" + + $" 状态: {(IsActive ? "活动" : "已销毁")}\n"; + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..61817a7 --- /dev/null +++ b/Program.cs @@ -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 + { + 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 + { + // 激光半主动制导导弹配置 + 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("仿真结束"); + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..97da885 --- /dev/null +++ b/README.md @@ -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. 巡航阶段 + - 导弹保持相对稳定的速度飞向��标 + - 根据导引系统类型,可能会进行中途修正 + +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 值,观察其对导弹性能的影响,以找到最适合特定场景的设置。 diff --git a/SimulationEnvironment/SimulationConfig.cs b/SimulationEnvironment/SimulationConfig.cs new file mode 100644 index 0000000..57061b0 --- /dev/null +++ b/SimulationEnvironment/SimulationConfig.cs @@ -0,0 +1,474 @@ +using System.Collections.Generic; +using System.ComponentModel; +using ActiveProtect.Models; +using Model; + +namespace ActiveProtect.SimulationEnvironment +{ + /// + /// 仿真配置类,包含整个仿真所需的所有配置信息 + /// + public class SimulationConfig + { + /// + /// 坦克配置列表 + /// + public List TankConfigs { get; set; } + + /// + /// 导弹配置列表 + /// + public List MissileConfigs { get; set; } + + /// + /// 激光指示器配置列表 + /// + public LaserDesignatorConfig LaserDesignatorConfig { get; set; } + + /// + /// 激光驾束仪配置列表 + /// + public LaserBeamRiderConfig LaserBeamRiderConfig { get; set; } + + /// + /// 激光告警器配置 + /// + public LaserWarnerConfig LaserWarnerConfig { get; set; } + + /// + /// 激光干扰器配置 + /// + public LaserJammerConfig LaserJammerConfig { get; set; } + + /// + /// 仿真时间步长(秒) + /// + public double SimulationTimeStep { get; set; } + + /// + /// 构造函数,初始化默认配置 + /// + public SimulationConfig() + { + TankConfigs = new List(); + MissileConfigs = new List(); + LaserDesignatorConfig = new LaserDesignatorConfig(); + LaserBeamRiderConfig = new LaserBeamRiderConfig(); + LaserWarnerConfig = new LaserWarnerConfig(); + LaserJammerConfig = new LaserJammerConfig(); + SimulationTimeStep = 0.1; // 默认时间步长为0.1秒 + } + } + + /// + /// 坦克配置类 + /// + public class TankConfig + { + /// + /// 初始位置 + /// + public Vector3D InitialPosition { get; set; } + + /// + /// 初始朝向 + /// + public Orientation InitialOrientation { get; set; } + + /// + /// 初始速度(米/秒) + /// + public double InitialSpeed { get; set; } + + /// + /// 最大速度(米/秒) + /// + public double MaxSpeed { get; set; } + + /// + /// 最大装甲值 + /// + public double MaxArmor { get; set; } + + /// + /// 是否装备激光告警器 + /// + public bool HasLaserWarner { get; set; } + + /// + /// 是否装备激光干扰器 + /// + public bool HasLaserJammer { get; set; } + + /// + /// 构造函数,设置默认值 + /// + 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; + } + } + + /// + /// 导弹配置类 + /// + public class MissileConfig + { + /// + /// 初始位置 + /// + public Vector3D InitialPosition { get; set; } + + /// + /// 初始朝向 + /// + public Orientation InitialOrientation { get; set; } + + /// + /// 初始速度(米/秒) + /// + public double InitialSpeed { get; set; } + + /// + /// 最大速度(米/秒) + /// + public double MaxSpeed { get; set; } + + /// + /// 目标索引 + /// + public int TargetIndex { get; set; } + + /// + /// 最大飞行时间(秒) + /// + public double MaxFlightTime { get; set; } + + /// + /// 最大飞行距离(米) + /// + public double MaxFlightDistance { get; set; } + + /// + /// 最大加速度(米/秒²) + /// + public double MaxAcceleration { get; set; } + + /// + /// 比例导引系数 + /// + public double ProportionalNavigationCoefficient { get; set; } + + /// + /// 飞行阶段配置 + /// + public FlightStageConfig StageConfig { get; set; } + + /// + /// 距离参数 + /// + public MissileDistanceParams DistanceParams { get; set; } + + /// + /// 推力加速度(米/秒²) + /// + public double ThrustAcceleration { get; set; } + + /// + /// 最大发动机燃烧时间(秒) + /// + public double MaxEngineBurnTime { get; set; } + + /// + /// 导弹质量(千克) + /// + public double Mass { get; set; } + + /// + /// 导弹类型 + /// + public MissileType Type { get; set; } + + /// + /// 构造函数,设置默认值 + /// + 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; + } + } + + /// + /// 激光指示器配置类 + /// + public class LaserDesignatorConfig + { + /// + /// 初始位置 + /// + public Vector3D InitialPosition { get; set; } + + /// + /// 激光功率(瓦特) + /// + public double LaserPower { get; set; } + + /// + /// 激光发散角 + /// + public double LaserDivergenceAngle { get; set; } + + /// + /// 构造函数,设置默认值 + /// + public LaserDesignatorConfig() + { + InitialPosition = new Vector3D(0, 0, 0); + LaserPower = 0; + LaserDivergenceAngle = 0; + } + } + + /// + /// 激光驾束仪配置类 + /// + public class LaserBeamRiderConfig + { + /// + /// 初始位置 + /// + public Vector3D InitialPosition { get; set; } + + /// + /// 激光功率(瓦特) + /// + public double LaserPower { get; set; } + + /// + /// 控制场直径(米) + /// + public double ControlFieldDiameter { get; set; } + + /// + /// 最大导引距离(米) + /// + public double MaxGuidanceDistance { get; set; } + + + /// + /// 构造函数,设置默认值 + /// + public LaserBeamRiderConfig() + { + InitialPosition = new Vector3D(0, 0, 0); + LaserPower = 0; + ControlFieldDiameter = 0; + } + } + + /// + /// 导弹类型枚举 + /// + public enum MissileType + { + StandardMissile, // 标准导弹 + LaserSemiActiveGuidance, // 激光半主动制导 + LaserBeamRiderGuidance, // 激光驾束制导 + InfraredCommandGuidance, // 红外指令制导 + InfraredImagingTerminalGuidance, // 红外成像末制导 + MillimeterWaveTerminalGuidance // 毫米波末制导 + } + + /// + /// 导弹距离参数结构 + /// + public struct MissileDistanceParams + { + /// + /// 终端制导距离(米) + /// + public double TerminalGuidanceDistance; + /// + /// 攻击距离(米) + /// + public double AttackDistance; + /// + /// 爆炸距离(米) + /// + public double ExplosionDistance; + + public MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance) + { + TerminalGuidanceDistance = terminalGuidanceDistance; + AttackDistance = attackDistance; + ExplosionDistance = explosionDistance; + } + } + + /// + /// + /// 导弹飞行阶段配置结构 + /// + public struct FlightStageConfig + { + /// + /// 启用发射阶段 + /// + public bool EnableLaunch; + /// + /// 启用加速阶段 + /// + public bool EnableAcceleration; + /// + /// 启用巡航阶段 + /// + public bool EnableCruise; + /// + /// 启用终端制导阶段 + /// + public bool EnableTerminalGuidance; + /// + /// 启用攻击阶段 + /// + public bool EnableAttack; + + /// + /// 标准导弹的预设配置, 所有阶段都启用 + /// + public static FlightStageConfig StandardMissile => new(true, true, true, true, true); + + /// + /// 激光半主动制导导弹的预设配置, 没有加速阶段 + /// + public static FlightStageConfig LaserSemiActiveGuidedMissile => new(true, false, true, true, true); + + /// + /// 激光驾束制导导弹的预设配置,没有巡航阶段 + /// + public static FlightStageConfig LaserBeamRiderGuidance => new(true, true, false, true, true); + + /// + /// 红外指令制导导弹的预设配置,没有巡航阶段 + /// + public static FlightStageConfig InfraredCommandGuidance => new(true, true, false, true, true); + + /// + /// 红外成像末制导导弹的预设配置 + /// + public static FlightStageConfig InfraredImagingTerminalGuidance => new(true, true, true, true, true); + + /// + /// 毫米波末制导导弹的预设配置 + /// + 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; + } + } + + /// + /// 激光告警器配置类 + /// + public class LaserWarnerConfig + { + /// + /// 警报持续时间(秒) + /// + public double AlarmDuration { get; set; } + + /// + /// 构造函数,设置默认值 + /// + public LaserWarnerConfig() + { + AlarmDuration = 5.0; // 默认警报持续5秒 + } + } + + /// + /// 激光干扰器配置类 + /// + public class LaserJammerConfig + { + /// + /// 最大干扰冷却时间(秒) + /// + public double MaxJammingCooldown { get; set; } + + /// + /// 最大干扰功率(瓦特) + /// + public double MaxJammingPower { get; set; } + + /// + /// 初始干扰功率(瓦特) + /// + public double InitialJammingPower { get; set; } + + /// + /// 功率增加速率(瓦特/秒) + /// + public double PowerIncreaseRate { get; set; } + + /// + /// 构造函数,设置默认值 + /// + public LaserJammerConfig() + { + MaxJammingCooldown = 5.0; + MaxJammingPower = 10000.0; + InitialJammingPower = 4000.0; + PowerIncreaseRate = 2000.0; // 每秒增加的功率 + } + } +} diff --git a/SimulationEnvironment/SimulationElement.cs b/SimulationEnvironment/SimulationElement.cs new file mode 100644 index 0000000..8323d37 --- /dev/null +++ b/SimulationEnvironment/SimulationElement.cs @@ -0,0 +1,101 @@ +using ActiveProtect.Models; + +namespace ActiveProtect.SimulationEnvironment +{ + /// + /// 仿真元素的抽象基类,所有仿真中的实体都继承自此类 + /// + public abstract class SimulationElement + { + /// + /// 仿真元素的唯一标识符 + /// + public virtual string Id { get; set; } + + /// + /// 仿真元素的当前位置 + /// + public virtual Vector3D Position { get; set; } + + /// + /// 仿真元素的当前速度 + /// + public virtual Vector3D Velocity { get; set; } + + /// + /// 仿真元素的当前朝向 + /// + public virtual Orientation Orientation { get; set; } + + /// + /// 仿真元素是否处于活动状态 + /// + public virtual bool IsActive { get; protected set; } + + /// + /// 仿真管理器的引用 + /// + public ISimulationManager SimulationManager { get; set; } + + /// + /// 构造函数 + /// + /// 仿真元素的唯一标识符 + /// 初始位置 + /// 初始朝向 + /// 仿真管理器 + protected SimulationElement(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager) + { + Id = id; + Position = position; + Orientation = orientation; + SimulationManager = simulationManager; + Velocity = Vector3D.Zero; + IsActive = true; + } + + /// + /// 更新仿真元素的状态 + /// + /// 时间步长 + public abstract void Update(double deltaTime); + + /// + /// 获取仿真元素的状态信息 + /// + /// 状态信息字符串 + public virtual string GetStatus() + { + return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}"; + } + + /// + /// 发布仿真事件 + /// + /// 要发布的事件 + protected void PublishEvent(SimulationEvent evt) + { + evt.SenderId = Id; + evt.Timestamp = SimulationManager.CurrentTime; + SimulationManager.PublishEvent(evt); + } + + /// + /// 激活仿真元素 + /// + public virtual void Activate() + { + IsActive = true; + PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id }); + } + + /// + /// 停用仿真元素 + /// + public virtual void Deactivate() + { + IsActive = false; + PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id }); + } + } +} diff --git a/SimulationEnvironment/SimulationEvents.cs b/SimulationEnvironment/SimulationEvents.cs new file mode 100644 index 0000000..3f5e1ee --- /dev/null +++ b/SimulationEnvironment/SimulationEvents.cs @@ -0,0 +1,171 @@ +using ActiveProtect.Models; + +namespace ActiveProtect.SimulationEnvironment +{ + /// + /// 仿真事件的基类 + /// + public class SimulationEvent + { + /// + /// 事件发送者的ID + /// + public string? SenderId { get; set; } + + /// + /// 事件发生的时间戳 + /// + public double Timestamp { get; set; } + } + + /// + /// 导弹发射事件 + /// + public class MissileFireEvent : SimulationEvent + { + /// + /// 目标ID + /// + public string? TargetId { get; set; } + } + + /// + /// 激光照射事件 + /// + public class LaserIlluminationStartEvent : SimulationEvent + { + /// + /// 激光定位器 + /// + public LaserDesignator? LaserDesignator { get; set; } + + /// + /// 目标元素 + /// + public SimulationElement? Target { get; set; } + } + + /// + /// 激光照射更新事件 + /// + public class LaserIlluminationUpdateEvent : SimulationEvent + { + /// + /// 激光定位器 + /// + public LaserDesignator? LaserDesignator { get; set; } + + /// + /// 目标元素 + /// + public SimulationElement? Target { get; set; } + } + + /// + public class LaserIlluminationStopEvent : SimulationEvent + { + public LaserDesignator? LaserDesignator { get; set; } + public SimulationElement? Target { get; set; } + } + + /// + /// 激光干扰事件 + /// + public class LaserJammingEvent : SimulationEvent + { + /// + /// 目标ID + /// + public string? TargetId { get; set; } + + /// + /// 干扰功率 + /// + public double JammingPower { get; set; } + } + + /// + /// 实体销毁事件 + /// + public class EntityDestroyedEvent : SimulationEvent + { + /// + /// 被销毁实体的ID + /// + public string? DestroyedEntityId { get; set; } + } + + + + /// + /// 激光告警器警报事件 + /// + public class LaserWarnerAlarmEvent : SimulationEvent + { + /// + /// 目标ID + /// + public string? TargetId { get; set; } + } + + /// + /// 激光告警器警报停止事件 + /// + public class LaserWarnerAlarmStopEvent : SimulationEvent + { + /// + /// 目标ID + /// + public string? TargetId { get; set; } + } + + /// + /// 实体激活事件 + /// + public class EntityActivatedEvent : SimulationEvent + { + /// + /// 被激活实体的ID + /// + public string? ActivatedEntityId { get; set; } + } + + /// + /// 实体停用事件 + /// + public class EntityDeactivatedEvent : SimulationEvent + { + /// + /// 被停用实体的ID + /// + public string? DeactivatedEntityId { get; set; } + } + + + /// + /// 激光开始事件 + /// + public class LaserBeamStartEvent : SimulationEvent + { + public LaserBeamRider? LaserBeamRider { get; set; } + } + + /// + /// 激光更新事件 + /// + public class LaserBeamUpdateEvent : SimulationEvent + { + public LaserBeamRider? LaserBeamRider { get; set; } + } + + /// + /// 激光停止事件 + /// + public class LaserBeamStopEvent : SimulationEvent + { + public LaserBeamRider? LaserBeamRider { get; set; } + } +} diff --git a/SimulationEnvironment/SimulationManager.cs b/SimulationEnvironment/SimulationManager.cs new file mode 100644 index 0000000..b35a6f9 --- /dev/null +++ b/SimulationEnvironment/SimulationManager.cs @@ -0,0 +1,399 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ActiveProtect.Models; + +namespace ActiveProtect.SimulationEnvironment +{ + /// + /// 仿真管理器接口,定义了仿真管理器的基本功能 + /// + public interface ISimulationManager + { + /// + /// 当前仿真时间 + /// + double CurrentTime { get; } + + /// + /// 添加仿真元素 + /// + void AddElement(SimulationElement element); + + /// + /// 根据ID获取仿真实体 + /// + SimulationElement GetEntityById(string id); + + /// + /// 处理目标被击中事件 + /// + void HandleTargetHit(string targetId, string missileId); + + /// + /// 发布仿真事件 + /// + void PublishEvent(SimulationEvent evt); + + /// + /// 订阅仿真事件 + /// + void SubscribeToEvent(Action handler) where T : SimulationEvent; + + /// + /// 取消订阅仿真事件 + /// + void UnsubscribeFromEvent(Action handler) where T : SimulationEvent; + + /// + /// 取消所有事件订阅 + /// + void UnsubscribeAllEvents(SimulationElement element); + } + + /// + /// 仿真管理器类,负责管理整个仿真过程 + /// + public class SimulationManager : ISimulationManager + { + /// + /// 仿真元素列表 + /// + public List Elements { get; private set; } + + /// + /// 当前仿真时间 + /// + public double CurrentTime { get; private set; } + + /// + /// 仿真是否结束 + /// + public bool IsSimulationEnded { get; private set; } + + private readonly SimulationConfig config; + private Dictionary> eventHandlers = new Dictionary>(); + private Dictionary> elementSubscriptions = new Dictionary>(); + + /// + /// 构造函数 + /// + public SimulationManager(SimulationConfig config) + { + this.config = config; + Elements = new List(); + CurrentTime = 0; + IsSimulationEnded = false; + InitializeSimulation(); + } + + /// + /// 初始化仿真 + /// + 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(); + } + } + + /// + /// 发布仿真事件 + /// + 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} 的处理程序"); + } + } + + /// + /// 订阅仿真事件 + /// + public void SubscribeToEvent(Action handler) where T : SimulationEvent + { + var eventType = typeof(T); + if (!eventHandlers.TryGetValue(eventType, out List? value)) + { + value = new List(); + 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)); + } + } + + /// + /// 取消订阅仿真事件 + /// + public void UnsubscribeFromEvent(Action handler) where T : SimulationEvent + { + var eventType = typeof(T); + if (eventHandlers.TryGetValue(eventType, out List? 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)); + } + } + + /// + /// 取消所有事件订阅 + /// + public void UnsubscribeAllEvents(SimulationElement element) + { + if (elementSubscriptions.ContainsKey(element)) + { + foreach (var subscription in elementSubscriptions[element]) + { + if (eventHandlers.TryGetValue(subscription.Item1, out List? value)) + { + value.Remove(subscription.Item2); + } + } + elementSubscriptions.Remove(element); + } + } + + /// + /// 更新仿真状态 + /// + 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(); + } + } + + /// + /// 打印仿真状态 + /// + public void PrintStatus() + { + Console.WriteLine($"仿真时间: {CurrentTime:F2}"); + foreach (var element in Elements) + { + Console.WriteLine(element.GetStatus()); + } + Console.WriteLine(); + } + + /// + /// 结束仿真 + /// + private void EndSimulation() + { + IsSimulationEnded = true; + Console.WriteLine("仿真结束"); + Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒"); + Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}"); + } + + /// + /// 根据ID获取仿真实体 + /// + public SimulationElement GetEntityById(string id) + { + return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found"); + } + + /// + /// 处理目标被击中事件 + /// + 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); + } + } + + /// + /// 计算导弹造成的伤害 + /// + private double CalculateMissileDamage(MissileBase missile) + { + // 这里可以根据导弹类型、速度等因素计算伤害 + // 现在我们简单地返回一个固定值 + return 50; + } + + /// + /// 记录击中事件 + /// + private static void LogHitEvent(string targetId, string missileId, double damage) + { + Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害"); + } + + /// + /// 添加仿真元素 + /// + public void AddElement(SimulationElement element) + { + Elements.Add(element); + } + } +}