重新提交全部代码, 去掉无用文件
This commit is contained in:
parent
813700e6b0
commit
47849abf9e
65
.cursorrules
Normal file
65
.cursorrules
Normal file
@ -0,0 +1,65 @@
|
||||
|
||||
# Cursor Rules
|
||||
|
||||
You are an expert in C#, Unity, and scalable game development.
|
||||
|
||||
Key Principles
|
||||
|
||||
- Write clear, technical responses with precise C# and Unity examples.
|
||||
- Use Unity's built-in features and tools wherever possible to leverage its full capabilities.
|
||||
- Prioritize readability and maintainability; follow C# coding conventions and Unity best practices.
|
||||
- Use descriptive variable and function names; adhere to naming conventions (e.g., PascalCase for public members, camelCase for private members).
|
||||
- Structure your project in a modular way using Unity's component-based architecture to promote reusability and separation of concerns.
|
||||
|
||||
C#/Unity
|
||||
|
||||
- Use MonoBehaviour for script components attached to GameObjects; prefer ScriptableObjects for data containers and shared resources.
|
||||
- Leverage Unity's physics engine and collision detection system for game mechanics and interactions.
|
||||
- Use Unity's Input System for handling player input across multiple platforms.
|
||||
- Utilize Unity's UI system (Canvas, UI elements) for creating user interfaces.
|
||||
- Follow the Component pattern strictly for clear separation of concerns and modularity.
|
||||
- Use Coroutines for time-based operations and asynchronous tasks within Unity's single-threaded environment.
|
||||
- Use System.Console for logging and debugging in the console.
|
||||
- Using C# 9.0 features.
|
||||
|
||||
Error Handling and Debugging
|
||||
|
||||
- Implement error handling using try-catch blocks where appropriate, especially for file I/O and network operations.
|
||||
- Use Unity's Debug class for logging and debugging (e.g., Debug.Log, Debug.LogWarning, Debug.LogError).
|
||||
- Utilize Unity's profiler and frame debugger to identify and resolve performance issues.
|
||||
- Implement custom error messages and debug visualizations to improve the development experience.
|
||||
- Use Unity's assertion system (Debug.Assert) to catch logical errors during development.
|
||||
|
||||
Dependencies
|
||||
|
||||
- Unity Engine
|
||||
- .NET Framework (version compatible with your Unity version)
|
||||
- Unity Asset Store packages (as needed for specific functionality)
|
||||
- Third-party plugins (carefully vetted for compatibility and performance)
|
||||
|
||||
Unity-Specific Guidelines
|
||||
|
||||
- Use Prefabs for reusable game objects and UI elements.
|
||||
- Keep game logic in scripts; use the Unity Editor for scene composition and initial setup.
|
||||
- Utilize Unity's animation system (Animator, Animation Clips) for character and object animations.
|
||||
- Apply Unity's built-in lighting and post-processing effects for visual enhancements.
|
||||
- Use Unity's built-in testing framework for unit testing and integration testing.
|
||||
- Leverage Unity's asset bundle system for efficient resource management and loading.
|
||||
- Use Unity's tag and layer system for object categorization and collision filtering.
|
||||
|
||||
Performance Optimization
|
||||
|
||||
- Use object pooling for frequently instantiated and destroyed objects.
|
||||
- Optimize draw calls by batching materials and using atlases for sprites and UI elements.
|
||||
- Implement level of detail (LOD) systems for complex 3D models to improve rendering performance.
|
||||
- Use Unity's Job System and Burst Compiler for CPU-intensive operations.
|
||||
- Optimize physics performance by using simplified collision meshes and adjusting fixed timestep.
|
||||
|
||||
Key Conventions
|
||||
|
||||
1. Follow Unity's component-based architecture for modular and reusable game elements.
|
||||
2. Prioritize performance optimization and memory management in every stage of development.
|
||||
3. Maintain a clear and logical project structure to enhance readability and asset management.
|
||||
|
||||
Refer to Unity documentation and C# programming guides for best practices in scripting, game architecture, and performance optimization.
|
||||
|
||||
237
.gitignore
vendored
Normal file
237
.gitignore
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
# Visual Studio files
|
||||
.vs/
|
||||
*.user
|
||||
*.userosscache
|
||||
*.suo
|
||||
*.userprefs
|
||||
*.pidb
|
||||
*.booproj
|
||||
*.svd
|
||||
*.pdb
|
||||
*.mdb
|
||||
*.opendb
|
||||
*.VC.db
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# ReSharper
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
11
ActiveProtect.csproj
Normal file
11
ActiveProtect.csproj
Normal file
@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
29
ActiveProtect.sln
Normal file
29
ActiveProtect.sln
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActiveProtect", "ActiveProtect.csproj", "{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {73773200-50D4-40ED-803B-FC16B131FFD2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
150
Design.md
Normal file
150
Design.md
Normal file
@ -0,0 +1,150 @@
|
||||
# 导弹仿真系统设计文档
|
||||
|
||||
## 系统架构设计思路
|
||||
|
||||
在处理导弹、坦克、告警设备、干扰设备等复杂交互关系时,我们采用了以下几种程序架构和设计模式的组合:
|
||||
|
||||
### 1. 事件驱动架构(Event-Driven Architecture)
|
||||
|
||||
事件驱动架构非常适合处理复杂的交互关系。每个实体(如导弹、坦克等)可以发布事件,其他实体可以订阅这些事件并作出反应。
|
||||
|
||||
``csharp
|
||||
public class EventManager
|
||||
{
|
||||
private Dictionary<string, List<Action<object>>> eventSubscribers = new Dictionary<string, List<Action<object>>>();
|
||||
public void Subscribe(string eventName, Action<object> listener) { ... }
|
||||
public void Publish(string eventName, object eventData) { ... }
|
||||
}
|
||||
``
|
||||
|
||||
### 2. 组件系统(Component System)
|
||||
|
||||
将每个实体分解为多个组件,每个组件负责特定的功能。这样可以更灵活地组合不同的功能。
|
||||
|
||||
``csharp
|
||||
public class Entity
|
||||
{
|
||||
public PositionComponent Position { get; set; }
|
||||
public VelocityComponent Velocity { get; set; }
|
||||
public HealthComponent Health { get; set; }
|
||||
}
|
||||
``
|
||||
|
||||
### 3. 观察者模式(Observer Pattern)
|
||||
|
||||
类似于事件驱动架构,但更加面向对象。每个实体可以作为观察者或被观察者。
|
||||
|
||||
``csharp
|
||||
public interface IObserver
|
||||
{
|
||||
void Update(ISubject subject);
|
||||
}
|
||||
|
||||
public interface ISubject
|
||||
{
|
||||
void Attach(IObserver observer);
|
||||
void Detach(IObserver observer);
|
||||
void Notify();
|
||||
}
|
||||
``
|
||||
|
||||
### 4. 状态机(State Machine)
|
||||
|
||||
对于有明确状态转换的实体(如导弹的飞行阶段),使用状态机可以更清晰地管理状态转换。
|
||||
|
||||
``csharp
|
||||
public enum MissileState
|
||||
{
|
||||
Idle,
|
||||
Tracking,
|
||||
Locking,
|
||||
Firing,
|
||||
Exploding
|
||||
}
|
||||
|
||||
public class Missile
|
||||
{
|
||||
public MissileState State { get; set; }
|
||||
public void ChangeState(MissileState newState) { ... }
|
||||
}
|
||||
|
||||
``csharp
|
||||
public interface IState
|
||||
{
|
||||
void Enter();
|
||||
void Update();
|
||||
void Exit();
|
||||
}
|
||||
public class MissileStateMachine
|
||||
{
|
||||
private IState currentState;
|
||||
public void ChangeState(IState newState) { ... }
|
||||
public void Update() { ... }
|
||||
}
|
||||
``
|
||||
|
||||
### 5. 命令模式(Command Pattern)
|
||||
|
||||
用于封装各种操作,使得可以轻松地添加新的交互行为。
|
||||
|
||||
``csharp
|
||||
public interface ICommand
|
||||
{
|
||||
void Execute();
|
||||
}
|
||||
|
||||
public class FireMissileCommand : ICommand
|
||||
{
|
||||
public void Execute() { ... }
|
||||
}
|
||||
``
|
||||
|
||||
## 架构组合使用
|
||||
|
||||
在实际应用中,我们将这些模式组合使用:
|
||||
|
||||
1. 使用事件驱动架构作为整体框架,处理系统中的各种事件。
|
||||
2. 采用组件系统来构建各个实体(如导弹、坦克、告警设备等)。
|
||||
3. 使用状态机来管理导弹的飞行阶段。
|
||||
4. 应用观察者模式来处理告警设备的通知机制。
|
||||
5. 使用命令模式来封装各种交互操作,如发射导弹、激活干扰设备等。
|
||||
|
||||
这种组合架构允许我们灵活地处理复杂的交互关系,同时保持代码的可维护性和可扩展性。
|
||||
|
||||
## 下一步计划
|
||||
|
||||
- 实现核心实体(导弹、坦克、告警设备、干扰设备)的基本功能。
|
||||
- 设计并实现事件系统,处理实体间的交互。
|
||||
- 开发状态机,管理导弹的飞行阶段。
|
||||
- 实现观察者模式,处理告警通知。
|
||||
- 使用命令模式封装关键操作。
|
||||
- 进行单元测试和集成测试,确保系统的正确性和稳定性。
|
||||
|
||||
## 数据库访问架构
|
||||
|
||||
在Unity3D环境中,考虑到兼容性和易用性,我推荐使用第二种方法:值对象模式。这种方式有以下几个优点:
|
||||
|
||||
1. 分离关注点:数据库实体(MissileConfigEntity)和游戏中使用的配置对象(MissileConfig)是分开的,这样可以避免 ORM 相关的属性和特性污染游戏逻辑。
|
||||
2. 灵活性:可以轻松地在数据库实体和游戏配置对象之间进行转换,而不影响现有的游戏逻辑。
|
||||
3. 序列化友好:Unity 经常需要序列化对象,使用纯粹的 C# 对象(如 MissileConfig)更容易进行序列化和反序列化。
|
||||
4. 兼容性好:这种方法不依赖于特定的 ORM 框架,如果将来需要更换数据库或 ORM 系统,影响会较小。
|
||||
|
||||
数据访问层使用了 Dapper(一个轻量级的 ORM),它在 Unity 中使用较为简单。
|
||||
|
||||
数据库设计
|
||||
|
||||
### 1. 导弹数据库设计
|
||||
|
||||
导弹数据库设计需要考虑导弹的属性、状态、行为等。
|
||||
|
||||
#### 1.1 导弹属性
|
||||
|
||||
导弹属性包括导弹的初始位置、初始速度、最大速度、目标索引、最大飞行时间、最大飞行距离、飞行阶段配置、推力加速度、最大发动机燃烧时间、最大加速度、距离参数、比例导引系数、类型等。
|
||||
|
||||
#### 1.2 导弹状态
|
||||
|
||||
导弹状态包括导弹的当前位置、当前速度、当前加速度、当前飞行阶段、当前目标索引、当前最大速度、当前最大加速度、当前最大飞行距离、当前最大飞行时间、当前比例导引系数等。
|
||||
|
||||
#### 1.3 导弹行为
|
||||
|
||||
导弹行为包括导弹的飞行行为、攻击行为、躲避行为、跟踪行为、锁定行为、发射行为、爆炸行为等。
|
||||
105
DesignMissile.md
Normal file
105
DesignMissile.md
Normal file
@ -0,0 +1,105 @@
|
||||
|
||||
# 实体设计
|
||||
|
||||
在仿真环境中,每个实体(如导弹)有几类参数:
|
||||
|
||||
1. 固有属性参数:如弹长、弹径、质量,最大速度、最大飞行距离、发动机推力等
|
||||
2. 运行时状态参数:如当前位置、速度、朝向、加速度,接收的辐射能量、导引头视野中目标角度等
|
||||
|
||||
为了设计一个结构清晰的实体类,我们采用组合模式和接口分离原则。这样可以将不同类型的参数和状态分开管理,同时保持良好的扩展性。
|
||||
|
||||
## 基础接口
|
||||
|
||||
首先,我们定义几个基础接口来表示不同类型的参数:
|
||||
|
||||
```csharp
|
||||
|
||||
public interface IProperties
|
||||
{
|
||||
double Length { get; }
|
||||
double Diameter { get; }
|
||||
double Mass { get; }
|
||||
}
|
||||
|
||||
public interface IState
|
||||
{
|
||||
Vector3 Position { get; set; }
|
||||
Vector3 Velocity { get; set; }
|
||||
Vector3 Acceleration { get; set; }
|
||||
double Heading { get; set; }
|
||||
double ReceivedRadiation { get; set; }
|
||||
double TargetDeviation { get; set; }
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 实现类
|
||||
|
||||
然后,我们为每个接口创建实现类:
|
||||
|
||||
public class MissileProperties : IProperties
|
||||
{
|
||||
public double Length { get; }
|
||||
public double Diameter { get; }
|
||||
public double Mass { get; }
|
||||
}
|
||||
|
||||
public class MissileState : IState
|
||||
{
|
||||
public Vector3 Position { get; set; }
|
||||
public Vector3 Velocity { get; set; }
|
||||
public Vector3 Acceleration { get; set; }
|
||||
public double Heading { get; set; }
|
||||
public double ReceivedRadiation { get; set; }
|
||||
public double TargetDeviation { get; set; }
|
||||
}
|
||||
|
||||
## 导弹实体类
|
||||
|
||||
接下来,我们创建一个导弹实体类,它将实现上述接口:
|
||||
|
||||
```csharp
|
||||
public class Missile : IProperties, IState
|
||||
{
|
||||
public MissileProperties Properties { get; set; }
|
||||
public MissileState State { get; set; }
|
||||
|
||||
public Missile()
|
||||
{
|
||||
Properties = new MissileProperties();
|
||||
State = new MissileState();
|
||||
}
|
||||
|
||||
// 其他方法,如更新状态、执行导航等
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
// 更新运行时状态和导引参数
|
||||
}
|
||||
public void Navigate()
|
||||
{
|
||||
// 执行导航逻辑
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 设计优点
|
||||
|
||||
1. 清晰的结构:每种类型的参数或状态都有自己的接口和实现类,使得结构非常清晰。
|
||||
2. 高度的模块化:可以轻松地替换或修改某一类参数,而不影响其他部分。
|
||||
3. 易于扩展:如果需要添加新的参数类型,只需创建新的接口和实现类,然后在 Missile 类中添加相应的属性。
|
||||
4. 符合单一职责原则:每个类都只负责一种类型的参数。
|
||||
5. 便于测试:可以轻松地为每种参数类型创建模拟对象,便于单元测试。
|
||||
6. 灵活性:可以为不同类型的导弹创建不同的参数实现,而保持相同的接口。
|
||||
|
||||
## 在激光驾束制导中, 为了实现更平滑的控制,同时将加速度控制在25 m/s²以下,并保持偏移在1.5米以内,我们可以采用以下几种方法
|
||||
|
||||
1. 使用PID控制器:
|
||||
PID(比例-积分-微分)控制器可以提供更平滑和精确的控制。它考虑了误差的历史、当前值和变化率。
|
||||
2. 非线性增益:
|
||||
使用非线性函数来计算增益,使得在接近目标时增益减小,远离目标时增益增大。
|
||||
3. 低通滤波:
|
||||
对计算出的加速度进行低通滤波,以减少高频振荡。
|
||||
4. 预测控制:
|
||||
基于当前状态预测未来的位置,提前做出调整。
|
||||
BIN
Models/.DS_Store
vendored
Normal file
BIN
Models/.DS_Store
vendored
Normal file
Binary file not shown.
10
Models/ActiveProtect.code-workspace
Normal file
10
Models/ActiveProtect.code-workspace
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../../ActiveProtect.Tests"
|
||||
},
|
||||
{
|
||||
"path": ".."
|
||||
}
|
||||
]
|
||||
}
|
||||
90
Models/BasicGuidanceSystem.cs
Normal file
90
Models/BasicGuidanceSystem.cs
Normal file
@ -0,0 +1,90 @@
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class BasicGuidanceSystem : IGuidanceSystem
|
||||
{
|
||||
public bool HasGuidance { get; protected set; }
|
||||
protected double ProportionalNavigationCoefficient { get; set; }
|
||||
protected Vector3D Position { get; set; }
|
||||
protected Vector3D Velocity { get; set; }
|
||||
protected Vector3D GuidanceCommand { get; set; }
|
||||
|
||||
public BasicGuidanceSystem(double proportionalNavigationCoefficient)
|
||||
{
|
||||
ProportionalNavigationCoefficient = proportionalNavigationCoefficient;
|
||||
HasGuidance = false;
|
||||
GuidanceCommand = Vector3D.Zero;
|
||||
Position = Vector3D.Zero;
|
||||
Velocity = Vector3D.Zero;
|
||||
}
|
||||
|
||||
public virtual void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
|
||||
{
|
||||
Position = missilePosition;
|
||||
Velocity = missileVelocity;
|
||||
}
|
||||
|
||||
public Vector3D GetGuidanceCommand()
|
||||
{
|
||||
return GuidanceCommand;
|
||||
}
|
||||
|
||||
protected virtual void CalculateGuidanceCommand(double deltaTime)
|
||||
{
|
||||
// 基础制导系统不计算制导指令
|
||||
// 派生类应该重写这个方法来实现特定的制导逻辑
|
||||
}
|
||||
|
||||
protected Vector3D CalculateProportionalNavigation(Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity)
|
||||
{
|
||||
// 预测时间(可以根据实际情况调整)
|
||||
double predictionTime = 2.0;
|
||||
|
||||
// 预测目标位置
|
||||
Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime;
|
||||
|
||||
Vector3D r = predictedTargetPosition - missilePosition;
|
||||
Vector3D v = targetVelocity - missileVelocity;
|
||||
|
||||
Vector3D LOS = r.Normalize();
|
||||
Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude();
|
||||
|
||||
Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * ProportionalNavigationCoefficient * missileVelocity.Magnitude();
|
||||
|
||||
return acceleration;
|
||||
}
|
||||
|
||||
public static (Vector3D newPosition, Vector3D newVelocity) RungeKutta4(double deltaTime, Vector3D position, Vector3D velocity, Vector3D acceleration)
|
||||
{
|
||||
// 定义一个局部函数来计算加速度
|
||||
Vector3D AccelerationFunction(Vector3D pos, Vector3D vel)
|
||||
{
|
||||
// 这里可以添加更复杂的加速度计算,比如考虑空气阻力等
|
||||
return acceleration;
|
||||
}
|
||||
|
||||
// 第一步
|
||||
Vector3D k1v = AccelerationFunction(position, velocity) * deltaTime;
|
||||
Vector3D k1r = velocity * deltaTime;
|
||||
|
||||
// 第二步
|
||||
Vector3D k2v = AccelerationFunction(position + k1r * 0.5, velocity + k1v * 0.5) * deltaTime;
|
||||
Vector3D k2r = (velocity + k1v * 0.5) * deltaTime;
|
||||
|
||||
// 第三步
|
||||
Vector3D k3v = AccelerationFunction(position + k2r * 0.5, velocity + k2v * 0.5) * deltaTime;
|
||||
Vector3D k3r = (velocity + k2v * 0.5) * deltaTime;
|
||||
|
||||
// 第四步
|
||||
Vector3D k4v = AccelerationFunction(position + k3r, velocity + k3v) * deltaTime;
|
||||
Vector3D k4r = (velocity + k3v) * deltaTime;
|
||||
|
||||
// 计算新的位置和速度
|
||||
Vector3D newPosition = position + (k1r + k2r * 2 + k3r * 2 + k4r) / 6;
|
||||
Vector3D newVelocity = velocity + (k1v + k2v * 2 + k3v * 2 + k4v) / 6;
|
||||
|
||||
return (newPosition, newVelocity);
|
||||
}
|
||||
}
|
||||
}
|
||||
297
Models/Common.cs
Normal file
297
Models/Common.cs
Normal file
@ -0,0 +1,297 @@
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示三维空间中的向量
|
||||
/// </summary>
|
||||
public class Vector3D
|
||||
{
|
||||
// 添加静态单位向量属性
|
||||
public static Vector3D UnitX => new Vector3D(1, 0, 0);
|
||||
public static Vector3D UnitY => new Vector3D(0, 1, 0);
|
||||
public static Vector3D UnitZ => new Vector3D(0, 0, 1);
|
||||
public static Vector3D Zero => new Vector3D(0, 0, 0);
|
||||
|
||||
/// <summary>
|
||||
/// X 坐标
|
||||
/// </summary>
|
||||
public double X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Y 坐标
|
||||
/// </summary>
|
||||
public double Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Z 坐标
|
||||
/// </summary>
|
||||
public double Z { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public Vector3D(double x, double y, double z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个向量之间的距离
|
||||
/// </summary>
|
||||
/// <param name="v1">第一个向量</param>
|
||||
/// <param name="v2">第二个向量</param>
|
||||
/// <returns>两个向量之间的距离</returns>
|
||||
public static double Distance(Vector3D v1, Vector3D v2)
|
||||
{
|
||||
return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将向量转换为字符串表示
|
||||
/// </summary>
|
||||
/// <returns>向量的字符串表示</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({X:F2}, {Y:F2}, {Z:F2})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量减法运算符重载
|
||||
/// </summary>
|
||||
public static Vector3D operator -(Vector3D a, Vector3D b)
|
||||
{
|
||||
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量加法运算符重载
|
||||
/// </summary>
|
||||
public static Vector3D operator +(Vector3D a, Vector3D b)
|
||||
{
|
||||
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量与标量乘法运算符重载
|
||||
/// </summary>
|
||||
public static Vector3D operator *(Vector3D a, double scalar)
|
||||
{
|
||||
return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量与标量除法运算符重载
|
||||
/// </summary>
|
||||
public static Vector3D operator /(Vector3D a, double scalar)
|
||||
{
|
||||
return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量反向
|
||||
/// </summary>
|
||||
public static Vector3D operator -(Vector3D a)
|
||||
{
|
||||
return new Vector3D(-a.X, -a.Y, -a.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算向量的模长
|
||||
/// </summary>
|
||||
/// <returns>向量的模长</returns>
|
||||
public double Magnitude()
|
||||
{
|
||||
return Math.Sqrt(X * X + Y * Y + Z * Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算向量模长的平方
|
||||
/// </summary>
|
||||
/// <returns>向量模长的平方</returns>
|
||||
public double MagnitudeSquared()
|
||||
{
|
||||
return X * X + Y * Y + Z * Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量归一化
|
||||
/// </summary>
|
||||
/// <returns>归一化后的向量</returns>
|
||||
public Vector3D Normalize()
|
||||
{
|
||||
double mag = Magnitude();
|
||||
if (mag > 0)
|
||||
{
|
||||
return new Vector3D(X / mag, Y / mag, Z / mag);
|
||||
}
|
||||
return new Vector3D(0, 0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个向量的叉积
|
||||
/// </summary>
|
||||
/// <param name="a">第一个向量</param>
|
||||
/// <param name="b">第二个向量</param>
|
||||
/// <returns>叉积结果</returns>
|
||||
public static Vector3D CrossProduct(Vector3D a, Vector3D b)
|
||||
{
|
||||
return new Vector3D(
|
||||
a.Y * b.Z - a.Z * b.Y,
|
||||
a.Z * b.X - a.X * b.Z,
|
||||
a.X * b.Y - a.Y * b.X
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算两个向量的点积
|
||||
/// </summary>
|
||||
/// <param name="a">第一个向量</param>
|
||||
/// <param name="b">第二个向量</param>
|
||||
/// <returns>点积结果</returns>
|
||||
public static double DotProduct(Vector3D a, Vector3D b)
|
||||
{
|
||||
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向量取反
|
||||
/// </summary>
|
||||
/// <param name="a">输入向量</param>
|
||||
/// <returns>取反后的向量</returns>
|
||||
public static Vector3D Negate(Vector3D a)
|
||||
{
|
||||
return new Vector3D(-a.X, -a.Y, -a.Z);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示三维空间中的方向
|
||||
/// </summary>
|
||||
public struct Orientation
|
||||
{
|
||||
/// <summary>
|
||||
/// 偏航角(绕Y轴旋转)
|
||||
/// </summary>
|
||||
public double Yaw { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 俯仰角(绕X轴旋转)
|
||||
/// </summary>
|
||||
public double Pitch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 滚转角(绕Z轴旋转)
|
||||
/// </summary>
|
||||
public double Roll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public Orientation(double yaw, double pitch, double roll)
|
||||
{
|
||||
Yaw = yaw;
|
||||
Pitch = pitch;
|
||||
Roll = roll;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将方向转换为字符串表示
|
||||
/// </summary>
|
||||
/// <returns>方向的字符串表示</returns>
|
||||
public override readonly string ToString()
|
||||
{
|
||||
return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将角度归一化到 [-π, π] 范围内
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
Yaw = NormalizeAngle(Yaw);
|
||||
Pitch = NormalizeAngle(Pitch);
|
||||
Roll = NormalizeAngle(Roll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将单个角度归一化到 [-π, π] 范围内
|
||||
/// </summary>
|
||||
/// <param name="angle">输入角度</param>
|
||||
/// <returns>归一化后的角度</returns>
|
||||
private static double NormalizeAngle(double angle)
|
||||
{
|
||||
while (angle > Math.PI) angle -= 2 * Math.PI;
|
||||
while (angle <= -Math.PI) angle += 2 * Math.PI;
|
||||
return angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据给定的方向向量创建方向
|
||||
/// </summary>
|
||||
/// <param name="direction">方向向量</param>
|
||||
/// <returns>对应的方向</returns>
|
||||
public static Orientation LookAt(Vector3D direction)
|
||||
{
|
||||
double yaw = Math.Atan2(direction.Z, direction.X);
|
||||
double pitch = Math.Atan2(direction.Y, Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z));
|
||||
return new Orientation(yaw, pitch, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将方向转换为单位向量
|
||||
/// </summary>
|
||||
/// <returns>对应的单位向量</returns>
|
||||
public readonly Vector3D ToVector()
|
||||
{
|
||||
double cosYaw = Math.Cos(Yaw);
|
||||
double sinYaw = Math.Sin(Yaw);
|
||||
double cosPitch = Math.Cos(Pitch);
|
||||
double sinPitch = Math.Sin(Pitch);
|
||||
|
||||
return new Vector3D(
|
||||
cosYaw * cosPitch,
|
||||
sinPitch,
|
||||
sinYaw * cosPitch
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从向量创建方向
|
||||
/// </summary>
|
||||
/// <param name="vector">输入向量</param>
|
||||
/// <returns>对应的方向</returns>
|
||||
public static Orientation FromVector(Vector3D vector)
|
||||
{
|
||||
Vector3D normalized = vector.Normalize();
|
||||
double pitch = Math.Asin(normalized.Y);
|
||||
double yaw;
|
||||
if (Math.Abs(normalized.Y) > 0.9999) // 接近垂直
|
||||
{
|
||||
yaw = 0; // 或者保持之前的偏航角
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw = Math.Atan2(normalized.Z, normalized.X);
|
||||
}
|
||||
return new Orientation(yaw, pitch, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public struct Vector2D
|
||||
{
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
|
||||
public Vector2D(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static Vector2D Zero => new Vector2D(0, 0);
|
||||
}
|
||||
}
|
||||
9
Models/IGuidanceSystem.cs
Normal file
9
Models/IGuidanceSystem.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public interface IGuidanceSystem
|
||||
{
|
||||
bool HasGuidance { get; }
|
||||
void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity);
|
||||
Vector3D GetGuidanceCommand();
|
||||
}
|
||||
}
|
||||
157
Models/LaserBeamRider.cs
Normal file
157
Models/LaserBeamRider.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserBeamRider : SimulationElement
|
||||
{
|
||||
// 激光功率(瓦特)
|
||||
public double LaserPower { get; private set; }
|
||||
|
||||
// 激光发散角(毫弧度)
|
||||
public double BeamDivergence { get; private set; } = 0.0;
|
||||
|
||||
// 控制场直径(米)
|
||||
public double ControlFieldDiameter { get; private set; }
|
||||
|
||||
// 激光方向
|
||||
public Vector3D LaserDirection { get; private set; }
|
||||
|
||||
// 最大导引距离(米)
|
||||
public double MaxGuidanceDistance { get; private set; }
|
||||
|
||||
// 激光束是否开启
|
||||
public bool IsBeamOn { get; private set; }
|
||||
|
||||
// 导弹
|
||||
public string MissileId { get; private set; }
|
||||
|
||||
// 目标
|
||||
public string TargetId { get; private set; }
|
||||
|
||||
public LaserBeamRider(string id, string missileId, string targetId, LaserBeamRiderConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, new Orientation(0, 0, 0), simulationManager)
|
||||
{
|
||||
LaserPower = config.LaserPower;
|
||||
ControlFieldDiameter = config.ControlFieldDiameter;
|
||||
LaserDirection = Vector3D.Zero;
|
||||
MaxGuidanceDistance = config.MaxGuidanceDistance;
|
||||
IsActive = false; // 初始状态为非激活
|
||||
IsBeamOn = false;
|
||||
MissileId = missileId;
|
||||
TargetId = targetId;
|
||||
SimulationManager = simulationManager;
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (IsActive && IsBeamOn)
|
||||
{
|
||||
// 更新驾束仪的激光指向
|
||||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||||
LaserDirection = (targetPosition - Position).Normalize();
|
||||
|
||||
Console.WriteLine($"激光驾束仪 {Id} 更新激光指向: {LaserDirection}");
|
||||
|
||||
PublishLaserBeamUpdateEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 激活激光驾束仪
|
||||
/// </summary>
|
||||
public override void Activate()
|
||||
{
|
||||
if (!IsActive)
|
||||
{
|
||||
IsActive = true;
|
||||
Console.WriteLine($"激光驾束仪 {Id} 已激活");
|
||||
}
|
||||
base.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用激光驾束仪
|
||||
/// </summary>
|
||||
public override void Deactivate()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
IsActive = false;
|
||||
if (IsBeamOn)
|
||||
{
|
||||
StopBeamIllumination();
|
||||
}
|
||||
Console.WriteLine($"激光驾束仪 {Id} 已停用");
|
||||
}
|
||||
base.Deactivate();
|
||||
}
|
||||
|
||||
public void StartBeamIllumination()
|
||||
{
|
||||
if (!IsBeamOn)
|
||||
{
|
||||
LaserDirection = (SimulationManager.GetEntityById(TargetId).Position - Position).Normalize();
|
||||
IsBeamOn = true;
|
||||
PublishLaserBeamStartEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public void StopBeamIllumination()
|
||||
{
|
||||
if (IsBeamOn)
|
||||
{
|
||||
IsBeamOn = false;
|
||||
LaserDirection = Vector3D.Zero;
|
||||
PublishLaserBeamStopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光束开始事件
|
||||
/// </summary>
|
||||
private void PublishLaserBeamStartEvent()
|
||||
{
|
||||
PublishEvent(new LaserBeamStartEvent
|
||||
{
|
||||
LaserBeamRider = this
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光束更新事件
|
||||
/// </summary>
|
||||
private void PublishLaserBeamUpdateEvent()
|
||||
{
|
||||
PublishEvent(new LaserBeamUpdateEvent
|
||||
{
|
||||
LaserBeamRider = this
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光束停止事件
|
||||
/// </summary>
|
||||
private void PublishLaserBeamStopEvent()
|
||||
{
|
||||
PublishEvent(new LaserBeamStopEvent
|
||||
{
|
||||
LaserBeamRider = this
|
||||
});
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光驾束仪 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 方向: {LaserDirection}\n" +
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}\n" +
|
||||
$" 激光功率: {LaserPower} W\n" +
|
||||
$" 发散角: {BeamDivergence} rad\n" +
|
||||
$" 控制场直径: {ControlFieldDiameter} m\n" +
|
||||
$" 最大导引距离: {MaxGuidanceDistance} m\n" +
|
||||
$" 激光束状态: {(IsBeamOn ? "开启" : "关闭")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
193
Models/LaserBeamRiderGuidanceSystem.cs
Normal file
193
Models/LaserBeamRiderGuidanceSystem.cs
Normal file
@ -0,0 +1,193 @@
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserBeamRiderGuidanceSystem : BasicGuidanceSystem
|
||||
{
|
||||
private Vector3D LaserSourcePosition { get; set; }
|
||||
private Vector3D LaserDirection { get; set; }
|
||||
public double LaserPower { get; set; }
|
||||
private const double MinDetectablePower = 1e-3; // 假设最小可探测功率为1毫瓦
|
||||
private const double DetectorDiameter = 0.1; // 假设探测器直径为10厘米
|
||||
private const double ControlFieldDiameter = 20.0; // 控制场直径(米)
|
||||
|
||||
private Vector3D LastError = Vector3D.Zero;
|
||||
|
||||
public Vector3D LastGuidanceCommand { get; private set; }
|
||||
|
||||
private Vector3D IntegralError = Vector3D.Zero;
|
||||
|
||||
|
||||
public LaserBeamRiderGuidanceSystem(double proportionalNavigationCoefficient)
|
||||
: base(proportionalNavigationCoefficient)
|
||||
{
|
||||
LaserSourcePosition = Vector3D.Zero;
|
||||
LaserDirection = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
HasGuidance = false;
|
||||
LastGuidanceCommand = Vector3D.Zero;
|
||||
}
|
||||
|
||||
public void ActivateLaserBeam(Vector3D sourcePosition, Vector3D direction, double laserPower)
|
||||
{
|
||||
LaserSourcePosition = sourcePosition;
|
||||
LaserDirection = direction.Normalize();
|
||||
LaserPower = laserPower;
|
||||
HasGuidance = true;
|
||||
}
|
||||
|
||||
public void UpdateLaserBeamRider(Vector3D sourcePosition, Vector3D direction, double laserPower)
|
||||
{
|
||||
LaserSourcePosition = sourcePosition;
|
||||
LaserDirection = direction.Normalize();
|
||||
LaserPower = laserPower;
|
||||
}
|
||||
|
||||
public void DeactivateLaserBeam(Vector3D sourcePosition, Vector3D direction)
|
||||
{
|
||||
LaserSourcePosition = Vector3D.Zero;
|
||||
LaserDirection = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
HasGuidance = false;
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
|
||||
{
|
||||
base.Update(deltaTime, missilePosition, missileVelocity);
|
||||
|
||||
UpdateGuidanceStatus();
|
||||
|
||||
if (HasGuidance)
|
||||
{
|
||||
CalculateGuidanceCommand(deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
GuidanceCommand = Vector3D.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGuidanceStatus()
|
||||
{
|
||||
// 计算导弹到激光束的最短距离
|
||||
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
|
||||
double shortestDistance = shortestDistanceVector.Magnitude();
|
||||
|
||||
// 检查导弹是否在控制场内
|
||||
if (shortestDistance > ControlFieldDiameter / 2)
|
||||
{
|
||||
HasGuidance = false;
|
||||
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 超出控制场范围, 距离: {shortestDistance}");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine($"激光驾束引导系统: 在控制场内, 距离: {shortestDistance}");
|
||||
|
||||
// 计算接收到的激光功率
|
||||
double beamArea = Math.PI * Math.Pow(ControlFieldDiameter / 2, 2);
|
||||
double powerDensity = LaserPower / beamArea;
|
||||
double receivedPower = powerDensity * (Math.PI * Math.Pow(DetectorDiameter / 2, 2));
|
||||
|
||||
if(HasGuidance = receivedPower >= MinDetectablePower)
|
||||
{
|
||||
HasGuidance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HasGuidance = false;
|
||||
Console.WriteLine($"激光驾束引导系统: 失去引导, 原因: 接收到的激光功率低于最小可探测功率,{LaserPower:E} W/{receivedPower:E} W");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CalculateGuidanceCommand(double deltaTime)
|
||||
{
|
||||
if (!HasGuidance)
|
||||
{
|
||||
GuidanceCommand = Vector3D.Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算导弹到激光束的最短距离
|
||||
Vector3D shortestDistanceVector = CalculateShortestDistanceToLaserBeam();
|
||||
|
||||
// PID控制
|
||||
double Kp = 30; // 增加比例系数,使系统对误差更敏感,反应更快 30
|
||||
double Ki = 0.05; // 减小积分系数,减少长期误差累积的影响 0.05
|
||||
double Kd = 5; // 增加微分系数,减少系统的超调量,提高稳定性 5
|
||||
double Kc = 0.5; // 减小非线性增益系数, 控制偏移量, 使得在更小的误差范围内有更大的修正 0.5
|
||||
|
||||
// 计算误差
|
||||
Vector3D error = shortestDistanceVector;
|
||||
|
||||
// 积分项
|
||||
IntegralError += error * deltaTime;
|
||||
|
||||
// 微分项
|
||||
Vector3D derivativeError = (error - LastError) / deltaTime;
|
||||
|
||||
// 计算PID输出
|
||||
Vector3D pidOutput = error * Kp + IntegralError * Ki + derivativeError * Kd;
|
||||
|
||||
// 非线性增益
|
||||
double distance = shortestDistanceVector.Magnitude();
|
||||
double nonLinearGain = Math.Tanh(distance / Kc);
|
||||
|
||||
// 计算横向加速度
|
||||
Vector3D lateralAcceleration = pidOutput * nonLinearGain;
|
||||
|
||||
// 限制最大加速度
|
||||
double maxAcceleration = 50; // 稍微增加最大加速度 50
|
||||
if (lateralAcceleration.Magnitude() > maxAcceleration)
|
||||
{
|
||||
lateralAcceleration = lateralAcceleration.Normalize() * maxAcceleration;
|
||||
}
|
||||
|
||||
// 计算前向加速度
|
||||
Vector3D forwardDirection = LaserDirection;
|
||||
Vector3D currentDirection = Velocity.Normalize();
|
||||
Vector3D rotationAxis = Vector3D.CrossProduct(currentDirection, forwardDirection);
|
||||
double rotationAngle = Math.Acos(Vector3D.DotProduct(currentDirection, forwardDirection));
|
||||
Vector3D forwardAcceleration = Vector3D.CrossProduct(rotationAxis, Velocity) * rotationAngle * ProportionalNavigationCoefficient;
|
||||
|
||||
// 合并横向和前向加速度
|
||||
GuidanceCommand = lateralAcceleration + forwardAcceleration;
|
||||
|
||||
// 低通滤波
|
||||
const double alpha = 0.2;
|
||||
GuidanceCommand = GuidanceCommand * alpha + LastGuidanceCommand * (1 - alpha);
|
||||
|
||||
// 更新上一次的误差和制导命令
|
||||
LastError = error;
|
||||
LastGuidanceCommand = GuidanceCommand;
|
||||
|
||||
Console.WriteLine($"Current Position: {Position}");
|
||||
Console.WriteLine($"Laser Source Position: {LaserSourcePosition}");
|
||||
Console.WriteLine($"Laser Direction: {LaserDirection}");
|
||||
Console.WriteLine($"Shortest Distance Vector: {shortestDistanceVector}");
|
||||
|
||||
//Console.WriteLine($"Guidance Command: {GuidanceCommand.Magnitude()}, Lateral Error: {shortestDistanceVector.Magnitude()}, Lateral Acceleration: {lateralAcceleration.Magnitude()}, Forward Acceleration: {forwardAcceleration.Magnitude()}");
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"LaserBeamRiderGuidanceSystem: HasGuidance={HasGuidance}, LaserSourcePosition={LaserSourcePosition}, LaserDirection={LaserDirection}, GuidanceCommand={GuidanceCommand}";
|
||||
}
|
||||
|
||||
private Vector3D CalculateShortestDistanceToLaserBeam()
|
||||
{
|
||||
// 计算导弹到激光源的向量
|
||||
Vector3D missileToSource = LaserSourcePosition - Position;
|
||||
|
||||
// 计算导弹在激光方向上的投影长度
|
||||
double projectionLength = Vector3D.DotProduct(missileToSource, LaserDirection);
|
||||
|
||||
// 计算激光束上最接近导弹的点
|
||||
Vector3D closestPointOnBeam = LaserSourcePosition - LaserDirection * projectionLength;
|
||||
|
||||
// 计算导弹到激光束最近点的向量(即最短距离向量)
|
||||
Vector3D shortestDistanceVector = closestPointOnBeam - Position;
|
||||
|
||||
return shortestDistanceVector;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
Models/LaserBeamRiderMissile.cs
Normal file
84
Models/LaserBeamRiderMissile.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserBeamRiderMissile : MissileBase
|
||||
{
|
||||
private LaserBeamRiderGuidanceSystem LaserBeamRiderGuidanceSystem;
|
||||
|
||||
|
||||
public LaserBeamRiderMissile(string id, string targetId, MissileConfig missileConfig, ISimulationManager simulationManager)
|
||||
: base(id, missileConfig, simulationManager)
|
||||
{
|
||||
LaserBeamRiderGuidanceSystem = new LaserBeamRiderGuidanceSystem(missileConfig.ProportionalNavigationCoefficient);
|
||||
TargetId = targetId;
|
||||
}
|
||||
|
||||
protected override Vector3D GetGuidanceCommand()
|
||||
{
|
||||
return LaserBeamRiderGuidanceSystem.GetGuidanceCommand();
|
||||
}
|
||||
|
||||
private void OnLaserBeamStart(LaserBeamStartEvent evt)
|
||||
{
|
||||
if (evt?.LaserBeamRider != null)
|
||||
{
|
||||
LaserBeamRiderGuidanceSystem?.ActivateLaserBeam(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection, evt.LaserBeamRider.LaserPower);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserBeamUpdate(LaserBeamUpdateEvent evt)
|
||||
{
|
||||
if (evt?.LaserBeamRider != null)
|
||||
{
|
||||
LaserBeamRiderGuidanceSystem?.UpdateLaserBeamRider(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection, evt.LaserBeamRider.LaserPower);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserBeamStop(LaserBeamStopEvent evt)
|
||||
{
|
||||
if (evt?.LaserBeamRider != null)
|
||||
{
|
||||
LaserBeamRiderGuidanceSystem?.DeactivateLaserBeam(evt.LaserBeamRider.Position, evt.LaserBeamRider.LaserDirection);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (LaserBeamRiderGuidanceSystem.HasGuidance)
|
||||
{
|
||||
LaserBeamRiderGuidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
this.HasGuidance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.HasGuidance = false;
|
||||
}
|
||||
|
||||
base.Update(deltaTime);
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
string baseStatus = base.GetStatus().Replace("导弹", "激光驾束制导导弹");
|
||||
string additionalStatus = $"\n 激光引导: {(LaserBeamRiderGuidanceSystem.HasGuidance ? "有效" : "无效")}";
|
||||
return baseStatus + additionalStatus;
|
||||
}
|
||||
|
||||
public override void Activate()
|
||||
{
|
||||
base.Activate();
|
||||
SimulationManager.SubscribeToEvent<LaserBeamStartEvent>(OnLaserBeamStart);
|
||||
SimulationManager.SubscribeToEvent<LaserBeamStopEvent>(OnLaserBeamStop);
|
||||
SimulationManager.SubscribeToEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
|
||||
}
|
||||
|
||||
public override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserBeamStartEvent>(OnLaserBeamStart);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserBeamStopEvent>(OnLaserBeamStop);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
235
Models/LaserDesignator.cs
Normal file
235
Models/LaserDesignator.cs
Normal file
@ -0,0 +1,235 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光指示器类,用于对目标进行激光照射
|
||||
/// </summary>
|
||||
public class LaserDesignator : SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string TargetId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹ID
|
||||
/// </summary>
|
||||
public string MissileId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 干扰阈值(分贝)
|
||||
/// </summary>
|
||||
public double JammingThreshold { get; private set; } = 0.0;
|
||||
|
||||
/// <summary>
|
||||
/// 是否被干扰
|
||||
/// </summary>
|
||||
public bool IsJammed { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在照射
|
||||
/// </summary>
|
||||
public bool IlluminationOn { get; private set; } = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 激光功率
|
||||
/// </summary>
|
||||
public double LaserPower { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 激光发散角
|
||||
/// </summary>
|
||||
public double LaserDivergenceAngle { get; private set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">激光指示器ID</param>
|
||||
/// <param name="targetId">目标ID</param>
|
||||
/// <param name="missileId">导弹ID</param>
|
||||
/// <param name="config">激光指示器配置</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public LaserDesignator(string id, string targetId, string missileId, LaserDesignatorConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, new Orientation(), simulationManager)
|
||||
{
|
||||
TargetId = targetId;
|
||||
MissileId = missileId;
|
||||
IsActive = false;
|
||||
IlluminationOn = false;
|
||||
LaserPower = config.LaserPower;
|
||||
LaserDivergenceAngle = config.LaserDivergenceAngle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新激光指示器状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长</param>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (IsActive && !IsJammed)
|
||||
{
|
||||
if (IlluminationOn)
|
||||
{
|
||||
PublishIlluminationUpdateEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始激光照射
|
||||
/// </summary>
|
||||
private void StartLaserIllumination()
|
||||
{
|
||||
if (!IlluminationOn)
|
||||
{
|
||||
IlluminationOn = true;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}");
|
||||
PublishIlluminationStartEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止激光照射
|
||||
/// </summary>
|
||||
private void StopLaserIllumination()
|
||||
{
|
||||
if (IlluminationOn)
|
||||
{
|
||||
IlluminationOn = false;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
|
||||
PublishIlluminationStopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光干扰事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光干扰事件</param>
|
||||
private void OnLaserJamming(LaserJammingEvent evt)
|
||||
{
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
var tank = SimulationManager.GetEntityById(TargetId) as Tank;
|
||||
if (tank != null)
|
||||
{
|
||||
double distanceToTarget = Vector3D.Distance(Position, tank.Position);
|
||||
double jammingEffectiveness = 20 * Math.Log10(evt.JammingPower) - 20 * Math.Log10(distanceToTarget) - 20 * Math.Log10(4 * Math.PI);
|
||||
|
||||
Console.WriteLine($"激光目标指示器 {Id} 收到干扰事件,干扰功率: {evt.JammingPower:F2}, 距离: {distanceToTarget:F2}, 干扰效果: {jammingEffectiveness:F2} dB, 阈值: {JammingThreshold:F2} dB");
|
||||
|
||||
if (jammingEffectiveness > JammingThreshold)
|
||||
{
|
||||
if (!IsJammed)
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
|
||||
IsJammed = true;
|
||||
StopLaserIllumination();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsJammed)
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
|
||||
IsJammed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活激光指示器
|
||||
/// </summary>
|
||||
public override void Activate()
|
||||
{
|
||||
if (!IsActive)
|
||||
{
|
||||
IsActive = true;
|
||||
IsJammed = false;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 已激活");
|
||||
StartLaserIllumination();
|
||||
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
|
||||
}
|
||||
base.Activate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用激光指示器
|
||||
/// </summary>
|
||||
public override void Deactivate()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
IsActive = false;
|
||||
StopLaserIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 已停用");
|
||||
SimulationManager.UnsubscribeFromEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.UnsubscribeFromEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
|
||||
}
|
||||
base.Deactivate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光照射事件
|
||||
/// </summary>
|
||||
private void PublishIlluminationStartEvent()
|
||||
{
|
||||
var evt = new LaserIlluminationStartEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
|
||||
PublishEvent(evt);
|
||||
Console.WriteLine($"激光指示器 {Id} 发布激光照射事件");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光照射更新事件
|
||||
/// </summary>
|
||||
private void PublishIlluminationUpdateEvent()
|
||||
{
|
||||
var evt = new LaserIlluminationUpdateEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
|
||||
PublishEvent(evt);
|
||||
Console.WriteLine($"激光指示器 {Id} 发布激光照射更新事件");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布激光照射停止事件
|
||||
/// </summary>
|
||||
private void PublishIlluminationStopEvent()
|
||||
{
|
||||
var evt = new LaserIlluminationStopEvent { LaserDesignator = this, Target = SimulationManager.GetEntityById(TargetId) as SimulationElement };
|
||||
PublishEvent(evt);
|
||||
Console.WriteLine($"激光指示器 {Id} 发布激光照射停止事件");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理实体停用事件
|
||||
/// </summary>
|
||||
/// <param name="evt">实体停用事件</param>
|
||||
private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt)
|
||||
{
|
||||
if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId)
|
||||
{
|
||||
StopLaserIllumination();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取激光指示器状态信息
|
||||
/// </summary>
|
||||
/// <returns>状态信息字符串</returns>
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光目标指示器 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 目标: {TargetId}\n" +
|
||||
$" 导弹: {MissileId}\n" +
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}\n" +
|
||||
$" 照射状态: {(IlluminationOn ? "正在照射" : "未照射")}\n" +
|
||||
$" 干扰状态: {(IsJammed ? "被干扰" : "正常")}\n" +
|
||||
$" 激光功率: {LaserPower:E} W";
|
||||
}
|
||||
}
|
||||
}
|
||||
196
Models/LaserJammer.cs
Normal file
196
Models/LaserJammer.cs
Normal file
@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光干扰器类,用于对抗激光制导武器
|
||||
/// </summary>
|
||||
public class LaserJammer : SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否正在进行干扰
|
||||
/// </summary>
|
||||
public bool IsJamming { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前干扰功率(瓦特)
|
||||
/// </summary>
|
||||
public double JammingPower { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前冷却时间(秒)
|
||||
/// </summary>
|
||||
private double jammingCooldown = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 最大冷却时间(秒)
|
||||
/// </summary>
|
||||
private readonly double maxJammingCooldown;
|
||||
|
||||
/// <summary>
|
||||
/// 最大干扰功率(瓦特)
|
||||
/// </summary>
|
||||
private readonly double maxJammingPower;
|
||||
|
||||
/// <summary>
|
||||
/// 初始干扰功率(瓦特)
|
||||
/// </summary>
|
||||
private readonly double initialJammingPower;
|
||||
|
||||
/// <summary>
|
||||
/// 功率增加速率(瓦特/秒)
|
||||
/// </summary>
|
||||
private readonly double powerIncreaseRate;
|
||||
|
||||
/// <summary>
|
||||
/// 被监视实体的ID
|
||||
/// </summary>
|
||||
public string MonitoredEntityId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">激光干扰器ID</param>
|
||||
/// <param name="position">初始位置</param>
|
||||
/// <param name="orientation">初始朝向</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
/// <param name="monitoredEntityId">被监视实体的ID</param>
|
||||
/// <param name="config">激光干扰器配置</param>
|
||||
public LaserJammer(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserJammerConfig config)
|
||||
: base(id, position, orientation, simulationManager)
|
||||
{
|
||||
MonitoredEntityId = monitoredEntityId;
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
maxJammingCooldown = config.MaxJammingCooldown;
|
||||
maxJammingPower = config.MaxJammingPower;
|
||||
initialJammingPower = config.InitialJammingPower;
|
||||
powerIncreaseRate = config.PowerIncreaseRate;
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新激光干扰器状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长</param>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
if (SimulationManager.GetEntityById(MonitoredEntityId) is Tank tank)
|
||||
{
|
||||
Position = tank.Position;
|
||||
Orientation = tank.Orientation;
|
||||
}
|
||||
|
||||
if (IsJamming)
|
||||
{
|
||||
JammingPower = Math.Min(JammingPower + powerIncreaseRate * deltaTime, maxJammingPower);
|
||||
|
||||
jammingCooldown += deltaTime;
|
||||
if (jammingCooldown >= maxJammingCooldown)
|
||||
{
|
||||
StopJamming();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发布干扰事件
|
||||
PublishEvent(new LaserJammingEvent
|
||||
{
|
||||
TargetId = MonitoredEntityId,
|
||||
JammingPower = JammingPower
|
||||
});
|
||||
}
|
||||
|
||||
Console.WriteLine($"激光干扰器 {Id} 正在工作,当前功率: {JammingPower:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光告警器警报事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光告警器警报事件</param>
|
||||
private void OnLaserWarnerAlarmEvent(LaserWarnerAlarmEvent evt)
|
||||
{
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
StartJamming();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光告警器警报停止事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光告警器警报停止事件</param>
|
||||
private void OnLaserWarnerAlarmStopEvent(LaserWarnerAlarmStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
StopJamming();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始干扰
|
||||
/// </summary>
|
||||
private void StartJamming()
|
||||
{
|
||||
if (!IsJamming)
|
||||
{
|
||||
IsJamming = true;
|
||||
JammingPower = initialJammingPower;
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"激光干扰器 {Id} 开始工作,初始功率: {JammingPower:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止干扰
|
||||
/// </summary>
|
||||
private void StopJamming()
|
||||
{
|
||||
if (IsJamming)
|
||||
{
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"激光干扰器 {Id} 停止工作");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取激光干扰器状态信息
|
||||
/// </summary>
|
||||
/// <returns>状态信息字符串</returns>
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光干扰器 {Id}:\n" +
|
||||
$" 监视实体: {MonitoredEntityId}\n" +
|
||||
$" 干扰状态: {(IsJamming ? "干扰中" : "未干扰")}\n" +
|
||||
$" 当前功率: {JammingPower:F2}/{maxJammingPower:F2}\n" +
|
||||
$" 冷却时间: {jammingCooldown:F2}/{maxJammingCooldown:F2}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活激光干扰器
|
||||
/// </summary>
|
||||
public override void Activate()
|
||||
{
|
||||
base.Activate();
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用激光干扰器
|
||||
/// </summary>
|
||||
public override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
142
Models/LaserSemiActiveGuidanceSystem.cs
Normal file
142
Models/LaserSemiActiveGuidanceSystem.cs
Normal file
@ -0,0 +1,142 @@
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserSemiActiveGuidanceSystem : BasicGuidanceSystem
|
||||
{
|
||||
private const double FieldOfViewAngle = Math.PI / 6; // 30度视场角
|
||||
private const double DetectorDiameter = 0.1; // 探测器直径(米)
|
||||
private const double FocusedSpotDiameter = 0.003; // 聚焦后光斑直径(米)
|
||||
private const double ReflectionCoefficient = 0.2; // 反射系数
|
||||
private const double LockThreshold = 1e-12; // 锁定阈值(瓦特)
|
||||
private const double TargetReflectiveArea = 1.0; // 目标有效反射面积(平方米)
|
||||
private Vector3D TargetPosition { get; set; }
|
||||
private Vector3D TargetVelocity { get; set; }
|
||||
private Vector3D LaserDesignatorPosition { get; set; }
|
||||
private double LaserPower { get; set; }
|
||||
private double LaserDivergenceAngle { get; set; }
|
||||
public LaserSemiActiveGuidanceSystem(double proportionalNavigationCoefficient, Vector3D initialMissilePosition, Vector3D initialTargetPosition, Vector3D initialTargetVelocity)
|
||||
: base(proportionalNavigationCoefficient)
|
||||
{
|
||||
Position = initialMissilePosition;
|
||||
TargetPosition = initialTargetPosition;
|
||||
TargetVelocity = initialTargetVelocity;
|
||||
LaserDesignatorPosition = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
}
|
||||
|
||||
public void ActivateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
|
||||
{
|
||||
HasGuidance = true;
|
||||
LaserDesignatorPosition = sourcePosition;
|
||||
TargetPosition = targetPosition;
|
||||
TargetVelocity = targetVelocity;
|
||||
LaserPower = laserPower;
|
||||
LaserDivergenceAngle = laserDivergenceAngle;
|
||||
}
|
||||
|
||||
public void UpdateLaserDesignator(Vector3D sourcePosition, Vector3D targetPosition, Vector3D targetVelocity, double laserPower, double laserDivergenceAngle)
|
||||
{
|
||||
LaserDesignatorPosition = sourcePosition;
|
||||
TargetPosition = targetPosition;
|
||||
TargetVelocity = targetVelocity;
|
||||
LaserPower = laserPower;
|
||||
LaserDivergenceAngle = laserDivergenceAngle;
|
||||
}
|
||||
|
||||
public void DeactivateLaserDesignator()
|
||||
{
|
||||
HasGuidance = false;
|
||||
LaserDesignatorPosition = Vector3D.Zero;
|
||||
TargetPosition = Vector3D.Zero;
|
||||
TargetVelocity = Vector3D.Zero;
|
||||
LaserPower = 0;
|
||||
LaserDivergenceAngle = 0;
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime, Vector3D missilePosition, Vector3D missileVelocity)
|
||||
{
|
||||
base.Update(deltaTime, missilePosition, missileVelocity);
|
||||
|
||||
HasGuidance = CalculateReceivedLaserPower() > LockThreshold;
|
||||
if (HasGuidance)
|
||||
{
|
||||
CalculateGuidanceCommand(deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
GuidanceCommand = Vector3D.Zero;
|
||||
}
|
||||
|
||||
PrintGuidanceInfo();
|
||||
}
|
||||
|
||||
private double CalculateReceivedLaserPower()
|
||||
{
|
||||
double distanceToTarget = (TargetPosition - LaserDesignatorPosition).Magnitude();
|
||||
double distanceToMissile = (Position - TargetPosition).Magnitude();
|
||||
|
||||
// 计算目标处的光斑面积
|
||||
double spotAreaAtTarget = Math.PI * Math.Pow(distanceToTarget * Math.Tan(LaserDivergenceAngle), 2);
|
||||
|
||||
// 计算目标处的激光功率密度
|
||||
double powerDensityAtTarget = LaserPower / spotAreaAtTarget;
|
||||
|
||||
// 计算从目标反射的总功率
|
||||
double reflectedPower = powerDensityAtTarget * TargetReflectiveArea * ReflectionCoefficient;
|
||||
|
||||
// 计算反射光在导弹处的扩散面积(假设漫反射)
|
||||
double reflectedSpotArea = 2 * Math.PI * Math.Pow(distanceToMissile, 2);
|
||||
|
||||
// 计算导弹接收到的功率
|
||||
double receivedPower = reflectedPower / reflectedSpotArea;
|
||||
|
||||
// 计算探测器接收到的功率比例
|
||||
double detectorArea = Math.PI * Math.Pow(DetectorDiameter / 2, 2);
|
||||
double illuminatedArea = Math.PI * Math.Pow(distanceToMissile * Math.Tan(FieldOfViewAngle / 2), 2);
|
||||
double powerRatio = Math.Min(1, detectorArea / illuminatedArea);
|
||||
|
||||
// 计算聚焦后的功率密度增加
|
||||
double focusedArea = Math.PI * Math.Pow(FocusedSpotDiameter / 2, 2);
|
||||
double focusingFactor = detectorArea / focusedArea;
|
||||
|
||||
// 计算最终接收到的功率
|
||||
double finalReceivedPower = receivedPower * powerRatio * focusingFactor;
|
||||
|
||||
return finalReceivedPower;
|
||||
}
|
||||
|
||||
protected override void CalculateGuidanceCommand(double deltaTime)
|
||||
{
|
||||
if (!HasGuidance)
|
||||
{
|
||||
GuidanceCommand = Vector3D.Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算比例导引加速度
|
||||
GuidanceCommand = CalculateProportionalNavigation(Position, Velocity, TargetPosition, TargetVelocity);
|
||||
|
||||
// 限制最大加速度
|
||||
double maxAcceleration = 100; // 根据实际情况调整
|
||||
if (GuidanceCommand.Magnitude() > maxAcceleration)
|
||||
{
|
||||
GuidanceCommand = GuidanceCommand.Normalize() * maxAcceleration;
|
||||
}
|
||||
}
|
||||
|
||||
private void PrintGuidanceInfo()
|
||||
{
|
||||
Console.WriteLine($"激光半主动导弹引导信息:");
|
||||
Console.WriteLine($" 位置: {Position}");
|
||||
Console.WriteLine($" 速度: {Velocity}");
|
||||
Console.WriteLine($" 速度大小: {Velocity.Magnitude():F2} m/s");
|
||||
Console.WriteLine($" 是否有引导: {HasGuidance}");
|
||||
Console.WriteLine($" 目标位置: {TargetPosition}");
|
||||
Console.WriteLine($" 制导指令: {GuidanceCommand}");
|
||||
Console.WriteLine($" 接收到的激光功率: {CalculateReceivedLaserPower():E} W");
|
||||
Console.WriteLine($" 锁定阈值: {LockThreshold:E} W");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Models/LaserSemiActiveGuidedMissile.cs
Normal file
126
Models/LaserSemiActiveGuidedMissile.cs
Normal file
@ -0,0 +1,126 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹类,继承自基础导弹类
|
||||
/// </summary>
|
||||
public class LaserSemiActiveGuidedMissile : MissileBase
|
||||
{
|
||||
private LaserSemiActiveGuidanceSystem LaserGuidanceSystem;
|
||||
private string LaserDesignatorId;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">导弹ID</param>
|
||||
/// <param name="laserDesignatorId">激光指示器ID</param>
|
||||
/// <param name="missileConfig">导弹配置</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public LaserSemiActiveGuidedMissile(string id, MissileConfig missileConfig, string laserDesignatorId, ISimulationManager simulationManager)
|
||||
: base(id, missileConfig, simulationManager)
|
||||
{
|
||||
Vector3D initialTargetPosition = simulationManager.GetEntityById($"Tank_{missileConfig.TargetIndex + 1}").Position;
|
||||
Vector3D initialTargetVelocity = simulationManager.GetEntityById($"Tank_{missileConfig.TargetIndex + 1}").Velocity;
|
||||
LaserGuidanceSystem = new LaserSemiActiveGuidanceSystem(
|
||||
missileConfig.ProportionalNavigationCoefficient,
|
||||
missileConfig.InitialPosition,
|
||||
initialTargetPosition,
|
||||
initialTargetVelocity
|
||||
);
|
||||
LaserDesignatorId = laserDesignatorId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光照射事件</param>
|
||||
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
|
||||
{
|
||||
if (evt?.LaserDesignator != null && evt?.Target != null)
|
||||
{
|
||||
LaserGuidanceSystem.ActivateLaserDesignator(evt.LaserDesignator.Position, evt.Target.Position, evt.Target.Velocity,
|
||||
evt.LaserDesignator.LaserPower, evt.LaserDesignator.LaserDivergenceAngle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射更新事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光照射更新事件</param>
|
||||
private void OnLaserIlluminationUpdate(LaserIlluminationUpdateEvent evt)
|
||||
{
|
||||
if (evt?.LaserDesignator != null && evt?.Target != null)
|
||||
{
|
||||
LaserGuidanceSystem.UpdateLaserDesignator(evt.LaserDesignator.Position, evt.Target.Position, evt.Target.Velocity,
|
||||
evt.LaserDesignator.LaserPower, evt.LaserDesignator.LaserDivergenceAngle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射停止事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光照射停止事件</param>
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
LaserGuidanceSystem.DeactivateLaserDesignator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取导弹状态信息
|
||||
/// </summary>
|
||||
/// <returns>状态信息字符串</returns>
|
||||
public override string GetStatus()
|
||||
{
|
||||
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
|
||||
string additionalStatus = $"\n 激光引导: {(LaserGuidanceSystem.HasGuidance ? "有效" : "无效")}";
|
||||
return baseStatus + additionalStatus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活导弹
|
||||
/// </summary>
|
||||
public override void Activate()
|
||||
{
|
||||
base.Activate();
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用导弹
|
||||
/// </summary>
|
||||
public override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationUpdateEvent>(OnLaserIlluminationUpdate);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (LaserGuidanceSystem.HasGuidance)
|
||||
{
|
||||
LaserGuidanceSystem.Update(deltaTime, Position, Velocity);
|
||||
this.HasGuidance = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.HasGuidance = false;
|
||||
}
|
||||
base.Update(deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取制导命令
|
||||
/// </summary>
|
||||
/// <returns>制导命令</returns>
|
||||
protected override Vector3D GetGuidanceCommand()
|
||||
{
|
||||
return LaserGuidanceSystem.GetGuidanceCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Models/LaserWarner.cs
Normal file
159
Models/LaserWarner.cs
Normal file
@ -0,0 +1,159 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光告警器类,用于检测激光照射并发出警报
|
||||
/// </summary>
|
||||
public class LaserWarner : SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否正在发出警报
|
||||
/// </summary>
|
||||
public bool IsAlarming { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 警报持续时间(秒)
|
||||
/// </summary>
|
||||
private readonly double alarmDuration;
|
||||
|
||||
/// <summary>
|
||||
/// 当前警报计时器
|
||||
/// </summary>
|
||||
private double alarmTimer = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 被监视实体的ID
|
||||
/// </summary>
|
||||
public string MonitoredEntityId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">激光告警器ID</param>
|
||||
/// <param name="position">初始位置</param>
|
||||
/// <param name="orientation">初始朝向</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
/// <param name="monitoredEntityId">被监视实体的ID</param>
|
||||
/// <param name="config">激光告警器配置</param>
|
||||
public LaserWarner(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserWarnerConfig config)
|
||||
: base(id, position, orientation, simulationManager)
|
||||
{
|
||||
MonitoredEntityId = monitoredEntityId;
|
||||
IsAlarming = false;
|
||||
alarmDuration = config.AlarmDuration;
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新激光告警器状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长</param>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
|
||||
if (tank != null)
|
||||
{
|
||||
Position = tank.Position;
|
||||
Orientation = tank.Orientation;
|
||||
}
|
||||
|
||||
if (IsAlarming)
|
||||
{
|
||||
alarmTimer += deltaTime;
|
||||
if (alarmTimer >= alarmDuration)
|
||||
{
|
||||
StopAlarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光照射事件</param>
|
||||
private void OnLaserIlluminationStart(LaserIlluminationStartEvent evt)
|
||||
{
|
||||
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
|
||||
{
|
||||
TriggerAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理激光照射停止事件
|
||||
/// </summary>
|
||||
/// <param name="evt">激光照射停止事件</param>
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt?.Target != null && evt.Target.Id == MonitoredEntityId)
|
||||
{
|
||||
StopAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发警报
|
||||
/// </summary>
|
||||
public void TriggerAlarm()
|
||||
{
|
||||
if (!IsAlarming)
|
||||
{
|
||||
IsAlarming = true;
|
||||
alarmTimer = 0;
|
||||
PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId });
|
||||
Console.WriteLine($"激光告警器 {Id} 发出警报!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止警报
|
||||
/// </summary>
|
||||
public void StopAlarm()
|
||||
{
|
||||
if (IsAlarming)
|
||||
{
|
||||
IsAlarming = false;
|
||||
alarmTimer = 0;
|
||||
PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId });
|
||||
Console.WriteLine($"激光告警器 {Id} 停止警报");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取激光告警器状态信息
|
||||
/// </summary>
|
||||
/// <returns>状态信息字符串</returns>
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光告警器 {Id}:\n" +
|
||||
$" 监视实体: {MonitoredEntityId}\n" +
|
||||
$" 警报状态: {(IsAlarming ? "警报中" : "正常")}\n" +
|
||||
$" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活激光告警器
|
||||
/// </summary>
|
||||
public override void Activate()
|
||||
{
|
||||
base.Activate();
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用激光告警器
|
||||
/// </summary>
|
||||
public override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStartEvent>(OnLaserIlluminationStart);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
675
Models/MissileBase.cs
Normal file
675
Models/MissileBase.cs
Normal file
@ -0,0 +1,675 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using Model;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示仿真中的导弹
|
||||
/// </summary>
|
||||
public class MissileBase : SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 导弹类型
|
||||
/// </summary>
|
||||
public MissileType Type { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前速度(米/秒)
|
||||
/// </summary>
|
||||
public double Speed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大速度(米/秒)
|
||||
/// </summary>
|
||||
public double MaxSpeed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string TargetId { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大飞行时间(秒)
|
||||
/// </summary>
|
||||
public double MaxFlightTime { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大飞行距离(米)
|
||||
/// </summary>
|
||||
public double MaxFlightDistance { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行时间(秒)
|
||||
/// </summary>
|
||||
public double FlightTime { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行距离(米)
|
||||
/// </summary>
|
||||
public double FlightDistance { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 与目标的距离(米)
|
||||
/// </summary>
|
||||
public double DistanceToTarget { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹距离参数
|
||||
/// </summary>
|
||||
public MissileDistanceParams DistanceParams { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 飞行阶段配置
|
||||
/// </summary>
|
||||
public FlightStageConfig StageConfig { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行阶段
|
||||
/// </summary>
|
||||
public FlightStage CurrentStage { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 上一帧目标位置
|
||||
/// </summary>
|
||||
private Vector3D LastTargetPosition;
|
||||
|
||||
/// <summary>
|
||||
/// 比例导引系数
|
||||
/// </summary>
|
||||
private const double N = 3;
|
||||
|
||||
/// <summary>
|
||||
/// 推力加速度(米/秒²)
|
||||
/// </summary>
|
||||
public double ThrustAcceleration { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前发动机燃烧时间(秒)
|
||||
/// </summary>
|
||||
public double EngineBurnTime { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大发动机燃烧时间(秒)
|
||||
/// </summary>
|
||||
public double MaxEngineBurnTime { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大加速度(米/秒²)
|
||||
/// </summary>
|
||||
public double MaxAcceleration { get; protected set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 比例导引系数
|
||||
/// </summary>
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否有制导
|
||||
/// </summary>
|
||||
public bool HasGuidance { get; protected set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 失去制导的时间(秒)
|
||||
/// </summary>
|
||||
protected double LostGuidanceTime { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 最后已知的速度向量
|
||||
/// </summary>
|
||||
protected Vector3D LastKnownVelocity = Vector3D.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// 发射速度(米/秒)
|
||||
/// </summary>
|
||||
public const double LAUNCH_SPEED = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 发射阶段持续时间(秒)
|
||||
/// </summary>
|
||||
public const double LAUNCH_DURATION = 0.5;
|
||||
|
||||
protected IMissileStageStrategy currentStage;
|
||||
private Dictionary<FlightStage, IMissileStageStrategy> stageStrategies;
|
||||
|
||||
/// <summary>
|
||||
/// 导弹质量(千克)
|
||||
/// </summary>
|
||||
public double Mass { get; protected set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public MissileBase(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
|
||||
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager)
|
||||
{
|
||||
// 初始化导弹属性
|
||||
Speed = missileConfig.InitialSpeed;
|
||||
MaxSpeed = missileConfig.MaxSpeed;
|
||||
MaxFlightTime = missileConfig.MaxFlightTime;
|
||||
MaxFlightDistance = missileConfig.MaxFlightDistance;
|
||||
DistanceParams = missileConfig.DistanceParams;
|
||||
StageConfig = missileConfig.StageConfig;
|
||||
IsActive = true;
|
||||
FlightTime = 0;
|
||||
FlightDistance = 0;
|
||||
SimulationManager = simulationManager;
|
||||
ThrustAcceleration = missileConfig.ThrustAcceleration;
|
||||
EngineBurnTime = 0;
|
||||
MaxEngineBurnTime = missileConfig.MaxEngineBurnTime;
|
||||
MaxAcceleration = missileConfig.MaxAcceleration;
|
||||
ProportionalNavigationCoefficient = missileConfig.ProportionalNavigationCoefficient;
|
||||
TargetId = $"Tank_{missileConfig.TargetIndex + 1}";
|
||||
Vector3D horizontalDirection = new Vector3D(Orientation.ToVector().X, 0, Orientation.ToVector().Z).Normalize();
|
||||
Velocity = horizontalDirection * missileConfig.InitialSpeed;
|
||||
|
||||
// 初始化策略字典
|
||||
stageStrategies = new Dictionary<FlightStage, IMissileStageStrategy>
|
||||
{
|
||||
{ FlightStage.Launch, new LaunchStageStrategy(this) },
|
||||
{ FlightStage.Acceleration, new AccelerationStageStrategy(this) },
|
||||
{ FlightStage.Cruise, new CruiseStageStrategy(this) },
|
||||
{ FlightStage.TerminalGuidance, new TerminalGuidanceStageStrategy(this) },
|
||||
{ FlightStage.Attack, new AttackStageStrategy(this) }
|
||||
};
|
||||
|
||||
// 设置初始阶段
|
||||
SetInitialStage();
|
||||
|
||||
currentStage = stageStrategies[CurrentStage];
|
||||
|
||||
LastTargetPosition = Position;
|
||||
|
||||
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置导弹的初始飞行阶段
|
||||
/// </summary>
|
||||
private void SetInitialStage()
|
||||
{
|
||||
if (StageConfig.EnableLaunch) CurrentStage = FlightStage.Launch;
|
||||
else if (StageConfig.EnableAcceleration) CurrentStage = FlightStage.Acceleration;
|
||||
else if (StageConfig.EnableCruise) CurrentStage = FlightStage.Cruise;
|
||||
else if (StageConfig.EnableTerminalGuidance) CurrentStage = FlightStage.TerminalGuidance;
|
||||
else if (StageConfig.EnableAttack) CurrentStage = FlightStage.Attack;
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 的初始阶段: {CurrentStage}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新导弹状态
|
||||
/// </summary>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
if (ShouldSelfDestruct())
|
||||
{
|
||||
SelfDestruct();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateEngineBurnTime(deltaTime);
|
||||
|
||||
Vector3D guidanceCommand = GetGuidanceCommand();
|
||||
|
||||
UpdateMotionState(deltaTime, guidanceCommand);
|
||||
|
||||
if (CheckHit())
|
||||
{
|
||||
Explode();
|
||||
return;
|
||||
}
|
||||
|
||||
currentStage.Update(deltaTime);
|
||||
}
|
||||
|
||||
protected virtual Vector3D GetGuidanceCommand()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void UpdateMotionState(double deltaTime, Vector3D guidanceCommand)
|
||||
{
|
||||
Vector3D acceleration = CalculateAcceleration(Velocity, guidanceCommand);
|
||||
|
||||
// 使用四阶龙格-库塔方法更新导弹的位置和速度
|
||||
(Position, Velocity) = BasicGuidanceSystem.RungeKutta4(deltaTime, Position, Velocity, acceleration);
|
||||
|
||||
// 限制速度不超过最大速度
|
||||
if (Velocity.Magnitude() > MaxSpeed)
|
||||
{
|
||||
Velocity = Velocity.Normalize() * MaxSpeed;
|
||||
}
|
||||
|
||||
UpdateMotionStatus(deltaTime);
|
||||
}
|
||||
|
||||
protected virtual void UpdateMotionStatus(double deltaTime)
|
||||
{
|
||||
Speed = Velocity.Magnitude();
|
||||
Orientation = Orientation.FromVector(Velocity);
|
||||
FlightTime += deltaTime;
|
||||
FlightDistance += Speed * deltaTime;
|
||||
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算导弹的加速度
|
||||
/// </summary>
|
||||
private Vector3D CalculateAcceleration(Vector3D velocity, Vector3D guidanceCommand)
|
||||
{
|
||||
Vector3D thrustAcceleration = Vector3D.Zero;
|
||||
Vector3D guidanceAcceleration = Vector3D.Zero;
|
||||
|
||||
switch (CurrentStage)
|
||||
{
|
||||
case FlightStage.Launch:
|
||||
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
break;
|
||||
case FlightStage.Acceleration:
|
||||
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
guidanceAcceleration = guidanceCommand;
|
||||
break;
|
||||
case FlightStage.Cruise:
|
||||
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
|
||||
guidanceAcceleration = guidanceCommand * 1;
|
||||
break;
|
||||
case FlightStage.TerminalGuidance:
|
||||
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.05);
|
||||
guidanceAcceleration = guidanceCommand * 1;
|
||||
break;
|
||||
case FlightStage.Attack:
|
||||
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration*0.05;
|
||||
guidanceAcceleration = guidanceCommand * 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!HasGuidance)
|
||||
{
|
||||
if (velocity.Magnitude() > 0)
|
||||
{
|
||||
thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
|
||||
}
|
||||
else
|
||||
{
|
||||
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
}
|
||||
}
|
||||
|
||||
//计算重力加速度(反坦克导弹一般升力很小, 主要依靠初始发射动能和持续的推力来维持飞行)
|
||||
//Vector3D gravityCompensation = new(0, 9.81, 0);
|
||||
Vector3D gravityAcceleration = new(0, -9.81, 0);
|
||||
|
||||
// 计算空气阻力的影响
|
||||
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
|
||||
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + gravityAcceleration +dragAcceleration;
|
||||
//Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration +dragAcceleration;
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {guidanceAcceleration}, 推力加速度: {thrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
|
||||
if (totalAcceleration.Magnitude() > MaxAcceleration)
|
||||
{
|
||||
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
|
||||
}
|
||||
|
||||
return totalAcceleration;
|
||||
}
|
||||
/// <summary>
|
||||
/// 切换导弹飞行阶段
|
||||
/// </summary>
|
||||
public void ChangeStage(FlightStage newStage)
|
||||
{
|
||||
if (stageStrategies.TryGetValue(newStage, out var strategy))
|
||||
{
|
||||
if (IsStageEnabled(newStage))
|
||||
{
|
||||
CurrentStage = newStage;
|
||||
currentStage = strategy;
|
||||
Console.WriteLine($"导弹 {Id} 切换到 {newStage} 阶段");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果目标阶段不可用,尝试切换到下一个可用阶段
|
||||
TryChangeToNextAvailableStage(newStage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 无法切换到未知阶段 {newStage}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查指定飞行阶段是否启用
|
||||
/// </summary>
|
||||
private bool IsStageEnabled(FlightStage stage)
|
||||
{
|
||||
return stage switch
|
||||
{
|
||||
FlightStage.Launch => StageConfig.EnableLaunch,
|
||||
FlightStage.Acceleration => StageConfig.EnableAcceleration,
|
||||
FlightStage.Cruise => StageConfig.EnableCruise,
|
||||
FlightStage.TerminalGuidance => StageConfig.EnableTerminalGuidance,
|
||||
FlightStage.Attack => StageConfig.EnableAttack,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试切换到下一个可用的飞行阶段
|
||||
/// </summary>
|
||||
private void TryChangeToNextAvailableStage(FlightStage startStage)
|
||||
{
|
||||
FlightStage[] stageOrder = new FlightStage[] {FlightStage.Launch, FlightStage.Acceleration, FlightStage.Cruise, FlightStage.TerminalGuidance, FlightStage.Attack};
|
||||
int startIndex = Array.IndexOf(stageOrder, startStage);
|
||||
|
||||
for (int i = startIndex + 1; i < stageOrder.Length; i++)
|
||||
{
|
||||
if (IsStageEnabled(stageOrder[i]))
|
||||
{
|
||||
ChangeStage(stageOrder[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有可用的下一个阶段,导弹自毁
|
||||
Console.WriteLine($"导弹 {Id} 没有可用的下一个阶段,准备自毁");
|
||||
SelfDestruct();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算导弹的加速度
|
||||
/// </summary>
|
||||
// private (Vector3D, Vector3D) CalculateDerivatives_RK4(Vector3D position, Vector3D velocity, double deltaTime)
|
||||
// {
|
||||
// Vector3D guidanceAcceleration = Vector3D.Zero;
|
||||
// Vector3D thrustAcceleration = Vector3D.Zero;
|
||||
|
||||
// switch (CurrentStage)
|
||||
// {
|
||||
// case FlightStage.Launch:
|
||||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
// break;
|
||||
// case FlightStage.Acceleration:
|
||||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
// guidanceAcceleration = CalculateProportionalNavigation(position);
|
||||
// break;
|
||||
// case FlightStage.Cruise:
|
||||
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
|
||||
// guidanceAcceleration = CalculateProportionalNavigation(position) * 0.5;
|
||||
// break;
|
||||
// case FlightStage.TerminalGuidance:
|
||||
// thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
|
||||
// guidanceAcceleration = CalculateProportionalNavigation(position) * 1.5;
|
||||
// break;
|
||||
// case FlightStage.Attack:
|
||||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
// guidanceAcceleration = CalculateProportionalNavigation(position) * 2;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (!HasGuidance)
|
||||
// {
|
||||
// guidanceAcceleration = Vector3D.Zero;
|
||||
// if (velocity.Magnitude() > 0)
|
||||
// {
|
||||
// thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 计算空气阻力的影响
|
||||
// Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
|
||||
|
||||
// // 计算重力加速度(反坦克导弹一般升力很小, 主要依靠初始发射动能和持续的推力来维持飞行)
|
||||
// //Vector3D gravityCompensation = new(0, 9.81, 0);
|
||||
// Vector3D gravityAcceleration = new(0, -9.81, 0);
|
||||
|
||||
// Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + gravityAcceleration + dragAcceleration;
|
||||
|
||||
// if (totalAcceleration.Magnitude() > MaxAcceleration)
|
||||
// {
|
||||
// totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
|
||||
// }
|
||||
|
||||
// return (velocity, totalAcceleration);
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 计算空气阻力
|
||||
/// </summary>
|
||||
private static double CalculateDrag(double speed)
|
||||
{
|
||||
const double dragCoefficient = 0.1; // 减小阻力系数
|
||||
const double airDensity = 1.225; // 海平面空气密度,kg/m^3
|
||||
const double referenceArea = 0.01; // 减小导弹的参考面积,m^2
|
||||
|
||||
return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否命中目标
|
||||
/// </summary>
|
||||
protected bool CheckHit()
|
||||
{
|
||||
return DistanceToTarget <= DistanceParams.ExplosionDistance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否应该自毁
|
||||
/// </summary>
|
||||
protected bool ShouldSelfDestruct()
|
||||
{
|
||||
if (FlightTime >= MaxFlightTime)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
if (FlightDistance >= MaxFlightDistance)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
if (Position.Y <= -1.0) // 数字略小于0
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新发动机燃烧时间
|
||||
/// </summary>
|
||||
private void UpdateEngineBurnTime(double deltaTime)
|
||||
{
|
||||
if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
|
||||
{
|
||||
EngineBurnTime += deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算比例导引加速度
|
||||
/// </summary>
|
||||
private Vector3D CalculateProportionalNavigation(Vector3D position)
|
||||
{
|
||||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||||
Vector3D LOS = targetPosition - position;
|
||||
Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
|
||||
LastTargetPosition = targetPosition;
|
||||
|
||||
return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
|
||||
* ProportionalNavigationCoefficient * Velocity.Magnitude();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹爆炸
|
||||
/// </summary>
|
||||
public void Explode()
|
||||
{
|
||||
Deactivate();
|
||||
SimulationManager.HandleTargetHit(TargetId, Id);
|
||||
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹自毁
|
||||
/// </summary>
|
||||
public void SelfDestruct()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
|
||||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
|
||||
Position.Y <= 0 ? "高度小于等于0" :
|
||||
!HasGuidance ? "失去引导" : "未知原因";
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置比例导引系数
|
||||
/// </summary>
|
||||
public void SetProportionalNavigationCoefficient(double newCoefficient)
|
||||
{
|
||||
ProportionalNavigationCoefficient = newCoefficient;
|
||||
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取导弹状态
|
||||
/// </summary>
|
||||
public override string GetStatus()
|
||||
{
|
||||
MissileRunningState missileRunningState = GetState();
|
||||
return $"导弹 {missileRunningState.Id}:\n" +
|
||||
$" 位置: {missileRunningState.Position}\n" +
|
||||
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
|
||||
$" 当前状态: {missileRunningState.CurrentStage}\n" +
|
||||
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MaxFlightTime:F2}\n" +
|
||||
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
|
||||
$" 距离目标: {missileRunningState.DistanceToTarget:F2}\n" +
|
||||
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
|
||||
$" 有引导: {(missileRunningState.HasGuidance ? "是" : "否")}\n" +
|
||||
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新导弹的制导状态
|
||||
/// </summary>
|
||||
protected virtual void UpdateGuidanceStatus()
|
||||
{
|
||||
// 基类中的默认实现
|
||||
}
|
||||
|
||||
public MissileRunningState GetState()
|
||||
{
|
||||
return new MissileRunningState
|
||||
{
|
||||
Id = Id,
|
||||
Type = Type,
|
||||
Position = Position,
|
||||
Velocity = Velocity,
|
||||
Orientation = Orientation,
|
||||
Speed = Speed,
|
||||
TargetId = TargetId,
|
||||
FlightTime = FlightTime,
|
||||
FlightDistance = FlightDistance,
|
||||
DistanceToTarget = DistanceToTarget,
|
||||
CurrentStage = CurrentStage,
|
||||
HasGuidance = HasGuidance,
|
||||
LostGuidanceTime = LostGuidanceTime,
|
||||
EngineBurnTime = EngineBurnTime,
|
||||
IsActive = IsActive
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示导弹的运行状态信息
|
||||
/// </summary>
|
||||
public struct MissileRunningState
|
||||
{
|
||||
/// <summary>
|
||||
/// 导弹ID
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹类型
|
||||
/// </summary>
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前位置
|
||||
/// </summary>
|
||||
public Vector3D Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前速度向量
|
||||
/// </summary>
|
||||
public Vector3D Velocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前朝向
|
||||
/// </summary>
|
||||
public Orientation Orientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前速度(米/秒)
|
||||
/// </summary>
|
||||
public double Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string TargetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行时间(秒)
|
||||
/// </summary>
|
||||
public double FlightTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行距离(米)
|
||||
/// </summary>
|
||||
public double FlightDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 与目标的距离(米)
|
||||
/// </summary>
|
||||
public double DistanceToTarget { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前飞行阶段
|
||||
/// </summary>
|
||||
public FlightStage CurrentStage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否有制导
|
||||
/// </summary>
|
||||
public bool HasGuidance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 失去制导时间(秒)
|
||||
/// </summary>
|
||||
public double LostGuidanceTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前发动机燃烧时间(秒)
|
||||
/// </summary>
|
||||
public double EngineBurnTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否处于活动状态
|
||||
/// </summary>
|
||||
public bool IsActive { get; set; }
|
||||
}
|
||||
}
|
||||
351
Models/MissileClass.cs
Normal file
351
Models/MissileClass.cs
Normal file
@ -0,0 +1,351 @@
|
||||
using System;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 坦克消息结构
|
||||
/// </summary>
|
||||
public struct TankInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 坦克编号
|
||||
/// </summary>
|
||||
public int TankID { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克类型编号
|
||||
/// </summary>
|
||||
public int TankType { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克X坐标
|
||||
/// </summary>
|
||||
public double xp { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克Y坐标
|
||||
/// </summary>
|
||||
public double yp { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克Z坐标
|
||||
/// </summary>
|
||||
public double zp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 烟幕标记
|
||||
/// </summary>
|
||||
public double fYMFlag { get; set; }
|
||||
/// <summary>
|
||||
/// 烟幕SNR
|
||||
/// </summary>
|
||||
public double fYMSNR { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光致盲标记,1-导弹;2-制导站;3-两者都不是
|
||||
/// </summary>
|
||||
public double fZMJGFlag { get; set; }
|
||||
/// <summary>
|
||||
/// 致盲能量
|
||||
/// </summary>
|
||||
public double fZMJGPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光诱骗假目标X坐标
|
||||
/// </summary>
|
||||
public double fFalseX { get; set; }
|
||||
/// <summary>
|
||||
/// 激光诱骗假目标Y坐标
|
||||
/// </summary>
|
||||
public double fFalseY { get; set; }
|
||||
/// <summary>
|
||||
/// 激光诱骗假目标Z坐标
|
||||
/// </summary>
|
||||
public double fFalseZ { get; set; }
|
||||
/// <summary>
|
||||
/// 红外诱骗能量值
|
||||
/// </summary>
|
||||
public double fFalseIRPower { get; set; }
|
||||
/// <summary>
|
||||
/// 激光诱骗能量值
|
||||
/// </summary>
|
||||
public double fFalseJGPower { get; set; }
|
||||
/// <summary>
|
||||
/// 毫米波补偿//1为开启
|
||||
/// </summary>
|
||||
public double fHMBBCFlag { get; set; }
|
||||
/// <summary>
|
||||
/// 毫米波干扰能量
|
||||
/// </summary>
|
||||
public double fHMBGRPower { get; set; }
|
||||
/// <summary>
|
||||
/// 红外干扰能量
|
||||
/// </summary>
|
||||
public double fHWGRPower { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克辐射红外能量
|
||||
/// </summary>
|
||||
public double fTankIRPower { get; set; }
|
||||
/// <summary>
|
||||
/// 坦克辐射激光能量
|
||||
/// </summary>
|
||||
public double fTankJGPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 坦克辐射毫米波能量
|
||||
/// </summary>
|
||||
public double fTankHMBPower { get; set; }
|
||||
/// <summary>
|
||||
/// 毫米波补偿特征值//大于导弹补偿成功,末敏弹子弹爆炸
|
||||
/// </summary>
|
||||
public double fFeature { get; set; }
|
||||
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 威胁源初始化信息结构
|
||||
/// </summary>
|
||||
public struct MIniInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 导弹ID
|
||||
/// </summary>
|
||||
public int nMisID;
|
||||
/// <summary>
|
||||
/// 导弹X坐标
|
||||
/// </summary>
|
||||
public double xm;
|
||||
/// <summary>
|
||||
/// 导弹Y坐标
|
||||
/// </summary>
|
||||
public double ym;
|
||||
/// <summary>
|
||||
/// 导弹Z坐标
|
||||
/// </summary>
|
||||
public double zm;
|
||||
/// <summary>
|
||||
/// 导弹方位角
|
||||
/// </summary>
|
||||
public double psi_m;
|
||||
/// <summary>
|
||||
/// 导弹俯仰角
|
||||
/// </summary>
|
||||
public double theta_m;
|
||||
/// <summary>
|
||||
/// 导弹飞行速度
|
||||
/// </summary>
|
||||
public double vm;
|
||||
/// <summary>
|
||||
/// 坦克X坐标
|
||||
/// </summary>
|
||||
public double xt;
|
||||
/// <summary>
|
||||
/// 坦克Y坐标
|
||||
/// </summary>
|
||||
public double yt;
|
||||
/// <summary>
|
||||
/// 坦克Z坐标
|
||||
/// </summary>
|
||||
public double zt;
|
||||
/// <summary>
|
||||
/// 光斑X坐标
|
||||
/// </summary>
|
||||
public double xd;
|
||||
/// <summary>
|
||||
/// 光斑Y坐标
|
||||
/// </summary>
|
||||
public double yd;
|
||||
/// <summary>
|
||||
/// 光斑Z坐标
|
||||
/// </summary>
|
||||
public double zd;
|
||||
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 威胁源运行信息结构
|
||||
/// </summary>
|
||||
public struct MRunInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 杀伤半径
|
||||
/// </summary>
|
||||
public double Rx;
|
||||
/// <summary>
|
||||
/// 仿真时间
|
||||
/// </summary>
|
||||
public double fSimTime;
|
||||
/// <summary>
|
||||
/// x坐标
|
||||
/// </summary>
|
||||
public double fMisX;
|
||||
/// <summary>
|
||||
/// y坐标
|
||||
/// </summary>
|
||||
public double fMisY;
|
||||
/// <summary>
|
||||
/// z坐标
|
||||
/// </summary>
|
||||
public double fMisZ;
|
||||
/// <summary>
|
||||
/// 导弹弹道倾角
|
||||
/// </summary>
|
||||
public double fMisDeltCw;
|
||||
/// <summary>
|
||||
/// 滚转角
|
||||
/// </summary>
|
||||
public double fMisRoll;
|
||||
/// <summary>
|
||||
/// 导弹弹道偏角
|
||||
/// </summary>
|
||||
public double fMisPitch;
|
||||
/// <summary>
|
||||
/// 导弹速度
|
||||
/// </summary>
|
||||
public double fMisV;
|
||||
/// <summary>
|
||||
/// 导弹辐射红外能量
|
||||
/// </summary>
|
||||
public double fIRPower;
|
||||
/// <summary>
|
||||
/// 导弹辐射红外波长
|
||||
/// </summary>
|
||||
public double fIRWaveLen;
|
||||
/// <summary>
|
||||
/// 导弹紫外能量
|
||||
/// </summary>
|
||||
public double fUVPower;
|
||||
/// <summary>
|
||||
/// 导弹紫外波长
|
||||
/// </summary>
|
||||
public double fUVWaveLen;
|
||||
/// <summary>
|
||||
/// 导弹激光能量
|
||||
/// </summary>
|
||||
public double fJGPower;
|
||||
// 导弹激光波长
|
||||
public double fJGWaveLen;
|
||||
/// <summary>
|
||||
/// 导弹毫米波能量
|
||||
/// </summary>
|
||||
public double fHMBPower;
|
||||
/// <summary>
|
||||
/// 导弹毫米波波长
|
||||
/// </summary>
|
||||
public double fHMBWaveLen;
|
||||
/// <summary>
|
||||
/// 制导站批号
|
||||
/// </summary>
|
||||
public double nZDZID;
|
||||
/// <summary>
|
||||
/// 架束仪位置x
|
||||
/// </summary>
|
||||
public double fZDZX;
|
||||
/// <summary>
|
||||
/// 架束仪位置Y
|
||||
/// </summary>
|
||||
public double fZDZY;
|
||||
/// <summary>
|
||||
/// 架束仪位置Z
|
||||
/// </summary>
|
||||
public double fZDZZ;
|
||||
/// <summary>
|
||||
/// 制导站辐射激光能量
|
||||
/// </summary>
|
||||
public double fZDZJGPower;
|
||||
/// <summary>
|
||||
/// 制导站辐射激光波长
|
||||
/// </summary>
|
||||
public double fZDZJGWaveLen;
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
public double nZDZCode;
|
||||
/// <summary>
|
||||
/// 脉冲重复频率
|
||||
/// </summary>
|
||||
public double fZDZReFre;
|
||||
/// <summary>
|
||||
/// 脉宽
|
||||
/// </summary>
|
||||
public double fZDZPulse;
|
||||
/// <summary>
|
||||
/// 末敏弹状态 1:母弹,2:子弹,3:子弹扫描状态
|
||||
/// </summary>
|
||||
public double nMMDState;
|
||||
/// <summary>
|
||||
/// 子弹数量
|
||||
/// </summary>
|
||||
public double nSubNum;
|
||||
/// <summary>
|
||||
/// 子弹1批号
|
||||
/// </summary>
|
||||
public double nSub1ID;
|
||||
/// <summary>
|
||||
/// 子弹1坐标X
|
||||
/// </summary>
|
||||
public double fSub1X;
|
||||
// 子弹1坐标Y
|
||||
public double fSub1Y;
|
||||
/// <summary>
|
||||
/// 子弹1坐标Z
|
||||
/// </summary>
|
||||
public double fSub1Z;
|
||||
/// <summary>
|
||||
/// 子弹1辐射毫米波能量
|
||||
/// </summary>
|
||||
public double fSub1HMBPower;
|
||||
/// <summary>
|
||||
/// 子弹1辐射毫米波波长
|
||||
/// </summary>
|
||||
public double fSub1HMBWaveLen;
|
||||
/// <summary>
|
||||
/// 子弹1扫描坐标X
|
||||
/// </summary>
|
||||
public double fSub1ScanX;
|
||||
/// <summary>
|
||||
/// 子弹1扫描坐标Y
|
||||
/// </summary>
|
||||
public double fSub1ScanY;
|
||||
/// <summary>
|
||||
/// 子弹1扫描坐标Z
|
||||
/// </summary>
|
||||
public double fSub1ScanZ;
|
||||
/// <summary>
|
||||
/// 防护手段 1:激光致盲;2:激光诱骗;3:红外干扰;4:红外诱骗;5:毫米波干扰;6:毫米波补偿;7:烟幕防护;8:致盲制导站
|
||||
/// </summary>
|
||||
public double nDisType;
|
||||
/// <summary>
|
||||
/// 0代表失败 1代表成功
|
||||
/// </summary>
|
||||
public double nDisRes;
|
||||
/// <summary>
|
||||
/// 后续进一步处理
|
||||
/// </summary>
|
||||
public double k1;
|
||||
/// <summary>
|
||||
/// 弹道偏角和倾角改变角度当亲步骤数
|
||||
/// </summary>
|
||||
public int Xi;
|
||||
|
||||
public int JG_GR_success;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 炮弹状态标志,0:正常,1:炸毁目标,2:自爆
|
||||
/// </summary>
|
||||
public int bombFlag;
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// 激光诱骗假目标X坐标
|
||||
///// </summary>
|
||||
//public double fFalseX;
|
||||
///// <summary>
|
||||
///// 激光诱骗假目标Y坐标
|
||||
///// </summary>
|
||||
//public double fFalseY;
|
||||
///// <summary>
|
||||
///// 激光诱骗假目标Z坐标
|
||||
///// </summary>
|
||||
//public double fFalseZ;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
168
Models/MissileStageStrategy.cs
Normal file
168
Models/MissileStageStrategy.cs
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 导弹飞行阶段枚举
|
||||
/// </summary>
|
||||
public enum FlightStage
|
||||
{
|
||||
Launch, // 发射阶段
|
||||
Acceleration, // 加速阶段
|
||||
Cruise, // 巡航阶段
|
||||
TerminalGuidance, // 终端制导阶段
|
||||
Attack, // 攻击阶段
|
||||
Explosion, // 爆炸阶段
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹飞行阶段策略接口
|
||||
/// </summary>
|
||||
public interface IMissileStageStrategy
|
||||
{
|
||||
void Update(double deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发射阶段策略
|
||||
/// </summary>
|
||||
public class LaunchStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
private double launchTime = 0;
|
||||
|
||||
public LaunchStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
launchTime += deltaTime;
|
||||
if (launchTime >= MissileBase.LAUNCH_DURATION || missile.Speed >= missile.MaxSpeed * 0.1)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.Acceleration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// 加速阶段策略
|
||||
/// </summary>
|
||||
public class AccelerationStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
|
||||
public AccelerationStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (missile.EngineBurnTime >= missile.MaxEngineBurnTime || missile.Speed >= missile.MaxSpeed)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.Cruise);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 巡航阶段策略
|
||||
/// </summary>
|
||||
public class CruiseStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
|
||||
public CruiseStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.TerminalGuidance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 终端制导阶段策略
|
||||
/// </summary>
|
||||
public class TerminalGuidanceStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
|
||||
public TerminalGuidanceStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.Attack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 攻击阶段策略
|
||||
/// </summary>
|
||||
public class AttackStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
|
||||
public AttackStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (missile.DistanceToTarget <= missile.DistanceParams.ExplosionDistance)
|
||||
{
|
||||
missile.Explode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无制导阶段策略
|
||||
/// </summary>
|
||||
public class UnguidedStageStrategy : IMissileStageStrategy
|
||||
{
|
||||
private readonly MissileBase missile;
|
||||
|
||||
public UnguidedStageStrategy(MissileBase missile)
|
||||
{
|
||||
this.missile = missile;
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
// 检查是否重新获得引导
|
||||
if (missile.HasGuidance)
|
||||
{
|
||||
Console.WriteLine($"导弹 {missile.Id} 重新获得引导,退出无制导阶段");
|
||||
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.Attack);
|
||||
}
|
||||
else if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
|
||||
{
|
||||
missile.ChangeStage(FlightStage.TerminalGuidance);
|
||||
}
|
||||
else
|
||||
{
|
||||
missile.ChangeStage(FlightStage.Cruise);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
100
Models/Tank.cs
Normal file
100
Models/Tank.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// 表示仿真中的坦克
|
||||
/// </summary>
|
||||
public class Tank : SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前速度(米/秒)
|
||||
/// </summary>
|
||||
public double Speed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大速度(米/秒)
|
||||
/// </summary>
|
||||
public double MaxSpeed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大装甲值
|
||||
/// </summary>
|
||||
public double MaxArmor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前装甲值
|
||||
/// </summary>
|
||||
public double CurrentArmor { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">坦克ID</param>
|
||||
/// <param name="tankConfig">坦克配置</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
public Tank(string id, TankConfig tankConfig, ISimulationManager simulationManager)
|
||||
: base(id, tankConfig.InitialPosition, tankConfig.InitialOrientation, simulationManager)
|
||||
{
|
||||
Speed = tankConfig.InitialSpeed;
|
||||
MaxSpeed = tankConfig.MaxSpeed;
|
||||
MaxArmor = tankConfig.MaxArmor;
|
||||
CurrentArmor = tankConfig.MaxArmor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新坦克状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长(秒)</param>
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
UpdatePosition(deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新坦克位置
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长(秒)</param>
|
||||
private void UpdatePosition(double deltaTime)
|
||||
{
|
||||
Vector3D direction = Orientation.ToVector();
|
||||
Vector3D movement = direction * Speed * deltaTime;
|
||||
Position += movement;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 坦克受到伤害
|
||||
/// </summary>
|
||||
/// <param name="damage">伤害值</param>
|
||||
/// <param name="isMissileDamage">是否为导弹造成的伤害</param>
|
||||
public void TakeDamage(double damage, bool isMissileDamage = false)
|
||||
{
|
||||
if (isMissileDamage)
|
||||
{
|
||||
damage = CurrentArmor * 0.5;
|
||||
}
|
||||
|
||||
CurrentArmor = Math.Max(0, CurrentArmor - damage);
|
||||
if (CurrentArmor <= 0)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取坦克状态信息
|
||||
/// </summary>
|
||||
/// <returns>坦克状态字符串</returns>
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"坦克 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 速度: {Speed:F2}/{MaxSpeed:F2}\n" +
|
||||
$" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" +
|
||||
$" 状态: {(IsActive ? "活动" : "已销毁")}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Program.cs
Normal file
138
Program.cs
Normal file
@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using ActiveProtect.Models;
|
||||
using Model;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ActiveProtect
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
TankInfo tankinfo = new()
|
||||
{
|
||||
xp = 100,
|
||||
yp = 0,
|
||||
zp = 100
|
||||
};
|
||||
|
||||
MIniInfo mIniInfo = new()
|
||||
{
|
||||
xm = 1500,
|
||||
ym = 200,
|
||||
zm = 100,
|
||||
psi_m = Math.PI,
|
||||
theta_m = -0.1,
|
||||
vm = 0
|
||||
};
|
||||
|
||||
// 创建仿真配置
|
||||
var config = new SimulationConfig
|
||||
{
|
||||
// 配置坦克
|
||||
TankConfigs = new List<TankConfig>
|
||||
{
|
||||
new TankConfig(tankinfo)
|
||||
{
|
||||
InitialOrientation = new Orientation(Math.PI/4, 0, 0),
|
||||
InitialSpeed = 15,
|
||||
MaxSpeed = 20,
|
||||
MaxArmor = 100,
|
||||
HasLaserWarner = false,
|
||||
HasLaserJammer = true
|
||||
}
|
||||
},
|
||||
// 配置激光指示器
|
||||
LaserDesignatorConfig = new LaserDesignatorConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(2000, 150, 100),
|
||||
LaserPower = 1e6,
|
||||
LaserDivergenceAngle = 0.01
|
||||
},
|
||||
// 配置激光告警器
|
||||
LaserWarnerConfig = new LaserWarnerConfig
|
||||
{
|
||||
AlarmDuration = 5.0
|
||||
},
|
||||
// 配置激光干扰器
|
||||
LaserJammerConfig = new LaserJammerConfig
|
||||
{
|
||||
MaxJammingCooldown = 5.0,
|
||||
MaxJammingPower = 10000.0,
|
||||
InitialJammingPower = 4000.0,
|
||||
PowerIncreaseRate = 2000.0
|
||||
},
|
||||
// 配置激光驾束仪
|
||||
LaserBeamRiderConfig = new LaserBeamRiderConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(2000, 10, 100),
|
||||
LaserPower = 1000,
|
||||
ControlFieldDiameter = 6
|
||||
},
|
||||
// 配置导弹
|
||||
MissileConfigs = new List<MissileConfig>
|
||||
{
|
||||
// 激光半主动制导导弹配置
|
||||
new MissileConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(2000, 100, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, -0.1, 0),
|
||||
InitialSpeed = 700,
|
||||
MaxSpeed = 800,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0.05,
|
||||
MaxFlightDistance = 5000,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 10,
|
||||
MaxAcceleration = 400,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile,
|
||||
DistanceParams = new MissileDistanceParams(500, 200, 20),
|
||||
Mass = 50,
|
||||
Type = MissileType.LaserSemiActiveGuidance
|
||||
},
|
||||
// 激光驾束制导导弹配置
|
||||
new MissileConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(2000, 10, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, 0.1, 0.0),
|
||||
InitialSpeed = 300,
|
||||
MaxSpeed = 400,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0.05,
|
||||
MaxFlightDistance = 3000,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 10,
|
||||
MaxAcceleration = 400,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = FlightStageConfig.LaserBeamRiderGuidance,
|
||||
DistanceParams = new MissileDistanceParams(500, 200, 10),
|
||||
Mass = 50,
|
||||
Type = MissileType.LaserBeamRiderGuidance
|
||||
}
|
||||
},
|
||||
|
||||
SimulationTimeStep = 0.025
|
||||
};
|
||||
|
||||
// 创建仿真管理器
|
||||
var simulationManager = new SimulationManager(config);
|
||||
|
||||
// 运行仿真
|
||||
int maxIterations = 1000;
|
||||
int iteration = 0;
|
||||
while (!simulationManager.IsSimulationEnded && iteration < maxIterations)
|
||||
{
|
||||
simulationManager.Update();
|
||||
simulationManager.PrintStatus();
|
||||
Thread.Sleep(100); // 暂停100毫秒,使输出更易读
|
||||
iteration++;
|
||||
}
|
||||
|
||||
Console.WriteLine("仿真结束");
|
||||
}
|
||||
}
|
||||
}
|
||||
171
README.md
Normal file
171
README.md
Normal file
@ -0,0 +1,171 @@
|
||||
# ActiveProtect 仿真系统
|
||||
|
||||
ActiveProtect 是一个用于模拟激光制导导弹和防御系统的仿真环境。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 激光半主动制导导弹仿真
|
||||
- 激光驾束制导导弹仿真
|
||||
- 坦克和激光告警器仿真
|
||||
- 激光干扰器仿真
|
||||
- 可扩展的仿真框架
|
||||
|
||||
## Unity 兼容性
|
||||
|
||||
本项目设计时考虑了与 Unity 游戏引擎的兼容性, 使用C# 9.0 语法。以下是在 Unity 中使用本项目的注意事项:
|
||||
|
||||
1. 向量和数学运算:本项目使用自定义的 `Vector3D` 类。在 Unity 中,您可以将其替换为 Unity 的 `Vector3` 类。
|
||||
|
||||
2. 仿真更新:Unity 使用 `MonoBehaviour` 的 `Update` 方法进行每帧更新。您可以创建一个 `SimulationManager` 脚本,并在其 `Update` 方法中调用仿真系统的更新逻辑。
|
||||
|
||||
3. 可视化:Unity 提供了强大的 3D 渲染能力。您可以为每个仿真元素(如导弹、坦克等)创建相应的 Unity 游戏对象,并在每帧更新其位置和旋转。
|
||||
|
||||
4. 输入处理:将键盘/鼠标输入处理逻辑替换为 Unity 的输入系统(如 `Input.GetKey()` 等)。
|
||||
|
||||
5. 协程:Unity 支持协程,可用于实现某些异步操作或时间相关的功能。
|
||||
|
||||
6. 物理系统:如果需要更复杂的物理模拟,可以考虑使用 Unity 的物理引擎替代当前的简化物理模型。
|
||||
|
||||
7. 事件系统:Unity 有自己的事件系统,您可能需要调整当前的事件处理机制以更好地与 Unity 集成。
|
||||
|
||||
8. 性能优化:在 Unity 中,您可以使用 Unity Profiler 来监控和优化性能。
|
||||
|
||||
通过这些调整,您应该能够将 ActiveProtect 仿真系统顺利集成到 Unity 项目中,从而获得更好的可视化效果和交互体验。
|
||||
|
||||
## 使用说明
|
||||
|
||||
1. 克隆仓库到本地
|
||||
2. 使用 Visual Studio 或其他 C# IDE 打开解决方案
|
||||
3. 编译并运行项目
|
||||
|
||||
## 贡献指南
|
||||
|
||||
欢迎提交 Pull Requests 来改进这个项目。在提交之前,请确保您的代码符合项目的编码规范,并且通过了所有的单元测试。
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目采用 MIT 许可证。详情请见 [LICENSE](LICENSE) 文件。
|
||||
|
||||
## 仿真运行流程(这个 Mermaid 图表会在支持 Mermaid 的 Markdown 查看器中渲染为一个流程图)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[开始仿真] --> B[初始化SimulationManager]
|
||||
B --> C[加载SimulationConfig]
|
||||
C --> D[创建仿真元素]
|
||||
D --> E[开始仿真循环]
|
||||
E --> F{是否结束仿真?}
|
||||
F -->|否| G[更新所有元素]
|
||||
G --> H[收集数据]
|
||||
H --> I[处理事件]
|
||||
I --> E
|
||||
F -->|是| J[结束仿真]
|
||||
J --> K[评估结果]
|
||||
K --> L[生成报告]
|
||||
L --> M[结束]
|
||||
```
|
||||
|
||||
## 反坦克导弹仿真系统
|
||||
|
||||
本项目旨在模拟反坦克导弹的飞行过程和攻击效果。
|
||||
|
||||
### 反坦克导弹飞行阶段
|
||||
|
||||
反坦克导弹的飞行过程通常可以分为以下几个主要阶段:
|
||||
|
||||
1. 发射阶段
|
||||
- 导弹从发射装置或发射管中被推出
|
||||
- 火箭发动机点火,提供初始推力
|
||||
|
||||
2. 加速阶段
|
||||
- 导弹迅速加速到巡航速度
|
||||
- 可能会抛掉一些辅助推进装置(如有)
|
||||
|
||||
3. 巡航阶段
|
||||
- 导弹保持相对稳定的速度飞向<E9A39E><E59091>标
|
||||
- 根据导引系统类型,可能会进行中途修正
|
||||
|
||||
4. 终端制导阶段
|
||||
- 导弹接近目标,进入最后的制导阶段
|
||||
- 可能会启动终端制导系统,如毫米波雷达或红外成像系统
|
||||
|
||||
5. 攻击阶段
|
||||
- 导弹进行最后的机动,以最佳角度接近目标
|
||||
- 可能会启动穿甲弹头或预制破片
|
||||
|
||||
6. 爆炸阶段
|
||||
- 导弹击中目标并引爆
|
||||
- 根据弹头类型,可能是穿甲、破片或破片-燃烧等效果
|
||||
|
||||
在仿真中,这些阶段被纳入计算,每个阶段可能有不同的物理特性和行为模式。例如,加速阶段可能有较大的加速度,而巡航阶段则保持恒定速度。终端制导阶段可能会有更频繁的方向调整。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```csharp
|
||||
ActiveProtect/
|
||||
│
|
||||
├── Models/ # 仿真模型目录
|
||||
│ ├── BasicGuidanceSystem.cs # 基础制导系统类
|
||||
│ ├── ILaserIlluminatable.cs # 可被激光照射的接口定义
|
||||
│ ├── LaserBeamRider.cs # 激光驾束仪类
|
||||
│ ├── LaserBeamRiderGuidanceSystem.cs # 激光驾束制导系统类
|
||||
│ ├── LaserBeamRiderMissile.cs # 激光驾束导弹类
|
||||
│ ├── LaserDesignator.cs # 激光指示器类
|
||||
│ ├── LaserJammer.cs # 激光干扰器类
|
||||
│ ├── LaserSemiActiveGuidedMissile.cs # 激光半主动制导导弹类
|
||||
│ ├── LaserWarner.cs # 激光告警器类
|
||||
│ ├── MissileClass.cs # 导弹基类
|
||||
│ └── Tank.cs # 坦克模型类
|
||||
│
|
||||
├── SimulationEnvironment/ # 仿真环境目录
|
||||
│ ├── SimulationConfig.cs # 仿真配置类
|
||||
│ ├── SimulationElement.cs # 仿真元素基类
|
||||
│ ├── SimulationEvents.cs # 仿真事件定义类
|
||||
│ └── SimulationManager.cs # 仿真管理器类
|
||||
│
|
||||
├── Program.cs # 程序入口点
|
||||
├── README.md # 项目说明文档
|
||||
└── Design.md # 设计文档
|
||||
```
|
||||
|
||||
## 如何运行
|
||||
|
||||
1. 确保你的系统已安装 .NET 6.0。
|
||||
2. 在终端中导航到项目根目录。
|
||||
3. 运行以下命令来构建项目:
|
||||
|
||||
```shell
|
||||
dotnet build
|
||||
```
|
||||
|
||||
4. 运行以下命令来启动仿真:
|
||||
|
||||
```shell
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 当前仿真使用简化模型,可能无法完全反映真实世界的复杂性。
|
||||
- 仿真结果仅供参考,不应用于实际军事决策。
|
||||
|
||||
## 比例导引系数(N)的选择
|
||||
|
||||
在导弹制导系统中,比例导引系数(N)是一个关键参数,它直接影响导弹的性能和行为。在我们的仿真系统中,用户可以根据不同的场景需求调整这个参数。
|
||||
|
||||
### N 值的影响
|
||||
|
||||
- **N = 3**:这是一个较为保守的选择,适合大多数情况。它提供了良好的稳定性和能源效率,但可能在应对高机动性目标时表现不佳。
|
||||
- **N = 4**:这个值提供了更积极的制导,适合需要更高机动性的场景。它能更快地响应目标的变化,但可能会增加能源消耗。
|
||||
- **N = 5**:这是一个更激进的选择,提供最高的机动性,但也带来了更大的能源消耗和可能的过度修正。
|
||||
|
||||
### 选择 N 值的考虑因素
|
||||
|
||||
1. **导弹类型**:大型、长程导弹通常使用较小的 N 值,而小型、短程导弹可以使用较大的 N 值。
|
||||
2. **目标特性**:对付高速、高机动性目标时,可能需要较大的 N 值。
|
||||
3. **作战环境**:在复杂环境中,可能需要更大的 N 值来应对突发情况。
|
||||
4. **能源限制**:如果导弹燃料有限,较小的 N 值可以帮助节省能源。
|
||||
5. **制导系统精度**:精度较高的系统可以使用较小的 N 值,而精度较低的系统可能需要较大的 N 值来补偿误差。
|
||||
6. **任务要求**:精确打击任务可能需要较大的 N 值,而区域防御任务可能使用较小的 N 值。
|
||||
|
||||
在我们的仿真系统中,用户可以通过调整 `ProportionalNavigationCoefficient` 参数来设置不同的 N 值,以模拟各种实际情况下的导弹行为。我们建议用户尝试不同的 N 值,观察其对导弹性能的影响,以找到最适合特定场景的设置。
|
||||
474
SimulationEnvironment/SimulationConfig.cs
Normal file
474
SimulationEnvironment/SimulationConfig.cs
Normal file
@ -0,0 +1,474 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using ActiveProtect.Models;
|
||||
using Model;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真配置类,包含整个仿真所需的所有配置信息
|
||||
/// </summary>
|
||||
public class SimulationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 坦克配置列表
|
||||
/// </summary>
|
||||
public List<TankConfig> TankConfigs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹配置列表
|
||||
/// </summary>
|
||||
public List<MissileConfig> MissileConfigs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光指示器配置列表
|
||||
/// </summary>
|
||||
public LaserDesignatorConfig LaserDesignatorConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光驾束仪配置列表
|
||||
/// </summary>
|
||||
public LaserBeamRiderConfig LaserBeamRiderConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光告警器配置
|
||||
/// </summary>
|
||||
public LaserWarnerConfig LaserWarnerConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光干扰器配置
|
||||
/// </summary>
|
||||
public LaserJammerConfig LaserJammerConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真时间步长(秒)
|
||||
/// </summary>
|
||||
public double SimulationTimeStep { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,初始化默认配置
|
||||
/// </summary>
|
||||
public SimulationConfig()
|
||||
{
|
||||
TankConfigs = new List<TankConfig>();
|
||||
MissileConfigs = new List<MissileConfig>();
|
||||
LaserDesignatorConfig = new LaserDesignatorConfig();
|
||||
LaserBeamRiderConfig = new LaserBeamRiderConfig();
|
||||
LaserWarnerConfig = new LaserWarnerConfig();
|
||||
LaserJammerConfig = new LaserJammerConfig();
|
||||
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 坦克配置类
|
||||
/// </summary>
|
||||
public class TankConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始位置
|
||||
/// </summary>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始朝向
|
||||
/// </summary>
|
||||
public Orientation InitialOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始速度(米/秒)
|
||||
/// </summary>
|
||||
public double InitialSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大速度(米/秒)
|
||||
/// </summary>
|
||||
public double MaxSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大装甲值
|
||||
/// </summary>
|
||||
public double MaxArmor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否装备激光告警器
|
||||
/// </summary>
|
||||
public bool HasLaserWarner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否装备激光干扰器
|
||||
/// </summary>
|
||||
public bool HasLaserJammer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public TankConfig()
|
||||
{
|
||||
SetDefaultValues();
|
||||
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
InitialOrientation = new Orientation(0, 0, 0);
|
||||
}
|
||||
|
||||
public TankConfig(TankInfo tankInfo){
|
||||
SetDefaultValues();
|
||||
|
||||
InitialPosition = new Vector3D(tankInfo.xp, tankInfo.yp, tankInfo.zp);
|
||||
InitialOrientation = new Orientation(0, 0, 0);
|
||||
}
|
||||
|
||||
public void SetDefaultValues(){
|
||||
InitialSpeed = 0;
|
||||
MaxSpeed = 0;
|
||||
MaxArmor = 0;
|
||||
HasLaserWarner = false;
|
||||
HasLaserJammer = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹配置类
|
||||
/// </summary>
|
||||
public class MissileConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始位置
|
||||
/// </summary>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始朝向
|
||||
/// </summary>
|
||||
public Orientation InitialOrientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始速度(米/秒)
|
||||
/// </summary>
|
||||
public double InitialSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大速度(米/秒)
|
||||
/// </summary>
|
||||
public double MaxSpeed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标索引
|
||||
/// </summary>
|
||||
public int TargetIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大飞行时间(秒)
|
||||
/// </summary>
|
||||
public double MaxFlightTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大飞行距离(米)
|
||||
/// </summary>
|
||||
public double MaxFlightDistance { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大加速度(米/秒²)
|
||||
/// </summary>
|
||||
public double MaxAcceleration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 比例导引系数
|
||||
/// </summary>
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 飞行阶段配置
|
||||
/// </summary>
|
||||
public FlightStageConfig StageConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 距离参数
|
||||
/// </summary>
|
||||
public MissileDistanceParams DistanceParams { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 推力加速度(米/秒²)
|
||||
/// </summary>
|
||||
public double ThrustAcceleration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大发动机燃烧时间(秒)
|
||||
/// </summary>
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹质量(千克)
|
||||
/// </summary>
|
||||
public double Mass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹类型
|
||||
/// </summary>
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public MissileConfig()
|
||||
{
|
||||
SetDefaultValues();
|
||||
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
InitialOrientation = new Orientation(0, 0, 0);
|
||||
}
|
||||
|
||||
public MissileConfig(MIniInfo mIniInfo){
|
||||
SetDefaultValues();
|
||||
|
||||
InitialPosition = new Vector3D(mIniInfo.xm, mIniInfo.ym, mIniInfo.zm);
|
||||
InitialOrientation = new Orientation(mIniInfo.psi_m, mIniInfo.theta_m, 0);
|
||||
InitialSpeed = mIniInfo.vm;
|
||||
}
|
||||
|
||||
public void SetDefaultValues(){
|
||||
InitialSpeed = 0;
|
||||
MaxSpeed = 0;
|
||||
TargetIndex = 0;
|
||||
MaxFlightTime = 0;
|
||||
MaxFlightDistance = 0;
|
||||
StageConfig = FlightStageConfig.StandardMissile;
|
||||
ThrustAcceleration = 0;
|
||||
MaxEngineBurnTime = 0;
|
||||
MaxAcceleration = 0;
|
||||
DistanceParams = new MissileDistanceParams(0, 0, 0);
|
||||
ProportionalNavigationCoefficient = 0;
|
||||
Type = MissileType.StandardMissile;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光指示器配置类
|
||||
/// </summary>
|
||||
public class LaserDesignatorConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始位置
|
||||
/// </summary>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光功率(瓦特)
|
||||
/// </summary>
|
||||
public double LaserPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光发散角
|
||||
/// </summary>
|
||||
public double LaserDivergenceAngle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public LaserDesignatorConfig()
|
||||
{
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
LaserPower = 0;
|
||||
LaserDivergenceAngle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光驾束仪配置类
|
||||
/// </summary>
|
||||
public class LaserBeamRiderConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始位置
|
||||
/// </summary>
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 激光功率(瓦特)
|
||||
/// </summary>
|
||||
public double LaserPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 控制场直径(米)
|
||||
/// </summary>
|
||||
public double ControlFieldDiameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大导引距离(米)
|
||||
/// </summary>
|
||||
public double MaxGuidanceDistance { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public LaserBeamRiderConfig()
|
||||
{
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
LaserPower = 0;
|
||||
ControlFieldDiameter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹类型枚举
|
||||
/// </summary>
|
||||
public enum MissileType
|
||||
{
|
||||
StandardMissile, // 标准导弹
|
||||
LaserSemiActiveGuidance, // 激光半主动制导
|
||||
LaserBeamRiderGuidance, // 激光驾束制导
|
||||
InfraredCommandGuidance, // 红外指令制导
|
||||
InfraredImagingTerminalGuidance, // 红外成像末制导
|
||||
MillimeterWaveTerminalGuidance // 毫米波末制导
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹距离参数结构
|
||||
/// </summary>
|
||||
public struct MissileDistanceParams
|
||||
{
|
||||
/// <summary>
|
||||
/// 终端制导距离(米)
|
||||
/// </summary>
|
||||
public double TerminalGuidanceDistance;
|
||||
/// <summary>
|
||||
/// 攻击距离(米)
|
||||
/// </summary>
|
||||
public double AttackDistance;
|
||||
/// <summary>
|
||||
/// 爆炸距离(米)
|
||||
/// </summary>
|
||||
public double ExplosionDistance;
|
||||
|
||||
public MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance)
|
||||
{
|
||||
TerminalGuidanceDistance = terminalGuidanceDistance;
|
||||
AttackDistance = attackDistance;
|
||||
ExplosionDistance = explosionDistance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// 导弹飞行阶段配置结构
|
||||
/// </summary>
|
||||
public struct FlightStageConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 启用发射阶段
|
||||
/// </summary>
|
||||
public bool EnableLaunch;
|
||||
/// <summary>
|
||||
/// 启用加速阶段
|
||||
/// </summary>
|
||||
public bool EnableAcceleration;
|
||||
/// <summary>
|
||||
/// 启用巡航阶段
|
||||
/// </summary>
|
||||
public bool EnableCruise;
|
||||
/// <summary>
|
||||
/// 启用终端制导阶段
|
||||
/// </summary>
|
||||
public bool EnableTerminalGuidance;
|
||||
/// <summary>
|
||||
/// 启用攻击阶段
|
||||
/// </summary>
|
||||
public bool EnableAttack;
|
||||
|
||||
/// <summary>
|
||||
/// 标准导弹的预设配置, 所有阶段都启用
|
||||
/// </summary>
|
||||
public static FlightStageConfig StandardMissile => new(true, true, true, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(true, false, true, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光驾束制导导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserBeamRiderGuidance => new(true, true, false, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 红外指令制导导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig InfraredCommandGuidance => new(true, true, false, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 红外成像末制导导弹的预设配置
|
||||
/// </summary>
|
||||
public static FlightStageConfig InfraredImagingTerminalGuidance => new(true, true, true, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 毫米波末制导导弹的预设配置
|
||||
/// </summary>
|
||||
public static FlightStageConfig MillimeterWaveTerminalGuidance => new(true, true, true, true, true);
|
||||
|
||||
public FlightStageConfig(bool enableLaunch, bool enableAcceleration, bool enableCruise, bool enableTerminalGuidance, bool enableAttack)
|
||||
{
|
||||
EnableLaunch = enableLaunch;
|
||||
EnableAcceleration = enableAcceleration;
|
||||
EnableCruise = enableCruise;
|
||||
EnableTerminalGuidance = enableTerminalGuidance;
|
||||
EnableAttack = enableAttack;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光告警器配置类
|
||||
/// </summary>
|
||||
public class LaserWarnerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 警报持续时间(秒)
|
||||
/// </summary>
|
||||
public double AlarmDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public LaserWarnerConfig()
|
||||
{
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光干扰器配置类
|
||||
/// </summary>
|
||||
public class LaserJammerConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大干扰冷却时间(秒)
|
||||
/// </summary>
|
||||
public double MaxJammingCooldown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最大干扰功率(瓦特)
|
||||
/// </summary>
|
||||
public double MaxJammingPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 初始干扰功率(瓦特)
|
||||
/// </summary>
|
||||
public double InitialJammingPower { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 功率增加速率(瓦特/秒)
|
||||
/// </summary>
|
||||
public double PowerIncreaseRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数,设置默认值
|
||||
/// </summary>
|
||||
public LaserJammerConfig()
|
||||
{
|
||||
MaxJammingCooldown = 5.0;
|
||||
MaxJammingPower = 10000.0;
|
||||
InitialJammingPower = 4000.0;
|
||||
PowerIncreaseRate = 2000.0; // 每秒增加的功率
|
||||
}
|
||||
}
|
||||
}
|
||||
101
SimulationEnvironment/SimulationElement.cs
Normal file
101
SimulationEnvironment/SimulationElement.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using ActiveProtect.Models;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真元素的抽象基类,所有仿真中的实体都继承自此类
|
||||
/// </summary>
|
||||
public abstract class SimulationElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真元素的唯一标识符
|
||||
/// </summary>
|
||||
public virtual string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真元素的当前位置
|
||||
/// </summary>
|
||||
public virtual Vector3D Position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真元素的当前速度
|
||||
/// </summary>
|
||||
public virtual Vector3D Velocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真元素的当前朝向
|
||||
/// </summary>
|
||||
public virtual Orientation Orientation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真元素是否处于活动状态
|
||||
/// </summary>
|
||||
public virtual bool IsActive { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真管理器的引用
|
||||
/// </summary>
|
||||
public ISimulationManager SimulationManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="id">仿真元素的唯一标识符</param>
|
||||
/// <param name="position">初始位置</param>
|
||||
/// <param name="orientation">初始朝向</param>
|
||||
/// <param name="simulationManager">仿真管理器</param>
|
||||
protected SimulationElement(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager)
|
||||
{
|
||||
Id = id;
|
||||
Position = position;
|
||||
Orientation = orientation;
|
||||
SimulationManager = simulationManager;
|
||||
Velocity = Vector3D.Zero;
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新仿真元素的状态
|
||||
/// </summary>
|
||||
/// <param name="deltaTime">时间步长</param>
|
||||
public abstract void Update(double deltaTime);
|
||||
|
||||
/// <summary>
|
||||
/// 获取仿真元素的状态信息
|
||||
/// </summary>
|
||||
/// <returns>状态信息字符串</returns>
|
||||
public virtual string GetStatus()
|
||||
{
|
||||
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布仿真事件
|
||||
/// </summary>
|
||||
/// <param name="evt">要发布的事件</param>
|
||||
protected void PublishEvent(SimulationEvent evt)
|
||||
{
|
||||
evt.SenderId = Id;
|
||||
evt.Timestamp = SimulationManager.CurrentTime;
|
||||
SimulationManager.PublishEvent(evt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活仿真元素
|
||||
/// </summary>
|
||||
public virtual void Activate()
|
||||
{
|
||||
IsActive = true;
|
||||
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停用仿真元素
|
||||
/// </summary>
|
||||
public virtual void Deactivate()
|
||||
{
|
||||
IsActive = false;
|
||||
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
171
SimulationEnvironment/SimulationEvents.cs
Normal file
171
SimulationEnvironment/SimulationEvents.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using ActiveProtect.Models;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真事件的基类
|
||||
/// </summary>
|
||||
public class SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件发送者的ID
|
||||
/// </summary>
|
||||
public string? SenderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 事件发生的时间戳
|
||||
/// </summary>
|
||||
public double Timestamp { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹发射事件
|
||||
/// </summary>
|
||||
public class MissileFireEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光照射事件
|
||||
/// </summary>
|
||||
public class LaserIlluminationStartEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光定位器
|
||||
/// </summary>
|
||||
public LaserDesignator? LaserDesignator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标元素
|
||||
/// </summary>
|
||||
public SimulationElement? Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary
|
||||
/// <summary>
|
||||
/// 激光照射更新事件
|
||||
/// </summary>
|
||||
public class LaserIlluminationUpdateEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 激光定位器
|
||||
/// </summary>
|
||||
public LaserDesignator? LaserDesignator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标元素
|
||||
/// </summary>
|
||||
public SimulationElement? Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary
|
||||
/// 激光照射停止事件
|
||||
/// </summary>
|
||||
public class LaserIlluminationStopEvent : SimulationEvent
|
||||
{
|
||||
public LaserDesignator? LaserDesignator { get; set; }
|
||||
public SimulationElement? Target { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光干扰事件
|
||||
/// </summary>
|
||||
public class LaserJammingEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string? TargetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 干扰功率
|
||||
/// </summary>
|
||||
public double JammingPower { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体销毁事件
|
||||
/// </summary>
|
||||
public class EntityDestroyedEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 被销毁实体的ID
|
||||
/// </summary>
|
||||
public string? DestroyedEntityId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 激光告警器警报事件
|
||||
/// </summary>
|
||||
public class LaserWarnerAlarmEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光告警器警报停止事件
|
||||
/// </summary>
|
||||
public class LaserWarnerAlarmStopEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 目标ID
|
||||
/// </summary>
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体激活事件
|
||||
/// </summary>
|
||||
public class EntityActivatedEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 被激活实体的ID
|
||||
/// </summary>
|
||||
public string? ActivatedEntityId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实体停用事件
|
||||
/// </summary>
|
||||
public class EntityDeactivatedEvent : SimulationEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// 被停用实体的ID
|
||||
/// </summary>
|
||||
public string? DeactivatedEntityId { get; set; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 激光开始事件
|
||||
/// </summary>
|
||||
public class LaserBeamStartEvent : SimulationEvent
|
||||
{
|
||||
public LaserBeamRider? LaserBeamRider { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光更新事件
|
||||
/// </summary>
|
||||
public class LaserBeamUpdateEvent : SimulationEvent
|
||||
{
|
||||
public LaserBeamRider? LaserBeamRider { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激光停止事件
|
||||
/// </summary>
|
||||
public class LaserBeamStopEvent : SimulationEvent
|
||||
{
|
||||
public LaserBeamRider? LaserBeamRider { get; set; }
|
||||
}
|
||||
}
|
||||
399
SimulationEnvironment/SimulationManager.cs
Normal file
399
SimulationEnvironment/SimulationManager.cs
Normal file
@ -0,0 +1,399 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ActiveProtect.Models;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真管理器接口,定义了仿真管理器的基本功能
|
||||
/// </summary>
|
||||
public interface ISimulationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前仿真时间
|
||||
/// </summary>
|
||||
double CurrentTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 添加仿真元素
|
||||
/// </summary>
|
||||
void AddElement(SimulationElement element);
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取仿真实体
|
||||
/// </summary>
|
||||
SimulationElement GetEntityById(string id);
|
||||
|
||||
/// <summary>
|
||||
/// 处理目标被击中事件
|
||||
/// </summary>
|
||||
void HandleTargetHit(string targetId, string missileId);
|
||||
|
||||
/// <summary>
|
||||
/// 发布仿真事件
|
||||
/// </summary>
|
||||
void PublishEvent(SimulationEvent evt);
|
||||
|
||||
/// <summary>
|
||||
/// 订阅仿真事件
|
||||
/// </summary>
|
||||
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
|
||||
|
||||
/// <summary>
|
||||
/// 取消订阅仿真事件
|
||||
/// </summary>
|
||||
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
|
||||
|
||||
/// <summary>
|
||||
/// 取消所有事件订阅
|
||||
/// </summary>
|
||||
void UnsubscribeAllEvents(SimulationElement element);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 仿真管理器类,负责管理整个仿真过程
|
||||
/// </summary>
|
||||
public class SimulationManager : ISimulationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 仿真元素列表
|
||||
/// </summary>
|
||||
public List<SimulationElement> Elements { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前仿真时间
|
||||
/// </summary>
|
||||
public double CurrentTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 仿真是否结束
|
||||
/// </summary>
|
||||
public bool IsSimulationEnded { get; private set; }
|
||||
|
||||
private readonly SimulationConfig config;
|
||||
private Dictionary<Type, List<Delegate>> eventHandlers = new Dictionary<Type, List<Delegate>>();
|
||||
private Dictionary<SimulationElement, List<(Type, Delegate)>> elementSubscriptions = new Dictionary<SimulationElement, List<(Type, Delegate)>>();
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public SimulationManager(SimulationConfig config)
|
||||
{
|
||||
this.config = config;
|
||||
Elements = new List<SimulationElement>();
|
||||
CurrentTime = 0;
|
||||
IsSimulationEnded = false;
|
||||
InitializeSimulation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化仿真
|
||||
/// </summary>
|
||||
private void InitializeSimulation()
|
||||
{
|
||||
// 创建坦克
|
||||
for (int i = 0; i < config.TankConfigs.Count; i++)
|
||||
{
|
||||
var tankConfig = config.TankConfigs[i];
|
||||
var tank = new Tank($"Tank_{i + 1}", tankConfig, this);
|
||||
Elements.Add(tank);
|
||||
|
||||
// // 为坦克创建激光告警器
|
||||
// if (tankConfig.HasLaserWarner)
|
||||
// {
|
||||
// var laserWarner = new LaserWarner(
|
||||
// $"LaserWarner_{tank.Id}",
|
||||
// tank.Position,
|
||||
// tank.Orientation,
|
||||
// this,
|
||||
// tank.Id,
|
||||
// config.LaserWarnerConfig
|
||||
// );
|
||||
// Elements.Add(laserWarner);
|
||||
// }
|
||||
|
||||
// // 为坦克创建激光干扰机
|
||||
// if (tankConfig.HasLaserJammer)
|
||||
// {
|
||||
// var laserJammer = new LaserJammer(
|
||||
// $"LaserJammer_{tank.Id}",
|
||||
// tank.Position,
|
||||
// tank.Orientation,
|
||||
// this,
|
||||
// tank.Id,
|
||||
// config.LaserJammerConfig
|
||||
// );
|
||||
// Elements.Add(laserJammer);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 创建导弹
|
||||
for (int i = 0; i < config.MissileConfigs.Count; i++)
|
||||
{
|
||||
var missileConfig = config.MissileConfigs[i];
|
||||
|
||||
// 确保 MaxFlightTime 设置合理
|
||||
if (missileConfig.MaxFlightTime <= 0)
|
||||
{
|
||||
missileConfig.MaxFlightTime = 300; // 设置一个默认值,比如 300 秒
|
||||
Console.WriteLine($"警告:导弹配置 {i} 的 MaxFlightTime 无效,已设置为默认值 300 秒");
|
||||
}
|
||||
|
||||
MissileBase missile = missileConfig.Type switch
|
||||
{
|
||||
MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
|
||||
$"LSGM_{i + 1}",
|
||||
missileConfig,
|
||||
"LD_1",
|
||||
this
|
||||
),
|
||||
MissileType.LaserBeamRiderGuidance => new LaserBeamRiderMissile(
|
||||
$"LBRM_{i + 1}",
|
||||
"Tank_1",
|
||||
missileConfig,
|
||||
this
|
||||
),
|
||||
_ => new MissileBase(
|
||||
$"NM_{i + 1}",
|
||||
missileConfig,
|
||||
this
|
||||
),
|
||||
};
|
||||
Elements.Add(missile);
|
||||
}
|
||||
|
||||
// 创建激光目标指示器
|
||||
var laserDesignatorConfig = config.LaserDesignatorConfig;
|
||||
var laserDesignator = new LaserDesignator(
|
||||
$"LD_1",
|
||||
"Tank_1",
|
||||
"LSGM_1",
|
||||
laserDesignatorConfig,
|
||||
this
|
||||
);
|
||||
Elements.Add(laserDesignator);
|
||||
|
||||
// 创建激光驾束仪
|
||||
var laserBeamRiderConfig = config.LaserBeamRiderConfig;
|
||||
var laserBeamRider = new LaserBeamRider(
|
||||
"LBR_1",
|
||||
"LBRM_2",
|
||||
"Tank_1",
|
||||
laserBeamRiderConfig,
|
||||
this
|
||||
);
|
||||
Elements.Add(laserBeamRider);
|
||||
|
||||
|
||||
// 激活所有元素
|
||||
ActivateAllElements();
|
||||
|
||||
// 启动激光驾束仪
|
||||
laserBeamRider.StartBeamIllumination();
|
||||
}
|
||||
|
||||
//激活所有元素
|
||||
private void ActivateAllElements()
|
||||
{
|
||||
foreach (var element in Elements)
|
||||
{
|
||||
element.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发布仿真事件
|
||||
/// </summary>
|
||||
public void PublishEvent(SimulationEvent evt)
|
||||
{
|
||||
var eventType = evt.GetType();
|
||||
//Console.WriteLine($"发布事件: {eventType.Name}, 发送者: {evt.SenderId}");
|
||||
if (eventHandlers.TryGetValue(eventType, out var handlers))
|
||||
{
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
handler.DynamicInvoke(evt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"没有找到事件 {eventType.Name} 的处理程序");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 订阅仿真事件
|
||||
/// </summary>
|
||||
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
{
|
||||
var eventType = typeof(T);
|
||||
if (!eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
|
||||
{
|
||||
value = new List<Delegate>();
|
||||
eventHandlers[eventType] = value;
|
||||
}
|
||||
|
||||
value.Add(handler);
|
||||
|
||||
// 记录订阅关系
|
||||
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
||||
if (element != null)
|
||||
{
|
||||
if (!elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
|
||||
{
|
||||
subscriptions = new List<(Type, Delegate)>();
|
||||
elementSubscriptions[element] = subscriptions;
|
||||
}
|
||||
|
||||
subscriptions.Add((eventType, handler as Delegate));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消订阅仿真事件
|
||||
/// </summary>
|
||||
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
{
|
||||
var eventType = typeof(T);
|
||||
if (eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
|
||||
{
|
||||
value.Remove(handler);
|
||||
}
|
||||
|
||||
// 移除订阅关系记录
|
||||
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
||||
if (element != null && elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
|
||||
{
|
||||
subscriptions.RemoveAll(s => Delegate.Equals(s.Item2, handler));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消所有事件订阅
|
||||
/// </summary>
|
||||
public void UnsubscribeAllEvents(SimulationElement element)
|
||||
{
|
||||
if (elementSubscriptions.ContainsKey(element))
|
||||
{
|
||||
foreach (var subscription in elementSubscriptions[element])
|
||||
{
|
||||
if (eventHandlers.TryGetValue(subscription.Item1, out List<Delegate>? value))
|
||||
{
|
||||
value.Remove(subscription.Item2);
|
||||
}
|
||||
}
|
||||
elementSubscriptions.Remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新仿真状态
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
if (IsSimulationEnded) return;
|
||||
|
||||
CurrentTime += config.SimulationTimeStep;
|
||||
|
||||
foreach (var element in Elements.ToList())
|
||||
{
|
||||
if (element.IsActive)
|
||||
{
|
||||
element.Update(config.SimulationTimeStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnsubscribeAllEvents(element);
|
||||
}
|
||||
}
|
||||
|
||||
// 移除不活跃的元素
|
||||
Elements.RemoveAll(e => !e.IsActive);
|
||||
|
||||
// 检查是否所有导弹都结束飞行
|
||||
if (!Elements.Any(e => e is MissileBase && e.IsActive))
|
||||
{
|
||||
EndSimulation();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打印仿真状态
|
||||
/// </summary>
|
||||
public void PrintStatus()
|
||||
{
|
||||
Console.WriteLine($"仿真时间: {CurrentTime:F2}");
|
||||
foreach (var element in Elements)
|
||||
{
|
||||
Console.WriteLine(element.GetStatus());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束仿真
|
||||
/// </summary>
|
||||
private void EndSimulation()
|
||||
{
|
||||
IsSimulationEnded = true;
|
||||
Console.WriteLine("仿真结束");
|
||||
Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒");
|
||||
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据ID获取仿真实体
|
||||
/// </summary>
|
||||
public SimulationElement GetEntityById(string id)
|
||||
{
|
||||
return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理目标被击中事件
|
||||
/// </summary>
|
||||
public void HandleTargetHit(string targetId, string missileId)
|
||||
{
|
||||
if (GetEntityById(targetId) is Tank tank && GetEntityById(missileId) is MissileBase missile)
|
||||
{
|
||||
// 计算导弹造成的伤害
|
||||
double damage = CalculateMissileDamage(missile);
|
||||
|
||||
// 对坦克造成伤害
|
||||
tank.TakeDamage(damage, true);
|
||||
|
||||
// 记录击中事件
|
||||
LogHitEvent(targetId, missileId, damage);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算导弹造成的伤害
|
||||
/// </summary>
|
||||
private double CalculateMissileDamage(MissileBase missile)
|
||||
{
|
||||
// 这里可以根据导弹类型、速度等因素计算伤害
|
||||
// 现在我们简单地返回一个固定值
|
||||
return 50;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 记录击中事件
|
||||
/// </summary>
|
||||
private static void LogHitEvent(string targetId, string missileId, double damage)
|
||||
{
|
||||
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加仿真元素
|
||||
/// </summary>
|
||||
public void AddElement(SimulationElement element)
|
||||
{
|
||||
Elements.Add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user