diff --git a/docs/design/technical/DefensePlanner-技术方案.md b/docs/design/technical/DefensePlanner-技术方案.md new file mode 100644 index 0000000..c4e643f --- /dev/null +++ b/docs/design/technical/DefensePlanner-技术方案.md @@ -0,0 +1,363 @@ +# DefensePlanner 防御规划引擎 — 技术方案 + +- **版本**:V2 +- **日期**:2026-06-12 +- **状态**:已定稿 + +--- + +## 1. 概述 + +DefensePlanner 是防御推荐模块的核心引擎。它接收**可用火力单元池**和**威胁编队列表**,综合考虑弹药匹配、空间可达性、时间约束、资源竞争,输出**最优分配方案**和**临界边际方案**。 + +**当前问题**: + +- `DefaultDefenseAdvisor` 本质是"单威胁 → 单方案"的规则匹配器 +- `Recommend()` 接收 `ThreatProfile`(不含火力单元信息),无法做资源分配 +- `RecommendMultiGroup()` 接收 `List`,但决策逻辑简单(先到先服务) +- 空基/地基平台类型通过 `PreferredPlatformType` 开关绕过,而非算法自主选择 + +**目标**:统一的规划入口,给定火力单元池和威胁列表,输出分配方案。 + +--- + +## 2. 输入模型 + +### 2.1 FireUnit(火力单元) + +统一表达空基和地基平台,作为规划器的基本资产单元: + +```csharp +class FireUnit { + string Id; // 唯一标识 + PlatformType Type; // AirBased / GroundBased + Vector3 Position; // 待命坐标(空基含巡航高度) + float CruiseSpeed; // 空基巡航速度 m/s;地基 = 0 + float ReleaseAltitude; // 空基投放高度 m + float MuzzleVelocity; // 地基初速 m/s + int TotalMunitions; // 总载弹量(一次部署的总弹药数) + List AmmoTypes; // 可装填的弹药类型(支持多弹种) + float Cooldown; // 同弹种连发间隔 s + float AmmoChangeTime; // 更换弹种所需时间 s +} +``` + +> 与当前 `FireUnit`(`AlgorithmTypes.cs`)的区别:新增 `Type`、`CruiseSpeed`、`ReleaseAltitude`、`MuzzleVelocity`、`TotalMunitions`、`AmmoTypes`(重命名自 `AvailableAmmo`)。 + +### 2.2 DroneGroup(威胁编队) + +```csharp +class DroneGroup { + string GroupId; // 编队 ID + TargetConfig Target; // 类型、数量、动力、翼展、速度、高度 + List Waypoints; // 航路点 + float ArrivalTime; // 预计算:到达防御区域中点的时间 s +} +``` + +### 2.3 CombatScene(作战环境) + +沿用现有的 `CombatScene`,提供风速、风向、天气等影响扩散模型计算的参数。 + +--- + +## 3. 输出模型 + +### 3.1 UnitAssignment(单元分配) + +```csharp +class UnitAssignment { + string FireUnitId; // 分配到的火力单元 + string DroneGroupId; // 对抗的威胁编队 + AerosolType AmmoType; // 装填的弹药类型 + int RoundsFired; // 本次发射几发 + float FirstFireTime; // 首发发射时机 s + List FireEvents; // 具体发射事件(含位置、时间) +} +``` + +### 3.2 DefensePlan(规划结果) + +```csharp +class DefensePlan { + List Assignments; // 分配方案 + List MergedSchedule; // 合并后的发射计划(排序) + float OverallProbability; // 总体拦截概率估计 + int ThreatsEngaged; // 被分配方案的威胁数 + int ThreatsUnengaged; // 无法分配方案的威胁数 + string Summary; // 人类可读概览 +} +``` + +### 3.3 DefensePlanner 输出 + +```csharp +class PlannerResult { + DefensePlan Best; // 最优方案 + DefensePlan Critical; // 临界方案(刚好有效) +} +``` + +--- + +## 4. 内部流程(五步法) + +``` +输入:List + List + CombatScene + │ + ▼ +Step 1 — 威胁排序 + │ 威胁指数 = 速度系数 × 目标类型系数(可扩展重量、载弹量等) + │ 综合优先级 = 威胁指数 / (到达时间 + 1) + │ 同到达时间下高威胁优先 + │ + ▼ +Step 2 — 弹药匹配 + │ PowerType → AerosolType(规则表) + │ 输出:每个威胁需要的弹药类型 + │ + ▼ +Step 3 — 候选生成 + │ 对每个(威胁, 火力单元)组合: + │ ① 弹药兼容性检查 + │ ② 空间可达性(地基:弹道射程;空基:飞行距离) + │ ③ 时间窗口计算(最早/最晚拦截时机) + │ 输出:List + │ + ▼ +Step 4 — 分配求解 + │ 贪心策略(v1,后续可升级回溯/匈牙利): + │ 按威胁优先级遍历 + │ → 选最早可拦截的兼容单元 + │ → 弹药必须精确匹配,不降级(ActiveMaterial 不能替代 InertGas) + │ → 标记单元占用(冷却 + 换弹 + 飞行时间) + │ → 弹药耗尽则移除 + │ + ▼ +Step 5 — 时序生成 + │ 对每个分配: + │ 地基:FireTime = 最佳交汇时刻 − 炮弹飞行时间 + │ 空基:FireTime = 最佳交汇时刻 − 平台飞行时间 − 弹药下落时间 + │ 合并排序 → MergedFireSchedule + │ + ▼ +输出:PlannerResult { Best, Critical } +``` + +--- + +## 5. 关键算法详设 + +### 5.1 威胁排序 + +**威胁指数** = 速度系数 × 目标类型系数(后续可扩展重量、载弹量等要素) + +| 目标类型 | 类型系数 | 理由 | +|----------|:------:|------| +| 高速目标(300km/h+) | 4 | 最快突防 | +| 喷气式 | 3 | 高温发动机,毁伤窗口短 | +| 固定翼 | 2 | 速度中等 | +| 活塞式 | 2 | 速度中等 | +| 旋翼 | 1 | 慢速 | +| 电推 | 1 | 慢速,无热源 | + +速度系数 = TypicalSpeed / 60(以 60 km/h 为基准归一化) + +**综合优先级** = 威胁指数 / (ArrivalTime + 1),按降序排列。同到达时间下高威胁优先。 + +### 5.2 InterceptCandidate(拦截候选) + +```csharp +class InterceptCandidate { + FireUnit Unit; + AerosolType AmmoType; + float EarliestTime; // 最早可拦截时刻(仿真秒) + float LatestTime; // 最晚可拦截时刻 + float Coverage; // 有效覆盖时长 + float KillProbability; // 预计杀伤概率 +} +``` + +**候选生成逻辑**: + +对于给定的威胁编队和火力单元: + +1. **弹药兼容性**:`Unit.AmmoTypes` 包含威胁需要的弹药类型 +2. **地基可达性**:计算目标与部署点的水平距离,校验 `MuzzleVelocity` 射程 +3. **空基可达性**:计算飞行距离,`飞行时间 = distance(巡逻点, 投放点) / CruiseSpeed` +4. **时间窗口**: + - 威胁到达防御区域的时间段 `[tEnter, tExit]` + - 单元可拦截的时间段 = 威胁窗口 ∩(单元可用时间 + 弹药飞行时间) + - 空基额外加平台飞行时间 +5. **覆盖率**:基于云团有效半径、持续时间、无人机速度的综合估计 + +### 5.3 贪心分配算法 + +``` +pending = threats.OrderBy(t => t.ArrivalTime) +available = fireUnits.Clone() + +timeNow = 0 +assignments = [] + +for each threat in pending: + candidates = GenerateCandidates(threat, available, timeNow) + if candidates.isEmpty: + threats.Unengaged++ + continue + + best = candidates.OrderBy(c => c.EarliestTime) + .ThenByDescending(c => c.KillProbability) + .First() + + assignment = Commit(best, threat) + assignments.Add(assignment) + + // 更新单元状态 + unit = best.Unit + unit.TotalMunitions -= assignment.RoundsFired + timeNow = max(timeNow, assignment.LastFireTime + unit.Cooldown) +``` + +### 5.4 临界方案(Critical Plan) + +临界方案 = 刚好达到可接受下限概率(默认 50%)的最小配置: +- 从最优方案的分配列表出发 +- 逐次减少每个单元分配的弹药数 +- 直到整体拦截概率刚好跌破 50% +- 上一轮(≥50% 的最小配置)即为临界方案 + +> 作用:给操作员一个置信区间——最优 vs 临界,展示"再少就不够了"的底线。 + +### 5.5 多编队合并 + +``` +Step 4 的贪心算法天然支持多威胁: + - 按优先级顺序处理 + - 前一威胁占用的单元在后续威胁中不可用(直到冷却/换弹完成) + - 弹药消耗全局追踪 +``` + +--- + +## 6. 接口设计 + +### 6.1 规划器接口 + +```csharp +public interface IDefensePlanner +{ + /// 为给定火力单元池和威胁列表生成规划方案 + PlannerResult Plan(List fireUnits, List threats, CombatScene environment); +} +``` + +### 6.2 兼容现有接口 + +`DefaultDefenseAdvisor` 改造为 `DefaultDefensePlanner`: + +```csharp +public class DefaultDefensePlanner : IDefensePlanner +{ + private readonly List _ammoCatalog; + + public DefaultDefensePlanner(List ammoCatalog) { ... } + + public PlannerResult Plan(List fireUnits, List threats, CombatScene env) + { + // Step 1-5 + } + + // 内部方法 + private List Prioritize(List threats) { ... } + private AerosolType MatchAmmo(PowerType power) { ... } + private List GenerateCandidates(DroneGroup threat, List units, float now) { ... } + private DefensePlan Solve(List threats, List units) { ... } + private DefensePlan DeriveCritical(DefensePlan best) { ... } +} +``` + +### 6.3 现有接口迁移 + +| 旧接口 | 新接口 | 状态 | +|--------|--------|------| +| `IDefenseAdvisor.Recommend(ThreatProfile)` | `IDefensePlanner.Plan(fireUnits, threats, env)` | 替换 | +| `IDefenseAdvisor.GetDefenseRecommendation(taskId)` | ScenarioService 调用 Planner | 保持 | +| `DefaultDefenseAdvisor.RecommendMultiGroup()` | Planner 原生支持多编队 | 删除 | + +--- + +## 7. 数据流改造 + +``` +ScenarioService.GetTaskDetail(taskId) + │ + │ // 组装输入 + ├── 收集 EquipmentDeployment → List + ├── 收集 TargetConfig + RoutePlan + Waypoint → List + └── CombatScene + │ + ▼ +IDefensePlanner.Plan(fireUnits, threats, env) + │ + ▼ +PlannerResult + ├── DefensePlan.Best + │ ├── Assignments → 写入 EquipmentDeployment(更新 PlatformType/AerosolType/MunitionCount 等) + │ └── MergedSchedule → 传给 SimulationEngine.SetFireSchedule() + └── DefensePlan.Critical + └── Assignments → 存入 CloudDispersal 的 Critical* 字段 +``` + +--- + +## 8. 与现有代码的关系 + +### 保留 + +- `Kinematics` 弹道/运动学工具类(被 Step 3/5 调用) +- `GaussianPuffDispersion` 扩散模型(被 Step 3 调用计算覆盖率) +- `DamageModelRouter` 毁伤模型(不影响规划) +- `FireEvent` / `FireSchedule`(Step 5 输出) +- `AmmunitionSpec` 弹药参数(弹药匹配和覆盖率计算) + +### 修改 + +- `DefaultDefenseAdvisor` → 改名为 `DefaultDefensePlanner`,实现 `IDefensePlanner` +- `AlgorithmTypes.FireUnit` → 扩展字段(Type, CruiseSpeed, ReleaseAltitude, MuzzleVelocity, TotalMunitions) +- `AlgorithmTypes.ThreatProfile` → 简化或废弃,输入直接使用 `DroneGroup` 列表 +- `AlgorithmTypes.DefenseRecommendation` → 替换为 `PlannerResult` + +### 删除 + +- `AlgorithmTypes.DroneGroup.GetArrivalTime()` → 移入规划器 +- `AlgorithmTypes.DefenseSolution` → 替换为 `DefensePlan` +- `IDefenseAdvisor` → 替换为 `IDefensePlanner` +- `AlgorithmFactory` 中 `IDefenseAdvisor` 注册 → 改为 `IDefensePlanner` + +### 不变 + +- `SimulationEngine` — 不感知 Planner,只接收 `FireSchedule` +- `ScenarioService` — 接口不变,内部调用 Planner +- 所有 Repository、数据模型(EquipmentDeployment 等)— 不需要改 + +--- + +## 9. 风险与应对 + +| 风险 | 影响 | 应对 | +|------|------|------| +| 贪心算法局部最优,整体非最优 | 部分威胁可能被跳过 | 后续可升级为匈牙利算法或回溯搜索;贪心结果对大多数场景足够 | +| 覆盖率估算依赖简化模型 | 拦截概率不精确 | 使用现有的 `GaussianPuffDispersion` + `Kinematics`,与仿真引擎一致 | +| 空基/地基混合分配复杂 | 边界情况遗漏 | Step 3 候选生成对每种平台类型独立计算,Step 4 统一排序;单元测试覆盖典型混合场景 | + +--- + +## 10. 已决策事项 + +| # | 议题 | 决策 | +|---|------|------| +| 1 | 威胁排序 | 综合威胁指数:类型系数(高速4/喷气3/固定翼2/活塞2/旋翼1/电推1)× 速度系数(km/h ÷ 60),除以到达时间。可扩展重量、载弹量等要素 | +| 2 | 临界方案 | 概率阈值定义:刚好 ≥ 50% 的最小资源配置 | +| 3 | 分配算法 | v1 贪心;后续按需升级回溯搜索或匈牙利算法 | +| 4 | Failover | 不做降级。弹药必须精确匹配(ActiveMaterial 不能替代 InertGas) |