using System; using System.Numerics; namespace ActiveProtect.Utility { public static class MotionAlgorithm { /// /// 计算抛物线弹道最佳发射方向(选择较小的仰角) /// /// 发射位置 /// 目标位置 /// 初始速度 /// 最佳发射方向,如果无解则返回null public static (Orientation? orientation, Vector3D? velocity) CalculateBestLaunchOrientation(Vector3D startPos, Vector3D targetPos, double initialSpeed) { // 计算水平距离 double dx = targetPos.X - startPos.X; double dz = targetPos.Z - startPos.Z; double horizontalDistance = Math.Sqrt(dx * dx + dz * dz); // 计算高度差 double dy = targetPos.Y - startPos.Y; double[]? angles = CalculateLaunchAngles(initialSpeed, horizontalDistance, dy); if (angles == null) { Console.WriteLine("无法计算发射角度"); return (null, null); } double bestAngle = Math.Min(angles[0], angles[1]); double azimuth = Math.Atan2(dz, dx); // 计算初始速度分量 double vx = initialSpeed * Math.Cos(bestAngle) * Math.Cos(azimuth); double vy = initialSpeed * Math.Sin(bestAngle); double vz = initialSpeed * Math.Cos(bestAngle) * Math.Sin(azimuth); // 返回方向和速度 return (new Orientation(bestAngle, azimuth, 0), new Vector3D(vx, vy, vz)); } /// /// 计算抛物线弹道发射角度 /// /// 初始速度(m/s) /// 目标点x坐标(m) /// 目标点y坐标(m) /// 重力加速度(m/s²) /// 两个可能的发射角度(弧度),如果无解则返回null public static double[]? CalculateLaunchAngles(double v0, double x, double y, double g = 9.81) { double v0_2 = v0 * v0; double v0_4 = v0_2 * v0_2; double discriminant = v0_4 - g * (g * x * x + 2 * y * v0_2); if (discriminant < 0) { Console.WriteLine("无实数解 - 目标不可达"); return null; } double angle1 = Math.Atan((v0_2 + Math.Sqrt(discriminant)) / (g * x)); double angle2 = Math.Atan((v0_2 - Math.Sqrt(discriminant)) / (g * x)); //Console.WriteLine($"计算得到的两个角度: {angle1 * 180 / Math.PI:F2}° 和 {angle2 * 180 / Math.PI:F2}°"); return new[] { angle1, angle2 }; } /// /// 使用运动学定律计算导弹运动状态,用于无制导状态(无制导时,使用该方法可以降低计算量) /// /// 当前位置 /// 当前速度 /// 加速度(通常包含重力加速度) /// 时间步长 /// 包含新位置和新速度的元组 public static (Vector3D newPosition, Vector3D newVelocity) CalculateBallisticMotion( Vector3D currentPosition, Vector3D currentVelocity, Vector3D acceleration, double deltaTime) { // 使用标准运动学方程 Vector3D newPosition = new( currentPosition.X + currentVelocity.X * deltaTime + 0.5 * acceleration.X * deltaTime * deltaTime, currentPosition.Y + currentVelocity.Y * deltaTime + 0.5 * acceleration.Y * deltaTime * deltaTime, currentPosition.Z + currentVelocity.Z * deltaTime + 0.5 * acceleration.Z * deltaTime * deltaTime ); Vector3D newVelocity = new( currentVelocity.X + acceleration.X * deltaTime, currentVelocity.Y + acceleration.Y * deltaTime, currentVelocity.Z + acceleration.Z * deltaTime ); return (newPosition, newVelocity); } /// /// 使用四阶龙格库塔法计算物体运动状态,用于有制导状态 /// /// 时间步长 /// 导弹位置 /// 导弹速度 /// 导弹加速度 /// 新的位置和速度 public static (Vector3D newPosition, Vector3D newVelocity) RungeKutta4(double deltaTime, Vector3D position, Vector3D velocity, Vector3D acceleration) { // 定义一个局部函数来计算加速度 Vector3D AccelerationFunction(Vector3D pos, Vector3D vel) { // 这里可以添加更复杂的加速度计算,比如考虑空气阻力等 return acceleration; } // 第一步 Vector3D k1v = AccelerationFunction(position, velocity) * deltaTime; Vector3D k1r = velocity * deltaTime; // 第二步 Vector3D k2v = AccelerationFunction(position + k1r * 0.5, velocity + k1v * 0.5) * deltaTime; Vector3D k2r = (velocity + k1v * 0.5) * deltaTime; // 第三步 Vector3D k3v = AccelerationFunction(position + k2r * 0.5, velocity + k2v * 0.5) * deltaTime; Vector3D k3r = (velocity + k2v * 0.5) * deltaTime; // 第四步 Vector3D k4v = AccelerationFunction(position + k3r, velocity + k3v) * deltaTime; Vector3D k4r = (velocity + k3v) * deltaTime; // 计算新的位置和速度 Vector3D newPosition = position + (k1r + k2r * 2 + k3r * 2 + k4r) / 6; Vector3D newVelocity = velocity + (k1v + k2v * 2 + k3v * 2 + k4v) / 6; return (newPosition, newVelocity); } /// /// 计算比例导引加速度 /// /// 比例导引系数 /// 导弹位置 /// 导弹速度 /// 目标位置 /// 目标速度 /// 比例导引加速度 public static Vector3D CalculateProportionalNavigation(double proportionalNavigationCoefficient, Vector3D missilePosition, Vector3D missileVelocity, Vector3D targetPosition, Vector3D targetVelocity) { // 预测时间(预测目标前进方向该时间后到达的位置,可以调整) double predictionTime = 0.01; // 预测目标位置 Vector3D predictedTargetPosition = targetPosition + targetVelocity * predictionTime; Vector3D r = predictedTargetPosition - missilePosition; Vector3D v = targetVelocity - missileVelocity; Vector3D LOS = r.Normalize(); Vector3D LOSRate = (v - (LOS * Vector3D.DotProduct(v, LOS))) / r.Magnitude(); Vector3D acceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), missileVelocity.Normalize()) * proportionalNavigationCoefficient * missileVelocity.Magnitude(); return acceleration; } /// /// 添加高斯噪声 /// /// 向量 /// 添加高斯噪声后的向量 public static Vector3D AddRandomPerturbation(Vector3D vector) { Random random = new(); // 添加高斯噪声 double sigma = 0.1; // 扰动标准差 // 使用Box-Muller变换来生成高斯随机数 double u1 = random.NextDouble(); // 生成[0, 1)之间的随机数 double u2 = random.NextDouble(); // 生成[0, 1)之间的随机数 double r = Math.Sqrt(-2.0 * Math.Log(u1)); double theta = 2.0 * Math.PI * u2; double gaussianX = r * Math.Cos(theta); double gaussianY = r * Math.Sin(theta); // 由于我们需要三个高斯随机数,我们将再次生成 u1 = random.NextDouble(); // 生成[0, 1)之间的随机数 u2 = random.NextDouble(); // 生成[0, 1)之间的随机数 r = Math.Sqrt(-2.0 * Math.Log(u1)); theta = 2.0 * Math.PI * u2; double gaussianZ = r * Math.Cos(theta); // 将高斯随机数转换为指定标准差的高斯随机数 gaussianX *= sigma; gaussianY *= sigma; gaussianZ *= sigma; return new Vector3D( vector.X + gaussianX, vector.Y + gaussianY, vector.Z + gaussianZ ); } } }