Flybase库加入工程

加入2d自动计算航线--待测试
加入3d自动计算航线--未完成
主界面顶部调整
导入检测飞机数量并提示
加入多个任务垂直旋转用于自动计算的航线
This commit is contained in:
xu 2020-05-12 10:54:54 +08:00
parent c1db1e3525
commit 8fbb41928d
8 changed files with 708 additions and 185 deletions

View File

@ -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

View File

@ -36,6 +36,25 @@
False="【飞行模式】"
True="【设计模式】" />
<cnv:BooleanToStringConverter x:Key="MainColorConverterDes"
False="White"
True="DeepSkyBlue" />
<cnv:BooleanToStringConverter x:Key="MainFontSizeConverterDes"
False="12"
True="14" />
<cnv:BooleanToStringConverter x:Key="MainColorConverterFly"
False="DeepSkyBlue"
True="White" />
<cnv:BooleanToStringConverter x:Key="MainFontSizeConverterFly"
False="14"
True="12" />
<cnv:BooleanToStringConverter x:Key="Show2d3dButtonContentConverter"
False="平面视图"
True="立体视图" />

View File

@ -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<Point3D> point1, List<Point3D> 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<FlightTaskSingleCopterInfo> preinfos, List<FlightTaskSingleCopterInfo> 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<int, Point3D> curTaskPoint = new Dictionary<int, Point3D>();
Dictionary<int, Point3D> prevTaskPoint = new Dictionary<int, Point3D>();
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<int, Point3D> 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<int, PLLocation> curTaskPoint = new Dictionary<int, PLLocation>();
Dictionary<int, PLLocation> prevTaskPoint = new Dictionary<int, PLLocation>();
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<int, LatLng> recordLatLng = new Dictionary<int, LatLng>();
Dictionary<int, PLLocation> recordLatLng = new Dictionary<int, PLLocation>();
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<PLLocation> point1, List<PLLocation> point2)
//计算中心点 (三维的)
private PLLocation CenterLatLng(List<PLLocation> point1, List<PLLocation> 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;
}

View File

@ -48,11 +48,39 @@
<Button Content="{Binding LoginDisp}"
Command="{Binding LoginCommand}" />
<Button Content="飞行面板"
Foreground="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainColorConverterFly}}"
FontSize="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainFontSizeConverterFly}}"
Command="{Binding HideModifyTaskViewCommand}" />
<Button Content="设计面板"
Foreground="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainColorConverterDes}}"
FontSize="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainFontSizeConverterDes}}"
Command="{Binding ShowModifyTaskViewCommand}" />
<Button Content="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource ShowModifyTaskViewButtonContentConverter}}"
Command="{Binding ShowOrHideModifyTaskViewCommand}" />
Command="{Binding ShowOrHideModifyTaskViewCommand}" Visibility="Collapsed" />
<Button Content="平面编辑"
Foreground="{Binding b2DMapMode, Converter={StaticResource MainColorConverterDes}}"
FontSize="{Binding b2DMapMode, Converter={StaticResource MainFontSizeConverterDes}}"
Command="{Binding Map2DCommand}"/>
<Button Content="实景效果"
Foreground="{Binding b2DMapMode, Converter={StaticResource MainColorConverterFly}}"
FontSize="{Binding b2DMapMode, Converter={StaticResource MainFontSizeConverterFly}}"
Command="{Binding Map3DCommand}"/>
<Button Content="{Binding b2DMapMode, Converter={StaticResource Show2d3dButtonContentConverter}}"
Command="{Binding ChangeMapModeCommand}"/>
Command="{Binding ChangeMapModeCommand}" Visibility="Collapsed"/>
<Button Content="重启监听"
Visibility="Collapsed"
Command="{Binding RestartListeningCommand}" />
@ -236,7 +264,7 @@
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Margin="10,4"
Text="{Binding Message}" Width="400" MouseUp="LogShowHide"/>
Text="{Binding Message}" Width="480" MouseUp="LogShowHide"/>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="0,8" BorderBrush="LightGray" BorderThickness="1"/>
<TextBlock Margin="10,4"
Width="300" Text="{Binding SysStatusText}" />

