纠正末敏弹分离算法,增加对小值的输出格式

This commit is contained in:
Tian jianyong 2025-05-11 12:07:20 +08:00
parent ca3897a415
commit e630dc3a4c
7 changed files with 69 additions and 25 deletions

View File

@ -102,7 +102,7 @@ namespace ThreatSource.Missile
/// <param name="missileId">导弹的唯一标识符</param>
/// <param name="targetId">目标的唯一标识符</param>
/// <param name="properties">导弹的配置参数</param>
/// <param name="launchParams">发射参数</param>
/// <param name="kinematicState">发射参数</param>
/// <param name="submunitionProperties">子弹的配置参数</param>
/// <param name="submunitionCount">子弹的数量</param>
/// <param name="submunitionConfig">子弹药配置参数</param>
@ -121,12 +121,12 @@ namespace ThreatSource.Missile
string missileId,
string targetId,
MissileProperties properties,
KinematicState launchParams,
KinematicState kinematicState,
MissileProperties submunitionProperties,
int submunitionCount,
TerminalSensitiveSubmunitionConfig submunitionConfig,
ISimulationManager manager)
: base(missileId, properties, launchParams, manager)
: base(missileId, properties, kinematicState, manager)
{
this.targetId = targetId;
this.submunitionProperties = submunitionProperties;
@ -136,18 +136,18 @@ namespace ThreatSource.Missile
//计算分离点坐标,使用配置中的分离高度和距离
SimulationElement target = SimulationManager.GetEntityById(targetId) as SimulationElement ?? throw new Exception("目标不存在");
separationPoint = Vector3D.PointOnLine(target.KState.Position, base.KState.Position, config.SeparationDistance) + new Vector3D(0, config.SeparationHeight, 0);
separationPoint = Vector3D.PointOnLine(target.KState.Position, KState.Position, config.SeparationDistance) + new Vector3D(0, config.SeparationHeight, 0);
//计算导弹发射角度
(Orientation? launchOrientation, Vector3D? launchVelocity) = MotionAlgorithm.CalculateBestLaunchOrientation(base.KState.Position, separationPoint, base.KState.Speed);
if (!launchOrientation.HasValue || launchVelocity is null)
Vector3D? launchVelocityNullable = MotionAlgorithm.CalculateBestLaunchOrientation(KState.Position, separationPoint, KState.Speed);
if (launchVelocityNullable == null)
{
throw new InvalidOperationException("无法计算发射方向");
}
else
{
KState.Orientation = launchOrientation.Value;
KState.Velocity = launchVelocity;
KState.Velocity = launchVelocityNullable;
KState.Orientation = Orientation.FromVector(launchVelocityNullable);
}
}
@ -232,7 +232,7 @@ namespace ThreatSource.Missile
/// </remarks>
private void UpdateCruiseStage(double deltaTime)
{
double distanceToSeparationPoint = (separationPoint - base.KState.Position).Magnitude();
double distanceToSeparationPoint = (separationPoint - KState.Position).Magnitude();
//距离分离点距离小于配置的分离范围,则分离
if (distanceToSeparationPoint <= config.SeparationRange)
{
@ -323,6 +323,10 @@ namespace ThreatSource.Missile
Debug.WriteLine($"注册末敏弹子弹 {submunitions[i].Id}");
submunitions[i].Activate();
Debug.WriteLine($"激活末敏弹子弹 {submunitions[i].Id}");
Console.WriteLine($"[末敏弹分离] 母弹 KS: Pos={KState.Position}, Orient={KState.Orientation}, Speed={KState.Speed}, Vel={KState.Velocity}");
Console.WriteLine($"[末敏弹分离] 子弹 {i} KS: Pos={submunitions[i].KState.Position}, Orient={submunitions[i].KState.Orientation}, Speed={submunitions[i].KState.Speed}, Vel={submunitions[i].KState.Velocity}");
submunitions[i].Fire();
}

View File

@ -172,7 +172,7 @@ namespace ThreatSource.Missile
/// <param name="missileId">导弹ID</param>
/// <param name="targetId">目标ID</param>
/// <param name="properties">子弹配置参数</param>
/// <param name="launchParams">发射参数</param>
/// <param name="kinemateState">发射参数</param>
/// <param name="submunitionConfig">子弹性能参数配置</param>
/// <param name="manager">仿真管理器实例</param>
/// <remarks>
@ -186,10 +186,10 @@ namespace ThreatSource.Missile
string missileId,
string targetId,
MissileProperties properties,
KinematicState launchParams,
KinematicState kinemateState,
TerminalSensitiveSubmunitionConfig submunitionConfig,
ISimulationManager manager)
: base(missileId, properties, launchParams, manager)
: base(missileId, properties, kinemateState, manager)
{
TargetId = targetId;
this.config = submunitionConfig;

View File

@ -32,7 +32,7 @@ namespace ThreatSource.Sensor
/// <returns>传感器数据字符串表示</returns>
public override string ToString()
{
return $"IsValid: {IsValid}";
return $"IsValid={IsValid}";
}
}
@ -82,7 +82,7 @@ namespace ThreatSource.Sensor
/// <returns>传感器数据字符串表示</returns>
public override string ToString()
{
return base.ToString() + $", Temperature: {Temperature:F2}, IsTargetDetected: {IsTargetDetected}, TargetAngle: {TargetAngle:F2}";
return base.ToString() + $", Temperature={Temperature:F2}, IsTargetDetected={IsTargetDetected}, TargetAngle={TargetAngle:F2}";
}
}
@ -132,7 +132,7 @@ namespace ThreatSource.Sensor
/// <returns>传感器数据字符串表示</returns>
public override string ToString()
{
return base.ToString() + $", RadiationIntensity: {RadiationIntensity:F2}, IsTargetDetected: {IsTargetDetected}, TargetAngle: {TargetAngle:F2}";
return base.ToString() + $", RadiationIntensity={RadiationIntensity:F2}, IsTargetDetected={IsTargetDetected}, TargetAngle={TargetAngle:F2}";
}
}
@ -161,7 +161,7 @@ namespace ThreatSource.Sensor
/// <returns>传感器数据字符串表示</returns>
public override string ToString()
{
return base.ToString() + $", Altitude: {Altitude:F2}";
return base.ToString() + $", Altitude={Altitude:F2}";
}
}
@ -191,7 +191,7 @@ namespace ThreatSource.Sensor
/// <returns>传感器数据字符串表示</returns>
public override string ToString()
{
return base.ToString() + $", Distance: {Distance:F2}";
return base.ToString() + $", Distance={Distance:F2}";
}
}
}

