feat: Planner→FireEvent 传递发射角; MunitionEntity 使用 planner 提供的角度(不再重算)

This commit is contained in:
tian 2026-06-17 08:20:54 +08:00
parent 3fd8433276
commit 69e41e3f7c
3 changed files with 20 additions and 20 deletions

View File

@ -366,13 +366,7 @@ namespace CounterDrone.Core.Algorithms
if (dist > maxRange) return null;
float shellTime = dist / unit.MuzzleVelocity;
// 用 InterceptCalculator 验证可行性 + 获取发射角
float speedKph = GetDroneSpeedKph(threat);
var (interceptArc, _, launchAngle) = InterceptCalculator.Compute(
threat.Waypoints, threat.DetectArc, speedKph,
_config.ReactionTime + expansionTime, unit.Position, unit.MuzzleVelocity);
if (interceptArc <= 0) return null;
if (!HasInterceptWindow(threat, midArc, expansionTime, shellTime)) return null;
float interceptTime = threat.ArrivalTime;
@ -408,14 +402,6 @@ namespace CounterDrone.Core.Algorithms
if (deliveryTime > interceptTime) return null;
if (!HasInterceptWindow(threat, midArc, expansionTime, deliveryTime)) return null;
// 空基也用 InterceptCalculator 验证
float speedKph = GetDroneSpeedKph(threat);
var (icArc, _, _) = InterceptCalculator.ComputeHorizontal(
threat.Waypoints, threat.DetectArc, speedKph,
_config.ReactionTime + expansionTime, unit.Position, unit.CruiseSpeed,
unit.ReleaseAltitude, (float)threat.Target.TypicalAltitude);
if (icArc <= 0) return null;
float avgSpeed = GetDroneSpeedMs(threat);
float neededExposure = _damageModel.RequiredExposureSeconds((TargetType)threat.Target.TargetType, (PowerType)threat.Target.PowerType, ammoType);
float actualExposure = effectiveR * 2f / avgSpeed;
@ -499,11 +485,23 @@ namespace CounterDrone.Core.Algorithms
float typicalSpeed = GetDroneSpeedKph(threat);
if (typicalSpeed <= 0) return (events, "目标速度无效");
// 航路感知布局:穿越点弧长 = 航路中点弧长 + 沿航路偏移
// targetOffset 现在是沿航路切向的弧长偏移(不再是 X 分量),支持任意方向航路
// 用 InterceptCalculator 计算拦截弧长和发射角
var mid = ThreatMidpoint(threat);
float midArc = RouteGeometry.ArcLengthNearestTo(wps, mid.X, mid.Z);
float crossArc = midArc + targetOffset;
float crossArc;
float launchAngle = 0;
if (unit.Type == PlatformType.GroundBased)
{
var (ia, _, la) = InterceptCalculator.Compute(
wps, threat.DetectArc, typicalSpeed,
_config.ReactionTime + expansionTime, unit.Position, unit.MuzzleVelocity);
crossArc = ia > 0 ? ia : midArc + targetOffset;
launchAngle = la;
}
else
{
crossArc = midArc + targetOffset;
}
// 编队横向偏移:按车道分布在航路法向上,与 DroneEntity 编队偏移一致(起点展开)。
// DroneEntity: latOffset = formationIndex * lateralSpacing0/50/100...
@ -578,6 +576,7 @@ namespace CounterDrone.Core.Algorithms
TargetY = ty,
TargetZ = cloudGenZ,
MuzzleVelocity = unit.Type == PlatformType.AirBased ? 0f : unit.MuzzleVelocity,
LaunchAngle = launchAngle,
});
return (events, null);

View File

@ -37,6 +37,7 @@ namespace CounterDrone.Core.Simulation
float targetX, float targetY, float targetZ,
float muzzleVelocity, float releaseAltitude,
float launchTime,
float? launchAngle = null,
float carrierVelX = 0f, float carrierVelY = 0f, float carrierVelZ = 0f)
{
Id = id;
@ -58,7 +59,7 @@ namespace CounterDrone.Core.Simulation
var dz = targetZ - startZ;
var horizontalDist = (float)System.Math.Sqrt(dx * dx + dz * dz);
_azimuth = horizontalDist > 0.001f ? (float)System.Math.Atan2(dx, dz) : 0;
_launchAngle = Kinematics.CalculateLaunchAngle(horizontalDist, muzzleVelocity, releaseAltitude);
_launchAngle = launchAngle ?? Kinematics.CalculateLaunchAngle(horizontalDist, muzzleVelocity, releaseAltitude);
_flightDuration = Kinematics.ParabolicTimeOfFlight(horizontalDist, _launchAngle, muzzleVelocity);
}
else

View File

@ -215,7 +215,7 @@ namespace CounterDrone.Core.Simulation
platform.AerosolType ?? Models.AerosolType.InertGas,
platform.PosX, platform.PosY, platform.PosZ,
fe.TargetX, fe.TargetY, fe.TargetZ, fe.MuzzleVelocity, _disperseHeight,
fe.FireTime);
fe.FireTime, fe.LaunchAngle);
_munitions.Add(m);
OnMunitionLaunched?.Invoke(m);
_frameEventPool.Add(new SimEvent { Type = SimEventType.MunitionLaunched, OccurredAt = fe.FireTime, SourceId = platform.Id, Description = $"计划发射 {m.Id} @({platform.PosX:F0},{platform.PosY:F0},{platform.PosZ:F0})→({fe.TargetX:F0},{fe.TargetY:F0},{fe.TargetZ:F0})" });