View File

@ -51,9 +51,6 @@
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="flyBase">
<HintPath>..\..\Tools\flyBase.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight, Version=5.2.0.37222, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
<HintPath>..\packages\MvvmLightLibs.5.2.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
<Private>True</Private>
@ -197,6 +194,7 @@
</Compile>
<Compile Include="Util\ICommsSerial.cs" />
<Compile Include="Util\ICorrections.cs" />
<Compile Include="Util\OptimizeRoute.cs" />
<Compile Include="Util\ParamFile.cs" />
<Compile Include="Util\PasswordBoxHelper.cs" />
<Compile Include="Util\rtcm3.cs" />
@ -451,6 +449,10 @@
<Project>{0111eb6e-72e3-499c-a3ba-022f5bbc4caf}</Project>
<Name>PlaneGcsSdk_Private_NET46</Name>
</ProjectReference>
<ProjectReference Include="..\..\Tools\flyBase\flyBase.csproj">
<Project>{be3280e8-8c7f-4961-9685-1124c5b990cb}</Project>
<Name>flyBase</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="gcs.ico" />

View File

@ -18,6 +18,7 @@ using Plane.FormationCreator.Views;
using System.Windows;
using Plane.Collections;
using Plane.Copters;
using Newtonsoft.Json.Linq;
namespace Plane.FormationCreator.ViewModels
{
@ -219,6 +220,30 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private ICommand _ShowModifyTaskViewCommand;
public ICommand ShowModifyTaskViewCommand
{
get
{
return _ShowModifyTaskViewCommand ?? (_ShowModifyTaskViewCommand = new RelayCommand(() =>
{
AppEx.Current.ShowModifyTaskView = true;
}));
}
}
private ICommand _HideModifyTaskViewCommand;
public ICommand HideModifyTaskViewCommand
{
get
{
return _HideModifyTaskViewCommand ?? (_HideModifyTaskViewCommand = new RelayCommand(() =>
{
AppEx.Current.ShowModifyTaskView =false;
}));
}
}
private ICommand _ShowOrHideModifyTaskViewCommand;
public ICommand ShowOrHideModifyTaskViewCommand
@ -256,6 +281,54 @@ namespace Plane.FormationCreator.ViewModels
private ICommand _Map2DCommand;
public ICommand Map2DCommand
{
get
{
return _Map2DCommand ?? (_Map2DCommand = new RelayCommand(() =>
{
MainWindow mainw = (MainWindow)App.Current.MainWindow;
mainw.map.Visibility = System.Windows.Visibility.Visible;
mainw.map3D.Visibility = System.Windows.Visibility.Collapsed;
MapMode = 0;
b2DMapMode = true;
_flightTaskManager.TaskRun_2D = b2DMapMode; //2D模式模拟显示
//强制刷新飞机位置
_copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
private ICommand _Map3DCommand;
public ICommand Map3DCommand
{
get
{
return _Map3DCommand ?? (_Map3DCommand = new RelayCommand(() =>
{
MainWindow mainw = (MainWindow)App.Current.MainWindow;
mainw.map.Visibility = System.Windows.Visibility.Collapsed;
mainw.map3D.Visibility = System.Windows.Visibility.Visible;
MapMode = 1;
b2DMapMode = false;
_flightTaskManager.TaskRun_2D = b2DMapMode; //3D模式模拟显示
}));
}
}
private ICommand _ChangeMapModeCommand;
public ICommand ChangeMapModeCommand
{
@ -500,8 +573,22 @@ namespace Plane.FormationCreator.ViewModels
//int task Newtonsoft.Json.Linq.JArray
if (taskinfo.Count == 0)
{
Alert.Show($"导入的文件没有飞行任务!", "提示");
return;
}
if ((taskinfo[0].singleCopterInfos.Count != _copterManager.Copters.Count))
{
Alert.Show($"导入的飞机数量不符!导入飞机{taskinfo[0].singleCopterInfos.Count},实际飞机{ _copterManager.Copters.Count}", "提示");
return;
}
if ((txtStarindex == 0) && (txtendindex == 0))
{

View File

@ -191,6 +191,34 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(directionvalueall), ref _directionvalueall, value); }
}
private int _taskstartno = 0;
public int taskstartno
{
get { return _taskstartno; }
set { Set(nameof(taskstartno), ref _taskstartno, value); }
}
private int _taskendno = 0;
public int taskendno
{
get { return _taskendno; }
set { Set(nameof(taskendno), ref _taskendno, value); }
}
private float _taskdirection = 0;
public float taskdirection
{
get { return _taskdirection; }
set { Set(nameof(taskdirection), ref _taskdirection, value); }
}
private double _FlyToLat;
public double FlyToLat
{
@ -226,9 +254,121 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(OnlySelected), ref _OnlySelected, value); }
}
/// <summary>
/// 垂直旋转多个任务
/// </summary>
private ICommand _MitTaskVrotationCommand;
public ICommand MitTaskVrotationCommand
{
get
{
return _MitTaskVrotationCommand ?? (_MitTaskVrotationCommand = new RelayCommand<float>(async =>
{
double lngsum = 0;
double latsum = 0;
double altsum = 0;
int selectcount = 0;
// double centlng = 0;
double centlat = 0;
double centalt = 0;
if ((taskstartno<=1)||(taskendno> _flightTaskManager.Tasks.Count()))
{
Alert.Show("任务范围不正确", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
//计算旋转中心轴
for (int i = taskstartno-1; i < taskendno; i++)
{
for (int j = 0; j < _flightTaskManager.Tasks[i].SingleCopterInfos.Count; j++)
{
lngsum += _flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetLng;
latsum += _flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetLat;
altsum += _flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetAlt;
selectcount++;
}
}
if (selectcount > 0)
{
// centlng = lngsum / selectcount;
centlat = latsum / selectcount;
centalt = altsum / selectcount;
}
//////////计算旋转,经测试用下面的函数组合计算比较准确
double k = (double)taskdirection / 180 * Math.PI;
double dx = 0;
double dy = 0;
double ax = 0;
double ay = 0;
double tlng = 0;
double tlat = 0;
for (int i = taskstartno-1; i < taskendno; i++)
{
for (int j = 0; j < _flightTaskManager.Tasks[i].SingleCopterInfos.Count; j++)
{
tlng = _flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetLng;
tlat = _flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetLat;
//纬度方向距离单位m
ax = CalculationLogLatDistance.GetDistanceOne(tlng, centlat, tlng, tlat) * 1000;
//方向角用于正负,0为正180为负
CalculationLogLatDistance.MyLatLng mypos1, mypos2;
mypos1 = new CalculationLogLatDistance.MyLatLng(tlng, centlat);
mypos2 = new CalculationLogLatDistance.MyLatLng(tlng, tlat);
double lpAzimuth = CalculationLogLatDistance.getAngle(mypos1, mypos2);
if (lpAzimuth > 90)
ax = -ax;
//高度方向距离单位m
ay = (_flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetAlt - centalt);
dx = ax * Math.Cos(k) + ay * Math.Sin(k);
dy = -ax * Math.Sin(k) + ay * Math.Cos(k);
//新高度(米)
_flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetAlt = (float)(centalt + dy);
//计算新纬度
double lng2 = 0;
double lat2 = 0;
if (dx < 0)
lpAzimuth = 180;
else
lpAzimuth = 0;
dx = Math.Abs(dx);
CalculationLogLatDistance.ConvertDistanceToLogLat(
tlng,
centlat, //旋转中心纬度
dx / 1000, //新距离
lpAzimuth, //方向垂直
out lng2,
out lat2);
_flightTaskManager.Tasks[i].SingleCopterInfos[j].TargetLat = lat2;
}
}
// await Task.Delay(100); // 如果不等待一段时间,很可能会再触发 DataStreamReceived 事件导致飞行器重新出现在地图上。
}));
}
}
private ICommand _ShowallTaskpointCommand;
public ICommand ShowallTaskpointCommand
@ -243,10 +383,6 @@ namespace Plane.FormationCreator.ViewModels
//_flightTaskManager.SelectedTask = null;
}));
}
}
//调整所有任务经度
private ICommand _ModiAllPosCommand;
@ -559,7 +695,7 @@ namespace Plane.FormationCreator.ViewModels
{
var tasksText = File.ReadAllText(dialog.FileName);
_flightTaskManager.ImportC4DFlytoTask(tasksText);
autoalltasktime();
_flightTaskManager.SetAllTaskFlytime();
}else
if ((extname == ".svg")|| (extname == ".obj"))
{
@ -575,43 +711,8 @@ namespace Plane.FormationCreator.ViewModels
public void autoalltasktime()
{
for (int taskIndex = 1; taskIndex < _flightTaskManager.Tasks.Count; taskIndex++)
{
if (taskIndex != 0 || _flightTaskManager.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 = _flightTaskManager.Tasks[taskIndex - 1].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
var curWaypoint = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
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},最大航点间距 = {Math.Round(maxDistance, 2)}米, 水平速度={Math.Round(speed, 2)}, 飞行时间 = {Math.Round(time, 2)}秒, 飞机编号:{copterName}");
_flightTaskManager.Tasks[taskIndex].FlytoTime = (int)Math.Round(time, 2);
}
}
}
}
private ICommand _ExportWayPointCommand;
@ -621,6 +722,9 @@ namespace Plane.FormationCreator.ViewModels
{
return _ExportWayPointCommand ?? (_ExportWayPointCommand = new RelayCommand<int>(async =>
{
// _flightTaskManager.OptimizeRouteNew();
// return;
var dialog = new SaveFileDialog
{
DefaultExt = "txt",
@ -645,58 +749,7 @@ namespace Plane.FormationCreator.ViewModels
{
return _AutoWayPointTmCommand ?? (_AutoWayPointTmCommand = new RelayCommand<int>(async =>
{
int taskIndex = _flightTaskManager.SelectedTaskIndex;
if (taskIndex != 0 || _flightTaskManager.SelectedTask.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 = _flightTaskManager.Tasks[taskIndex - 1].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
var curWaypoint = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
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($"最大航点间距 = {Math.Round(maxDistance, 2)}米, 水平速度={Math.Round(speed, 2)}, 飞行时间 = {Math.Round(time, 2)}秒, 飞机编号:{copterName}");
_flightTaskManager.SelectedTask.FlytoTime = (int)Math.Round(time, 2);
}
}
_flightTaskManager.SetTaskFlytime(_flightTaskManager.SelectedTaskIndex);
}));
}
}
@ -714,16 +767,26 @@ namespace Plane.FormationCreator.ViewModels
if (Alert.Show("本操作将导致所有任务飞行时间重新计算,您确定要继续吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
== MessageBoxResult.OK)
{
autoalltasktime();
_flightTaskManager.SetAllTaskFlytime();
}
}));
}
}
private ICommand _OptimizeRouteCommand3D;
public ICommand OptimizeRouteCommand3D
{
get
{
return _OptimizeRouteCommand3D ?? (_OptimizeRouteCommand3D = new RelayCommand<int>(async =>
{
//_flightTaskManager.OptimizeRoute2();
// _flightTaskManager.OptimizeRouteNew (); //最后可用的,但是经纬度计算,
_flightTaskManager.OptimizeRouteMeter(true); //采用米计算逻辑和OptimizeRouteNew一样
}));
}
}
private ICommand _OptimizeRouteCommand;
public ICommand OptimizeRouteCommand
{
@ -732,7 +795,8 @@ namespace Plane.FormationCreator.ViewModels
return _OptimizeRouteCommand ?? (_OptimizeRouteCommand = new RelayCommand<int>(async =>
{
//_flightTaskManager.OptimizeRoute2();
_flightTaskManager.OptimizeRouteNew();
// _flightTaskManager.OptimizeRouteNew (); //最后可用的,但是经纬度计算,
_flightTaskManager.OptimizeRouteMeter(); //采用米计算逻辑和OptimizeRouteNew一样
}));
}
}
@ -919,23 +983,7 @@ public ICommand VerticlAlignmentCommand
}
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;
}
@ -1546,35 +1594,8 @@ public ICommand VerticlAlignmentCommand
{
return _MaxDistinceAndTimeCommand ?? (_MaxDistinceAndTimeCommand = new RelayCommand<double>(async =>
{
int taskIndex = _flightTaskManager.SelectedTaskIndex;
if (taskIndex != 0 || _flightTaskManager.SelectedTask.TaskType == FlightTaskType.FlyTo)
{
if (_copterManager.AcceptingControlCopters.Count() > 0)
{
double maxDistance = 0.0f;
string copterName = "";
double speed = 0.0f;
foreach (var copter in _copterManager.AcceptingControlCopters)
{
var prevWaypoint = _flightTaskManager.Tasks[taskIndex - 1].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
var curWaypoint = _flightTaskManager.Tasks[taskIndex].SingleCopterInfos.FirstOrDefault(c => c.Copter == copter);
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($"最大航点间距 = {Math.Round(maxDistance, 2)}米, 水平速度={Math.Round(speed, 2)}, 飞行时间 = {Math.Round(time, 2)}秒, 飞机编号:{copterName}");
}
}
//不设置时间,只是计算
_flightTaskManager.SetTaskFlytime(_flightTaskManager.SelectedTaskIndex, false);
}));
}
}

