AircraftLandSJ.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. using KYFramework;
  2. using Model;
  3. using MongoDB.Bson;
  4. using MuShiApp;
  5. using SimulationCommon;
  6. using SimulationSingleServer.Utils;
  7. using Unity.Mathematics;
  8. using Point = SimulationCommon.Point;
  9. using Random = System.Random;
  10. using QuYuSaoMiao;
  11. using System.Threading;
  12. namespace SimulationServer;
  13. public class AircraftLandSJ : AircraftEntity
  14. {
  15. public bool IsOver;
  16. public LandSouXunTask taskContent;
  17. public EquationHelper helper;
  18. public GetNCData getNCData;
  19. public bool isseePerson = false;
  20. public MissionEndPoint MissionEndPoint;
  21. public SearchMissionMode SearchMissionMode;
  22. public bool Success = false; //本目标搜救是否成功
  23. public SearchMissionPayload searchMissionPayload;
  24. public double resulttime;
  25. int Days;
  26. int Hour;
  27. public bool isEndWhile;
  28. public int targetCount;
  29. public int sbCount;
  30. public double landArea;
  31. public bool isReadNC;
  32. Text_readNC text_ReadNC;
  33. public override void Reset()
  34. {
  35. base.Reset();
  36. IsOver = false;
  37. isseePerson = false;
  38. Success = false;
  39. SearchTime = 0;
  40. TotalTime = 0;
  41. isEndWhile = false;
  42. resulttime = 0;
  43. targetCount = 0;
  44. sbCount = 0;
  45. landArea = 0;
  46. }
  47. public override void Start()
  48. {
  49. if (FlightPlanEditor.targetpoint[0].TargetType.Type == "遇险人员")
  50. {
  51. targetCount = FlightPlanEditor.targetpoint[0].TargetType.Count;
  52. sbCount = targetCount;
  53. }
  54. else
  55. sbCount = 1;
  56. landArea = SearchMissionMode.LandArea;
  57. int Year = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[0]);
  58. int Month = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[0]);
  59. int Day = Convert.ToInt32(taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[1].Split("日")[0]);
  60. Hour = Convert.ToInt32(taskContent.missionInformation.StartTime.Split("时")[0]);
  61. Days = GetDaysInYear(Year, Month, Day);
  62. Velocitys = new double[5] { 220, 220, 60, 110, 0 }; // 速度
  63. List<double[]> route = new List<double[]>();
  64. if (SearchMissionMode.SearchMode == "扇形搜索")
  65. {
  66. List<double[]> trajectory = new List<double[]>();
  67. foreach (var item in SearchMissionMode.Poly)
  68. {
  69. trajectory.Add(new double[]
  70. {
  71. item[1],item[0]
  72. });
  73. }
  74. var points = SeaSJ.getminEnclosingRect(trajectory);
  75. var startPoint1 = new Point
  76. {
  77. lat = points[0][0] / 2 + points[1][0] / 2,
  78. lon = points[0][1] / 2 + points[1][1] / 2
  79. };
  80. var startPoint2 = new Point
  81. {
  82. lat = points[2][0] / 2 + points[3][0] / 2,
  83. lon = points[2][1] / 2 + points[3][1] / 2
  84. };
  85. var centerPoint = new Point
  86. {
  87. lat = startPoint1.lat / 2 + startPoint2.lat / 2,
  88. lon = startPoint1.lon / 2 + startPoint2.lon / 2
  89. };
  90. List<Point> temp = SectorSearch.sectorSearch(centerPoint, 30, SearchMissionMode.SearchWidth);
  91. foreach (Point point in temp)
  92. {
  93. route.Add(new double[]
  94. {
  95. point.lon, point.lat,3500
  96. });
  97. }
  98. }
  99. else if (SearchMissionMode.SearchMode == "等高线搜索")
  100. {
  101. route = ContourSearch.ContourSearch1(SearchMissionMode.Poly, SearchMissionMode.interval, SearchMissionMode.MinLength, SearchMissionMode.TrueH, SearchMissionMode.JG, ContourSearch.DemHelper());
  102. }
  103. // route 转成 List<AirRoute>
  104. List<AirRoute> airRoutes = new List<AirRoute>();
  105. foreach (var item in route)
  106. {
  107. airRoutes.Add(new AirRoute
  108. {
  109. AirRouteLatitude = item[1],
  110. AirRouteLongitude = item[0],
  111. AirRouteHeight = item[2]
  112. });
  113. }
  114. FlightPlanEditor.airroute = airRoutes.ToArray();
  115. FlightPlanEditor.missionpoint = new MissionPoint()
  116. {
  117. MissionPointLongitude = FlightPlanEditor.airroute[0].AirRouteLongitude,
  118. MissionPointLatitude = FlightPlanEditor.airroute[0].AirRouteLatitude,
  119. MissionPointHeight = FlightPlanEditor.airroute[0].AirRouteHeight
  120. };
  121. FXJHGenerate.FromStartToMission(FlightPlanEditor, ref TurningPoints); //生成从起点到任务段起点的航路点
  122. // TODO 与王子涵确认这个方法
  123. FXJHGenerate.LandSouJiu(FlightPlanEditor, ref TurningPoints);
  124. FXJHGenerate.FXJHTPDiedai(FlightPlanEditor, ref TurningPoints, Velocitys, FuelConsumptions);
  125. double time = 0; // 第一次 搜寻结束
  126. for (int i = 0; i < TurningPoints.Count - 2; i++)
  127. {
  128. time += TurningPoints[i].SegmentFlightTime;
  129. }
  130. double3 targetPoint = new double3(FlightPlanEditor.targetpoint[0].TargetPointLongitude,
  131. FlightPlanEditor.targetpoint[0].TargetPointLatitude,
  132. FlightPlanEditor.targetpoint[0].TargetPointHeight);
  133. string cityName = helper.getCityName(targetPoint.x, targetPoint.y);
  134. //var visibility = helper.getVisibility(cityName, DateTime.Now.ToString("yyyy-MM-dd HH"));
  135. string year = taskContent.missionInformation.StartDate.Split("年")[0];
  136. string month = taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[0];
  137. if (Convert.ToInt32(month) < 10) month = "0" + month;
  138. string day = taskContent.missionInformation.StartDate.Split("年")[1].Split("月")[1].Split("日")[0];
  139. if (Convert.ToInt32(day) < 10) day = "0" + day;
  140. //string hour = taskContent.missionInformation.StartTime.Split("时")[0];
  141. string date = year + "-" + month + "-" + day;// + " " + hour;
  142. //Console.Write(date);
  143. //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH"));
  144. var visibility = helper.getVisibilityByDb(targetPoint.x, targetPoint.y, date); //DateTime.Now.ToString("yyyy-MM-dd HH")
  145. //getNCData = new GetNCData();
  146. //getNCData.initlatitudes = FlightPlanEditor.targetpoint[0].TargetPointLatitude;
  147. //getNCData.initlongitudes = FlightPlanEditor.targetpoint[0].TargetPointLongitude;
  148. //getNCData.GetData();
  149. Task.Run(() =>
  150. {
  151. bool isseePerson = false;
  152. double temptime = 0; // 自增时间,每次增加1s
  153. CurrentLocation currentLocation = new CurrentLocation();
  154. double probability = 0;
  155. double finalProbability = 1.0;
  156. Random random = new Random();
  157. int fireIndex = -1; // 记录发现火点的位置
  158. //IsOver = true;
  159. do
  160. {
  161. if (!isseePerson && temptime >= time)
  162. {
  163. FXJHGenerate.LandSouJiu(FlightPlanEditor, ref TurningPoints);
  164. FXJHGenerate.FXJHTPDiedai(FlightPlanEditor, ref TurningPoints, Velocitys, FuelConsumptions);
  165. time = 0;
  166. for (int i = 0; i < TurningPoints.Count - 2; i++)
  167. {
  168. time += TurningPoints[i].SegmentFlightTime;
  169. }
  170. Log.Info($"+++++++++++搜寻结束 TurningPoints Count: {TurningPoints.Count} 下次结束的时间 {time}++++++++++++++++");
  171. }
  172. (currentLocation, _) =
  173. FXJHGenerate.GetAllCurrentLocation(TurningPoints, temptime); // 获取飞机当前位置
  174. double3 aricraftPoint = new double3(currentLocation.CurrentLon, currentLocation.CurrentLat,
  175. currentLocation.CurrentHei);
  176. var distance = Utils.Util.GetDistance(currentLocation.CurrentLon, targetPoint.x,
  177. currentLocation.CurrentLat,
  178. targetPoint.y);
  179. Log.Info("距离:====================" + distance);
  180. if (searchMissionPayload.SearchPayload == "雷达搜索")
  181. {
  182. // Pd0 = 0.5 / Pf0 = Math.Pow(10,-6) / Pf = Math.Pow(10,-6) / R0 = 23645 / sigma0 = 5000 / sigma = Editor雷达截面面积 // R 单位m
  183. probability = helper.GetRadarPossibility(0.5, Math.Pow(10, -6), Math.Pow(10, -6), 23645, aricraftPoint, FlightPlanEditor.targetpoint[0], FlightPlanEditor.targetpoint[0].TargetType.RadarArea, 5000, visibility);
  184. }
  185. else if (searchMissionPayload.SearchPayload == "目视搜索")
  186. {
  187. probability = helper.GetMushiLandProbability(aricraftPoint, visibility, FlightPlanEditor.targetpoint[0]);
  188. }
  189. else if (searchMissionPayload.SearchPayload == "光电(红外)搜索")
  190. {
  191. // Lt = 探测目标亮度 Editor / At = 探测目标面积 Editor / τa = 1 / Lb = 3 / A0 = 1 / D0 = 0.075 / Dstar = 3 / τo = 0.8 / Ad = 0.0073728 / Δf = 0.125 / δ = 0.5 / Pf0 = Math.Pow(10, -6);
  192. probability = helper.GetInfraredDetectionProbability(FlightPlanEditor.targetpoint[0].TargetType.TargetBrightness, FlightPlanEditor.targetpoint[0].TargetType.TargetArea, 1, 3, 1, aricraftPoint, FlightPlanEditor.targetpoint[0], 0.075, 3, 0.8, 0073728, 0.125, 0.5, Math.Pow(10, -6));
  193. }
  194. //probability =
  195. // helper.GetMushiLandProbability(aricraftPoint, visibility, FlightPlanEditor.targetpoint[0]);
  196. //finalProbability *= (1 - probability);
  197. if (probability > 0.8)
  198. {
  199. probability -= 0.5f;
  200. probability *= random.NextDouble();
  201. double random1 = random.NextInt64(8000, 9200); // 生成随机数比较概率 调整概率使任务成功率降低 至 5%(0.05) 第一个参数越低概率越低 // 1000
  202. random1 /= 10000;
  203. probability += (0.5 * random1);
  204. }
  205. double randomValue = random.NextInt64(9006, 10000); // 生成随机数比较概率 调整概率使任务成功率降低 至 5%(0.05) 第一个参数越高概率越低
  206. randomValue /= 10000;
  207. Log.Info(
  208. $"陆上任务:{taskContent.missionInformation.MissionName} 机型: {AircraftId} 当前时间:{temptime},当前位置:{currentLocation.CurrentLon},{currentLocation.CurrentLat},{currentLocation.CurrentHei},概率:{probability},是否看到遇险人员:{isseePerson}");
  209. if (randomValue < probability) // 1 - finalProbability
  210. {
  211. isseePerson = true;
  212. this.isseePerson = true;
  213. fireIndex = currentLocation.Currentsegnum; // 记录当前航路点位置
  214. //IsOver = true;
  215. isEndWhile = true;
  216. //Success = true;
  217. //resulttime = get_result_time_rope(30, FlightPlanEditor.targetpoint[0].TargetType.Count, windSpeed, visibility, 0.75, 1.38).time; //调运时间
  218. //Console.WriteLine("resulttime:" + resulttime);
  219. }
  220. else
  221. {
  222. isseePerson = false;
  223. }
  224. temptime += 10;
  225. if (temptime >= taskContent.missionInformation.TaskEndConditions.TaskTime)
  226. {
  227. //IsOver = true;
  228. isEndWhile = true;
  229. isseePerson = false;
  230. fireIndex = currentLocation.Currentsegnum;
  231. }
  232. } while (!isseePerson && isEndWhile == false);
  233. //finalProbability = 1 - finalProbability;
  234. if (fireIndex != -1)
  235. {
  236. // 删除目标点位置开始的所有后续航路点
  237. TurningPoints.RemoveRange(fireIndex + 1, TurningPoints.Count - fireIndex - 1);
  238. MissionPoint missionPoint = new MissionPoint
  239. {
  240. MissionPointLongitude = currentLocation.CurrentLon,
  241. MissionPointLatitude = currentLocation.CurrentLat,
  242. MissionPointHeight = currentLocation.CurrentHei
  243. };
  244. FXJHGenerate.SeaSouJiu2(FlightPlanEditor, missionPoint, ref TurningPoints);
  245. //发现的目标坐标,需要其他模型输入
  246. FXJHGenerate.FromMissionToEnd(FlightPlanEditor, MissionEndPoint, ref TurningPoints);
  247. }
  248. if (isseePerson)
  249. {
  250. double seeTime = 0;
  251. if (FlightPlanEditor.targetpoint[0].TargetType.Type == "遇险人员")
  252. {
  253. if (!isReadNC)
  254. {
  255. text_ReadNC = new Text_readNC();
  256. text_ReadNC.initlatitudes = FlightPlanEditor.targetpoint[0].TargetPointLatitude;
  257. text_ReadNC.initlongitudes = FlightPlanEditor.targetpoint[0].TargetPointLongitude;
  258. //text_ReadNC = new Text_readNC();
  259. bool isSuccess = false;
  260. while (!isSuccess)
  261. {
  262. isSuccess = text_ReadNC.GetNCData();
  263. }
  264. isReadNC = true;
  265. }
  266. var nCread = text_ReadNC.windNCread;
  267. var wind = SeaSJ.GetWindVelocityFromAPI(nCread, currentLocation.CurrentLat, currentLocation.CurrentLon,
  268. temptime, text_ReadNC.times, text_ReadNC.latitudes, text_ReadNC.longitudes, text_ReadNC.times1, text_ReadNC.latitudes1, text_ReadNC.longitudes1, Days, Hour);
  269. double windSpeed = Math.Sqrt(wind[0] * wind[0] + wind[1] * wind[1]);
  270. for (int i = 0; i < TurningPoints.Count - 1; i++)
  271. {
  272. seeTime += TurningPoints[i].SegmentFlightTime;
  273. }
  274. double latitude = FlightPlanEditor.targetpoint[0].TargetPointLatitude; //落水人员纬度;数据测试用
  275. double longitude = FlightPlanEditor.targetpoint[0].TargetPointLongitude; //落水人员经度,数据测试用
  276. double survivalTime = FlightPlanEditor.targetpoint[0].TargetType.LiveTime;//幸存时间
  277. // SHJParameter.person_number = Eidtor里读取 SHJParameter.windspeed Nc/Editor目标气象信息读取时间先取任务初始时间
  278. resulttime = get_result_time_rope(30, FlightPlanEditor.targetpoint[0].TargetType.Count, windSpeed, visibility, 0.75, 1.38).time; //调运时间
  279. Console.WriteLine("resulttime:" + resulttime);
  280. //Console.WriteLine("survivalTime:" + survivalTime);
  281. if (survivalTime * 3600 > seeTime)
  282. {
  283. Success = true;
  284. }
  285. //Log.Info("TotalTime:" + TotalTime);
  286. //Log.Info("幸存时间:" + survivalTime);
  287. }
  288. }
  289. //Console.WriteLine(
  290. // $"海上任务1:{taskContent.missionInformation.MissionName} 机型: {AircraftId} 当前时间:{temptime},当前位置:{currentLocation.CurrentLon},{currentLocation.CurrentLat},{currentLocation.CurrentHei},概率:{probability},最终概率:{1 - finalProbability},是否看到落水人员:{isseePerson}");
  291. Log.Info(
  292. $"陆上任务:{taskContent.missionInformation.MissionName} 机型: {AircraftId} 当前时间:{temptime},当前位置:{currentLocation.CurrentLon},{currentLocation.CurrentLat},{currentLocation.CurrentHei},概率:{probability},是否看到遇险人员:{isseePerson}");
  293. FXJHGenerate.FXJHTPDiedai(FlightPlanEditor, ref TurningPoints, Velocitys, FuelConsumptions);
  294. End();
  295. });
  296. }
  297. public static handling_result get_result_time_rope(double H, int person_number, double windspeed, double vis, double upspeed, double downspeed)
  298. {
  299. handling_result result = new handling_result();
  300. if (windspeed < 8 && vis > 3)
  301. {
  302. result.time = (person_number * H) / downspeed + (person_number * H) / upspeed;
  303. result.success = true;
  304. }
  305. else
  306. {
  307. result.success = false;
  308. }
  309. return result;
  310. }
  311. public static int GetDaysInYear(int year, int month, int day)
  312. {
  313. int[] daysInMonths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  314. if (IsLeapYear(year))
  315. {
  316. daysInMonths[1] = 29;
  317. }
  318. int days = day;
  319. for (int i = 0; i < month - 1; i++)
  320. {
  321. days += daysInMonths[i];
  322. }
  323. return days;
  324. }
  325. public static bool IsLeapYear(int year)
  326. {
  327. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  328. }
  329. public override void End()
  330. {
  331. for (int i = 0; i < TurningPoints.Count - 2; i++)
  332. {
  333. EffMisTime += TurningPoints[i].SegmentFlightTime;
  334. }
  335. for (int i = 0; i < TurningPoints.Count - 3; i++)
  336. {
  337. SearchTime += TurningPoints[i].SegmentFlightTime; //搜索时间
  338. }
  339. for (int i = 0; i < TurningPoints.Count; i++)
  340. {
  341. TotalTime += TurningPoints[i].SegmentFlightTime; // 总时间
  342. }
  343. TotalFuelConsumption = TurningPoints[0].RemainingFuel -
  344. TurningPoints[TurningPoints.Count - 1].RemainingFuel;
  345. IsOver = true;
  346. }
  347. }
  348. [ObjectSystem]
  349. public class AircraftLandSJAwakeSystem : AwakeSystem<AircraftLandSJ, FlightPlanEditor>
  350. {
  351. public override void Awake(AircraftLandSJ self, FlightPlanEditor flightPlanEditor)
  352. {
  353. self.FlightPlanEditor = flightPlanEditor;
  354. self.helper = new EquationHelper(HttpInterface.baseUrl);
  355. self.Awake();
  356. }
  357. }