docs: 总体架构设计校准与探测设备设计补全(V10→V13)
文档与代码对齐 + 探测设备行为设计固化。
1. 文档校准(修正与实现不符的错误):
- AlgorithmFactory 实际为 Func<object> 工厂委托(非 Type+Activator)
- IDefensePlanner.Plan 为 4 参数(含 detectionSources)
- IDamageModel 补 RequiredExposureSeconds
- FrameDataStore 是类非 IFrameDataStore 接口;删除不存在的 IRecordService
- DroneEntity 运动模型为弧长驱动(不受风偏);Tick 流程顺序对齐
- StateData 改为强类型字段+入库时序列化的双轨说明
2. 新增第十三章 性能设计(Tick 热路径优化,实测 <20 到 200+ FPS):
- 航路几何缓存、仿真期零字符串分配、多边形顶点缓存
- 帧数据内存缓存+批量落库、毁伤快速排斥、移除索引复用
3. 新增第十四章 探测设备设计(统一信息网络):
- 区分事前静态规划(已实现)与运行时实时探测(待实现)双链路
- 三维球冠探测几何(俯仰角+高度门限,IsInCoverage)
- 5 项行为决策确认:回退 Undetected / 融合取最早-同刻取精度高 /
不影响 FireSchedule / 盲区仅可视化 / 支持 3D 球冠
- EquipmentDeployment 加 4 个 3D 探测字段 + 数据模型变更清单
4. 附带:技术要求终版.txt 错别字修正(晕图案 改 云团)
This commit is contained in:
parent
ce9d44db7e
commit
68b7434ddc
@ -1,11 +1,12 @@
|
||||
# 反无人机仿真系统 — 总体架构设计
|
||||
|
||||
> **版本**:V10
|
||||
> **日期**:2026-06-15
|
||||
> **状态**:已实现
|
||||
> **版本**:V13
|
||||
> **日期**:2026-06-16
|
||||
> **状态**:已实现(探测实时链路 + 3D 球冠待实现)
|
||||
> **Unity 版本**:22.3.62
|
||||
> **.NET 版本**:.NET Standard 2.1
|
||||
> **变更**:Group 表移除;GroupId → WaveId;DroneGroup → DroneWave;编组概念升级为批次+火力单元
|
||||
> **变更**:V13 探测行为决策固化——5 项规则确认(回退 Undetected / 融合取最早-同刻取精度高 / 不影响 FireSchedule / 盲区仅可视化 / 3D 球冠);新增 14.2.1 三维球冠几何(IsInCoverage)+ 14.7 数据模型变更清单;EquipmentDeployment 表加 4 个 3D 探测字段;DetectionSource 同步扩展
|
||||
> **历史变更**:V12 探测双链路设计(静态规划+实时探测待实现);V11 文档校准 + 第十三章性能设计;V10 Group 表移除,批次+火力单元概念升级
|
||||
|
||||
---
|
||||
|
||||
@ -165,7 +166,7 @@ public class SimulationRunner : MonoBehaviour
|
||||
| **单元测试** | xUnit + Moq | Repository 增删改查、Service 业务逻辑、Algorithm 计算正确性 |
|
||||
| **仿真确定性测试** | xUnit | 固定输入 + 固定 deltaTime → 断言帧 N 的实体位置 = 预期值 |
|
||||
| **集成测试** | xUnit + SQLite 文件 | 完整想定配置 → 启动仿真 → 跑 1000 帧 → 断言事件序列和对抗结果 |
|
||||
| **性能测试** | BenchmarkDotNet | Tick() 单帧耗时 P99 < 5ms |
|
||||
| **性能验证** | 实测帧率 | Unity 实测:满载场景渲染帧率从优化前 <20 FPS 提升至 200+ FPS(详见第十四章) |
|
||||
|
||||
> Core 测试无需 Unity,`dotnet test` 即可运行全部测试,适合 CI 流水线。
|
||||
|
||||
@ -196,7 +197,7 @@ enum AerosolType { InertGas = 0, ActiveMaterial = 1, ActiveFuel = 2 }
|
||||
enum ReleaseMode { Single = 0, Continuous = 1, Pulse = 2 }
|
||||
enum TriggerMode { Time = 0, Area = 1, Manual = 2 }
|
||||
|
||||
// === 毁伤状态阶段(输出到 StateData 供 Unity 渲染)===
|
||||
// === 毁伤状态阶段(EntitySnapshot.DamageStage,前端直读;入库时进 StateData JSON)===
|
||||
enum DamageStage { Normal = 0, EngineAnomaly = 1, AttitudeLoss = 2, Destroyed = 3 }
|
||||
|
||||
// === 编队 ===
|
||||
@ -215,15 +216,15 @@ enum FormationMode { Single = 0, Formation = 1, Swarm = 2 }
|
||||
|
||||
// === 运行时 ===
|
||||
enum EntityType { Drone = 0, Platform = 1, DetectionEquip = 2, Cloud = 3, Munition = 4 }
|
||||
enum EventType
|
||||
enum SimEventType
|
||||
{
|
||||
TargetDetected = 0,
|
||||
TargetDetected = 0, // 探测发现目标【待实现,当前未触发,详见第十四章】
|
||||
MunitionLaunched = 1,
|
||||
CloudGenerated = 2,
|
||||
DroneEnteredCloud = 3,
|
||||
DroneDestroyed = 4,
|
||||
DroneReachedTarget = 5,
|
||||
ZoneIntruded = 6, // 无人机侵入管控区域
|
||||
ZoneIntruded = 6, // 无人机侵入管控区域
|
||||
WaypointReached = 7,
|
||||
SimulationEnd = 8
|
||||
}
|
||||
@ -395,6 +396,11 @@ CounterDroneBackend_Data/
|
||||
| EORange | REAL | NULLABLE | 光电探测距离 m(受 Visibility 衰减) |
|
||||
| IRRange | REAL | NULLABLE | 红外探测距离 m(不受 Visibility 影响) |
|
||||
| DetectionAccuracy | REAL | NULLABLE | 探测精度 m(位置误差,影响抛撒散布范围) |
|
||||
| // 三维球冠几何(决策 5,待新增字段;详见第十四章) |
|
||||
| MinElevation | REAL | NULLABLE | 俯仰角下限(度) |
|
||||
| MaxElevation | REAL | NULLABLE | 俯仰角上限(度) |
|
||||
| MinDetectAlt | REAL | NULLABLE | 可探测高度下界 m |
|
||||
| MaxDetectAlt | REAL | NULLABLE | 可探测高度上界 m |
|
||||
|
||||
> **装备体系说明**:
|
||||
> - **搭载平台**(2 种):
|
||||
@ -484,18 +490,19 @@ CounterDroneBackend_Data/
|
||||
| RotX | REAL | | |
|
||||
| RotY | REAL | | |
|
||||
| RotZ | REAL | | |
|
||||
| StateData | TEXT | | JSON,包含:DestroyStage、CloudRadius、CloudColor 等 |
|
||||
| StateData | TEXT | | JSON,由 EntityType 决定结构。**仅 Flush 入库时生成**,仿真期间保持空 |
|
||||
|
||||
> StateData JSON 结构(供 Unity 粒子系统 & 毁伤渲染):
|
||||
> **StateData 双轨设计**:仿真热路径上 `EntitySnapshot` 携带**强类型字段**(`Hp`/`CloudRadius`/`CloudOpacity` 等),前端直接读取,零 JSON 解析;仅 `FrameDataStore.Flush` 入库时按 `EntityType` 序列化为 JSON 字符串写入 `SimFrameRecord.StateData`,供历史回放解析。
|
||||
>
|
||||
> StateData JSON 按实体类型差异化(字段名与 Flush 中模板严格一致):
|
||||
> ```json
|
||||
> {
|
||||
> "damageStage": 0, // DamageStage 枚举
|
||||
> "hp": 0.75, // 剩余血量 0~1
|
||||
> "cloudRadius": 150.0, // 云团当前半径 m(CloudEntity)
|
||||
> "cloudOpacity": 0.8, // 云团透明度(CloudEntity)
|
||||
> "cloudColor": "#AABBCC", // 云团颜色(CloudEntity)
|
||||
> "particleEmitRate": 500 // 粒子发射率(CloudEntity)
|
||||
> }
|
||||
> // Drone:
|
||||
> { "damageStage": 0, "hp": 0.75 } // DamageStage 枚举;剩余血量 0~1
|
||||
> // Platform(仅空基平台记录快照):
|
||||
> { "state": "Flying" } // 平台状态字符串
|
||||
> // Cloud:
|
||||
> { "radius": 150.0, "opacity": 0.8, "phase": 2, "elapsed": 35.0 }
|
||||
> // radius=当前半径m, opacity=透明度, phase=扩散阶段(1/2/3), elapsed=已存在秒数
|
||||
> ```
|
||||
|
||||
#### SimEvent — 仿真事件(时序图数据源)
|
||||
@ -527,7 +534,9 @@ SimulationEngine
|
||||
├── List<PlatformEntity> ← 搭载平台(发射方)★重构
|
||||
│ ├── AirBasedPlatform ← 空基(大型无人机)
|
||||
│ └── GroundBasedPlatform ← 地基(火炮)
|
||||
├── List<DetectionEntity> ← 探测设备
|
||||
├── List<DetectionEntity> ← 探测设备(统一信息网络)★实时探测【待实现】
|
||||
│ ├── 持有 DetectionSource(位置/雷达/光电/红外距离/精度)
|
||||
│ └── 每个威胁的探测状态机:Undetected → Detected → Tracked
|
||||
├── List<MunitionEntity> ← 飞行中的弹药
|
||||
│ ├── 空基投放:短程自由落体/滑翔
|
||||
│ └── 地基发射:抛物线弹道
|
||||
@ -538,12 +547,43 @@ SimulationEngine
|
||||
└── FrameDataStore ← 帧数据写入(任务分库)
|
||||
```
|
||||
|
||||
> **探测设备的两阶段角色**(详见第十五章):
|
||||
> - **事前规划阶段**(已实现):`DefensePlanner` 调用 `DetectionCalculator.EarliestDetection` 静态估算每个威胁的最早发现弧长,反推拦截时机。
|
||||
> - **运行时实时探测**(待实现):`DetectionEntity` 在 Tick 内扫描飞行无人机,首次进入探测范围 → 触发 `TargetDetected` 事件。两阶段共用同一 `EffectiveRange` 物理公式保证一致。
|
||||
|
||||
### 5.2 拦截链路(完整流程)
|
||||
|
||||
系统存在**两条并行的探测链路**,分别服务于"事前规划"和"运行时观测":
|
||||
|
||||
```
|
||||
探测设备扫描
|
||||
│ 发现目标 → 输出目标坐标
|
||||
═══ 链路 A:事前规划(已实现,开环)═════════════════════════════
|
||||
|
||||
仿真启动前 DefensePlanner.Plan():
|
||||
DetectionCalculator.EarliestDetection(threatRoute, sources, visibility)
|
||||
│ 静态计算每个威胁航路进入探测网的最早弧长
|
||||
▼
|
||||
拦截时机 = 最早发现弧长 + 弹药飞行时间反推
|
||||
│ 一次性生成 FireSchedule(开环,不依赖运行时观测)
|
||||
▼
|
||||
SimulationEngine 按 FireSchedule 时间表执行发射
|
||||
|
||||
|
||||
═══ 链路 B:运行时实时探测(待实现,闭环观测)═════════════════
|
||||
|
||||
Tick 内 DetectionEntity 扫描飞行无人机:
|
||||
│ 首次进入 EffectiveRange → 状态 Undetected→Detected
|
||||
▼
|
||||
触发 OnTargetDetected(TargetDetected 事件 → 写 SimEvent)
|
||||
│ 输出目标当前坐标(含探测精度散布)
|
||||
▼
|
||||
持续跟踪(Detected→Tracked)→ 坐标更新
|
||||
│ (未来:驱动动态火控重分配 / 自适应拦截)
|
||||
▼
|
||||
与链路 A 的静态计划协同:观测印证规划 / 补救漏网目标
|
||||
|
||||
|
||||
═══ 公共后段(两条链路最终汇入)═══════════════════════════════
|
||||
|
||||
火控分配(分配给可用搭载平台)
|
||||
│
|
||||
├── 空基平台:飞至投放点
|
||||
@ -574,53 +614,70 @@ SimulationEngine
|
||||
Unity 渲染毁伤效果(尾焰异常、姿态失控、坠落)
|
||||
```
|
||||
|
||||
> **当前实现状态**:链路 A(静态规划)已完整实现,是拦截时机的唯一来源;链路 B(实时探测)尚未接入 Tick,`TargetDetected` 事件已定义但未触发。详见第十五章探测设备设计。
|
||||
|
||||
### 5.3 仿真 Tick 流程
|
||||
|
||||
```
|
||||
1. 【发射阶段】
|
||||
按 FireSchedule 执行:
|
||||
├─ SimulationTime ≥ FireTime → 平台发射弹药
|
||||
├─ SimulationTime ≥ FireTime → 平台发射弹药(空基先 CommandFlyTo,地基直接 Release)
|
||||
├─ 空基平台到达投放点 → 投放弹药(继承载机速度)
|
||||
└─ 触发 OnMunitionLaunched 事件
|
||||
|
||||
2. 【弹药飞行 → 云团生成】
|
||||
FOR EACH MunitionEntity:
|
||||
├─ 抛物线弹道 / 自由落体
|
||||
└─ 到达释放高度 → 生成 CloudEntity → 触发 OnCloudGenerated
|
||||
├─ 抛物线弹道(地基)/ 自由落体+水平惯性(空基)
|
||||
└─ 到达释放高度 → AlgorithmFactory.Create<ICloudDispersionModel>() → 生成 CloudEntity
|
||||
→ 触发 OnCloudGenerated,弹药移除(倒序索引)
|
||||
|
||||
3. 【云团演化】
|
||||
FOR EACH CloudEntity:
|
||||
├─ GaussianPuffDispersion.Tick():三阶段扩散
|
||||
├─ 更新粒子参数(半径、透明度 → 写入 StateData)
|
||||
└─ 消散条件满足 → 移除
|
||||
├─ GaussianPuffDispersion.Tick():三阶段扩散(爆轰→湍流→高斯)
|
||||
├─ 更新粒子参数(半径、透明度)
|
||||
└─ 消散条件满足 → 移除(倒序索引)
|
||||
|
||||
4. 【毁伤判定】
|
||||
FOR EACH DroneEntity × CloudEntity:
|
||||
├─ 无人机坐标 ∈ 云团有效范围?
|
||||
├─ 是 → IDamageModel.CalculateDamage()
|
||||
├─ drone.HP -= damage
|
||||
└─ HP ≤ 0 → 触发 OnDroneDestroyed
|
||||
4. 【无人机移动】
|
||||
├─ 预过滤 Flying 状态无人机到复用缓冲 _flyingDrones(避免多次遍历)
|
||||
├─ SavePreviousPosition(为毁伤路径积分保存上一帧位置)
|
||||
└─ FOR EACH 飞行 DroneEntity:Update(deltaTime)(弧长驱动,详见 5.4)
|
||||
到达终点 → ReachedTarget → 触发 OnDroneReachedTarget
|
||||
|
||||
5. 【无人机移动】
|
||||
FOR EACH 存活 DroneEntity:
|
||||
├─ 沿航路点线性插值
|
||||
├─ 风偏影响
|
||||
└─ 到达终点 → 触发 OnDroneReachedTarget
|
||||
5. 【实时探测扫描】★待实现(见第十五章)
|
||||
FOR EACH DetectionEntity × 飞行无人机:
|
||||
├─ effRange = DetectionCalculator.EffectiveRange(radar, eo, ir, visibility)
|
||||
├─ ‖drone - detector‖ ≤ effRange?
|
||||
├─ 是 且 drone 探测状态 == Undetected → 状态置 Detected
|
||||
│ ├─ 触发 OnTargetDetected(TargetDetected 事件,SourceId=探测设备, TargetId=无人机)
|
||||
│ └─ 输出含精度散布的目标坐标(散布半径 = DetectionCalculator.SpreadRadius(accuracy))
|
||||
├─ 持续在范围内 → 状态升 Tracked(坐标持续刷新)
|
||||
└─ 离开范围 → (策略待定:保持 Tracked 或回退)
|
||||
> 当前此步缺失:探测只在事前 planner 静态计算(链路 A),Tick 内无实时探测。
|
||||
|
||||
6. 【平台冷却】
|
||||
FOR EACH PlatformEntity:Cooldown -= dt
|
||||
6. 【毁伤判定】 FOR EACH 飞行无人机 × CloudEntity:
|
||||
├─ 快速排斥 1:cloud.CoreDensity < 有效浓度阈值 → 跳过
|
||||
├─ 快速排斥 2:‖drone - cloudCenter‖ > 2×EffectiveRadius → 跳过(不可能穿云)
|
||||
├─ DamageAssessment.PathInSphere:积分无人机本帧路径段在球体内的长度 inCloudDistance
|
||||
│ (云团参考系修正:扣除本帧风偏位移 cloudD×dt,使无人机表现为"穿云")
|
||||
├─ exposureIncrement = inCloudDistance / (TypicalSpeed/3.6)
|
||||
├─ drone.ExposureTime += exposureIncrement
|
||||
├─ dmg = IDamageModel.CalculateDamage(...);drone.ApplyDamage(dmg)
|
||||
└─ HP ≤ 0 → Destroyed → 触发 OnDroneDestroyed
|
||||
|
||||
7. 【管控区域判定】
|
||||
FOR EACH 存活 DroneEntity:
|
||||
├─ Point-in-Polygon 判定
|
||||
└─ 侵入 → 触发 OnZoneIntruded
|
||||
7. 【平台冷却】
|
||||
FOR EACH PlatformEntity:Update(deltaTime)
|
||||
|
||||
8. 【结束判定】
|
||||
所有无人机 Status ≠ Flying → 触发 OnSimulationEnded
|
||||
8. 【管控区域判定】
|
||||
FOR EACH 飞行无人机 × ControlZone:
|
||||
├─ 高度区间检查 + Point-in-Polygon(顶点 2D 数组构造时缓存,每帧零分配)
|
||||
└─ 侵入 → MarkZoneIntruded → 触发 OnZoneIntruded
|
||||
|
||||
9. 【结束判定】
|
||||
├─ 所有无人机 (被摧毁 OR 到达目标 OR 侵入管控区) → SimulationEnd
|
||||
├─ 停止录制
|
||||
└─ 更新 SimulationState
|
||||
所有无人机 Status ≠ Flying → SimulationState.Completed → 触发 OnSimulationEnded
|
||||
|
||||
10. 【录制】(若 RecordFrames)
|
||||
├─ CollectSnapshots:填充强类型字段(位置/Hp/云团半径等)到复用池,零字符串分配
|
||||
└─ FrameDataStore.RecordFrame:仅追加内存缓冲 List<FrameRecord>
|
||||
```
|
||||
|
||||
### 5.4 实体行为模型
|
||||
@ -636,10 +693,13 @@ Unity 渲染毁伤效果(尾焰异常、姿态失控、坠落)
|
||||
- 目标类型 TargetType、动力类型 PowerType
|
||||
- 存活状态(飞行中/抵达目标/侵入管控区/被摧毁)
|
||||
|
||||
运动模型(简化运动学):
|
||||
- 两航路点之间线性插值
|
||||
- 实际位移 = 航向位移 + 风速矢量 × deltaTime
|
||||
- 到达判定:||currentPos - waypointPos|| < 1m
|
||||
运动模型(弧长驱动,统一在 RouteGeometry):
|
||||
- 构造时一次性预计算航路几何缓存:_totalArc(总弧长)、_segLen[](各段段长)、_cumArc[](累积弧长)
|
||||
- 每 Tick:_traveledArc += (TypicalSpeed/3.6) × deltaTime
|
||||
- 在 _cumArc[] 中定位所在段,分段线性插值得到 3D 位置
|
||||
- 无人机严格按航路匀速飞行,**不受风偏影响**(真实无人机有飞控修正航向)
|
||||
- 云团受风偏影响 → 毁伤判定中对云团做参考系修正(详见 5.3 第4步)
|
||||
- 到达判定:_traveledArc ≥ _totalArc → ReachedTarget
|
||||
|
||||
结束条件(任一触发即该无人机结束):
|
||||
- 被毁伤(HP ≤ 0)→ Destroyed
|
||||
@ -735,31 +795,33 @@ Unity 渲染毁伤效果(尾焰异常、姿态失控、坠落)
|
||||
/// <summary>算法工厂 — 统一管理所有算法组件的创建与替换</summary>
|
||||
public static class AlgorithmFactory
|
||||
{
|
||||
// 注册表:每个接口 → 实现类型
|
||||
private static readonly Dictionary<Type, Type> _registry = new()
|
||||
// 注册表:每个接口 → 创建委托(Func<object>)
|
||||
private static readonly Dictionary<Type, Func<object>> _registry = new()
|
||||
{
|
||||
{ typeof(ICloudDispersionModel), typeof(GaussianPuffDispersion) },
|
||||
{ typeof(IDamageModel), typeof(DamageModelRouter) },
|
||||
{ typeof(IDefensePlanner), typeof(DefaultDefensePlanner) },
|
||||
[typeof(ICloudDispersionModel)] = () => new GaussianPuffDispersion(),
|
||||
[typeof(IDamageModel)] = () => new DamageModelRouter(),
|
||||
};
|
||||
|
||||
/// <summary>替换某个算法实现(第三方接入点)</summary>
|
||||
public static void Register<TInterface, TImpl>() where TImpl : TInterface
|
||||
public static void Register<TInterface>(Func<object> factory)
|
||||
{
|
||||
_registry[typeof(TInterface)] = typeof(TImpl);
|
||||
_registry[typeof(TInterface)] = factory;
|
||||
}
|
||||
|
||||
/// <summary>创建实例,SimulationEngine 统一调用此方法</summary>
|
||||
public static T Create<T>(params object[] args)
|
||||
public static T Create<T>() where T : class
|
||||
{
|
||||
var implType = _registry[typeof(T)];
|
||||
return (T)Activator.CreateInstance(implType, args);
|
||||
if (_registry.TryGetValue(typeof(T), out var factory))
|
||||
return (T)factory();
|
||||
throw new InvalidOperationException($"No implementation for {typeof(T).Name}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **替换示例**:将来第三方提供 `ThirdPartyDispersion.dll`,只需一行:
|
||||
> `AlgorithmFactory.Register<ICloudDispersionModel, ThirdPartyDispersion>();`
|
||||
> **注**:`IDefensePlanner` 由 DI 直接注入 `SimulationEngine`(不经过 AlgorithmFactory,因为它是单例策略对象,不是每云团/每帧 new)。AlgorithmFactory 仅管理**每实例**的算法组件(云团扩散、毁伤模型)。
|
||||
>
|
||||
> **替换示例**:将来第三方提供 `ThirdPartyDispersion.dll`,只需一行:
|
||||
> `AlgorithmFactory.Register<ICloudDispersionModel>(() => new ThirdPartyDispersion());`
|
||||
> 无需改动 SimulationEngine 任何代码。
|
||||
|
||||
### 6.2 第三方提供的数据
|
||||
@ -908,12 +970,15 @@ public interface IDamageModel
|
||||
/// <param name="aerosolType">气溶胶类型</param>
|
||||
/// <param name="cloudDensity">当前位置云团密度(kg/m³)</param>
|
||||
/// <param name="exposureTime">累计暴露时间(s)</param>
|
||||
/// <param name="deltaTime">本次 Tick 时长</param>
|
||||
/// <param name="deltaTime">本次增量暴露时长(s)</param>
|
||||
/// <returns>本次毁伤值(0~1 归一化)</returns>
|
||||
float CalculateDamage(TargetType droneType, PowerType powerType,
|
||||
AerosolType aerosolType, float cloudDensity,
|
||||
float exposureTime, float deltaTime);
|
||||
|
||||
|
||||
/// <summary>达到 100% 毁伤所需的连续暴露时间 (s),供 planner 估算拦截可行性</summary>
|
||||
float RequiredExposureSeconds(TargetType droneType, PowerType powerType, AerosolType aerosolType);
|
||||
|
||||
DamageStage GetDamageStage(float accumulatedDamage);
|
||||
}
|
||||
```
|
||||
@ -1096,7 +1161,12 @@ planner 所有策略参数从 `data/planner_config.json` 读取,代码零默
|
||||
// === 防御规划 ===
|
||||
public interface IDefensePlanner
|
||||
{
|
||||
PlannerResult Plan(List<FireUnit> fireUnits, List<DroneWave> threats, CombatScene environment);
|
||||
/// <param name="fireUnits">可用的火力单元(空基/地基统一表达)</param>
|
||||
/// <param name="threats">威胁批次列表</param>
|
||||
/// <param name="environment">作战环境(含天气,影响光电探测距离)</param>
|
||||
/// <param name="detectionSources">统一信息网络的探测源列表(独立探测设备 + 火力单元自带探测)。可为空列表。</param>
|
||||
PlannerResult Plan(List<FireUnit> fireUnits, List<DroneWave> threats,
|
||||
CombatScene environment, List<DetectionSource> detectionSources);
|
||||
}
|
||||
|
||||
// ThreatProfile / DefenseRecommendation / DefenseSolution 等模型见本节上文
|
||||
@ -1152,7 +1222,8 @@ public interface IDefensePlanner
|
||||
┌─ 步骤 3:SimulationEngine 无感知切换 ───────────────┐
|
||||
│ │
|
||||
│ var dispersion = AlgorithmFactory │
|
||||
│ .Create<ICloudDispersionModel>(ammo, env, pos, t);│
|
||||
│ .Create<ICloudDispersionModel>(); │
|
||||
│ dispersion.Initialize(ammo, env, pos, t); │
|
||||
│ │
|
||||
│ // 后续代码完全不变,无论底层是自主实现还是第三方 DLL │
|
||||
│ dispersion.Tick(deltaTime, windSpeed, windDir); │
|
||||
@ -1184,36 +1255,34 @@ public interface IDefensePlanner
|
||||
|
||||
## 七、数据录制与回放
|
||||
|
||||
### 7.1 IFrameDataStore 接口
|
||||
### 7.1 FrameDataStore 实现
|
||||
|
||||
`FrameDataStore` 是**具体类**(非接口),采用内存缓存 + 仿真结束批量落库策略,避免每帧磁盘 IO:
|
||||
|
||||
```csharp
|
||||
/// <summary>帧数据存储 — 每任务一个独立 SQLite 文件</summary>
|
||||
public interface IFrameDataStore
|
||||
/// <summary>帧数据存储 — 内存缓存,仿真结束时批量写入 SQLite</summary>
|
||||
public class FrameDataStore
|
||||
{
|
||||
/// <summary>为任务创建帧数据库文件</summary>
|
||||
void CreateTaskDb(string taskId);
|
||||
|
||||
/// <summary>批量写入一帧所有实体状态</summary>
|
||||
void WriteFrame(string taskId, int frameIdx, float timestamp,
|
||||
List<EntitySnapshot> entities);
|
||||
|
||||
/// <summary>按帧范围读取(回放用)</summary>
|
||||
List<SimFrameRecord> ReadFrames(string taskId, int fromFrame, int toFrame);
|
||||
|
||||
/// <summary>删除任务的帧数据库</summary>
|
||||
void BeginRecording(string taskId); // 仿真启动:清空缓冲区
|
||||
void RecordFrame(int frameIdx, float timestamp, // 每 Tick:仅写内存缓冲(零字符串分配)
|
||||
List<EntitySnapshot> snapshots);
|
||||
void Flush(); // 仿真结束:序列化 JSON + 单次事务批量入库
|
||||
void Discard(); // 丢弃未落库的缓冲
|
||||
List<SimFrameRecord> ReadFrames(string taskId, int fromFrame, int toFrame); // 回放读
|
||||
void DeleteTaskDb(string taskId);
|
||||
|
||||
/// <summary>清理过期的帧数据库(定时调用)</summary>
|
||||
void CleanupExpired(DateTime olderThan);
|
||||
int CleanupExpired(); // TTL 清理(按 RetentionDays,默认 180 天)
|
||||
int BufferedFrameCount { get; } // 已缓冲帧数
|
||||
}
|
||||
```
|
||||
|
||||
> **关键设计**:`RecordFrame` 在仿真热路径上**只搬强类型标量字段**(位置/血量/云团半径等)到内存 `List<FrameRecord>`,不做任何 JSON 拼接。JSON 序列化推迟到 `Flush` 一次性完成(详见第十四章性能设计)。
|
||||
|
||||
### 7.2 录制
|
||||
|
||||
- 仿真启动时创建 `frames/{taskId}.db`
|
||||
- 仿真启动时 `BeginRecording` 清空内存缓冲区
|
||||
- 录制帧率 = 仿真 TickRate(每想定可配置,默认 20Hz)
|
||||
- 每 Tick 调用 `WriteFrame()` 写入该帧所有实体状态
|
||||
- SQLite 事务批量提交(如每 50 帧一批,减少磁盘 IO)
|
||||
- 每 Tick 调用 `RecordFrame()`,仅追加到内存 `List<FrameRecord>`,零磁盘 IO、零字符串分配
|
||||
- 仿真结束 `Flush()`:序列化为 `SimFrameRecord` + 单事务 `InsertAll` 批量写入 `frames/{taskId}.db`
|
||||
- 仿真事件 `SimEvent` 直接写入主库 `main.db`(每任务 ~30 条,轻量)
|
||||
|
||||
### 7.3 回放
|
||||
@ -1338,7 +1407,7 @@ interface IScenarioService
|
||||
interface ISimulationEngine
|
||||
{
|
||||
void Initialize(string taskId);
|
||||
SimulationFrameResult Tick(float deltaTime);
|
||||
SimulationFrameResult Tick(float deltaTime); // 返回本帧快照+新事件(复用对象池)
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Stop();
|
||||
@ -1346,15 +1415,18 @@ interface ISimulationEngine
|
||||
}
|
||||
|
||||
// === 数据录制 ===
|
||||
interface IRecordService
|
||||
// 说明:录制职责由具体类 FrameDataStore 承担(无 IRecordService 接口)。
|
||||
// SimulationEngine 内部持有 FrameDataStore,每 Tick 调 RecordFrame(仅内存),
|
||||
// Stop/完成时调 Flush 批量落库。事件 SimEvent 由引擎直接写入主库。
|
||||
class FrameDataStore
|
||||
{
|
||||
void StartRecording(string taskId, int tickRate);
|
||||
void WriteFrame(int frameIdx, float timestamp, List<EntitySnapshot> entities);
|
||||
void WriteEvent(SimEvent evt);
|
||||
void StopRecording();
|
||||
List<SimFrameRecord> GetFrames(string taskId, int from, int to);
|
||||
List<SimEvent> GetEvents(string taskId);
|
||||
void CleanupExpired(DateTime olderThan); // TTL 清理
|
||||
void BeginRecording(string taskId);
|
||||
void RecordFrame(int frameIdx, float timestamp, List<EntitySnapshot> entities);
|
||||
void Flush(); // 批量落库
|
||||
void Discard();
|
||||
List<SimFrameRecord> ReadFrames(string taskId, int fromFrame, int toFrame);
|
||||
void DeleteTaskDb(string taskId);
|
||||
int CleanupExpired(); // TTL 清理(RetentionDays,默认 180)
|
||||
}
|
||||
|
||||
// === 仿真报告 ===
|
||||
@ -1527,7 +1599,7 @@ void SaveRoute(string taskId, string waveId, RoutePlan route, List<Waypoint> wps
|
||||
| 10 | 毁伤模型 | **三种机制自主实现** | 吸入式灭火(阈值型)、爆燃式(触发型)、吸入式爆炸(指数累积型) |
|
||||
| 11 | 防御方案推荐 | **IDefensePlanner(自主实现)** | 五步规划:威胁排序 → 弹药匹配 → 候选生成 → 贪心分配 → 时序生成 |
|
||||
| 12 | 第三方数据 | **静态配置(JSON → SQLite)** | 仅提供弹药基础参数和初始扩散状态,不提供运行时算法 |
|
||||
| 13 | 运动学 | 简化运动学 + 风偏 | 航路点线性插值 + 风速矢量 |
|
||||
| 13 | 运动学 | 弧长驱动匀速运动 | 无人机严格按航路匀速飞行(不受风偏,飞控修正);云团受风偏,毁伤判定做参考系修正 |
|
||||
| 14 | 弹药弹道 | 抛物线(地基)/ 自由落体(空基) | 基于初速、角度、释放高度计算 |
|
||||
| 15 | 批次 / 火力单元 | WaveId + 火力单元独立作战 | 批次关联航路但不独占;火力单元是最小独立作战单位,不需要上层编组 |
|
||||
| 16 | 管控区域 | ControlZone 表 + Tick 判定 | 电子围栏,侵入即任务失败 |
|
||||
@ -1552,14 +1624,303 @@ void SaveRoute(string taskId, string waveId, RoutePlan route, List<Waypoint> wps
|
||||
|
||||
---
|
||||
|
||||
## 十三、待后续讨论
|
||||
## 十三、性能设计(Tick 热路径优化)
|
||||
|
||||
> 本节记录仿真引擎 `SimulationEngine.Tick()` 热路径上的性能优化。实测:Unity 端满载场景渲染帧率从优化前 **<20 FPS(卡顿)** 提升至 **200+ FPS**。
|
||||
|
||||
### 13.1 设计原则:零分配热路径
|
||||
|
||||
`Tick` 在仿真期间以 TickRate(默认 20Hz)被 Unity `Update` 反复调用,且每帧需向 Unity 传回所有实体快照。优化的核心原则是**仿真热路径上零(或极少)托管堆分配**,把所有可复用的对象、数组、字符串构造移出热路径:
|
||||
|
||||
| 原则 | 手段 |
|
||||
|------|------|
|
||||
| 对象池复用 | 快照列表、事件列表、帧结果、移除索引缓冲、飞行无人机缓冲均 `Clear()` 复用,不每帧 new |
|
||||
| 延迟序列化 | 强类型字段在仿真期流转,JSON/字符串只在 `Flush` 一次性生成 |
|
||||
| 几何预计算 | 航路、多边形顶点等静态数据构造时算一次,缓存供每帧查询 |
|
||||
| 批量落库 | 帧数据先全量驻留内存,仿真结束单事务写入,杜绝每帧磁盘 IO |
|
||||
|
||||
### 13.2 关键优化点
|
||||
|
||||
#### A. DroneEntity 航路几何缓存(消除每帧重复几何运算)
|
||||
|
||||
**问题**:原实现每帧对每架无人机调用 `RouteGeometry.TotalLength(Route)`(O(N) 全扫求和)+ `PositionAt`(O(N) 重扫定位),航路静态却每帧重算。
|
||||
|
||||
**优化**:构造时一次性预计算 `_totalArc`(总弧长)、`_segLen[]`(各段段长)、`_cumArc[]`(累积弧长)。`Update()` 内 `_traveledArc += speed×dt`,在 `_cumArc[]` 线性定位所在段(航点数通常 ≤10)后插值。
|
||||
|
||||
**收益**:每架无人机每帧从 O(N) ×2 降为 O(N) ×1(仅定位,无重算总长)。无人机数 × 航点数 × FPS 规模下收益显著。
|
||||
|
||||
#### B. 仿真期零字符串分配 + JSON 推迟到 Flush(最大收益项)
|
||||
|
||||
**问题**:原实现每帧每实体在 `CollectSnapshots` 拼 JSON 字符串(`StateData`),Unity 端 `SimulationRunner` 又对每个云团 `JsonDocument.Parse` 解析 —— 拼装 + 解析两端分配,是帧率杀手。
|
||||
|
||||
**优化**:
|
||||
- `EntitySnapshot` 新增强类型字段(`DamageStage`/`Hp`/`CloudRadius`/`CloudOpacity`/`CloudPhase`/`CloudElapsed`/`PlatformStateStr`),`CollectSnapshots` 直接填标量,零字符串分配。
|
||||
- Unity 端直读 `snap.CloudRadius`/`snap.CloudOpacity`,移除 `JsonDocument.Parse`。
|
||||
- JSON 序列化推迟到 `FrameDataStore.Flush`:按 `EntityType` switch 拼装(模板与历史格式逐字节一致),单次完成。
|
||||
|
||||
**收益**:热路径上彻底消除字符串分配与 JSON 解析。**这是帧率从 <20 提升到 200+ 的主因**。
|
||||
|
||||
#### C. ControlZoneEntity 顶点 2D 缓存(消除每帧数组分配)
|
||||
|
||||
**问题**:`ContainsPoint` 每 tick 被 `O(飞行无人机 × 管控区)` 调用,原实现每次 `new (float X, float Z)[]` 并逐元素拷贝。
|
||||
|
||||
**优化**:构造时缓存 `_vertices2D`(水平投影顶点数组),`ContainsPoint` 直接传给 `Kinematics.PointInPolygon`(数组隐式转 `ReadOnlySpan`,零分配)。
|
||||
|
||||
#### D. 帧数据内存缓存 + 批量落库
|
||||
|
||||
**问题**:每帧写 SQLite 会产生磁盘 IO 与事务开销。
|
||||
|
||||
**优化**:`FrameDataStore` 用 `List<FrameRecord>`(struct,连续存储)做内存缓冲,`RecordFrame` 仅追加;`Flush` 时序列化 + 单事务 `InsertAll` 批量入库。仿真期间零磁盘 IO。
|
||||
|
||||
#### E. 毁伤判定快速排斥
|
||||
|
||||
`O(无人机 × 云团)` 嵌套循环前两层裁剪:
|
||||
1. `cloud.CoreDensity < 有效浓度阈值` → 跳过(浓度不足不可能造成毁伤)。
|
||||
2. `‖drone − cloudCenter‖² > (2R)²` → 跳过(距离超 2 倍有效半径,本帧不可能穿云),避免进入 `PathInSphere` 解析计算。
|
||||
|
||||
#### F. 移除索引复用 + 预过滤
|
||||
|
||||
- 弹药/云团移除用倒序索引缓冲 `_removalIndices`,避免 `ToList()`。
|
||||
- 飞行无人机预过滤到复用缓冲 `_flyingDrones`,避免后续多步重复 `Where`。
|
||||
|
||||
### 13.3 优化前后对照
|
||||
|
||||
| 场景 | 优化前 | 优化后 |
|
||||
|------|--------|--------|
|
||||
| Unity 渲染帧率(满载) | <20 FPS(卡顿) | 200+ FPS |
|
||||
| 每帧 GC 分配 | 每实体 1 个 JSON 字符串 + 解析端 DOM | 零字符串分配 |
|
||||
| 每帧无人机几何运算 | O(无人机×航点) ×2 重算 | O(无人机×航点) ×1 定位 |
|
||||
| 每帧管控区数组分配 | 每次调用 new 数组 | 构造时缓存,零分配 |
|
||||
| 帧数据磁盘 IO | 每帧写库 | 仿真结束单次批量 |
|
||||
|
||||
### 13.4 后续可扩展方向(当前规模无需)
|
||||
|
||||
当实体规模大幅增长(如数百架无人机 + 数十云团)时,可能出现的新瓶颈与应对:
|
||||
- 毁伤判定 `O(drone × cloud)` 嵌套 → 空间分区(均匀网格 / AABB 树)。
|
||||
- 回放 `ReplayController.GetFrame` 用 `Where().ToList()` 线性扫描 → 改为按 FrameIndex 建索引或分组字典。
|
||||
- 极长回放全量加载内存 → 分段/流式读取。
|
||||
|
||||
> 按 YAGNI,上述在当前规模(<30 FPS 需求、200+ FPS 实测)下不做,仅记录备查。
|
||||
|
||||
---
|
||||
|
||||
## 十四、探测设备设计(统一信息网络)
|
||||
|
||||
> 探测设备是"统一信息网络"的感知层,负责对来袭威胁的搜索、发现与跟踪。本系统支持三种探测手段,统一抽象为 `DetectionSource`,由独立探测节点(`EquipmentRole.Detection`)和火力单元自带的探测能力共同构成探测网。
|
||||
|
||||
### 14.1 设计现状:两阶段角色
|
||||
|
||||
探测设备在系统中承担两个阶段的角色,**两者共用同一套物理公式**(`DetectionCalculator`)以保证一致:
|
||||
|
||||
| 阶段 | 角色 | 状态 | 输入 | 输出 |
|
||||
|------|------|------|------|------|
|
||||
| **事前规划** | 静态估算最早发现点 | ✅ 已实现 | 威胁航路 + 探测网 + 能见度 | 每个威胁的最早发现弧长 `DetectArc` + 精度 |
|
||||
| **运行时实时** | 扫描→发现→跟踪 | ⏳ 待实现 | 飞行无人机实时位置 + 探测网 | `TargetDetected` 事件 + 跟踪坐标流 |
|
||||
|
||||
- **事前规划**(链路 A):`DefensePlanner.Plan` 调 `DetectionCalculator.EarliestDetection`,沿威胁航路求其进入探测网范围的最早点,反推拦截时机。这是当前拦截时机的唯一来源(开环)。
|
||||
- **运行时实时**(链路 B):`DetectionEntity` 在 Tick 内扫描,产生"何时真正发现"的事件流与可视化。**当前未接入 Tick**,`TargetDetected` 事件已定义(`SimEventType.TargetDetected = 0`)但全代码库未触发。
|
||||
|
||||
### 14.2 三种探测手段
|
||||
|
||||
| 手段 | 字段 | 特性 | 受能见度影响 |
|
||||
|------|------|------|------|
|
||||
| **雷达** | `RadarRange` | 全天候,三维波束 | 否 |
|
||||
| **光电(EO)** | `EORange` | 可见光成像 | 是:有效 = 基准 × min(1, Visibility/基准) |
|
||||
| **红外(IR)** | `IRRange` | 热源探测,夜间可用 | 否 |
|
||||
|
||||
综合有效距离取三者最大(任一手段发现即算发现):
|
||||
|
||||
```csharp
|
||||
// DetectionCalculator.EffectiveRange —— planner 与运行时实时共用
|
||||
// 注:返回的是"最大水平距离基准",3D 球冠判定在其上层(见 14.2.1)
|
||||
float EffectiveRange(float radarRange, float eoRange, float irRange, float visibility)
|
||||
{
|
||||
float effRadar = radarRange;
|
||||
float effEO = eoRange > 0 ? eoRange * Math.Min(1f, visibility / eoRange) : 0f; // 光电衰减
|
||||
float effIR = irRange;
|
||||
return Math.Max(effRadar, Math.Max(effEO, effIR));
|
||||
}
|
||||
```
|
||||
|
||||
> **统一原则**:planner 的静态估算与运行时实时扫描必须用同一个探测几何判定,否则会出现"规划以为能发现、运行时却没发现"的不一致。
|
||||
|
||||
### 14.2.1 三维球冠探测几何(决策 5)
|
||||
|
||||
**当前实现**:`EffectiveRange` 仅做水平面距离判定(`EarliestEntryArc` 求线段-圆交点),忽略高度与俯仰。这是简化模型。
|
||||
|
||||
**目标态**:探测范围为以设备为中心的**三维球冠**——由最大水平距离、俯仰角范围、高度门限共同界定,反映真实雷达/光电/红外的波束形状。
|
||||
|
||||
```
|
||||
MaxDetectAlt ─────────────── 高度上界
|
||||
╱ ╲
|
||||
╱ ╲ ← 俯仰角上限 MaxElevation
|
||||
╱ 球冠 ╲
|
||||
设备 ●──────╱ ◌ ╲────── EffectiveRange(最大水平距离)
|
||||
╲ 区域 ╱
|
||||
╲ ╱ ← 俯仰角下限 MinElevation
|
||||
╲ ╱
|
||||
MinDetectAlt ─────────────── 高度下界
|
||||
```
|
||||
|
||||
**目标判定函数**(待实现,planner 与实时探测共用):
|
||||
|
||||
```csharp
|
||||
// DetectionCalculator.IsInCoverage —— 三维球冠判定
|
||||
// ① 水平距离 ≤ EffectiveRange(含能见度衰减后的综合距离)
|
||||
// ② 俯仰角 ∈ [MinElevation, MaxElevation](设备指向目标的高低角)
|
||||
// ③ 目标高度 ∈ [MinDetectAlt, MaxDetectAlt]
|
||||
bool IsInCoverage(
|
||||
Vector3 target, Vector3 detector,
|
||||
float effectiveRange,
|
||||
float minElevation, float maxElevation,
|
||||
float minDetectAlt, float maxDetectAlt)
|
||||
{
|
||||
float dx = target.X - detector.X;
|
||||
float dy = target.Y - detector.Y; // 高度差
|
||||
float dz = target.Z - detector.Z;
|
||||
float horizDistSq = dx * dx + dz * dz;
|
||||
if (horizDistSq > effectiveRange * effectiveRange) return false; // ①
|
||||
if (target.Y < minDetectAlt || target.Y > maxDetectAlt) return false; // ③
|
||||
float horizDist = MathF.Sqrt(horizDistSq);
|
||||
if (horizDist < 0.0001f) return true; // 正顶/正下,按角度门限放行
|
||||
float elevation = MathF.Atan2(dy, horizDist) * (180f / MathF.PI); // 俯仰角(度)
|
||||
return elevation >= minElevation && elevation <= maxElevation; // ②
|
||||
}
|
||||
```
|
||||
|
||||
> **planner 适配**:`EarliestDetection`/`EarliestEntryArc` 当前用线段-圆求交,升级 3D 后需改为"沿航路逐采样点调用 `IsInCoverage`"(解析求三维球冠-折线交点复杂度高,采样法足够且与实时探测判定一致)。这是 3D 升级的主要工作量。
|
||||
|
||||
### 14.3 探测源构成
|
||||
|
||||
`DetectionSource` 来自两类装备(`SimulationEngine.BuildDetectionSources`):
|
||||
|
||||
```
|
||||
统一信息网络探测源 = 独立探测节点 + 火力单元自带探测
|
||||
(EquipmentRole.Detection) (LaunchPlatform 的 RadarRange/EO/IR 字段)
|
||||
```
|
||||
|
||||
判定规则:任一探测字段(RadarRange/EORange/IRRange)非 null 且 > 0,即为有效探测源。
|
||||
|
||||
### 14.4 探测精度与抛撒散布
|
||||
|
||||
- `DetectionAccuracy`(m):探测设备的位置误差。
|
||||
- 精度越差 → planner 增大横向覆盖范围,对冲定位不确定性:
|
||||
```csharp
|
||||
// DetectionCalculator.SpreadRadius
|
||||
float SpreadRadius(float accuracy) => Math.Max(0f, accuracy); // 散布半径 ≈ 精度值
|
||||
```
|
||||
- 运行时实时探测输出目标坐标时,同样按此散布半径叠加位置扰动(待实现)。
|
||||
|
||||
### 14.5 实时探测设计(待实现)
|
||||
|
||||
#### 14.5.1 DetectionSource / DetectionEntity
|
||||
|
||||
`DetectionSource` 需扩展三维几何参数(决策 5):
|
||||
|
||||
```csharp
|
||||
public class DetectionSource
|
||||
{
|
||||
public Vector3 Position { get; set; }
|
||||
public float RadarRange { get; set; } // 雷达水平距离 m
|
||||
public float EORange { get; set; } // 光电水平距离 m(受 Visibility 衰减)
|
||||
public float IRRange { get; set; } // 红外水平距离 m
|
||||
public float Accuracy { get; set; } // 探测精度 m(位置误差)
|
||||
// ── 三维球冠几何参数(决策 5,待新增)──
|
||||
public float MinElevation { get; set; } // 俯仰角下限(度)
|
||||
public float MaxElevation { get; set; } // 俯仰角上限(度)
|
||||
public float MinDetectAlt { get; set; } // 可探测高度下界 m
|
||||
public float MaxDetectAlt { get; set; } // 可探测高度上界 m
|
||||
}
|
||||
|
||||
// 待新增:仿真运行时的探测设备实体
|
||||
public class DetectionEntity
|
||||
{
|
||||
public string Id { get; }
|
||||
public DetectionSource Source { get; }
|
||||
// 每个威胁的探测状态机(按无人机 Id 索引)
|
||||
// Undetected ⇄ Detected(决策 1:离开范围回退 Undetected,再次进入重新触发事件)
|
||||
}
|
||||
```
|
||||
|
||||
#### 14.5.2 Tick 内扫描逻辑(接入 5.3 第5步)
|
||||
|
||||
```
|
||||
FOR EACH 飞行无人机(维护"本帧已发现该目标的最优探测设备"暂存):
|
||||
bestDetector = null; bestTime = +∞; bestAccuracy = +∞ // 决策 2:最早发现,同时则精度高
|
||||
|
||||
FOR EACH DetectionEntity:
|
||||
effRange = DetectionCalculator.EffectiveRange(雷达, 光电, 红外, 场景能见度)
|
||||
inCover = DetectionCalculator.IsInCoverage( // 三维球冠判定(14.2.1)
|
||||
drone.Pos, detector.Pos, effRange,
|
||||
MinElevation, MaxElevation, MinDetectAlt, MaxDetectAlt)
|
||||
IF inCover:
|
||||
IF 该无人机对此设备状态 == Undetected:
|
||||
标记"候选首次发现",按决策 2 比较更新 bestDetector(最早;同 tick 取精度高)
|
||||
该无人机对此设备状态 → Detected
|
||||
ELSE:
|
||||
该无人机对此设备状态 → Undetected // 决策 1:离开即回退
|
||||
|
||||
// 本帧所有设备遍历完后,统一触发至多一次 TargetDetected(决策 2 融合)
|
||||
IF bestDetector != null:
|
||||
触发 OnTargetDetected(
|
||||
SimEvent { Type = TargetDetected,
|
||||
SourceId = bestDetector.Id, // 最早/精度最高者
|
||||
TargetId = drone.Id,
|
||||
OccurredAt = SimulationTime })
|
||||
> 决策 3/4:实时探测只产生事件与可视化,不回调 planner、不改 FireSchedule、不触发额外拦截
|
||||
```
|
||||
|
||||
#### 14.5.3 TargetDetected 事件契约
|
||||
|
||||
| 字段 | 取值 |
|
||||
|------|------|
|
||||
| `Type` | `SimEventType.TargetDetected` |
|
||||
| `SourceId` | 探测设备 Id |
|
||||
| `TargetId` | 被发现的无人机 Id |
|
||||
| `OccurredAt` | 发现时刻(仿真秒) |
|
||||
| `DataJson` | 发现点坐标 + 探测精度(待定义结构) |
|
||||
| `Description` | 如"雷达 R1 发现 drone_3 @(x,y,z)" |
|
||||
|
||||
事件写入主库 `SimEvent` 表,是**时序图**的核心数据源之一(与 MunitionLaunched/DroneDestroyed 等并列)。
|
||||
|
||||
### 14.6 探测行为决策(已确认)
|
||||
|
||||
下列探测行为规则已确认,实现时严格遵循:
|
||||
|
||||
| # | 议题 | 决策 | 说明 |
|
||||
|---|------|------|------|
|
||||
| 1 | 目标离开探测范围后状态 | **回退 Undetected** | 失去接触即认为丢失目标。若再次进入(同一设备或另一设备)→ 重新置 Detected 并**再次触发 `TargetDetected`**(对应真实防空"失跟→重新捕获",事件流允许多次发现记录) |
|
||||
| 2 | 多设备发现同一目标的融合 | **取最早发现者;同时发现取精度最高者** | `TargetDetected.SourceId` 取最早发现该目标的设备;若同一 tick 内多设备同时首次发现,取 `DetectionAccuracy` 值最小(精度最高)的设备 |
|
||||
| 3 | 实时探测是否影响 FireSchedule | **不影响** | FireSchedule 保持 planner 一次性生成(链路 A)。实时探测是**纯只读观测层**,不回调 planner、不改发射计划 |
|
||||
| 4 | 探测盲区/漏网目标 | **仅可视化提示,不触发额外行为** | 配合决策 3:实时探测整体定位为观测+展示(时序图/告警文字/UI 标记),不驱动任何拦截逻辑 |
|
||||
| 5 | 高度与角度范围 | **支持,3D 球冠几何** | 探测范围从纯水平面圆升级为以设备为中心的三维球冠(详见 14.2.1);几何参数随装备配置录入(详见 14.7) |
|
||||
|
||||
### 14.7 数据模型变更(实现清单)
|
||||
|
||||
实现实时探测 + 3D 球冠所需的数据模型改动,集中在此便于落地追踪:
|
||||
|
||||
| 改动项 | 位置 | 内容 | 状态 |
|
||||
|--------|------|------|------|
|
||||
| **EquipmentDeployment 表加字段** | 4.3 | `MinElevation`/`MaxElevation`(度)、`MinDetectAlt`/`MaxDetectAlt`(m),均可空 | 待加列 |
|
||||
| **DetectionSource 类加字段** | 14.5.1 | 同上 4 个三维几何字段 | 待加属性 |
|
||||
| **DetectionCalculator.IsInCoverage** | 14.2.1 | 三维球冠判定(水平距离 + 俯仰角 + 高度门限),planner 与实时探测共用 | 待实现 |
|
||||
| **DetectionCalculator.EffectiveRange** | 14.2 | 现有签名不变(返回综合水平距离基准),3D 判定在其上层 | 已实现(基础) |
|
||||
| **planner 适配 3D** | 14.2.1 | `EarliestDetection` 由"线段-圆求交"改为"沿航路采样点调 IsInCoverage" | 待改造 |
|
||||
| **SimulationEngine 加 _detectionEntities** | 5.1 | Initialize 时从配置构建 `List<DetectionEntity>`,Tick 第5步遍历 | 待实现 |
|
||||
| **Tick 第5步实时探测** | 5.3 / 14.5.2 | 扫描 + 状态机 + 决策1/2/3/4 落地,触发 `TargetDetected` | 待实现 |
|
||||
|
||||
> **数据库迁移**:`EquipmentDeployment` 新增 4 列均为 NULLABLE,不影响存量数据;`SimulationEngine.BuildDetectionSources` 读取新字段构造 `DetectionSource`(缺失时按"无角度/高度限制"的退化球冠处理,等价当前 2D 行为,保证平滑过渡)。
|
||||
|
||||
---
|
||||
|
||||
## 十五、待后续讨论
|
||||
|
||||
| # | 议题 | 说明 |
|
||||
|---|------|------|
|
||||
| 1 | 第三方 DLL 的具体接口规范 | 需与供应商对齐函数签名、数据结构、调用约定 |
|
||||
| 2 | 3 种毁伤机制的差异化细节 | 吸入式灭火 vs 爆燃式 vs 吸入式爆炸的毁伤曲线差异 |
|
||||
| 3 | 探测设备融合逻辑 | 多设备发现同一目标时的数据融合策略 |
|
||||
| 4 | 火控分配策略 | 多目标时的优先级分配规则 |
|
||||
| 3 | 探测设备融合逻辑 | 多设备发现同一目标时的数据融合策略(→ 见 14.6 待决策 #2) |
|
||||
| 4 | 火控分配策略 | 多目标时的优先级分配规则(→ 实时探测接入后见 14.6 待决策 #3) |
|
||||
| 5 | 蜂群模式运动模型 | 随机扰动范围、个体行为差异 |
|
||||
| 6 | 报告模板具体格式 | 统计维度、图表需求 |
|
||||
| 7 | 场景类型对仿真的影响 | 山区是否影响探测/运动 |
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
类型、数量、挂载气溶胶的类型、数量(一发炮弹打出的云团大概覆盖体积)
|
||||
|
||||
根据算法自动推荐晕图案的抛洒位置、抛洒时机,
|
||||
根据算法自动推荐云团的抛洒位置、抛洒时机,
|
||||
最佳值和最危险值
|
||||
]:支持自定义云团的抛撒位置、抛撒时机、风速风向参数。
|
||||
(2)目标配置:预置典型目标库,包括多种无人机。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user