CounterDroneBackend/test/unit/CounterDrone.Core.Tests/MunitionEntityTests.cs
tian a5fef98858 wip: 空基Planner修正——投放点后移抵消载具漂移;云团/发射事件用精确时刻
- 空基 GenerateFireEventsAt 投放点后移 driftX = cruiseSpeed * fallTime
- MunitionEntity 记录 launchTime + flightDuration → ArrivalTime 精确计算
- 云团 Initialization 用 munition.ArrivalTime 非 SimulationTime
- CloudGenerated 事件 OccurredAt 用精确到达时刻
- PlatformEntity 存储 ExactReleaseTime
- 修复缺失 else 导致的空基走地基分支
2026-06-13 16:40:27 +08:00

100 lines
3.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using CounterDrone.Core.Simulation;
using Xunit;
namespace CounterDrone.Core.Tests
{
public class MunitionEntityTests
{
[Fact]
public void GroundBased_DoesNotArriveImmediately()
{
var m = new MunitionEntity("m1", PlatformType.GroundBased,
AerosolType.InertGas,
startX: 0, startY: 0, startZ: 0,
targetX: 5000, targetY: 300, targetZ: 0,
muzzleVelocity: 500f, releaseAltitude: 300f, launchTime: 0f);
m.Update(0.05f);
Assert.False(m.HasArrived, "炮弹不能第一帧就到达");
}
[Fact]
public void GroundBased_ArrivesAtTargetPosition()
{
// 验证炮弹到达时,水平位置接近目标
var m = new MunitionEntity("m1", PlatformType.GroundBased,
AerosolType.InertGas,
startX: 0, startY: 0, startZ: 0,
targetX: 5000, targetY: 300, targetZ: 0,
muzzleVelocity: 500f, releaseAltitude: 300f, launchTime: 0f);
for (int i = 0; i < 500; i++)
{
m.Update(0.05f);
if (m.HasArrived) break;
}
Assert.True(m.HasArrived, "炮弹应到达");
// 到达释放高度
Assert.True(System.Math.Abs(m.PosY - 300f) < 5f, $"PosY={m.PosY:F1} 应≈300");
// 水平位置接近目标
var dist = System.Math.Sqrt(
(m.PosX - m.TargetX) * (m.PosX - m.TargetX) +
(m.PosZ - m.TargetZ) * (m.PosZ - m.TargetZ));
Assert.True(dist < 1000f, $"到达点距目标 {dist:F0}m应<1000m");
}
[Fact]
public void GroundBased_LaunchAngle_ReachesReleaseAltitude()
{
// 验证运动学:给定距离和初速,弹道能达到释放高度
var range = 5000f;
var v0 = 500f;
var releaseAlt = 300f;
var angle = Kinematics.CalculateLaunchAngle(range, v0, releaseAlt);
// 弹道顶点高度 >= 释放高度
var peakH = v0 * v0 * (float)System.Math.Sin(angle) * (float)System.Math.Sin(angle) / (2f * 9.81f);
Assert.True(peakH >= releaseAlt,
$"弹道顶点 {peakH:F0}m ≥ 释放高度 {releaseAlt}m, angle={angle * 180 / System.Math.PI:F1}°");
}
[Fact]
public void GroundBased_MovesForwardOverTime()
{
var m = new MunitionEntity("m1", PlatformType.GroundBased,
AerosolType.InertGas,
startX: 0, startY: 0, startZ: 0,
targetX: 1000, targetY: 300, targetZ: 0,
muzzleVelocity: 500f, releaseAltitude: 300f, launchTime: 0f);
m.Update(1f);
var dist = System.Math.Sqrt(m.PosX * m.PosX + m.PosZ * m.PosZ);
Assert.True(dist > 100f, "1秒后炮弹应水平移动 > 100m");
}
[Fact]
public void AirBased_DropsToReleaseAltitude()
{
var m = new MunitionEntity("m1", PlatformType.AirBased,
AerosolType.InertGas,
startX: 0, startY: 500, startZ: 0,
targetX: 1000, targetY: 300, targetZ: 0,
muzzleVelocity: 0, releaseAltitude: 300f, launchTime: 0f);
// 空基投放:自由落体 500m → 300m = 200m 下落
// h = 0.5*g*t² → t = sqrt(2*200/9.81) ≈ 6.4s
for (int i = 0; i < 500; i++)
{
m.Update(0.05f);
if (m.HasArrived) break;
}
Assert.True(m.HasArrived, "空基弹药应到达释放高度");
Assert.True(m.PosY <= 300f + 1f);
}
}
}