CounterDroneBackend/docs/design/technical/DefensePlanner-技术方案.md
tian 4e157834f7 docs: 总体架构V9 + DefensePlanner V3 同步当前实现
- 架构文档: IDefenseAdvisor→IDefensePlanner 全量替换,架构图更新
- DefensePlanner: FireUnit模型补全通道/检测字段,数据流改为引擎内部调用
- 旧接口迁移表标记完成,实现状态分已实现/已删除/不变
2026-06-13 12:40:54 +08:00

12 KiB
Raw Blame History

DefensePlanner 防御规划引擎 — 技术方案

  • 版本V3
  • 日期2026-06-13
  • 状态:已实现

1. 概述

DefensePlanner 是防御推荐模块的核心引擎。它接收可用火力单元池威胁编队列表,综合考虑弹药匹配、空间可达性、时间约束、资源竞争,输出最优分配方案临界边际方案

当前问题

  • DefaultDefenseAdvisor 本质是"单威胁 → 单方案"的规则匹配器
  • Recommend() 接收 ThreatProfile(不含火力单元信息),无法做资源分配
  • RecommendMultiGroup() 接收 List<FireUnit>,但决策逻辑简单(先到先服务)
  • 空基/地基平台类型通过 PreferredPlatformType 开关绕过,而非算法自主选择

目标:统一的规划入口,给定火力单元池和威胁列表,输出分配方案。


2. 输入模型

2.1 FireUnit火力单元

统一表达空基和地基平台,作为规划器的基本资产单元:

class FireUnit {
    string Id;                         // 唯一标识
    PlatformType Type;                 // AirBased / GroundBased
    Vector3 Position;                  // 待命坐标(空基含巡航高度)
    // ── 发射装置 ──
    int GunCount;                      // 火炮数量(默认 1
    int ChannelsPerGun;                // 每炮火力通道数(默认 1
    int TotalChannels => GunCount * ChannelsPerGun;
    float ChannelInterval;             // 同通道连发最小间隔 s
    // ── 弹药 ──
    int TotalMunitions;                // 总载弹量
    List<AerosolType> AmmoTypes;       // 可装填的弹药类型
    float Cooldown;                    // 通道冷却时间 s
    float AmmoChangeTime;              // 更换弹种时间 s
    // ── 搜索跟踪 ──
    float RadarRange;                  // 雷达探测距离 m
    float EORange;                     // 光电探测距离 m
    float IRRange;                     // 红外探测距离 m
    // ── 空基 ──
    float CruiseSpeed;                 // 巡航速度 m/s
    float ReleaseAltitude;             // 投放高度 m
    // ── 地基 ──
    float MuzzleVelocity;              // 初速 m/s
}

2.2 DroneGroup威胁编队

class DroneGroup {
    string GroupId;                    // 编队 ID
    TargetConfig Target;               // 类型、数量、动力、翼展、速度、高度
    List<Waypoint> Waypoints;          // 航路点
    float ArrivalTime;                 // 预计算:到达防御区域中点的时间 s
}

2.3 CombatScene作战环境

沿用现有的 CombatScene,提供风速、风向、天气等影响扩散模型计算的参数。


3. 输出模型

3.1 UnitAssignment单元分配

class UnitAssignment {
    string FireUnitId;                 // 分配到的火力单元
    string DroneGroupId;               // 对抗的威胁编队
    AerosolType AmmoType;              // 装填的弹药类型
    int RoundsFired;                   // 本次发射几发
    float FirstFireTime;               // 首发发射时机 s
    List<FireEvent> FireEvents;        // 具体发射事件(含位置、时间)
}

3.2 DefensePlan规划结果

class DefensePlan {
    List<UnitAssignment> Assignments;  // 分配方案
    List<FireEvent> MergedSchedule;    // 合并后的发射计划(排序)
    float OverallProbability;          // 总体拦截概率估计
    int ThreatsEngaged;                // 被分配方案的威胁数
    int ThreatsUnengaged;              // 无法分配方案的威胁数
    string Summary;                    // 人类可读概览
}

3.3 DefensePlanner 输出

class PlannerResult {
    DefensePlan Best;                  // 最优方案
    DefensePlan Critical;              // 临界方案(刚好有效)
}

4. 内部流程(五步法)

