Plane.FormationCreator/Plane.FormationCreator/Formation/FlightTaskManager.cs
pxzleo 7e04c83e26 1.飞机按编号顺序加入飞行列表
2.默认起飞高度为15米
3.修改航点位置改为按住左shift再按下asdw,不按shift则是控制移动飞机
4.修复上下旋转的高度bug
5.为防止碰撞,加入两个按钮,一个为自动计算高度(未实现),一个为自动设为前一步高度,这样一个图案应该有三个同样形状的飞行任务,一个进入(高度不同)一个表演,一个退出(高度不同)
2017-03-17 23:02:08 +08:00

957 lines
40 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Plane.Collections;
using Plane.Copters;
using Plane.Geography;
using Plane.Windows.Messages;
using GalaSoft.MvvmLight;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public class FlightTaskManager : ObservableObject
{
public FlightTaskManager(CopterManager copterManager)
{
_copterManager = copterManager;
//AddTakeOffTask(_copterManager.Copters);
_copterManager.Copters.CollectionChanged += (sender, e) =>
{
// TODO: 林俊清, 20150724, 需要改为正确的做法(清除旧飞机的任务,补充新飞机的任务)。
AddTakeOffTask(e.NewItems?.Cast<ICopter>());
};
_copterManager.SelectedCoptersChanged += (sender, e) =>
{
// TODO: 林俊清, 20150803, 处理选中多个飞行器的情况。
if (_copterManager.SelectedCopters.Count() > 1)
{
return;
}
var selectedCopter = _copterManager.SelectedCopters.FirstOrDefault();
foreach (var task in Tasks)
{
foreach (var info in task.SingleCopterInfos)
{
if (info.Copter == selectedCopter)
{
task.ModifyingSingleCopterInfo = info;
break;
}
}
}
if (selectedCopter!=null)
selectedCopter.SetShowLEDFlashAsync(1, 100);
};
TaskAdded += (sender, e) =>
{
// TODO: 林俊清, 20150803, 处理选中多个飞行器的情况。
if (_copterManager.SelectedCopters.Count() > 1)
{
return;
}
var selectedCopter = _copterManager.SelectedCopters.FirstOrDefault();
var task = e.AddedTask;
foreach (var info in task.SingleCopterInfos)
{
if (info.Copter == selectedCopter)
{
task.ModifyingSingleCopterInfo = info;
break;
}
}
};
}
private CopterManager _copterManager;
private double _OriginLat;
public double OriginLat
{
get { return _OriginLat; }
set { Set(nameof(OriginLat), ref _OriginLat, value); }
}
private int _TakeOffNumAttr = 1;
public int TakeOffNumAttr
{
get { return _TakeOffNumAttr; }
set
{
Set(nameof(TakeOffNumAttr), ref _TakeOffNumAttr, value);
bool takeOffTaskExisted = Tasks.Count >= 1;
FlightTask takeOffTask;
if (takeOffTaskExisted)
{
takeOffTask = Tasks[0];
takeOffTask.TakeOffNumAttr = TakeOffNumAttr;
}
}
}
private double _OriginLng;
public double OriginLng
{
get { return _OriginLng; }
set { Set(nameof(OriginLng), ref _OriginLng, value); }
}
private void AddTakeOffTask(IEnumerable<ICopter> copters)
{
if (copters == null || !copters.Any()) return;
bool takeOffTaskExisted = Tasks.Count >= 1;
FlightTask takeOffTask;
if (takeOffTaskExisted)
{
takeOffTask = Tasks[0];
}
else
{
takeOffTask = new FlightTask(FlightTaskType.TakeOff);
takeOffTask.TakeOffNumAttr = TakeOffNumAttr;
Tasks.Add(takeOffTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { AddedTask = takeOffTask });
}
foreach (var copter in copters)
{
takeOffTask.SingleCopterInfos.Add(FlightTaskSingleCopterInfo.CreateForTakeOffTask(copter, targetAlt: 15));
}
}
public ObservableCollection<FlightTask> Tasks { get; } = new ObservableCollection<FlightTask>();
private FlightTask _SelectedTask;
public FlightTask SelectedTask
{
get { return _SelectedTask; }
set
{
if (_SelectedTask != value)
{
if (_SelectedTask != null) _SelectedTask.IsSelected = false;
if (value != null) value.IsSelected = true;
}
Set(nameof(SelectedTask), ref _SelectedTask, value);
}
}
private int _SelectedTaskIndex;
public int SelectedTaskIndex
{
get { return _SelectedTaskIndex; }
set { Set(nameof(SelectedTaskIndex), ref _SelectedTaskIndex, value); }
}
// 右键单击任务,用于隐藏任务图标, added by ZJF
private int _RightSelectedTaskIndex;
public int RightSelectedTaskIndex
{
get { return _RightSelectedTaskIndex; }
set { Set(nameof(RightSelectedTaskIndex), ref _RightSelectedTaskIndex, value); }
}
private FlightTask _CurrentRunningTask;
public FlightTask CurrentRunningTask
{
get { return _CurrentRunningTask; }
private set { Set(nameof(CurrentRunningTask), ref _CurrentRunningTask, value); }
}
private int _CurrentRunningTaskIndex;
public int CurrentRunningTaskIndex
{
get { return _CurrentRunningTaskIndex; }
private set { Set(nameof(CurrentRunningTaskIndex), ref _CurrentRunningTaskIndex, value); }
}
public event EventHandler<FlightTaskAddedEventArgs> TaskAdded;
public event EventHandler<SingleCopterInfoChangedEventArgs> SingleCopterInfoChanged;
public void RaiseSingleCopterTaskChanged(FlightTaskSingleCopterInfo singleCopterInfo)
{
SingleCopterInfoChanged?.Invoke(this, new SingleCopterInfoChangedEventArgs(singleCopterInfo));
}
public event EventHandler TasksCleared;
public void AddTask()
{
//if (AppEx.Instance.CurrentMode == AppMode.PreparedForRunningTasks)
{
var copters = _copterManager.Copters;
if (!copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var nullableCenter = copters.GetCenter();
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)
{
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,
lastTask.SingleCopterInfos.Find(info => info.Copter == copter).TargetAlt, true);
newSingleCopterInfo.TargetHeading = lastSingleCopterInfo.TargetHeading;
newSingleCopterInfo.CenterDirectionDeg = lastSingleCopterInfo.TargetHeading;
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
try
{
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = newTask });
}
catch (Exception ex)
{
//RaiseExceptionThrown(ex);
}
SelectedTask = newTask;
SelectedTaskIndex = Tasks.Count - 1;
}
}
public void ClearTasks()
{
ResetTasks();
this.Tasks.Clear();
SelectedTask = null;
SelectedTaskIndex = 0;
TasksCleared?.Invoke(this, EventArgs.Empty);
AddTakeOffTask(_copterManager.Copters);
}
public void ResetTasks()
{
Pause();
CurrentRunningTaskIndex = 0;
if (CurrentRunningTask != null)
{
CurrentRunningTask.Status = FlightTaskStatus.Saved;
CurrentRunningTask = null;
}
for (int i = 0; i < Tasks.Count; i++)
{
// 将起飞的阶段标志位都置位0
if (Tasks[i].TaskType == FlightTaskType.TakeOff)
{
var infos = Tasks[i].SingleCopterInfos;
for (int j = 0; j < infos.Count; j++)
{
var info = infos[j];
info.takeOffStage = 0;
}
}
// 将降落的阶段标志位都置位0
if (Tasks[i].TaskType == FlightTaskType.ReturnToLand)
{
var infos = Tasks[i].SingleCopterInfos;
for (int j = 0; j < infos.Count; j++)
{
var info = infos[j];
info.RTLStage = 0;
}
}
}
}
public void RestoreFlyToTask(bool staggerRoutes, dynamic singleCopterInfos)
{
var copters = _copterManager.Copters;
if (!copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var nullableCenter = copters.GetCenter();
if (nullableCenter == null) return;
var center = nullableCenter.Value;
var newTask = new FlightTask(FlightTaskType.FlyTo) { StaggerRoutes = staggerRoutes };
// TODO: 林俊清, 20150801, 处理实际飞行器数目与记录中数目不一致的情况。
for (int i = 0; i < copters.Count && i < singleCopterInfos.Count; i++)
{
var copter = copters[i];
var singleCopterInfoObj = singleCopterInfos[i];
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForFlyToTask(copter, new LatLng((double)singleCopterInfoObj.latOffset, (double)singleCopterInfoObj.lngOffset), (float)singleCopterInfoObj.targetAlt,(bool)singleCopterInfoObj.showLED);
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = newTask });
SelectedTask = newTask;
SelectedTaskIndex = Tasks.Count - 1;
}
private void RestoreTurnTask(dynamic singleCopterInfos)
{
var copters = _copterManager.Copters;
if (!copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var newTask = new FlightTask(FlightTaskType.Turn);
// TODO: 林俊清, 20150806, 处理实际飞行器数目与记录中数目不一致的情况。
for (int i = 0; i < copters.Count && i < singleCopterInfos.Count; i++)
{
var copter = copters[i];
var singleCopterInfoObj = singleCopterInfos[i];
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForTurnTask(copter, new LatLng((double)singleCopterInfoObj.latOffset, (double)singleCopterInfoObj.lngOffset), (float)singleCopterInfoObj.targetAlt, (short)singleCopterInfoObj.targetHeading);
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = newTask });
SelectedTask = newTask;
SelectedTaskIndex = Tasks.Count - 1;
}
private void RestoreCircleTask(dynamic singleCopterInfos)
{
var copters = _copterManager.Copters;
if (!copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var newTask = new FlightTask(FlightTaskType.Circle);
// TODO: 林俊清, 20150806, 处理实际飞行器数目与记录中数目不一致的情况。
for (int i = 0; i < copters.Count && i < singleCopterInfos.Count; i++)
{
var copter = copters[i];
var singleCopterInfoObj = singleCopterInfos[i];
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForCircleTask(copter, new LatLng((double)singleCopterInfoObj.latOffset, (double)singleCopterInfoObj.lngOffset), (float)singleCopterInfoObj.targetAlt, (short)singleCopterInfoObj.centerDirectionDeg, (int)singleCopterInfoObj.radius, (int)singleCopterInfoObj.rate, (int)singleCopterInfoObj.turns, (ushort)singleCopterInfoObj.channel3);
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = newTask });
SelectedTask = newTask;
SelectedTaskIndex = Tasks.Count - 1;
}
private void RestoreSimpleCircleTask(dynamic singleCopterInfos)
{
var copters = _copterManager.Copters;
if (!copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var newTask = new FlightTask(FlightTaskType.SimpleCircle);
// TODO: 林俊清, 20150806, 处理实际飞行器数目与记录中数目不一致的情况。
for (int i = 0; i < copters.Count && i < singleCopterInfos.Count; i++)
{
var copter = copters[i];
var singleCopterInfoObj = singleCopterInfos[i];
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForSimpleCircleTask(copter, new LatLng((double)singleCopterInfoObj.latOffset, (double)singleCopterInfoObj.lngOffset), (float)singleCopterInfoObj.targetAlt, (int)singleCopterInfoObj.rate, (int)singleCopterInfoObj.turns, (ushort)singleCopterInfoObj.channel3);
newTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(newTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = newTask });
SelectedTask = newTask;
SelectedTaskIndex = Tasks.Count - 1;
}
// added by ZJF
private void RestoreReturnToLandTask(IEnumerable<ICopter> copters,int retnumber,int rtlalt)
{
if (copters == null || !copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var RTLTask = new FlightTask(FlightTaskType.ReturnToLand);
RTLTask.RetNumAttr = retnumber;
RTLTask.RTLAlt = rtlalt;
foreach (var copter in copters)
{
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForReturnToLandTask(copter, targetAlt:10);
RTLTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(RTLTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = RTLTask });
SelectedTask = RTLTask;
SelectedTaskIndex = Tasks.Count - 1;
}
// added by ZJF
private void RestoreLoiterTimeTask(float LoiteTimeTmp, bool flashCheck, float flashCheckPeriod,
bool oneByOneCheck, float oneByOneCheckPeriod, string flashNameArray, string flashIndexArray,
bool ChangeYaw, float HeadYaw,
dynamic singleCopterInfos)
{
var copters = _copterManager.Copters;
if (copters == null || !copters.Any()) return;
AppEx.Current.AppMode = AppMode.ModifyingTask;
var lastTask = Tasks.LastOrDefault();
var loiterTimeTask = new FlightTask(FlightTaskType.Loiter)
{
LoiterTimeAttr = LoiteTimeTmp
};
loiterTimeTask.flashAttr = flashCheck;
loiterTimeTask.flashPeriodAttr = flashCheckPeriod;
loiterTimeTask.oneByOneAttr = oneByOneCheck;
loiterTimeTask.oneByOnePeriodAttr = oneByOneCheckPeriod;
loiterTimeTask.flashCopterNameArray = flashNameArray;
loiterTimeTask.flashCopterIndexArray = flashIndexArray;
loiterTimeTask.ChangeYaw = ChangeYaw;
loiterTimeTask.HeadYaw = HeadYaw;
// foreach (var copter in copters)
for (int i=0; i < copters.Count && i < singleCopterInfos.Count; i++)
{
var copter = copters[i];
var singleCopterInfoObj = singleCopterInfos[i];
var newSingleCopterInfo = FlightTaskSingleCopterInfo.CreateForLoiterTimeTask(copter, new LatLng((double)singleCopterInfoObj.latOffset, (double)singleCopterInfoObj.lngOffset), (float)singleCopterInfoObj.targetAlt);
loiterTimeTask.SingleCopterInfos.Add(newSingleCopterInfo);
}
Tasks.Add(loiterTimeTask);
TaskAdded?.Invoke(this, new FlightTaskAddedEventArgs { LastTask = lastTask, AddedTask = loiterTimeTask });
SelectedTask = loiterTimeTask;
SelectedTaskIndex = Tasks.Count - 1;
}
public string ExportTasks()
{
// For reference.
//var tasks = new object[]
//{
// new
// {
// type = FlightTaskType.TakeOff,
// },
// new
// {
// type = FlightTaskType.FlyTo,
// staggerRoutes = false,
// singleCopterInfos = new object[] {
// new {
// latOffset = 0.0001,
// lngOffset = 0.0001,
// targetAlt = 10
// },
// new {
// latOffset = 0.0003,
// lngOffset = 0.0003,
// targetAlt = 15
// }
// }
// },
// new
// {
// type = FlightTaskType.Turn,
// singleCopterInfos = new object[] {
// new {
// latOffset = 0.0001,
// lngOffset = 0.0001,
// targetAlt = 10,
// targetHeading = 90
// },
// new {
// latOffset = 0.0001,
// lngOffset = 0.0001,
// targetAlt = 10,
// targetHeading = 270
// }
// }
// },
// new
// {
// type = FlightTaskType.Circle,
// singleCopterInfos = new object[] {
// new {
// latOffset = 0.0001,
// lngOffset = 0.0001,
// targetAlt = 10,
// centerDirectionDeg = 90,
// radius = 1000,
// rate = 20,
// turns = 1,
// channel3 = 1500
// },
// new {
// latOffset = 0.0003,
// lngOffset = 0.0003,
// targetAlt = 15,
// centerDirectionDeg = 270,
// radius = 1000,
// rate = 20,
// turns = 1,
// channel3 = 1500
// }
// }
// },
// new
// {
// type = FlightTaskType.SimpleCircle,
// singleCopterInfos = new object[] {
// new {
// latOffset = 0.0001,
// lngOffset = 0.0001,
// targetAlt = 10,
// rate = 20,
// turns = 1,
// channel3 = 1500
// },
// new {
// latOffset = 0.0003,
// lngOffset = 0.0003,
// targetAlt = 15,
// rate = 20,
// turns = 1,
// channel3 = 1500
// }
// }
// }
//};
var tasks = Tasks.Select<FlightTask, object>(task =>
{
var type = task.TaskType;
switch (type)
{
case FlightTaskType.TakeOff:
return new {
type = type,
takeoffnumber = TakeOffNumAttr
};
case FlightTaskType.FlyTo:
return new
{
type = type,
staggerRoutes = task.StaggerRoutes,
singleCopterInfos = task.SingleCopterInfos.Select(info =>
{
var offset = info.LatLngOffset;
return new
{
latOffset = offset.Lat,
lngOffset = offset.Lng,
targetAlt = info.TargetAlt,
showLED = info.FlytoShowLED
};
})
};
case FlightTaskType.Turn:
return new
{
type = type,
singleCopterInfos = task.SingleCopterInfos.Select(info =>
{
var offset = info.LatLngOffset;
return new
{
latOffset = offset.Lat,
lngOffset = offset.Lng,
targetAlt = info.TargetAlt,
targetHeading = info.TargetHeading
};
})
};
case FlightTaskType.Loiter: // 导出悬停任务
return new
{
type = type,
loiterTimeAttr = task.LoiterTimeAttr,
flashCheck = task.flashAttr,
flashCheckPeriod = task.flashPeriodAttr,
oneByOneCheck = task.oneByOneAttr,
oneByOneCheckPeriod = task.oneByOnePeriodAttr,
flashNameArray = task.flashCopterNameArray,
flashIndexArray = task.flashCopterIndexArray,
ChangeYaw = task.ChangeYaw,
HeadYaw = task.HeadYaw,
singleCopterInfos = task.SingleCopterInfos.Select(info =>
{
var offset = info.LatLngOffset;
return new
{
latOffset = offset.Lat,
lngOffset = offset.Lng,
targetAlt = info.TargetAlt
};
})
};
case FlightTaskType.Circle:
return new
{
type = type,
singleCopterInfos = task.SingleCopterInfos.Select(info =>
{
var offset = info.LatLngOffset;
return new
{
latOffset = offset.Lat,
lngOffset = offset.Lng,
targetAlt = info.TargetAlt,
centerDirectionDeg = info.CenterDirectionDeg,
radius = info.Radius,
rate = info.Rate,
turns = info.Turns,
channel3 = info.Channel3
};
})
};
case FlightTaskType.SimpleCircle:
return new
{
type = type,
singleCopterInfos = task.SingleCopterInfos.Select(info =>
{
var offset = info.LatLngOffset;
return new
{
latOffset = offset.Lat,
lngOffset = offset.Lng,
targetAlt = info.TargetAlt,
rate = info.Rate,
turns = info.Turns,
channel3 = info.Channel3
};
})
};
case FlightTaskType.ReturnToLand: // added by ZJF
return new
{
type = type,
rtlalt= task.RTLAlt,
retnumber = task.RetNumAttr
};
default:
throw new NotImplementedException(type + " task export not implemented.");
}
});
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);
var copters = _copterManager.Copters;
foreach (var task in tasks)
{
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;
}
}
}
public void Select(int taskIndex, ICopter copter)
{
this.SelectedTaskIndex = taskIndex;
this.SelectedTask = Tasks[taskIndex];
// 在悬停任务时左键waypoint为选中
// 在悬停任务模式且LED控制被选中时
if ((this.SelectedTask.TaskType == FlightTaskType.Loiter) && (this.SelectedTask.flashAttr || this.SelectedTask.oneByOneAttr))
{
string copterNameStr = this.SelectedTask.flashCopterNameArray;
string[] copterArray = copterNameStr.Split(',');
bool flag = false;
for (int i = 0; i < copterArray.Length; i++)
{
if (copterArray[i].Equals(""))
continue;
if (copterArray[i].Equals(copter.Name))
{
flag = true;
break;
}
}
if (!flag)
{
if (copterArray[0].Equals(""))
{
this.SelectedTask.flashCopterNameArray += copter.Name;
SelectedTask.flashCopterIndexArray += Name2Index(copter.Name);
}
else
{
this.SelectedTask.flashCopterNameArray += "," + copter.Name;
SelectedTask.flashCopterIndexArray += "," + Name2Index(copter.Name);
}
}
}
}
/**
* 在悬停任务时右键waypoint为取消选中
*/
public void RightSelect(int taskIndex, ICopter copter)
{
this.SelectedTaskIndex = taskIndex;
this.SelectedTask = Tasks[taskIndex];
// 在悬停任务模式且LED控制被选中时
if ((this.SelectedTask.TaskType == FlightTaskType.Loiter) && (this.SelectedTask.flashAttr || this.SelectedTask.oneByOneAttr))
{
this.SelectedTask.flashCopterNameArray = DeleteSelectedName(this.SelectedTask.flashCopterNameArray, copter.Name);
this.SelectedTask.flashCopterIndexArray = DeleteSelectedName(this.SelectedTask.flashCopterIndexArray, Name2Index(copter.Name).ToString());
}
}
private int Name2Index(string name) // 获取指定copter名字对应的序号
{
int index = -1;
for (int i = 0; i < SelectedTask.SingleCopterInfos.Count; i++)
{
if (name.Equals(SelectedTask.SingleCopterInfos[i].Copter.Name))
{
return i;
}
}
return index;
}
private string DeleteSelectedName( string nameArray, string name ) // 删除字符串中的指定项
{
string copterStr = nameArray;
if (copterStr.Equals(""))
return "";
string[] copterNameArray = copterStr.Split(',');
copterNameArray = copterNameArray.Where(str => !str.Equals(name)).ToArray();
copterStr = "";
for (int i = 0; i < copterNameArray.Length; i++)
{
copterStr = copterStr + copterNameArray[i];
if (i < (copterNameArray.Length - 1))
{
copterStr = copterStr + ",";
}
}
return copterStr;
}
public void Select(FlightTask flightTask)
{
this.SelectedTaskIndex = Tasks.IndexOf(flightTask);
this.SelectedTask = flightTask;
}
// 右键选中任务
public void RightSelect(FlightTask flightTask)
{
int RightSelectedTaskIndexTmp = Tasks.IndexOf(flightTask);
if (this.RightSelectedTaskIndex == RightSelectedTaskIndexTmp)
{
this.RightSelectedTaskIndex = -RightSelectedTaskIndexTmp;
}
else
{
this.RightSelectedTaskIndex = RightSelectedTaskIndexTmp;
}
}
#region Run and pause.
private bool? _IsPaused;
public bool? IsPaused
{
get { return _IsPaused; }
private set { Set(nameof(IsPaused), ref _IsPaused, value); }
}
public async Task RunAsync()
{
IsPaused = false;
AppEx.Current.AppMode = AppMode.RunningTasks;
StartAvoidingCrash();
for (int i = CurrentRunningTaskIndex; i < Tasks.Count; i++)
{
var task = Tasks[i];
task.Status = FlightTaskStatus.Running;
CurrentRunningTask = task;
CurrentRunningTaskIndex = i;
await task.RunAsync().ConfigureAwait(false);
// 1. 被暂停时,中断 RunAsync。继续运行时将把此时运行了一半的 CurrentRunningTask 重新运行一遍。
if (IsPaused == true) return;
task.Status = FlightTaskStatus.Saved;
}
// 2. 正常结束时,重置 CurrentRunningTask、CurrentRunningTaskIndex 和 IsPaused。
CurrentRunningTask = null;
CurrentRunningTaskIndex = 0;
IsPaused = null;
}
public void Pause()
{
IsPaused = true;
}
#endregion Run and pause.
private async void StartAvoidingCrash()
{
await Task.Factory.StartNew(LoopToAvoidCrash);
}
private async void LoopToAvoidCrash()
{
while (IsPaused == false)
{
try
{
// 在目前的起飞、降落逻辑,如果起飞或最后一个任务是返航降落,不要检查两架飞机距离过近. added by ZJF
bool RTLFlag = ( CurrentRunningTaskIndex == Tasks.Count()-1 ) && ( CurrentRunningTask.TaskType == FlightTaskType.ReturnToLand );
// bool RTLFlag = false;
if ( (CurrentRunningTaskIndex != 0) && !RTLFlag)
{
foreach (var copter in _copterManager.Copters)
{
foreach (var anotherCopter in _copterManager.Copters)
{
if (copter != anotherCopter && copter.IsTooCloseTo(anotherCopter))
{
Pause();
Alert.Show($"{copter.Name} 与 {anotherCopter.Name} 距离过近,已中止任务。");
return;
}
}
}
}
}
catch // 林俊清, 20151102, 通常是“集合已修改”异常。
{
}
finally
{
await Task.Delay(100).ConfigureAwait(false);
}
}
}
}
public class FlightTaskAddedEventArgs : EventArgs
{
public FlightTask LastTask { get; set; }
public FlightTask AddedTask { get; set; }
}
public class SingleCopterInfoChangedEventArgs : EventArgs
{
public SingleCopterInfoChangedEventArgs(FlightTaskSingleCopterInfo changedSingleCopterInfo)
{
this.ChangedSingleCopterInfo = changedSingleCopterInfo;
}
public FlightTaskSingleCopterInfo ChangedSingleCopterInfo { get; set; }
}
}