Browse Source

添加空投空送子任务部分代码

liyang 6 months ago
parent
commit
c56cf3c99c

+ 1 - 0
Models/SimulationCommon/Define.cs

@@ -12,6 +12,7 @@ public class TurningPoint //类中删除了转弯半径
     public double SegmentFlightFuelConsumption;
     public double SegmentFlightTime;
     public double RemainingFuel; //新添加了当前剩余油量
+    public double HeadingAngle;
 
     public TurningPoint[] turningpoint;
 }

+ 68 - 1
Models/SimulationCommon/FXJHGenenrate.cs

@@ -196,6 +196,18 @@ namespace Model
                 SegmentFlightTime = resulttime,
                 RemainingFuel = 0,
             });
+
+            turningPoints.Add(new TurningPoint
+            {
+                TurningPointName = "索滑降",
+                TurningPointLongitude = editor.missionpoint.MissionPointLongitude,
+                TurningPointLatitude = editor.missionpoint.MissionPointLatitude,
+                TurningPointHeight = editor.missionpoint.MissionPointHeight,
+                TurningPointType = "索滑降",
+                SegmentFlightFuelConsumption = 2,
+                SegmentFlightTime = 0,
+                RemainingFuel = 0,
+            });
         }
 
         public static void XunHu(FlightPlanEditor editor,ref List<TurningPoint> turningPoints)
@@ -305,6 +317,37 @@ namespace Model
             });
         }
 
+
+        public static void KouTouKouSong(FlightPlanEditor editor, ref List<TurningPoint> turningPoint)
+        {
+            turningPoint.Add(new TurningPoint
+            {
+                TurningPointName = "转运",
+                TurningPointLongitude = editor.missionpoint.MissionPointLongitude,
+                TurningPointLatitude = editor.missionpoint.MissionPointLatitude,
+                TurningPointHeight = editor.missionpoint.MissionPointHeight,
+                TurningPointType = "转运",
+                SegmentFlightFuelConsumption = 2,
+                SegmentFlightTime = 0,
+                RemainingFuel = 0,
+            });
+        }
+
+        public static void KouTouKouSong1(MissionPoint missionpoint, ref List<TurningPoint> turningPoint)
+        {
+            turningPoint.Add(new TurningPoint
+            {
+                TurningPointName = "转运",
+                TurningPointLongitude = missionpoint.MissionPointLongitude,
+                TurningPointLatitude = missionpoint.MissionPointLatitude,
+                TurningPointHeight = missionpoint.MissionPointHeight,
+                TurningPointType = "转运",
+                SegmentFlightFuelConsumption = 2,
+                SegmentFlightTime = 0,
+                RemainingFuel = 0,
+            });
+        }
+
         public static void JijiangJiuYuan1(FlightPlanEditor editor, ref List<TurningPoint> turningPoint)
         {
             turningPoint.Add(new TurningPoint
@@ -632,7 +675,31 @@ namespace Model
 
         }
 
-     
+
+        public static void CalculateTrueHeading(FlightPlanEditor editor, ref List<TurningPoint> turningPoints)
+        {
+            for (int i = 0; i < turningPoints.Count - 1; i++)
+            {
+                // 转换为弧度
+                double lat1Rad = turningPoints[i].TurningPointLatitude * Math.PI / 180;
+                double lon1Rad = turningPoints[i].TurningPointLongitude * Math.PI / 180;
+                double lat2Rad = turningPoints[i + 1].TurningPointLatitude * Math.PI / 180;
+                double lon2Rad = turningPoints[i + 1].TurningPointLongitude * Math.PI / 180;
+                double deltaLon = lon2Rad - lon1Rad;
+
+                double x = Math.Sin(deltaLon) * Math.Cos(lat2Rad);
+                double y = Math.Cos(lat1Rad) * Math.Sin(lat2Rad) - Math.Sin(lat1Rad) * Math.Cos(lat2Rad) * Math.Cos(deltaLon);
+
+                // 计算航向角
+                double headingRad = Math.Atan2(x, y);
+
+                // 转换为度并标准化
+                double headingDeg = headingRad * 180 / Math.PI;
+                headingDeg = (headingDeg + 360) % 360;
+                turningPoints[i].HeadingAngle = headingDeg;
+            }
+        }
+
 
         /// <summary>
         /// 巡护用

+ 1 - 0
Models/SimulationCommon/FlightPlanEditor.cs

@@ -15,6 +15,7 @@ public class FlightPlanEditor
   
     [JsonProperty("任务点")]
     public MissionPoint missionpoint = new MissionPoint();
+
     [JsonProperty("火点")]
     public FirePoint[] firepoint = new FirePoint[1];
     [JsonProperty("搜救目标初始点")]

+ 12 - 0
Models/SimulationCommon/TaskConfig.cs

@@ -145,6 +145,18 @@ public class SHJTask
     //public string NextTaskId;
 }
 
