From 0a3c444a4b5ed15d2a9c0de4f289334cefe16f59 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Fri, 12 Jun 2026 17:52:44 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=8E=A8=E8=8D=90=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E7=BB=9F=E4=B8=80=E5=A4=84=E7=90=86=E7=A9=BA=E5=9F=BA?= =?UTF-8?q?/=E5=9C=B0=E5=9F=BA=E5=B9=B3=E5=8F=B0=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ThreatProfile 新增 PreferredPlatformType 字段 - DefaultDefenseAdvisor 根据平台类型正确计算 FireTime/CruiseSpeed/ReleaseAltitude - 空基:FireTime 提前扣除飞行+下落时间;地基:保持原逻辑 - 删除 SimulationEngine.AdjustFireTimesForAirBased(引擎不再做适配) - 集成测试直接用 PreferredPlatformType 驱动空基方案 - 实施文档同步 --- .../tasks/实施计划与任务跟踪.md | 2 +- .../Algorithms/AlgorithmTypes.cs | 2 + .../Algorithms/DefaultDefenseAdvisor.cs | 72 ++++++++++++------- .../Simulation/SimulationEngine.cs | 26 ------- .../FullPipelineTests.cs | 34 +++------ 5 files changed, 60 insertions(+), 76 deletions(-) diff --git a/docs/implementation/tasks/实施计划与任务跟踪.md b/docs/implementation/tasks/实施计划与任务跟踪.md index 392ebce..2e487ec 100644 --- a/docs/implementation/tasks/实施计划与任务跟踪.md +++ b/docs/implementation/tasks/实施计划与任务跟踪.md @@ -160,7 +160,7 @@ Phase 8 ⬜ 待开发 |---|------|------| | 8.1.1 | 探测设备搜索逻辑 | `DetectionEntity` 类已存在,需接入 `SimulationEngine` 实现探测→火控链路闭环 | | 8.1.2 | 蜂群运动模型 | `FormationMode.Swarm` 枚举已定义,需差异化行为(随机扰动、个体差异) | -| 8.1.3 | 空基平台飞行动态 | `PlatformEntity` 状态机(Idle→FlyingToTarget→ReadyToRelease),巡航飞行,弹药继承载机速度下落,`Kinematics` 工具类支撑,集成测试通过 | ✅ | +| 8.1.3 | 空基平台飞行动态 | ✅ `PlatformEntity` 状态机,巡航飞行,弹药继承载机速度。**推荐算法统一处理平台类型**,`ThreatProfile.PreferredPlatformType` 驱动,`DefaultDefenseAdvisor` 根据类型正确计算 `FireTime`/`CruiseSpeed`/`ReleaseAltitude`。引擎零适配逻辑 | ✅ | | 8.1.4 | 预置典型目标库 | 具体无人机型号 JSON 配置(如 DJI Mavic 3、Shahed-136 等),导入 `TargetConfig` 默认值 | | 8.1.5 | 毁伤曲线参数校准 | 三种毁伤模型的 damageRate/threshold/burstDamage 需甲方/领域专家确认后写入 | diff --git a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs index 0544ff0..4c78eb1 100644 --- a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs +++ b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs @@ -11,6 +11,8 @@ namespace CounterDrone.Core.Algorithms public RoutePlan Route { get; set; } = new(); public List Waypoints { get; set; } = new(); public List ControlZones { get; set; } = new(); + /// 偏好平台类型(null = 算法自行决定,当前默认地基) + public PlatformType? PreferredPlatformType { get; set; } } /// 防御推荐方案 diff --git a/src/CounterDrone.Core/Algorithms/DefaultDefenseAdvisor.cs b/src/CounterDrone.Core/Algorithms/DefaultDefenseAdvisor.cs index 177234c..09334f8 100644 --- a/src/CounterDrone.Core/Algorithms/DefaultDefenseAdvisor.cs +++ b/src/CounterDrone.Core/Algorithms/DefaultDefenseAdvisor.cs @@ -105,20 +105,58 @@ namespace CounterDrone.Core.Algorithms var expansionTime = (float)Math.Pow((effectiveR - r0) / k, 2); var recommendedTiming = halfTime - expansionTime; - // 生成发射计划 + // 平台类型 + var platType = threat.PreferredPlatformType ?? PlatformType.GroundBased; + var isAirBased = platType == PlatformType.AirBased; + + // 空基参数 + var cruiseSpeed = 55f; // ~200 km/h + var releaseAlt = isAirBased ? (float)target.TypicalAltitude + 500f : 0f; + var fallTime = isAirBased ? Kinematics.AirDropFallTime(releaseAlt, (float)target.TypicalAltitude) : 0f; + + // 生成发射计划和平台部署 var fireSchedule = new List(); + var platforms = new List(); + var gunCount = roundsNeeded; + for (int i = 0; i < roundsNeeded; i++) { var offset = (i - (roundsNeeded - 1) / 2f) * spacing; - fireSchedule.Add(new FireEvent + var tx = mid.X + offset; var ty = mid.Y; var tz = mid.Z; + + if (isAirBased) { - FireTime = recommendedTiming, - PlatformIndex = i % roundsNeeded, - TargetX = mid.X + offset, - TargetY = mid.Y, - TargetZ = mid.Z, - MuzzleVelocity = 800f, - }); + // 巡逻点:防御圈边缘,偏离目标侧方 + var patrolX = mid.X - 2000; + var patrolY = 2500f; + var patrolZ = mid.Z - 2000; + var flightDist = Kinematics.Distance3D(patrolX, patrolY, patrolZ, tx, releaseAlt, tz); + var flightTime = flightDist / cruiseSpeed; + var fireTime = recommendedTiming - flightTime - fallTime; + if (fireTime < 0.1f) fireTime = 0.1f; + + fireSchedule.Add(new FireEvent { FireTime = fireTime, PlatformIndex = i, TargetX = tx, TargetY = ty, TargetZ = tz, MuzzleVelocity = 0f }); + platforms.Add(new RecommendedPlatform + { + Type = PlatformType.AirBased, + Position = new Vector3(patrolX + i * 30, patrolY, patrolZ), + Quantity = 1, MunitionCount = 1, + CruiseSpeed = cruiseSpeed, ReleaseAltitude = releaseAlt, + Cooldown = 5f, CoverageVolume = (float)ammo.InitialVolume, + }); + } + else + { + fireSchedule.Add(new FireEvent { FireTime = recommendedTiming, PlatformIndex = i, TargetX = tx, TargetY = ty, TargetZ = tz, MuzzleVelocity = 800f }); + platforms.Add(new RecommendedPlatform + { + Type = PlatformType.GroundBased, + Position = new Vector3(mid.X + i * 50, 0, 50), + Quantity = 1, MunitionCount = 1, + MuzzleVelocity = 800f, Cooldown = 5f, + CoverageVolume = (float)ammo.InitialVolume, + }); + } } var bestCloud = new CloudDispersal @@ -138,22 +176,6 @@ namespace CounterDrone.Core.Algorithms EstimatedProbability = prob, }; - // 平台部署:假设齐射(同时发射),每门炮打一发后冷却 5s - // 需要 roundsNeeded 门炮同时发射 - var gunCount = roundsNeeded; - var platforms = new List(); - for (int i = 0; i < gunCount; i++) - platforms.Add(new RecommendedPlatform - { - Type = PlatformType.GroundBased, - Position = new Vector3(mid.X + i * 50, 0, 50), - Quantity = 1, - MunitionCount = 1, - CoverageVolume = (float)ammo.InitialVolume, - Cooldown = 5f, - MuzzleVelocity = 800f, - }); - result.Best = new DefenseSolution { RecommendedAerosolType = aerosolType, diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index bdb55d5..54ffb51 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -114,7 +114,6 @@ namespace CounterDrone.Core.Simulation SimulationTime = 0; _entityCounter = 0; _nextFireIndex = 0; - AdjustFireTimesForAirBased(); _frameDb = _frameStore.CreateOrOpen(_taskId); State = SimulationState.Running; } @@ -265,31 +264,6 @@ namespace CounterDrone.Core.Simulation public void Resume() { if (State == SimulationState.Paused) State = SimulationState.Running; } public void Stop() { State = SimulationState.Stopped; _frameDb?.Close(); } - /// 为空基平台提前发射时间,补偿飞行耗时 - private void AdjustFireTimesForAirBased() - { - for (int i = 0; i < _fireSchedule.Count; i++) - { - var fe = _fireSchedule[i]; - if (fe.PlatformIndex >= _platforms.Count) continue; - var p = _platforms[fe.PlatformIndex]; - if (p.PlatformType != Models.PlatformType.AirBased) continue; - - var releaseAlt = p.ReleaseAltitude > 0 ? p.ReleaseAltitude : _disperseHeight; - float dx = fe.TargetX - p.PatrolX; - float dy = releaseAlt - p.PatrolY; - float dz = fe.TargetZ - p.PatrolZ; - float flightDist = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz); - float flightTime = flightDist / (p.CruiseSpeed > 0.1f ? p.CruiseSpeed : 55f); - float fallTime = Kinematics.AirDropFallTime(releaseAlt, _disperseHeight); - - fe.FireTime -= flightTime + fallTime; - if (fe.FireTime < 0) fe.FireTime = 0.1f; - } - _fireSchedule.Sort((a, b) => a.FireTime.CompareTo(b.FireTime)); - _nextFireIndex = 0; - } - private List CollectSnapshots() { var list = new List(); diff --git a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs index 6ce1487..da24b1e 100644 --- a/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs +++ b/test/unit/CounterDrone.Core.Tests/FullPipelineTests.cs @@ -78,7 +78,7 @@ namespace CounterDrone.Core.Tests } /// 将 DefenseAdvisor 推荐方案写入想定 - private DefenseRecommendation GetAndApplyRecommendation() + private DefenseRecommendation GetAndApplyRecommendation(PlatformType? preferredPlatform = null) { var detail = _scenario.GetTaskDetail(_taskId)!; var threat = new ThreatProfile @@ -87,6 +87,7 @@ namespace CounterDrone.Core.Tests Targets = detail.Targets, Route = detail.Routes[0], Waypoints = detail.WaypointGroups["default"], + PreferredPlatformType = preferredPlatform, }; var rec = new DefaultDefenseAdvisor(_ammoCatalog).Recommend(threat); @@ -115,7 +116,9 @@ namespace CounterDrone.Core.Tests AerosolType = (int)rec.Best.RecommendedAerosolType, MunitionCount = p.MunitionCount, Cooldown = p.Cooldown, - MuzzleVelocity = p.MuzzleVelocity, + MuzzleVelocity = p.MuzzleVelocity > 0 ? p.MuzzleVelocity : null, + CruiseSpeed = p.CruiseSpeed > 0 ? p.CruiseSpeed : null, + ReleaseAltitude = p.ReleaseAltitude > 0 ? p.ReleaseAltitude : null, }); _scenario.SaveDeployment(_taskId, equips); _lastFireSchedule = rec.Best.FireSchedule; @@ -364,30 +367,13 @@ namespace CounterDrone.Core.Tests new Waypoint { PosX = 15000, PosY = 500, PosZ = 0, Speed = 300 }, }); - // 先用推荐算法生成方案 - var rec = GetAndApplyRecommendation(); + // 用推荐算法生成空基方案 + var rec = GetAndApplyRecommendation(PlatformType.AirBased); Assert.NotNull(rec.Best.FireSchedule); Assert.True(rec.Best.FireSchedule.Count > 0); + Assert.Equal(PlatformType.AirBased, rec.Best.Platforms[0].Type); + Assert.True(rec.Best.Platforms[0].CruiseSpeed > 0); - // 将推荐的地基平台改为空基:巡逻点在防御圈边缘空中 - var saved = _scenario.GetTaskDetail(_taskId)!; - var midX = (float)(saved.Cloud.PositionX); - var airEquips = new List(); - foreach (var e in saved.Equipment.Where(eq => eq.EquipmentRole == (int)EquipmentRole.LaunchPlatform)) - { - e.PlatformType = (int)Models.PlatformType.AirBased; - // 巡逻点:防御圈边缘,侧方 2000m,高度 2500m 巡航 - e.PositionX = midX - 2000; - e.PositionY = 2500; - e.PositionZ = -2000; - e.CruiseSpeed = 55; // ~200 km/h - e.ReleaseAltitude = 1500; // 投放高度 - e.MuzzleVelocity = null; // 空基不需要炮口初速 - airEquips.Add(e); - } - _scenario.SaveDeployment(_taskId, airEquips); - - // 更新 FireSchedule:引擎初始化时会自动 AdjustFireTimesForAirBased _lastFireSchedule = rec.Best.FireSchedule; var eng = RunSimulation(8000); @@ -396,7 +382,7 @@ namespace CounterDrone.Core.Tests var cloudsGenerated = eng.Events.Count(e => e.Type == SimEventType.CloudGenerated); var drone = eng.Drones[0]; - var msg = $"AirBased: platforms={airEquips.Count}, launched={launched}, clouds={cloudsGenerated}, " + + var msg = $"AirBased: platforms={rec.Best.Platforms.Count}, launched={launched}, clouds={cloudsGenerated}, " + $"droneStatus={drone.Status}, hp={drone.Hp:F3}, simTime={eng.SimulationTime:F1}s"; Assert.True(launched > 0, msg);