自动生成航点和飞机按方阵生成

限制卫星地图放大最大为19级
飞行航线和实际航线默认不显示,增加显示选项
可导入某些步骤
This commit is contained in:
pxzleo 2017-03-15 23:17:14 +08:00
parent cd3f894449
commit 84659afdab
12 changed files with 331 additions and 40 deletions

View File

@ -201,15 +201,46 @@ namespace Plane.FormationCreator.Formation
if (nullableCenter == null) return;
var center = nullableCenter.Value;
var newTask = new FlightTask(FlightTaskType.FlyTo);
int coptindex = 0;
int colnum = 5; //自动生成列数=4
float coldis = 5;//列相距5米
float rowdis = 5;//行相距5米
float matrixdis = 20; //生成方阵距离30米
int currcol = 0; //当前列号
int currrow = 0; //当前行
Tuple<double,double> colLatLng = new Tuple<double, double>(0, 0);
Tuple<double, double> targetLatLng = new Tuple<double, double>(0, 0);
FlightTaskSingleCopterInfo lastSingleCopterInfo =null;
foreach (var copter in copters)
{
var lastSingleCopterInfo = lastTask.SingleCopterInfos.Find(info => info.Copter == copter);
var direction = GeographyUtils.CalcDirection2D(center.Lat, center.Lng, lastSingleCopterInfo.TargetLat, lastSingleCopterInfo.TargetLng);
var targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(lastSingleCopterInfo.TargetLat, lastSingleCopterInfo.TargetLng, (float)GeographyUtils.RadToDeg(direction), 5);
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForFlyToTask(copter, targetLatLng.Item1, targetLatLng.Item2, lastSingleCopterInfo.TargetAlt,true);
if (coptindex == 0)
{
lastSingleCopterInfo = lastTask.SingleCopterInfos.Find(info => info.Copter == copter);
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(lastSingleCopterInfo.TargetLat, lastSingleCopterInfo.TargetLng, 0, matrixdis);
colLatLng = targetLatLng;
}
else
{
if (currcol < colnum)
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Item1, colLatLng.Item2, 90, currcol* coldis);
else
{
currrow++;
currcol = 0;
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Item1, colLatLng.Item2, 180, rowdis);
colLatLng = targetLatLng;
}
}
currcol++;
coptindex++;
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForFlyToTask(copter, targetLatLng.Item1, targetLatLng.Item2, lastSingleCopterInfo.TargetAlt, true);
newSingleCopterInfo.TargetHeading = lastSingleCopterInfo.TargetHeading;
newSingleCopterInfo.CenterDirectionDeg = lastSingleCopterInfo.TargetHeading;
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
try
@ -633,6 +664,49 @@ namespace Plane.FormationCreator.Formation
return JsonConvert.SerializeObject(tasks);
}
public void ImportTasksindex(string tasksText,int startindex,int endindex)
{
dynamic tasks = JsonConvert.DeserializeObject(tasksText);
var copters = _copterManager.Copters;
int i=1;
foreach (var task in tasks)
{
if ((i >= startindex)&& (i <= endindex))
{
switch ((FlightTaskType)task.type)
{
case FlightTaskType.TakeOff:
// AddTakeOffTask(copters); // added by ZJF
// TakeOffNumAttr = task.takeoffnumber;
break;
case FlightTaskType.FlyTo:
RestoreFlyToTask((bool)task.staggerRoutes, task.singleCopterInfos);
break;
case FlightTaskType.Turn:
RestoreTurnTask(task.singleCopterInfos);
break;
case FlightTaskType.Circle:
RestoreCircleTask(task.singleCopterInfos);
break;
case FlightTaskType.Loiter:
RestoreLoiterTimeTask((float)task.loiterTimeAttr, (bool)task.flashCheck, (float)task.flashCheckPeriod,
(bool)task.oneByOneCheck, (float)task.oneByOneCheckPeriod, (string)task.flashNameArray,
(string)task.flashIndexArray, (bool)task.ChangeYaw, (float)task.HeadYaw, task.singleCopterInfos);
break;
case FlightTaskType.SimpleCircle:
RestoreSimpleCircleTask(task.singleCopterInfos);
break;
case FlightTaskType.ReturnToLand:
// RestoreReturnToLandTask(copters, (int)task.retnumber, (int)task.rtlalt);
break;
}
}
i++;
}
}
public void ImportTasks(string tasksText)
{
dynamic tasks = JsonConvert.DeserializeObject(tasksText);

View File

@ -525,8 +525,7 @@ namespace Plane.FormationCreator.Formation
tasks[i] = await Task.Factory.StartNew(async () =>
{
var internalInfo = info;
await info.Copter.SetShowLEDAsync(info.FlytoShowLED);
//if (i1 > 0)
//if (i1 > 0)
//{
// var prevCopter = infos[i1 - 1].Copter;
// while (CheckCrossing(infos, i1) &&
@ -645,6 +644,7 @@ namespace Plane.FormationCreator.Formation
if ((bool)_copterManager.CopterStatus[copterIndex])
return;
await info.Copter.SetShowLEDAsync(info.FlytoShowLED);
DateTime dtNow = DateTime.Now;
DateTime dtLastTime = DateTime.Now;
TimeSpan ts = dtNow - dtLastTime;

View File

@ -70,8 +70,8 @@
<Grid Margin="10,20,10,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75*" />
<ColumnDefinition Width="25*" MinWidth="360" />
<ColumnDefinition Width="73*" />
<ColumnDefinition Width="27*" MinWidth="360" />
</Grid.ColumnDefinitions>
<Grid Margin="0,0,10,0"

View File

@ -140,7 +140,13 @@ namespace Plane.FormationCreator
}
if (copterisselect)
{
_flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat+= e.Key == Key.W ? 0.00001 : -0.00001;
// double tlat = _flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat;
// int tmplat = (int)(tlat * 100000);
// tlat = (float)(tmplat * 1.0) / 100000;
// _flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat = tlat;
_flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat+= e.Key == Key.W ? 0.00001 : -0.00001;
}
}
@ -185,6 +191,11 @@ namespace Plane.FormationCreator
}
if (copterisselect)
{
// double tlng = _flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLng;
// int tmplng = (int)(tlng * 100000);
// tlng = (float)(tmplng * 1.0) / 100000;
// _flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLng = tlng;
_flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLng += e.Key == Key.D ? 0.00001 : -0.00001;

View File

@ -14,6 +14,7 @@ using System.Windows;
using System.Windows.Input;
using System.Threading;
using Plane.Communication;
using Plane.Geography;
namespace Plane.FormationCreator.ViewModels
{
@ -52,13 +53,71 @@ namespace Plane.FormationCreator.ViewModels
{
var center = _mapManager.Center;
string id;
int colnum = 5; //自动生成列数=4
float coldis = 5;//列相距5米
float rowdis = 5;//行相距5米
int currcol = 0; //当前列号
int currrow = 0; //当前行
Tuple<double, double> colheadLatLng = new Tuple<double, double>(0, 0);
Tuple<double, double> targetLatLng = new Tuple<double, double>(0, 0);
LatLng? colLatLng = new LatLng(center.Lat, center.Lng); ;
for (int i = 0; i < addcount; ++i, ++_virtualCopterId)
{
id = _virtualCopterId.ToString();
_lastVirtualCopterLocation =
if (i == 0)
{
_lastVirtualCopterLocation = new LatLng(center.Lat, center.Lng);
colLatLng = _lastVirtualCopterLocation;
}
else
{
if (currcol < colnum)
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Value.Lat, colLatLng.Value.Lng , 90, currcol * coldis);
else
{
currrow++;
currcol = 0;
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Value.Lat, colLatLng.Value.Lng, 180, rowdis);
colLatLng = new LatLng(targetLatLng.Item1, targetLatLng.Item2);
colheadLatLng = targetLatLng;
}
_lastVirtualCopterLocation= new LatLng(targetLatLng.Item1, targetLatLng.Item2);
}
currcol++;
/* _lastVirtualCopterLocation =
_lastVirtualCopterLocation == null ?
new LatLng(center.Lat, center.Lng) :
new LatLng(_lastVirtualCopterLocation.Value.Lat, _lastVirtualCopterLocation.Value.Lng + 0.0001);
*/
var copter = new FakeCopter(SynchronizationContext.Current);
copter.SetProperties(

View File

@ -149,6 +149,24 @@ namespace Plane.FormationCreator.ViewModels
get { return _Distancevalue; }
set { Set(nameof(Distancevalue), ref _Distancevalue, value); }
}
private int _txtStarindex=0;
public int txtStarindex
{
get { return _txtStarindex; }
set { Set(nameof(txtStarindex), ref _txtStarindex, value); }
}
private int _txtendindex=0;
public int txtendindex
{
get { return _txtendindex; }
set { Set(nameof(txtendindex), ref _txtendindex, value); }
}
private double _FlyToLat;
public double FlyToLat
{
@ -212,8 +230,23 @@ namespace Plane.FormationCreator.ViewModels
};
if (dialog.ShowDialog() == true)
{
int _startindex = txtStarindex;
int _endindex= txtendindex;
var tasksText = File.ReadAllText(dialog.FileName);
_flightTaskManager.ImportTasks(tasksText);
if ((txtStarindex == 0) && (txtendindex == 0))
_flightTaskManager.ImportTasks(tasksText);
else
{
_endindex = txtendindex;
if (_startindex == 0)
_startindex = 1;
if (_endindex == 0)
_endindex = _startindex;
_flightTaskManager.ImportTasksindex(tasksText, _startindex, _endindex);
}
}
}));
}
@ -221,6 +254,7 @@ namespace Plane.FormationCreator.ViewModels
private ICommand _LevelAverageCommand;
public ICommand LevelAverageCommand
{
@ -355,7 +389,7 @@ namespace Plane.FormationCreator.ViewModels
if (copterisselect)
{
_flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat = minlat + avgl * coptnum;
_flightTaskManager.SelectedTask.SingleCopterInfos[i].TargetLat = maxlat - avgl * coptnum;
coptnum++;
}

View File

@ -57,7 +57,7 @@
<TextBox x:Name="txtVirtualCopterCount"
Width="35"
Margin="0,0,5,0"
Text="3"
Text="10"
VerticalContentAlignment="Center" />
<Button Content="添加虚拟飞行器"
VerticalContentAlignment="Center"

View File

@ -22,21 +22,41 @@
</bingMaps:Map.Center>
<!--<m:OpenStreetMapTileLayer UriFormat="http://tile.openstreetmap.org/{z}/{x}/{y}.png" />-->
</bingMaps:Map>
<!--<Grid HorizontalAlignment="Right"
VerticalAlignment="Top">
<Button Content="测距" />
</Grid>-->
<ComboBox x:Name="MapSelectionComboBox"
<StackPanel HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal"
>
<CheckBox Grid.Row="0" Content="计划航线" Margin="5,5,0,0"
Click="showpanline_Checked"
Foreground="White"
/>
<CheckBox Grid.Row="0" Content="实时航线" Margin="5,5,0,0"
Foreground="White"
Click="showrealtimeline_Checked" />
<ComboBox x:Name="MapSelectionComboBox"
HorizontalAlignment="Right"
Foreground="White"
Background="#232323"
Margin="5,0,0,0"
VerticalAlignment="Top"
SelectionChanged="MapSelectionComboBox_SelectionChanged">
<ComboBoxItem Content="卫星地图"
<ComboBoxItem Content="卫星地图"
Tag="卫星地图"
IsSelected="True" />
<ComboBoxItem Content="道路"
<ComboBoxItem Content="道路"
Tag="道路" />
<ComboBoxItem Content="OpenStreet"
<ComboBoxItem Content="OpenStreet"
Tag="OpenStreet" />
</ComboBox>
</ComboBox>
</StackPanel>
</Grid>
</UserControl>

View File

@ -138,6 +138,15 @@ namespace Plane.FormationCreator.Views
var center = _appConfig.Center;
map.Center = new Location(center.Lat, center.Lng);
map.ZoomLevel = _appConfig.ZoomLevel;
map.ViewChangeOnFrame += (object sender, MapEventArgs e) =>
{
if ( map.Mode.GetType().ToString() == "Microsoft.Maps.MapControl.WPF.AerialMode")
if (map.ZoomLevel >19)
map.ZoomLevel = 19;
};
}
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
@ -268,19 +277,46 @@ namespace Plane.FormationCreator.Views
RemoveTileLayers();
break;
case "道路":
map.Mode = new RoadMode();
// map.Mode = new GoogleMode();
map.Mode = new RoadMode();
RemoveTileLayers();
break;
case "OpenStreet":
map.Mode = new MercatorMode();
if (!map.Children.OfType<OpenStreetMapTileLayer>().Any())
{
map.Children.Add(new OpenStreetMapTileLayer { UriFormat = "http://tile.openstreetmap.org/{z}/{x}/{y}.png" });
map.Children.Add(new OpenStreetMapTileLayer
{ UriFormat =
"http://tile.openstreetmap.org/{z}/{x}/{y}.png"
});
}
break;
}
}
private void showpanline_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.SetShowroute(chk.IsChecked);
}
}
private void showrealtimeline_Checked(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.SetShowtrack (chk.IsChecked);
}
}
private void RemoveTileLayers()
{
for (int i = map.Children.Count - 1; i >= 0; i--)

View File

@ -101,7 +101,9 @@ namespace Plane.FormationCreator.Views
Track.Stroke = _brush;
Track.StrokeThickness = 3.0;
Track.Locations = new LocationCollection();
_map.Children.Add(Track);
//实时飞行航线
// _map.Children.Add(Track);
Dot = new Polygon();
@ -133,7 +135,12 @@ namespace Plane.FormationCreator.Views
this.Route = new MapPolyline { Locations = new LocationCollection { location } };
this.Route.Stroke = _brush;
this.Route.StrokeThickness = 2.0;
_map.Children.Add(this.Route);
//显示计划航线
// _map.Children.Add(this.Route);
this.LastLocation = location;
RegisterEventHandlersForDraggingCopter(DotContainer);
@ -339,6 +346,26 @@ namespace Plane.FormationCreator.Views
}
}
public void SetShowroute(bool? showroute)
{
if (showroute ?? false )
_map.Children.Add(this.Route);
else
_map.Children.Remove(this.Route);
}
public void SetShowtrack(bool? showtrack)
{
if (showtrack ?? false)
_map.Children.Add(Track);
else
_map.Children.Remove(Track);
}
public void SetEffect(bool selected)
{
Dot.Effect = selected ? _selectedEffect : null;

View File

@ -7,7 +7,7 @@
xmlns:vm="clr-namespace:Plane.FormationCreator.ViewModels"
xmlns:m="clr-namespace:Plane.FormationCreator.Formation"
mc:Ignorable="d"
d:DesignWidth="300" Height="400">
d:DesignWidth="300" Height="420">
<StackPanel Orientation="Vertical" Margin="0,0,0,-28.5">
<StackPanel.Resources>
@ -16,6 +16,9 @@
Value="Horizontal" />
</Style>
</StackPanel.Resources>
<TextBlock Text="任务操作" FontWeight="Bold" />
<StackPanel>
<Button Content="导出任务"
@ -23,18 +26,24 @@
Command="{Binding ExportTasksCommand}" />
<Button Content="导入任务"
Margin="5,5,0,0"
Command="{Binding ImportTasksCommand}" />
<TextBlock Text="同时起飞数量:" Margin="5,10,5,0" />
<TextBox x:Name="txttakeoff"
Width="25"
Command="{Binding ImportTasksCommand}"
/>
<TextBlock Text="导入起始" Margin="5, 10, 5, 0"/>
<TextBox x:Name="txtStarindex"
Width="45"
Margin="0,5,5,0"
VerticalContentAlignment="Center"
DataContext="{Binding FlightTaskManager}"
Text="{Binding TakeOffNumAttr, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding txtStarindex, UpdateSourceTrigger=PropertyChanged}"
/>
<TextBlock Text="结束" Margin="0, 10, 5, 0"/>
<TextBox x:Name="txtendindex"
Width="45"
Margin="0,5,5,0"
VerticalContentAlignment="Center"
Text="{Binding txtendindex, UpdateSourceTrigger=PropertyChanged}"
/>
</StackPanel>
<StackPanel>
<Button Content="上边对齐"
@ -68,13 +77,15 @@
Text="0"
VerticalContentAlignment="Center" />
<TextBlock Text="度" Margin="0, 10, 5, 0"/>
</StackPanel>
<TextBlock Text="垂直旋转前必须高度相同需要45度表演请转-135度" Margin="0, 10, 5, 0"/>
<StackPanel>
<Button Content="缩放比例"
Margin="0,5,5,0"
Command="{Binding ScaleCommand}"
@ -100,10 +111,25 @@
Text="{Binding Distancevalue, UpdateSourceTrigger=PropertyChanged}"
/>
<TextBlock Text="米" Margin="0, 10, 5, 0"/>
</StackPanel>
<Separator />
<TextBlock Text="任务属性" Margin="0, 0, 5, 0" FontWeight="Bold" />
<StackPanel>
<TextBlock Text="起飞数量:" Margin="5,10,5,0" />
<TextBox x:Name="txttakeoff"
Width="25"
Margin="0,5,5,0"
VerticalContentAlignment="Center"
DataContext="{Binding FlightTaskManager}"
Text="{Binding TakeOffNumAttr, UpdateSourceTrigger=PropertyChanged}"
/>
</StackPanel>
<TabControl Margin="0,5"
<TabControl Margin="0,5"
Grid.IsSharedSizeScope="True"
DataContext="{Binding FlightTaskManager.SelectedTask}"
SelectedIndex="{Binding TaskTypeIndex}">

View File

@ -46,6 +46,7 @@
</Button.Template>
</Button>
<Button HorizontalAlignment="Left"
Background="#232323"
Visibility="{Binding FlightTaskManager.IsPaused, Converter={StaticResource IsPausedToPauseButtonVisibilityConverter}}"
Command="{Binding PauseTasksCommand}">
<Button.Template>
@ -114,10 +115,13 @@
Orientation="Horizontal"
VerticalAlignment="Bottom">
<Button Content="添加任务"
Background="#232323"
Command="{Binding AddTaskCommand}" />
<Button Content="清除任务"
Background="#232323"
Command="{Binding ClearTasksCommand}" />
<Button Content="重置任务"
Background="#232323"
Command="{Binding ResetTasksCommand}" />
<!--<Button Content="保存" />
<Button Content="取消" />-->