View File

@ -60,11 +60,30 @@ namespace ThreatSource.Simulation
/// <returns>状态的字符串表示</returns>
public override string ToString()
{
string baseInfo = $"仿真元素 {ElementType} {Id} at {KState.Position}, Active: {IsActive}";
string baseInfo = $"[{ElementType}] Id={Id}, Active={IsActive}, 位置={KState.Position}, 方向={KState.Orientation}, 速度={KState.Speed:F2}, 速度矢量={KState.Velocity}";
if (ExtendedProperties.Count > 0)
{
string extendedInfo = string.Join(", ", ExtendedProperties.Select(p => $"{p.Key}={p.Value}"));
string extendedInfo = string.Join(", ", ExtendedProperties.Select(p =>
{
string valueStr;
if (p.Value is double d)
{
if (d > 0 && d < 1e-4)
{
valueStr = d.ToString("E2");
}
else
{
valueStr = d.ToString("F2");
}
}
else
{
valueStr = p.Value?.ToString() ?? "null"; // 处理可能的null值
}
return $"{p.Key}={valueStr}";
}));
return $"{baseInfo}, {extendedInfo}";
}

View File

@ -23,12 +23,12 @@ namespace ThreatSource.Utils
/// <param name="startPos">发射位置坐标</param>
/// <param name="targetPos">目标位置坐标</param>
/// <param name="initialSpeed">发射初速度,单位:米/秒</param>
/// <returns>包含最佳发射方向和初始速度向量的元组如果无解则返回null</returns>
/// <returns>最佳发射初始速度如果无解则返回null</returns>
/// <remarks>
/// 该方法使用弹道方程计算两个可能的发射角度,并选择较小的仰角作为最佳发射方向。
/// 计算考虑了重力影响,但未考虑空气阻力。
/// </remarks>
public static (Orientation? orientation, Vector3D? velocity) CalculateBestLaunchOrientation(Vector3D startPos, Vector3D targetPos, double initialSpeed)
public static Vector3D? CalculateBestLaunchOrientation(Vector3D startPos, Vector3D targetPos, double initialSpeed)
{
// 计算水平距离
double dx = targetPos.X - startPos.X;
@ -43,7 +43,7 @@ namespace ThreatSource.Utils
if (angles == null)
{
Debug.WriteLine("无法计算发射角度");
return (null, null);
return null;
}
double bestAngle = Math.Min(angles[0], angles[1]);
@ -54,7 +54,7 @@ namespace ThreatSource.Utils
double vz = initialSpeed * Math.Cos(bestAngle) * Math.Sin(azimuth);
// 返回方向和速度
return (new Orientation(bestAngle, azimuth, 0), new Vector3D(vx, vy, vz));
return new Vector3D(vx, vy, vz);
}
/// <summary>
@ -89,7 +89,7 @@ namespace ThreatSource.Utils
Debug.WriteLine($"计算得到的两个角度: {angle1 * 180 / Math.PI:F2}° 和 {angle2 * 180 / Math.PI:F2}°");
return new[] { angle1, angle2 };
return [angle1, angle2];
}
/// <summary>

View File

@ -304,4 +304,25 @@
2. 接近计算出的落点时,两个目标都离开了导引头视野,不再计算落点。导弹会惯性飞行,会偏离之前计算出的落点。
## 末敏弹实验记录v0.2.16
时间2025-05-10 10:00:00
版本v0.2.16
### 初始设置
1. 末敏弹初始位置
300.0,0.0,20.0
2. 子弹分离点
高度 1000米距离 1000米分离角 45度
3. 坦克初始参数
位置0.0,1.2,0.0
朝向0.0,0.0,0.0-Z轴
### 实验结果
1. 坦克初速 0米/秒,仿真运行 30.2 秒,命中
2. 坦克速度 0.5米/秒,仿真运行 29.7 秒,命中
3. 坦克速度 1米/秒,仿真运行 38 秒,自毁

View File

@ -193,7 +193,7 @@ namespace ThreatSource.Tools.MissileSimulation
{
Position = new Vector3D(0, 1.2, 0),
Orientation = new Orientation(0.0, 0.0, 0.0),
Speed = 1.0
Speed = 0.0
};
string targetId = "Tank_1";
var target = _threatSourceFactory.CreateTarget(targetId, "mbt_001", motionParameters);