输入List<FireUnit> + List<DroneGroup> + CombatScene
  │
  ▼
Step 1 — 威胁排序
  │  威胁指数 = 速度系数 × 目标类型系数(可扩展重量、载弹量等)
  │  综合优先级 = 威胁指数 / (到达时间 + 1)
  │  同到达时间下高威胁优先
  │
  ▼
Step 2 — 弹药匹配
  │  PowerType → AerosolType规则表
  │  输出:每个威胁需要的弹药类型
  │
  ▼
Step 3 — 候选生成
  │  对每个(威胁, 火力单元)组合:
  │    ① 弹药兼容性检查
  │    ② 空间可达性(地基:弹道射程;空基:飞行距离)
  │    ③ 时间窗口计算(最早/最晚拦截时机)
  │  输出List<InterceptCandidate>
  │
  ▼
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拦截候选

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 规划器接口

public interface IDefensePlanner
{
    /// <summary>为给定火力单元池和威胁列表生成规划方案</summary>
    PlannerResult Plan(List<FireUnit> fireUnits, List<DroneGroup> threats, CombatScene environment);
}

6.2 兼容现有接口

DefaultDefenseAdvisor 改造为 DefaultDefensePlanner

public class DefaultDefensePlanner : IDefensePlanner
{
    private readonly List<AmmunitionSpec> _ammoCatalog;

    public DefaultDefensePlanner(List<AmmunitionSpec> ammoCatalog) { ... }

    public PlannerResult Plan(List<FireUnit> fireUnits, List<DroneGroup> threats, CombatScene env)
    {
        // Step 1-5
    }

    // 内部方法
    private List<DroneGroup> Prioritize(List<DroneGroup> threats) { ... }
    private AerosolType MatchAmmo(PowerType power) { ... }
    private List<InterceptCandidate> GenerateCandidates(DroneGroup threat, List<FireUnit> units, float now) { ... }
    private DefensePlan Solve(List<DroneGroup> threats, List<FireUnit> units) { ... }
    private DefensePlan DeriveCritical(DefensePlan best) { ... }
}

6.3 接口迁移(已完成)

旧接口 新接口 状态
IDefenseAdvisor.Recommend(ThreatProfile) IDefensePlanner.Plan(fireUnits, threats, env) 已替换
IDefenseAdvisor.GetDefenseRecommendation(taskId) 不再需要 已删除
DefaultDefenseAdvisor.RecommendMultiGroup() Planner 原生支持多编队 已删除

7. 数据流改造(已实现)

SimulationEngine.Initialize(taskId)
  │
  │  // 引擎内部组装
  ├── BuildFireUnits(config)     → List<FireUnit>
  ├── BuildDroneGroups(config)   → List<DroneGroup>
  └── _scene (CombatScene)
  │
  ▼
IDefensePlanner.Plan(fireUnits, threats, scene)
  │
  ▼
PlannerResult.Best.MergedSchedule
  │
  ▼
引擎 Tick() 按发射计划执行

引擎是 Planner 的唯一调用者。测试和 UI 代码不再直接接触 Planner。


8. 实现状态

已实现

  • IDefensePlanner + DefaultDefensePlanner(五步流水线)
  • FireUnit 通道模型GunCount/ChannelsPerGun/ChannelInterval/搜索跟踪设备)
  • 贪心分配 + 物理间隔错发 + 按目标点独立计时
  • 空基/地基弹道统一处理
  • SimulationEngine 内部调用 Planner 自动生成发射计划
  • DefaultFireUnits 4 种模板
  • 报告显示 per-unit 发射数和火力单元列
  • 所有硬编码默认值和静默 fallback 已删除

已删除

  • IDefenseAdvisor / DefaultDefenseAdvisor / RecommendMultiGroup
  • ThreatProfile / DefenseSolution / DefenseRecommendation / MultiGroupRecommendationAlgorithmTypes 中保留但未使用)
  • Models.SimEvent(死代码)
  • 所有 ?. + 任意默认值模式

🔒 不变

  • Kinematics / GaussianPuffDispersion / DamageModelRouter
  • 所有 Repository 和数据模型EquipmentDeployment 新增 GunCount/ChannelsPerGun/ChannelInterval
  • ScenarioService 接口

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