diff --git a/Plane.FormationCreator.sln b/Plane.FormationCreator.sln index 5013cb2..dadee74 100644 --- a/Plane.FormationCreator.sln +++ b/Plane.FormationCreator.sln @@ -4,6 +4,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.FormationCreator", "Plane.FormationCreator\Plane.FormationCreator.csproj", "{61E2F31E-220A-4E3F-A64D-F7CDC2135008}" + ProjectSection(ProjectDependencies) = postProject + {BE3280E8-8C7F-4961-9685-1124C5B990CB} = {BE3280E8-8C7F-4961-9685-1124C5B990CB} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Windows", "..\Plane.Libraries\Plane.Windows\Plane.Windows.csproj", "{06848293-9B17-4068-9B35-44D0ED713CD4}" EndProject @@ -23,6 +26,8 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk_Shared", "..\Pl EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk.Contract_Shared", "..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.shproj", "{695733D7-99FF-4707-8C89-474E949CADCB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "flyBase", "..\Tools\flyBase\flyBase.csproj", "{BE3280E8-8C7F-4961-9685-1124C5B990CB}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.projitems*{0111eb6e-72e3-499c-a3ba-022f5bbc4caf}*SharedItemsImports = 4 @@ -101,6 +106,14 @@ Global {47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU {47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU {47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.Release|Any CPU.Build.0 = Release|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU + {BE3280E8-8C7F-4961-9685-1124C5B990CB}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Plane.FormationCreator/App.xaml b/Plane.FormationCreator/App.xaml index ca1595e..b3c077f 100644 --- a/Plane.FormationCreator/App.xaml +++ b/Plane.FormationCreator/App.xaml @@ -36,6 +36,25 @@ False="【飞行模式】" True="【设计模式】" /> + + + + + + + + + + + diff --git a/Plane.FormationCreator/Formation/FlightTaskManager.cs b/Plane.FormationCreator/Formation/FlightTaskManager.cs index 7628d6e..10007a2 100644 --- a/Plane.FormationCreator/Formation/FlightTaskManager.cs +++ b/Plane.FormationCreator/Formation/FlightTaskManager.cs @@ -13,6 +13,10 @@ using System.Threading.Tasks; using Plane.CommunicationManagement; using FlightRoute; using System.IO; +using System.Windows.Media.Media3D; +using System.Diagnostics; +using Plane.FormationCreator.Util; +using System.Collections; namespace Plane.FormationCreator.Formation { @@ -993,7 +997,6 @@ namespace Plane.FormationCreator.Formation if (copters == null || !copters.Any()) return; AppEx.Current.AppMode = AppMode.ModifyingTask; var lastTask = Tasks.LastOrDefault(); - FlightTask takeOffTask = Tasks[0]; takeOffTask.TakeOffTime = takeOffTime; for (int i = 0; i < copters.Count; i++) @@ -1307,11 +1310,250 @@ namespace Plane.FormationCreator.Formation } } + + //计算中心点 (三维的) + private Point3D CenterFormMeter(List point1, List point2) + { + Point3D centerPoint = new Point3D(0, 0, 0); + if (point1.Count != point2.Count) return centerPoint; + + double minX = point1[0].X; + double maxX = point1[0].X; + + double minY = point1[0].Y; + double maxY = point1[0].Y; + + + double minZ = point1[0].Z; + double maxZ = point1[0].Z; + + + + int count = point1.Count; + for (int i = 0; i < count; i++) + { + minX = Math.Min(minX, Math.Min(point1[i].X, point2[i].X)); + maxX = Math.Max(maxX, Math.Min(point1[i].X, point2[i].X)); + + minY = Math.Min(minY, Math.Min(point1[i].Y, point2[i].Y)); + maxY = Math.Max(maxY, Math.Max(point1[i].Y, point2[i].Y)); + + minZ = Math.Min(minZ, Math.Min(point1[i].Z, point2[i].Z)); + maxZ = Math.Max(maxZ, Math.Max(point1[i].Z, point2[i].Z)); + + + } + centerPoint.X = (minX + maxX) / 2; + centerPoint.Y = (minY + maxY) / 2; + centerPoint.Z = (minZ + maxZ) / 2; + return centerPoint; + } + + + public double SumFlyLines(List preinfos, List currinfos) + { + double sumdis = 0; + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + //当前任务 + Point3D preLoc = new Point3D(preinfos[i].X, preinfos[i].Y, preinfos[i].TargetAlt); + Point3D curLoc = new Point3D(currinfos[i].X, currinfos[i].Y, currinfos[i].TargetAlt); + //算距离 + sumdis += Point3D.Subtract(curLoc, preLoc).Length; + } + return sumdis; + } + public void SetAllTaskFlytime() + { + for (int taskIndex = 1; taskIndex < Tasks.Count; taskIndex++) + SetTaskFlytime(taskIndex); + } + + + public void SetTaskFlytime(int taskIndex,bool settime=true) + { + if ((taskIndex > 0 )&&(taskIndex < Tasks.Count) &&( Tasks[taskIndex].TaskType == FlightTaskType.FlyTo)) + { + if (_copterManager.Copters.Count() > 0) + { + double maxDistance = 0.0f; + string copterName = ""; + double speed = 0.0f; + foreach (var copter in _copterManager.Copters) + { + var prevWaypoint = Tasks[taskIndex - 1].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter); + var curWaypoint = Tasks[taskIndex].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter); + if ((curWaypoint.IsChangeSpeed) && (curWaypoint.LevelSpeed == -1)) + { + Message.Show($"任务{taskIndex + 1}飞机编号:{copter.Id}是自动速度,无法计算时间!"); + return ; + } + double distance = GeographyUtils.CalcDistance( + prevWaypoint.TargetLat, prevWaypoint.TargetLng, prevWaypoint.TargetAlt, + curWaypoint.TargetLat, curWaypoint.TargetLng, curWaypoint.TargetAlt); + if (distance > maxDistance) + { + maxDistance = distance; + copterName = copter.Name; + speed = curWaypoint.LevelSpeed; + } + } + + double time = CalculateFlyIime(maxDistance, speed); + Message.Show($"任务{taskIndex+1}最大航点间距 = {Math.Round(maxDistance, 2)}米, 水平速度={Math.Round(speed, 2)}, 飞行时间 = {Math.Round(time, 2)}秒, 飞机编号:{copterName}"); + if (settime) + Tasks[taskIndex].FlytoTime = (int)Math.Round(time, 2); + } + } + + return ; + } + + + public static double CalculateFlyIime(double s, double v) + { + double t; + double a = 1; //加速度1米每秒 + double at = v / a; + double a_s = 0.5f * a * at * at; + if (a_s > (s / 2)) //还没到特定速度就到了中点了 + { + t = (float)System.Math.Sqrt(s / a) * 2; + } + else + { + t = (s - a_s * 2) / v + at * 2; + } + + return t; + } //计算优化线路,采用米计算 + public void OptimizeRouteMeter(bool Is3d=false) + { + Dictionary curTaskPoint = new Dictionary(); + Dictionary prevTaskPoint = new Dictionary(); + var stopWatch = new Stopwatch(); + stopWatch.Start(); + //获取当前航点与前一航点所有经纬高 + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + //当前任务 + var curinfo = SelectedTask.SingleCopterInfos[i]; + Point3D curLoc = new Point3D(curinfo.X, curinfo.Y, curinfo.TargetAlt); + curTaskPoint.Add(i, curLoc); + + //前一任务 + var prevInfo = Tasks[SelectedTaskIndex - 1].SingleCopterInfos[i]; + Point3D prevLoc = new Point3D(prevInfo.X, prevInfo.Y, prevInfo.TargetAlt); + prevTaskPoint.Add(i, prevLoc); + } + //Dictionary RouteRes = Util.OptimizeRoute.GenRoute(curTaskPoint, prevTaskPoint); + if (Is3d) + { + ArrayList resarray = Util.OptimizeRoute.Gen3DRoute(curTaskPoint.Values.ToArray(), prevTaskPoint.Values.ToArray()); + Vector3[] RouteRes; + //最终 + RouteRes = (Vector3[])resarray[0]; + + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + SelectedTask.SingleCopterInfos[i].X = RouteRes[i].x; + SelectedTask.SingleCopterInfos[i].Y = RouteRes[i].y; + SelectedTask.SingleCopterInfos[i].TargetAlt = (float)RouteRes[i].z; + } + + SetTaskFlytime(SelectedTaskIndex); + + + } + else + { + ArrayList resarray = Util.OptimizeRoute.Gen2DRoute(curTaskPoint.Values.ToArray(), prevTaskPoint.Values.ToArray()); + Vector3[] RouteRes; + //有错层,需要插入2个错层任务 + if (resarray.Count == 3) + { + //选中前一个任务,插入错层 + SelectTask(SelectedTaskIndex - 1); + AddTask(); + + //第一个错层 + RouteRes = (Vector3[])resarray[0]; + + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + SelectedTask.SingleCopterInfos[i].X = RouteRes[i].x; + SelectedTask.SingleCopterInfos[i].Y = RouteRes[i].y; + SelectedTask.SingleCopterInfos[i].TargetAlt = (float)RouteRes[i].z; + } + SetTaskFlytime(SelectedTaskIndex); + + + //第二个错层 + AddTask(); + + RouteRes = (Vector3[])resarray[1]; + + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + SelectedTask.SingleCopterInfos[i].X = RouteRes[i].x; + SelectedTask.SingleCopterInfos[i].Y = RouteRes[i].y; + SelectedTask.SingleCopterInfos[i].TargetAlt = (float)RouteRes[i].z; + } + + SetTaskFlytime(SelectedTaskIndex); + + + SelectTask(SelectedTaskIndex + 1); + + //最终 + RouteRes = (Vector3[])resarray[2]; + + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + SelectedTask.SingleCopterInfos[i].X = RouteRes[i].x; + SelectedTask.SingleCopterInfos[i].Y = RouteRes[i].y; + SelectedTask.SingleCopterInfos[i].TargetAlt = (float)RouteRes[i].z; + } + SetTaskFlytime(SelectedTaskIndex); + + + } + else + { + //最终 + RouteRes = (Vector3[])resarray[0]; + + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + SelectedTask.SingleCopterInfos[i].X = RouteRes[i].x; + SelectedTask.SingleCopterInfos[i].Y = RouteRes[i].y; + SelectedTask.SingleCopterInfos[i].TargetAlt = (float)RouteRes[i].z; + } + SetTaskFlytime(SelectedTaskIndex); + + } + } + stopWatch.Stop(); + + double sumlength = SumFlyLines(Tasks[SelectedTaskIndex - 1].SingleCopterInfos, SelectedTask.SingleCopterInfos); + + Message.Show($"计算用时:{stopWatch.Elapsed.TotalMilliseconds}ms,总飞行距离{sumlength}米"); + + + return; + } + + + + + //计算优化线路,采用经纬度计算 public void OptimizeRouteNew() { Dictionary curTaskPoint = new Dictionary(); Dictionary prevTaskPoint = new Dictionary(); + var stopWatch = new Stopwatch(); + stopWatch.Start(); //获取当前航点与前一航点所有经纬高 for (int i = 0; i < _copterManager.Copters.Count; i++) { @@ -1326,72 +1568,74 @@ namespace Plane.FormationCreator.Formation prevTaskPoint.Add(i, prevLoc); } - // int sss = Plane.AutoLine.CalAutoLine(curTaskPoint, prevTaskPoint); - // Message.Show($"中心点:{sss}"); + // int sss = Plane.AutoLine.CalAutoLine(curTaskPoint, prevTaskPoint); + // Message.Show($"中心点:{sss}"); double farDistance; double nearDistance; int index; - Dictionary recordLatLng = new Dictionary(); + Dictionary recordLatLng = new Dictionary(); while (curTaskPoint.Count > 0) { farDistance = double.MinValue; - + PLLocation centerLatLng = CenterLatLng(curTaskPoint.Values.ToList(), prevTaskPoint.Values.ToList()); index = 0; - LatLng centerLatLng = CenterLatLng(curTaskPoint.Values.ToList(), prevTaskPoint.Values.ToList()); //计算两个列表距离中心最远距离 - + // Message.Show($"有{curTaskPoint.Count}个点,当前中心点:{centerLatLng.Longitude},{centerLatLng.Latitude},{centerLatLng.Altitude}"); double distance1; bool farIsCurTaskPoint = true; foreach (var item in curTaskPoint) { - distance1 = GeographyUtils.CalcDistance(centerLatLng.Lat, centerLatLng.Lng, 1, - item.Value.Latitude, item.Value.Longitude, 1); + distance1 =Math.Round(GeographyUtils.CalcDistance(centerLatLng,item.Value),4); if (distance1 > farDistance) { index = item.Key; farDistance = distance1; farIsCurTaskPoint = true; + // Message.Show($"调整距离{farDistance}是{farIsCurTaskPoint}的{index}"); + } } foreach (var item in prevTaskPoint) { - distance1 = GeographyUtils.CalcDistance(centerLatLng.Lat, centerLatLng.Lng, 1, - item.Value.Latitude, item.Value.Longitude, 1); + distance1 = Math.Round(GeographyUtils.CalcDistance(centerLatLng,item.Value),4); if (distance1 > farDistance) { index = item.Key; farDistance = distance1; farIsCurTaskPoint = false; + // Message.Show($"调整距离{farDistance}是{farIsCurTaskPoint}的{index}"); + } } + // Message.Show($"最远{farDistance}是{farIsCurTaskPoint}的{index}"); + + double tempDistance1; nearDistance = double.MaxValue; int nearIndex = 0; if (farIsCurTaskPoint) { - double curLat = curTaskPoint[index].Latitude; - double curLng = curTaskPoint[index].Longitude; //最远的航点在当前任务 - foreach (var item in prevTaskPoint) { - tempDistance1 = GeographyUtils.CalcDistance(curLat, curLng, 1, - item.Value.Latitude, item.Value.Longitude, 1); + tempDistance1 = Math.Round(GeographyUtils.CalcDistance(curTaskPoint[index],item.Value),4); if (tempDistance1 < nearDistance) { nearDistance = tempDistance1; nearIndex = item.Key; } } + //最远的航点在当前任务 + // Message.Show($"最远是当前任务{index}距离它最近的前一任务点:ind={nearIndex},记录前一任务序号和当前任务位置"); - recordLatLng.Add(nearIndex, new LatLng(curLat, curLng)); + recordLatLng.Add(nearIndex, curTaskPoint[index]); curTaskPoint.Remove(index); prevTaskPoint.Remove(nearIndex); @@ -1401,20 +1645,20 @@ namespace Plane.FormationCreator.Formation //最远的航点在前一任务 double prevLat = prevTaskPoint[index].Latitude; double prevLng = prevTaskPoint[index].Longitude; + float prevAlt = prevTaskPoint[index].Altitude; //最远的航点在当前任务 + //Message.Show($"最远点在前一任务:ind={index},距离{farDistance}"); foreach (var item in curTaskPoint) { - tempDistance1 = GeographyUtils.CalcDistance(prevLat, prevLng, 1, - item.Value.Latitude, item.Value.Longitude, 1); + tempDistance1 = Math.Round(GeographyUtils.CalcDistance(prevTaskPoint[index],item.Value),4); if (tempDistance1 < nearDistance) { nearDistance = tempDistance1; nearIndex = item.Key; } } - - recordLatLng.Add(index, new LatLng(curTaskPoint[nearIndex].Latitude, curTaskPoint[nearIndex].Longitude)); - + // Message.Show($"最远是前一任务{index}距离它最近的当前任务点:ind={nearIndex},记录前一任务序号和当前任务位置"); + recordLatLng.Add(index, curTaskPoint[nearIndex]); curTaskPoint.Remove(nearIndex); prevTaskPoint.Remove(index); } @@ -1424,16 +1668,81 @@ namespace Plane.FormationCreator.Formation for (int i = 0; i < _copterManager.Copters.Count; i++) { - SelectedTask.SingleCopterInfos[i].TargetLat = recordLatLng[i].Lat; - SelectedTask.SingleCopterInfos[i].TargetLng = recordLatLng[i].Lng; + SelectedTask.SingleCopterInfos[i].TargetLat = recordLatLng[i].Latitude; + SelectedTask.SingleCopterInfos[i].TargetLng = recordLatLng[i].Longitude ; + SelectedTask.SingleCopterInfos[i].TargetAlt = recordLatLng[i].Altitude; + } + stopWatch.Stop(); + double sumlength = SumFlyLines(Tasks[SelectedTaskIndex - 1].SingleCopterInfos, SelectedTask.SingleCopterInfos); + + + + + double Dist; + int crosscount = 0; + for (int i = 0; i < _copterManager.Copters.Count; i++) + + { + for (int j = i + 1; j < _copterManager.Copters.Count; j++) + { + + + Dist = Util.OptimizeRoute.SqureDistanceSegmentToSegment( + new Point3D(Tasks[SelectedTaskIndex - 1].SingleCopterInfos[i].X, + Tasks[SelectedTaskIndex - 1].SingleCopterInfos[i].Y, + Tasks[SelectedTaskIndex - 1].SingleCopterInfos[i].TargetAlt), + + new Point3D(Tasks[SelectedTaskIndex].SingleCopterInfos[i].X, + Tasks[SelectedTaskIndex].SingleCopterInfos[i].Y, + Tasks[SelectedTaskIndex].SingleCopterInfos[i].TargetAlt), + + new Point3D(Tasks[SelectedTaskIndex - 1].SingleCopterInfos[j].X, + Tasks[SelectedTaskIndex - 1].SingleCopterInfos[j].Y, + Tasks[SelectedTaskIndex - 1].SingleCopterInfos[j].TargetAlt), + + new Point3D(Tasks[SelectedTaskIndex].SingleCopterInfos[j].X, + Tasks[SelectedTaskIndex].SingleCopterInfos[j].Y, + Tasks[SelectedTaskIndex].SingleCopterInfos[j].TargetAlt) + ); + //交叉 + if (Dist < 0.01) + { + crosscount++; + // Message.Show($"飞机{i}和飞机{j}有交叉,距离{Dist}"); + + + } + } + + } + + + + + + + + + + + + + + + + + + + Message.Show($"经纬方式计算用时:{stopWatch.Elapsed.TotalMilliseconds}ms,总飞行距离{sumlength}米,有{crosscount}个交叉"); + } - //计算中心点 (二维的-只算水平面) - private LatLng CenterLatLng(List point1, List point2) + //计算中心点 (三维的) + private PLLocation CenterLatLng(List point1, List point2) { - LatLng centerLatLng = new LatLng(0, 0); + PLLocation centerLatLng = new PLLocation(0,0,0); if (point1.Count != point2.Count) return centerLatLng; double minLat = point1[0].Latitude; @@ -1442,18 +1751,29 @@ namespace Plane.FormationCreator.Formation double minLng = point1[0].Longitude; double maxLng = point1[0].Longitude; + + double minAlt = point1[0].Altitude; + double maxAlt = point1[0].Altitude; + + + int count = point1.Count; for (int i = 0; i < count; i++) { minLat = Math.Min(minLat, Math.Min(point1[i].Latitude, point2[i].Latitude)); - maxLat = Math.Min(maxLat, Math.Min(point1[i].Latitude, point2[i].Latitude)); + maxLat = Math.Max(maxLat, Math.Min(point1[i].Latitude, point2[i].Latitude)); minLng = Math.Min(minLng, Math.Min(point1[i].Longitude, point2[i].Longitude)); maxLng = Math.Max(maxLng, Math.Max(point1[i].Longitude, point2[i].Longitude)); - } - centerLatLng.Lat = (minLat + maxLat) / 2; - centerLatLng.Lng = (minLng + maxLng) / 2; + minAlt = Math.Min(minAlt, Math.Min(point1[i].Altitude, point2[i].Altitude)); + maxAlt = Math.Max(maxAlt, Math.Max(point1[i].Altitude, point2[i].Altitude)); + + + } + centerLatLng.Latitude = (minLat + maxLat) / 2; + centerLatLng.Longitude = (minLng + maxLng) / 2; + centerLatLng.Altitude =(float)(minAlt + maxAlt) / 2; return centerLatLng; } diff --git a/Plane.FormationCreator/MainWindow.xaml b/Plane.FormationCreator/MainWindow.xaml index 97abeed..e98b081 100644 --- a/Plane.FormationCreator/MainWindow.xaml +++ b/Plane.FormationCreator/MainWindow.xaml @@ -48,11 +48,39 @@