+public class KTKSTask
+{
+    [JsonProperty("任务信息")]
+    public MissionInformation missionInformation;
+    [JsonProperty("应用航空器")]
+    public AircraftInfo[] aircraftInfos;
+    [JsonProperty("索滑降参数")]
+    public SHJParameter[] SHJParameters;
+    [JsonProperty("空投点")]
+    public MissionPoint[] MissionPoints;
+}
+
 public class SHJParameter
 {
     [JsonProperty("应用飞机编号")]

+ 336 - 0
SimulationServer/Entity/AircraftKTKS.cs

@@ -0,0 +1,336 @@
+using KYFramework;
+using Model;
+using Newtonsoft.Json;
+using Org.BouncyCastle.Utilities;
+using SimulationCommon;
+using SimulationServer.Utils;
+using Define = SimulationServer.Utils.Define;
+
+namespace SimulationServer;
+
+public class AircraftKTKS : AircraftEntity
+{
+    public string NextMissionId; // 下一个任务ID
+    public MissionEndPoint missionEndPoint = new MissionEndPoint();
+
+    public int LandingPersonnel; //personCount
+    public MHRescueMission mhRescueMission;
+
+    public int landingPoint = 0; // 任务文件获取
+
+    public MissionPoint missionpoint = new MissionPoint();
+
+    public KTKSTask taskContent; // 创建任务里需要赋值!!!
+    int Days;
+    int Hour;
+
+    public override void End()
+    {
+
+    }
+
+    public override void Reset()
+    {
+        base.Reset();
+    }
+    public override void Start()
+    {
+        // FlightPlanEditor.targetpoint = 空投点
+
+        FXJHGenerate.FromStartToMission(FlightPlanEditor, ref TurningPoints);//生成从起点到任务段起点的航路点
+
+        int TransportNumber = (int)Math.Ceiling(LandingPersonnel / FlightPlanEditor.aircraftparameter.MaxPassengerNumber);
+
+        int j = 0;
+        //FlightPlanEditor.missionpoint.MissionPointLatitude = FlightPlanEditor.targetpoint[0].TargetPointLatitude;
+        //FlightPlanEditor.missionpoint.MissionPointLongitude = FlightPlanEditor.targetpoint[0].TargetPointLongitude;
+        //FlightPlanEditor.missionpoint.MissionPointHeight = FlightPlanEditor.targetpoint[0].TargetPointHeight;
+        FXJHGenerate.KouTouKouSong(FlightPlanEditor, ref TurningPoints);
+        double alpha = CalculateEastBaseAngle(TurningPoints[0].TurningPointLatitude, TurningPoints[0].TurningPointLongitude, TurningPoints[2].TurningPointLatitude, TurningPoints[2].TurningPointLongitude);
+        //FXJHGenerate.CalculateTrueHeading(FlightPlanEditor, ref TurningPoints);
+        // FXJHGenerate.InitializeVelocities(FlightPlanEditor, TurningPoints, ref Velocitys);
+        // FXJHGenerate.InitializeFuelConsumptions(FlightPlanEditor, TurningPoints,ref FuelConsumptions);
+
+        //FXJHGenerate.FromMissionToEnd(FlightPlanEditor, missionEndPoint, ref TurningPoints);
+        //FXJHGenerate.FXJHTPDiedai(FlightPlanEditor, ref TurningPoints, Velocitys, FuelConsumptions); // 更新了 计算油耗的方法
+
+        int Year = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[0]);
+        int Month = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[0]);
+        int Day = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[1].Split("日")[0]);
+        Hour = Convert.ToInt32(taskContent.missionInformation.StartTime.Split("时")[0]);
+        Days = GetDaysInYear(Year, Month, Day);
+        Text_readNC text_ReadNC = new Text_readNC();
+        text_ReadNC.GetNCData();
+        var nCread = text_ReadNC.windNCread;
+
+        double[] windVelocity = GetWindVelocityFromAPI(nCread, FlightPlanEditor.targetpoint[0].TargetPointLatitude, FlightPlanEditor.targetpoint[0].TargetPointLongitude, text_ReadNC.latitudes, text_ReadNC.longitudes, Days, Hour);
+        var windSpeed = Math.Sqrt(windVelocity[0] * windVelocity[0] + windVelocity[1] * windVelocity[1]);
+        var theta = Math.Asin(windVelocity[0] / windSpeed);
+
+        List<double> KTiniposition = new List<double>();
+        List<double> KTresultPostion = new List<double>();
+
+        double KTheight;
+        if("开伞空投" == "True")  //空投空送任务文件读取
+        {
+            KTheight = 200;
+            // 空投迎风面积 = 1.5 空投空送任务文件读取 50 = 空投重量 空投空送任务文件读取
+            KTiniposition = getPositionWithUmbrella(FlightPlanEditor.missionpoint.MissionPointLongitude, FlightPlanEditor.missionpoint.MissionPointLatitude, KTheight, windSpeed, theta, 1.5, 50);
+            double inix = Mokatuo_lon(KTiniposition[1]);
+            double iniy = Mokatuo_lat(KTiniposition[0]);
+
+            double resultX = inix + 33 * Math.Cos(alpha) * KTiniposition[2];
+            double resultY = iniy + 33 * Math.Sin(alpha) * KTiniposition[2];
+
+            KTresultPostion[0] = ReMokatuo_lat(resultY);
+            KTresultPostion[1] = ReMokatuo_lon(resultX);
+        }
+        else
+        {
+            KTheight = 20;
+            KTiniposition = getPositionWithoutUmbrella(FlightPlanEditor.missionpoint.MissionPointLongitude, FlightPlanEditor.missionpoint.MissionPointLatitude, KTheight, windSpeed, 22, alpha, theta);
+        }
+
+        TurningPoints.RemoveAt(2);
+        FlightPlanEditor.missionpoint.MissionPointLatitude = KTiniposition[0];
+        FlightPlanEditor.missionpoint.MissionPointLongitude = KTiniposition[1];
+        FlightPlanEditor.missionpoint.MissionPointHeight = KTheight;
+
+        missionpoint.MissionPointLatitude = KTresultPostion[0];
+        missionpoint.MissionPointLongitude = KTresultPostion[1];
+        missionpoint.MissionPointHeight = KTheight;
+
+        FXJHGenerate.KouTouKouSong(FlightPlanEditor, ref TurningPoints);
+        FXJHGenerate.KouTouKouSong1(missionpoint, ref TurningPoints);
+
+        missionEndPoint.MissionEndPointLatitude = KTresultPostion[0];
+        missionEndPoint.MissionEndPointLongitude = KTresultPostion[1];
+        missionEndPoint.MissionEndPointHeight = KTheight;
+
+        FXJHGenerate.FromMissionToEnd(FlightPlanEditor, missionEndPoint, ref TurningPoints);
+        FXJHGenerate.FXJHTPDiedai(FlightPlanEditor, ref TurningPoints, Velocitys, FuelConsumptions); // 更新了 计算油耗的方法
+    }
+
+    //private double GetDistance(double lon1, double lon2, double lat1, double lat2)
+    //{
+    //    double R = 6371; // 地球的半径(公里)
+    //    double dLat = (lat2 - lat1) * Math.PI / 180.0;
+    //    double dLon = (lon2 - lon1) * Math.PI / 180.0;
+    //    double a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) +
+    //               Math.Cos(lat1 * Math.PI / 180.0) * Math.Cos(lat2 * Math.PI / 180.0) *
+    //               Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
+    //    double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
+    //    double distance = R * c;
+
+    //    return distance;
+    //}
+
+    public override void Update(double time)
+    {
+
+    }
+
+    // --接口
+    // --输入
+    // --
+    // 1)遇险人员位置经度(空投拟落点位置经度)
+    // --longitude(double)
+    // 2)遇险人员位置维度(空投拟落点位置维度)
+    //--latitude(double)
+    // 3)释放空投时飞机的高度(m)
+    //--altitude(double)
+    // 4)飞行器空投速度(m/s)
+    //--windspeed(double)
+    // 5)飞行速度与维度夹角(度)(应该可以在飞机的运动学参数读出来)__________东向为0
+    //--alpha(double)__________先定值,后续与子涵对
+    // 6)风速与维度夹角(度)(环境参数)__________东向为0
+    //--theta(double)__________改成风向
+    // 7)风速(m/s)
+    //--windspeed(double)
+    // 8)空投重量(kg)
+    //--m(double)
+    // 9)空投迎风面积(m2)(空投侧面积即可)
+    //--s(double)
+    // 10)空投距离多远算做成功
+    //--l(m)(double)
+    // --
+    // --输出
+    // --
+    // 1)可以空投区域的中心点经纬度
+    //--result(List<double>)
+    // 2)空投距离多远算做成功(m)
+    //--l(double)
+    // -- 三个输出变量构一个圆形区域
+    // --
+    //返回高度、速度、空投任务段时间
+
+    public static double[] GetWindVelocityFromAPI(NCread windNCread, double latitude, double longitude, int latitudes, int longitudes, int days, int hour)
+    {
+        float[] longitudeArray = windNCread.longitudeArray;//经度一维数组来源自文件'Text_readNC.cs'
+        float[] latitudeArray = windNCread.latitudeArray;//纬度一维数组来源自文件'Text_readNC.cs'
+        float[][][] u10Array = windNCread.u10Array;//风的10米U(向东)分量三维数组来源自文件'Text_readNC.cs'
+        float[][][] v10Array = windNCread.v10Array;//风的10米V(向北)分量三维数组来源自文件'Text_readNC.cs'
+
+        int longitudeNum = 0;
+        int latitudeNum = 0;
+        int temptimeNum = 0;
+        //定义NC文件中读取不到的坐标点海洋数据信息(后续可采用插值法等)
+        //经度连续化
+        for (int i = 0; i < longitudes - 1; i++)
+        {
+            if (longitude >= longitudeArray[i] && longitude < longitudeArray[i + 1])
+            {
+                longitude = longitudeArray[i];
+                longitudeNum = i;
+            }
+        }
+
+        //纬度连续化
+        for (int i = 0; i < latitudes - 1; i++)
+        {
+            if (latitude >= latitudeArray[i] && latitude < latitudeArray[i + 1])
+            {
+                latitude = latitudeArray[i];
+                latitudeNum = i;
+            }
+        }
+
+        temptimeNum += (days - 1) * 24 + hour - 1;
+
+        double windX = (double)u10Array[temptimeNum][latitudeNum][longitudeNum];
+        double windY = (double)v10Array[temptimeNum][latitudeNum][longitudeNum];
+
+        return new double[] { windX, windY };
+    }
+
+    // --主要方法
+    // --墨卡托投影函
+    public double Mokatuo_lat(double lat)
+    {
+        double R = 6378.137;
+        double y = R * Math.Log(Math.Tan((lat + 90) * Math.PI / 360));
+        return y;
+    }
+    public double Mokatuo_lon(double lon)
+    {
+        double R = 6378.137;
+        double x = (lon * Math.PI * R) / 180;
+        return x;
+    }
+
+    // --反墨卡托投影函数
+    public double ReMokatuo_lat(double y)
+    {
+        double R = 6378.137;
+        double lat = (2 * Math.Atan(Math.Exp(y / R)) - Math.PI / 2) * 180 / Math.PI;
+        return lat;
+    }
+
+    public double ReMokatuo_lon(double x)
+    {
+        double R = 6378.137;
+        double lon = x * 180 / (Math.PI * R);
+        return lon;
+    }
+    // --不开伞空投计算函数
+    //速度80km/h;高度20m
+    public List<double> getPositionWithoutUmbrella(double longitude, double latitude, double altitude, double windspeed, double velocity, double alpha, double theta)
+    {
+        double g = 9.8;
+        double time = Math.Sqrt(2 * altitude / g);
+        double x = Mokatuo_lon(longitude);
+        double y = Mokatuo_lat(latitude);
+        double vx = velocity * Math.Cos(alpha) + windspeed * Math.Cos(theta);
+        double vy = velocity * Math.Sin(alpha) + windspeed * Math.Sin(theta);
+        double y_new = y + vy * time / 1000;
+        double x_new = x + vx * time / 1000;
+        double lat = ReMokatuo_lat(y_new);
+        double lon = ReMokatuo_lon(x_new);
+        List<double> result = new List<double>()
+            {lat, lon,time};
+        return result; //投放空投的位置
+    }
+    // --开伞空投计算函数
+    //速度120km/h;高度200m
+    public List<double> getPositionWithUmbrella(double longitude, double latitude, double altitude, double windspeed, double theta, double s, double m)
+    {
+        double g = 9.8;
+        double k = 3.824 * s;
+        double vz = Math.Sqrt(m * g / k);
+        double time = altitude / vz;
+        double x = Mokatuo_lon(longitude);
+        double y = Mokatuo_lat(latitude);
+        double y_new = y + windspeed * Math.Sin(theta) * time / 1000;
+        double x_new = x + windspeed * Math.Cos(theta) * time / 1000;
+        double lat = ReMokatuo_lat(y_new);
+        double lon = ReMokatuo_lon(x_new);
+        List<double> result = new List<double>()
+            {lat, lon};
+        Console.WriteLine(y_new);
+        Console.WriteLine(y);
+        return result; //投放空投的位置
+    }
+
+    public static int GetDaysInYear(int year, int month, int day)
+    {
+        int[] daysInMonths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+        if (IsLeapYear(year))
+        {
+            daysInMonths[1] = 29;
+        }
+        int days = day;
+        for (int i = 0; i < month - 1; i++)
+        {
+            days += daysInMonths[i];
+        }
+        return days;
+    }
+
+    public static bool IsLeapYear(int year)
+    {
+        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
+    }
+
+    public static double CalculateEastBaseAngle(double lat1, double lon1, double lat2, double lon2)
+    {
+        // 转换为弧度
+        double lat1Rad = lat1 * Math.PI / 180;
+        double lon1Rad = lon1 * Math.PI / 180;
+        double lat2Rad = lat2 * Math.PI / 180;
+        double lon2Rad = lon2 * Math.PI / 180;
+
+        double deltaLon = lon2Rad - lon1Rad;
+
+        // 计算真航向角
+        double x = Math.Sin(deltaLon) * Math.Cos(lat2Rad);
+        double y = Math.Cos(lat1Rad) * Math.Sin(lat2Rad) - Math.Sin(lat1Rad) * Math.Cos(lat2Rad) * Math.Cos(deltaLon);
+
+        double headingRad = Math.Atan2(x, y);
+        double headingDeg = headingRad * 180 / Math.PI;
+
+        // 标准化真航向角(以正北为基准)
+        headingDeg = (headingDeg + 360) % 360;
+
+        // 转换为以正东为基准的角度,逆时针方向
+        double eastBaseAngle = (90 - headingDeg) % 360;
+        if (eastBaseAngle < 0)
+        {
+            eastBaseAngle += 360;
+        }
+
+        return eastBaseAngle;
+    }
+
+}
+
+
+[ObjectSystem]
+public class AircraftKTKSAwakeSystem : AwakeSystem<AircraftKTKS, FlightPlanEditor>
+{
+    public override void Awake(AircraftKTKS self, FlightPlanEditor flightPlanEditor)
+    {
+        self.FlightPlanEditor = flightPlanEditor;
+        self.Awake();
+        self.Reset();
+    }
+}