View File

@ -70,7 +70,9 @@
<TextBlock Margin="0,5,5,0" Text="所有:" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Button Margin="0,5,5,0" Content="导入航点" Command="{Binding ImportWayPointCommand}"
Visibility="Collapsed"/>
<Button Margin="0,5,5,0" Content="优化路线" Width="105" Command="{Binding OptimizeRouteCommand}"
<Button Margin="0,5,5,0" Content="计算航线2D" Width="105" Command="{Binding OptimizeRouteCommand}"
/>
<Button Margin="0,5,5,0" Content="计算航线3D" Width="105" Command="{Binding OptimizeRouteCommand3D}"
/>
<Button Margin="0,5,5,0" Content="导出到C4D" Width="105" Command="{Binding ExportWayPointCommand}"/>
<Button Margin="0,5,5,0" Content="估计时间" Width="105" Command="{Binding AutoWayPointTmCommand}"/>
@ -569,8 +571,9 @@
<StackPanel x:Name="PanelDesign2">
<StackPanel Orientation="Horizontal" Margin="0,5,0,5" >
<Button Content="整体旋转" Width="120"
<Button Content="整体水平旋转" Width="120"
Margin="10,5,0,5" Height="26"
ToolTip="用于整体飞行方向调整,地面飞机矩阵同时旋转"
Command="{Binding TaskRotateCommand}"
CommandParameter="{Binding ElementName=txtAlignmentLine1, Path=Text}"/>
<TextBox x:Name="txtAlignmentLine1"
@ -620,7 +623,36 @@
Margin="10,5,0,5" Height="26"
Command="{Binding ShowallTaskpointCommand}"
/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,5" >
<Button Content="垂直旋转" Width="120"
Margin="10,5,5,5" Height="26"
ToolTip="用于多个任务同时倾斜角度,旋转中心为各任务的共同中心,各任务图案位置尽量重叠"
Command="{Binding MitTaskVrotationCommand}"
/>
<TextBlock Text="开始任务" Margin="5, 10, 5, 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox
Width="35"
Margin="5,5,0,5" Height="26"
HorizontalContentAlignment="Right"
Text="{Binding taskstartno, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="结束任务" Margin="5, 10, 5, 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox
Width="35"
Margin="0,5,0,5" Height="26"
HorizontalContentAlignment="Right"
Text="{Binding taskendno, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="角度" Margin="5, 10, 5, 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<TextBox
Width="35"
Margin="0,5,0,5" Height="26"
HorizontalContentAlignment="Right"
Text="{Binding taskdirection, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="度" Margin="5, 10, 5, 0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</StackPanel>
@ -630,6 +662,7 @@
</StackPanel>
</TabItem>