diff --git a/Plane.FormationCreator/Formation/FlightTask.cs b/Plane.FormationCreator/Formation/FlightTask.cs index 5e90ca2..de65925 100644 --- a/Plane.FormationCreator/Formation/FlightTask.cs +++ b/Plane.FormationCreator/Formation/FlightTask.cs @@ -163,7 +163,11 @@ namespace Plane.FormationCreator.Formation get { return _ModifyingSingleCopterInfo; } set { Set(nameof(ModifyingSingleCopterInfo), ref _ModifyingSingleCopterInfo, value); } } - + /// + /// 实际执行某一个任务--包含等待 + /// + /// + /// public async Task RunAsync() { switch (TaskType) @@ -172,8 +176,6 @@ namespace Plane.FormationCreator.Formation await RunFlyToTaskAsync().ConfigureAwait(false); break; case FlightTaskType.TakeOff: - //多架同时起飞 - //await MutilRunTakeOffTaskAsync().ConfigureAwait(false); await NewMutilRunTakeOffTaskAsync().ConfigureAwait(false); break; case FlightTaskType.Land: diff --git a/Plane.FormationCreator/Formation/FlightTaskManager.cs b/Plane.FormationCreator/Formation/FlightTaskManager.cs index f039dd8..820f907 100644 --- a/Plane.FormationCreator/Formation/FlightTaskManager.cs +++ b/Plane.FormationCreator/Formation/FlightTaskManager.cs @@ -22,6 +22,10 @@ using Plane.CommunicationManagement; using Microsoft.Practices.ServiceLocation; using Plane.FormationCreator.ViewModels; using MahApps.Metro.Controls; +using Newtonsoft.Json.Linq; +using GMap.NET.MapProviders; +using GMap.NET; +using static Plane.FormationCreator.CalculationLogLatDistance; namespace Plane.FormationCreator.Formation { @@ -648,7 +652,21 @@ namespace Plane.FormationCreator.Formation // SelectedTaskIndex = 0; } - + //模拟紧急返航 + public async Task sim_DoMissionEmergencyRetAsync(PLLocation takeoffcentloc, PLLocation taskcentloc, float mindistance,int rettime, bool descending) + { + var copters = _copterManager.Copters; + if (TaskState == TasksStatus.Stop) + return; + IsEmergencyRet = true; + //设置所有模拟飞机的位置 + for (int j = 0; j < copters.Count; j++) + { + var copter = copters[j]; + var fc = copter as FakeCopter; + await fc.EmergencyRetAsync(takeoffcentloc, taskcentloc, mindistance, rettime, descending); + } + } public async Task ForceNextTasks() { @@ -2199,6 +2217,15 @@ namespace Plane.FormationCreator.Formation } return ret; } + CancellationTokenSource cts ; + + //绕行取消,用于3D绕行计算 + public void cancel_ABypassBAsync() + { + if (cts!=null) + cts.Cancel(); //取消掉 异步执行的 绕行函数 + } + //新开线程异步调用ABypassB并等待返回 public async Task<(List>,bool)> ABypassBAsync(FlightRouteV2.Vector3[] aVecs, FlightRouteV2.Vector3[] bVecs) { @@ -2207,7 +2234,8 @@ namespace Plane.FormationCreator.Formation var task = Task.Run(() => { - ret = FlyVecFun.ABypassB(aVecs, bVecs, Routecallback, Cronograma, out isPasstmp); + cts = new CancellationTokenSource(); + ret = FlyVecFun.ABypassB(aVecs, bVecs, Routecallback, Cronograma, cts.Token, out isPasstmp); }); try { @@ -2852,8 +2880,24 @@ namespace Plane.FormationCreator.Formation Message.Show($"经纬方式计算用时:{stopWatch.Elapsed.TotalMilliseconds}ms,总飞行距离{sumlength}米,有{crosscount}个交叉"); } - - //计算中心点 (三维的) + //计算一个图案的重心点 (三维的) + private PLLocation CenterGravityLatLng(List points) + { + double aLatitude = 0; + double aLongitude = 0; + double aAlt = 0; + foreach (var item in points) + { + aLatitude += item.Latitude; + aLongitude += item.Longitude; + aAlt += item.Altitude; + } + aLatitude = aLatitude / points.Count; + aLongitude = aLongitude / points.Count; + aAlt = aAlt / points.Count; + return new PLLocation(aLatitude, aLongitude, (float)aAlt); + } + //计算两个图案的共同几何中心点 (三维的) private PLLocation CenterLatLng(List point1, List point2) { PLLocation centerLatLng = new PLLocation(0,0,0); @@ -3195,8 +3239,30 @@ namespace Plane.FormationCreator.Formation } } + private bool _IsEmergencyRet=false; + public bool IsEmergencyRet + { + get { return _IsEmergencyRet; } + private set + { + if (Set(nameof(IsEmergencyRet), ref _IsEmergencyRet, value)) + { + if (_IsEmergencyRet) + { + MessageText = "任务紧急返航中!"; + } + else + { + MessageText = "任务运行中"; + } + } + + + } + } + TimeSpan timeSpan; - DateTime taskStartTime; + public DateTime taskStartTime; public async Task RunTaskAsync() { if (Tasks.Count == 0) return; @@ -3249,10 +3315,14 @@ namespace Plane.FormationCreator.Formation } } - + /// + /// 开始运行模拟任务 + /// + /// public async Task RunAsync() { IsPaused = false; + IsEmergencyRet = false; for (int i = CurrentRunningTaskIndex; i < Tasks.Count; i++) { var task = Tasks[i]; @@ -3261,6 +3331,10 @@ namespace Plane.FormationCreator.Formation } AppEx.Current.AppMode = AppMode.RunningTasks; StartAvoidingCrash(); //开始碰撞检测 + + //告诉所有飞机开始任务--模拟飞机不计算起飞延迟,直接传0 + foreach (var copter in _copterManager.Copters) + await copter.MissionStartAsync(0, 0, 0, 0, 0); TaskState = TasksStatus.Running; for (int i = CurrentRunningTaskIndex; i < Tasks.Count; i++) { @@ -3269,16 +3343,13 @@ namespace Plane.FormationCreator.Formation task.Status = FlightTaskStatus.Running; CurrentRunningTask = task; CurrentRunningTaskIndex = i; - - //////////////////显示提示信息 + //显示提示信息 int starttime = 0; for (int j = 0; j < task.TaskIndex; j++) starttime += GetTaskTime(j); TimeSpan ts = new TimeSpan(0, 0, Convert.ToInt32(starttime)); Message.Show($"{ts}:任务{i+1} {task.TaskCnName } 开始执行,需{ GetTaskTime(task.TaskIndex)}秒"); - ///////////////////////// - - + //开始执行任务 await task.RunAsync().ConfigureAwait(false); // 1. 被暂停时,中断 RunAsync。继续运行时将把此时运行了一半的 CurrentRunningTask 重新运行一遍。 if (IsPaused == true) @@ -3288,10 +3359,17 @@ namespace Plane.FormationCreator.Formation Message.Show($"任务{i + 1} {task.TaskCnName } 暂停执行"); return; } + //紧急返航中-跳出任务循环 + if (IsEmergencyRet == true) break; task.Status = FlightTaskStatus.Stop; } - // 2. 正常结束时,重置 CurrentRunningTask、CurrentRunningTaskIndex 和 IsPaused。 + //紧急返航中-等待返航结束 + while (IsEmergencyRet) { + //延时10ms等待 + await Task.Delay(10); + } + // 2. 正常结束时,重置 CurrentRunningTask、CurrentRunningTaskIndex 和 IsPaused。 TaskState = TasksStatus.Stop; CurrentRunningTask = null; CurrentRunningTaskIndex = 0; @@ -3306,11 +3384,179 @@ namespace Plane.FormationCreator.Formation #endregion Run and pause. + //计算飞行一段时间后的位置 + private PLLocation TaskFlyLoc(PLLocation startloc, PLLocation tarloc,int currflytime,int flytime ) + { + PLLocation flyLatLng; + if (currflytime >= flytime) + { + flyLatLng=new PLLocation(tarloc.Latitude, tarloc.Longitude, tarloc.Altitude); + return flyLatLng; + } + double _direction = startloc.CalcDirection2D(tarloc.Latitude, tarloc.Longitude); + double _Lng_delta = (float)(Math.Sin(_direction) * GeographyUtils.CalcMetersToLngSpan(tarloc.Latitude)); + double _Lat_delta = (float)(Math.Cos(_direction) * GeographyUtils.METERS_TO_LAT_SPAN); + + //计算xy和z方向距离 + float _distance_xy = (float)startloc.CalcDistance2D(tarloc); + float _distance_z = tarloc.Altitude - startloc.Altitude; + + float currdis_xy= _distance_xy/ flytime* currflytime; + float currdis_z = _distance_z / flytime * currflytime; + // 更新位置 + float Altitude = startloc.Altitude + currdis_z; + double Longitude = startloc.Longitude + currdis_xy * _Lng_delta; + double Latitude = startloc.Latitude + currdis_xy * _Lat_delta; + flyLatLng = new PLLocation(Latitude, Longitude, Altitude); + return flyLatLng; + } + + + + + + + //计算紧急返航数据 + //rettime :返航时间点--从起飞开始计算的秒数 + //takeoffcentloc:起飞图案重心点 + //taskcentloc:返航图案重心点 + //mindistance:离起飞重心点最近飞机距离 + //overlapping:两个图案是否有重叠--用来决定飞机是先降低高度还是先横着飞 + //返回值:是否可以计算返航--起飞不能用这个函数,直接降落 + public bool EmergencyRet(int rettime, out PLLocation takeoffcentloc, out PLLocation taskcentloc, out double mindistance, out bool overlapping) + { + mindistance = 0; + int starttime = 0; + int flyedtasktime = 0; + int rettaskindex = -1; + int taskflytime = 0; + taskcentloc = null; + overlapping = false; + + double takeoffmaxlat=0; + double takeoffmaxlng = 0; + double takeoffminlat = double.MaxValue; + double takeoffminlng = double.MaxValue; + double taskmaxlat = 0; + double taskmaxlng = 0; + double taskminlat = double.MaxValue; + double taskminlng = double.MaxValue; + + + + + Dictionary curTaskPoint = new Dictionary(); + + //计算地面起飞矩阵的中心点 + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + //起飞任务 + var curinfo = Tasks[0].SingleCopterInfos[i]; + PLLocation curLoc = new PLLocation(curinfo.TargetLat, curinfo.TargetLng,0); + if (curinfo.TargetLat > takeoffmaxlat) + takeoffmaxlat = curinfo.TargetLat; + if (curinfo.TargetLng > takeoffmaxlng) + takeoffmaxlng = curinfo.TargetLng; + if (curinfo.TargetLat < takeoffminlat) + takeoffminlat = curinfo.TargetLat; + if (curinfo.TargetLng < takeoffminlng) + takeoffminlng = curinfo.TargetLng; + curTaskPoint.Add(i, curLoc); + } + takeoffcentloc = CenterGravityLatLng(curTaskPoint.Values.ToList()); + curTaskPoint.Clear(); + + //计算返航时间正在飞行哪个航点,飞了多久 + for (int i = 0; i < Tasks.Count; i++) + { + flyedtasktime= GetTaskTime(i); + if ((starttime+ flyedtasktime) > rettime) + { + rettaskindex = i; + taskflytime = rettime - starttime; + } + starttime += flyedtasktime; + } + //起飞不能用这个函数,直接降落 + if (rettaskindex<1) return false; + mindistance = double.MaxValue; + + //计算悬停图案的重心点 + for (int i = 0; i < _copterManager.Copters.Count; i++) + { + var curinfo = Tasks[rettaskindex].SingleCopterInfos[i]; + var prvcurinfo = Tasks[rettaskindex - 1].SingleCopterInfos[i]; + PLLocation curLoc; + if (taskflytime < Tasks[rettaskindex].FlytoTime) + { + PLLocation coptercurLoc = new PLLocation(curinfo.TargetLat, curinfo.TargetLng, curinfo.TargetAlt); + PLLocation copterprvLoc = new PLLocation(prvcurinfo.TargetLat, prvcurinfo.TargetLng, prvcurinfo.TargetAlt); + //计算飞行一段时间后的位置 + curLoc = TaskFlyLoc(copterprvLoc, coptercurLoc, taskflytime, Tasks[rettaskindex].FlytoTime); + } + else //正在悬停 + curLoc = new PLLocation(curinfo.TargetLat, curinfo.TargetLng, 0); + + curTaskPoint.Add(i, curLoc); + if (curinfo.TargetLat > taskmaxlat) + taskmaxlat = curinfo.TargetLat; + if (curinfo.TargetLng > taskmaxlng) + taskmaxlng = curinfo.TargetLng; + if (curinfo.TargetLat < taskminlat) + taskminlat = curinfo.TargetLat; + if (curinfo.TargetLng < taskminlng) + taskminlng = curinfo.TargetLng; + double taskdistance = takeoffcentloc.CalcDistance(curLoc); + if (taskdistance < mindistance) + mindistance = taskdistance; + } + taskcentloc = CenterGravityLatLng(curTaskPoint.Values.ToList()); + curTaskPoint.Clear(); + + //判断两个图案是否有重叠 + overlapping = DoRectanglesOverlap(takeoffminlat, takeoffminlng, takeoffmaxlat, takeoffmaxlng, + taskminlat, taskminlng, taskmaxlat, taskmaxlng); + + + + return true; + } + + /// + /// 判断两个矩形是否有重叠 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + static bool DoRectanglesOverlap(double minLat1, double minLng1, double maxLat1, double maxLng1, + double minLat2, double minLng2, double maxLat2, double maxLng2) + { + // 判断第一个矩形在第二个矩形的左边或右边 + if (minLng1 > maxLng2 || minLng2 > maxLng1) + { + return false; + } + + // 判断第一个矩形在第二个矩形的上边或下边 + if (minLat1 > maxLat2 || minLat2 > maxLat1) + { + return false; + } + + return true; + } + + Dictionary AvoidCrashLog = new Dictionary(); - - + private async void StartAvoidingCrash() { diff --git a/Plane.FormationCreator/Formation/FlightTaskStatus.cs b/Plane.FormationCreator/Formation/FlightTaskStatus.cs index 169c4fb..5c4cbb1 100644 --- a/Plane.FormationCreator/Formation/FlightTaskStatus.cs +++ b/Plane.FormationCreator/Formation/FlightTaskStatus.cs @@ -1,13 +1,13 @@ -public enum FlightTaskStatus -{ - Stop, - Running, - Paused, - Selected -} -public enum TasksStatus -{ - Stop, - Running, - Paused +public enum FlightTaskStatus +{ + Stop, + Running, + Paused, + Selected +} +public enum TasksStatus +{ + Stop, + Running, + Paused } \ No newline at end of file diff --git a/Plane.FormationCreator/Formation/FlightTask_FlyTo.cs b/Plane.FormationCreator/Formation/FlightTask_FlyTo.cs index 48c2770..057a0db 100644 --- a/Plane.FormationCreator/Formation/FlightTask_FlyTo.cs +++ b/Plane.FormationCreator/Formation/FlightTask_FlyTo.cs @@ -1,262 +1,212 @@ -using Plane.Copters; -using Plane.Geography; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Plane.Windows.Messages; - -namespace Plane.FormationCreator.Formation -{ - public partial class FlightTask - { - private bool _StaggerRoutes = true; - - //是否有交错 - public bool StaggerRoutes - { - get { return _StaggerRoutes; } - set { Set(nameof(StaggerRoutes), ref _StaggerRoutes, value); } - } - - //同一个任务每一架飞机的FlytoTime和LoiterTime保持统一 - private int _FlytoTime = 10; - public int FlytoTime - { - get { return _FlytoTime; } - set - { - if (value > 4095) value = 4095; - if (value < 0) value = 0; - Set(nameof(FlytoTime), ref _FlytoTime, value); - } - } - private int _LoiterTime = 1; - public int LoiterTime - { - get { return _LoiterTime; } - set - { - if (value > 4095) value = 4095; - if (value < 0) value = 0; - Set(nameof(LoiterTime), ref _LoiterTime, value); - } - - } - - - private bool _VerticalLift = false; - public bool VerticalLift // 垂直升降标志位,后面需要加入即使拖动地图上的飞机,也不会变化经纬度. added by ZJF - { - get { return _VerticalLift; } - set - { - if (value) - { - int currentIndex = _flightTaskManager.SelectedTaskIndex; - var currentCopterInfos = _flightTaskManager.SelectedTask.SingleCopterInfos; - var previousCopterInfos = _flightTaskManager.Tasks[currentIndex - 1].SingleCopterInfos; - for (int i = 0; i < currentCopterInfos.Count; i++) - { - currentCopterInfos[i].TargetLat = previousCopterInfos[i].TargetLat; - currentCopterInfos[i].TargetLng = previousCopterInfos[i].TargetLng; - currentCopterInfos[i].TargetAlt = previousCopterInfos[i].TargetAlt; - } - } - - Set(nameof(VerticalLift), ref _VerticalLift, value); - } - } - - - - - - - - - public async Task RunFlyToTaskAsync() // 全部飞到指定航点 - { - //是否有交错 - if (StaggerRoutes) - { - var infos = SingleCopterInfos; - var tasks = new Task[infos.Count]; - for (int i = 0; i < infos.Count; i++) - { - var info = infos[i]; - - tasks[i] = await Task.Factory.StartNew(async () => - { - var internalInfo = info; - //if (i1 > 0) - //{ - // var prevCopter = infos[i1 - 1].Copter; - // while (CheckCrossing(infos, i1) && - // prevCopter.Altitude - copter.Altitude < 2) - // { - // await Task.Delay(25).ConfigureAwait(false); - // } - //} - - await FlyToTaskFlySingleCopterAsync(internalInfo); - }); - } - await Task.WhenAll(tasks).ConfigureAwait(false); - - } - else - { - await Task.WhenAll( - SingleCopterInfos.Select(info => FlyToTaskFlySingleCopterAsync(info)) - ).ConfigureAwait(false); - } - } - - - // private int RuningTaskRemaining = 0; - - private async Task FlyToTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info) - { - DateTime dtNow = DateTime.Now; - DateTime dtLastTime = DateTime.Now; - TimeSpan ts = dtNow - dtLastTime; - - - FlightTask task = _flightTaskManager.CurrentRunningTask; - int flyToTime = task.FlytoTime * 1000; - int loiterTime = task.LoiterTime * 1000; - int taskIndex = _flightTaskManager.CurrentRunningTaskIndex; - int copterIndex = SingleCopterInfos.IndexOf(info); - - - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } - - await info.Copter.SetShowLEDAsync(info.FlytoShowLED); - - if (info.Copter.State != Plane.Copters.CopterState.CommandMode) - await info.Copter.GuidAsync(); - - - double targetLat = info.TargetLat; - double targetLng = info.TargetLng; - if (info.IsLandWaypoint) - { - targetLat = info.Copter.TakeOffPoint.Latitude; - targetLng = info.Copter.TakeOffPoint.Longitude; - } - int flytype = _flightTaskManager.getflytype(taskIndex); - await info.Copter.FlyToAsync(targetLat, targetLng, info.TargetAlt, task.FlytoTime, flytype); - // await Task.Delay(10).ConfigureAwait(false); - - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - - // int sendFlyToTimes = 0; - - /* - //第0个任务为takeoff - if (taskIndex > 0) - { - FlightTask prevTask = _flightTaskManager.Tasks[taskIndex - 1]; - if (prevTask.TaskType == FlightTaskType.FlyTo && prevTask.LoiterTime == 0) - flyToTime += prevTask.RuningTaskRemaining; - } - */ - - //while (!info.Copter.ArrivedTarget(info.TargetLat, info.TargetLng, info.TargetAlt)) //按航点飞 :所有Copter到达目标点开始飞下个航点 - while (ts.TotalMilliseconds < (flyToTime + loiterTime)) //按时间轴飞:当前任务时间到达后自动飞往下个航点 - { - /* - //悬停时间等于0为快速航点 到达之后立即出发下个航点 切时间累积 - if (loiterTime == 0 && - info.Copter.ArrivedTarget(info.TargetLat, info.TargetLng, info.TargetAlt)) - { - task.RuningTaskRemaining = flyToTime - (int)ts.TotalMilliseconds; - break; - } - */ - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(100).ConfigureAwait(false); //判断是否到达位置10hz - - - - // if (info.LEDInfos.Count > 0) - // { - // string LEDRGB = ""; - // List LedControl = info.LEDInfos.OrderBy(i=>i.Delay).ToList(); - // for (int i = 0; i < LedControl.Count; i++) - // { - // var led = LedControl[i]; - // if (ts.TotalMilliseconds >= led.Delay * 1000) - // LEDRGB = info.LEDInfos[i].LEDRGB; - // else - // break; - // } - // info.Copter.LEDColor = LEDRGB; - // - // } - - if (info.LEDInfos.Count > 0) - { - string LEDRGB = ""; - List LedControl = info.LEDInfos.ToList(); - double time = 0; - for (int i = 0; i < LedControl.Count; i++) - { - - var led = LedControl[i]; - time += led.Delay * 1000; - if (ts.TotalMilliseconds >= time) - LEDRGB = info.LEDInfos[i].LEDRGB; - else - break; - } - info.Copter.LEDColor = LEDRGB; - - } - - - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - } - // await info.Copter.HoverAsync(); - if (taskIndex == _flightTaskManager.Tasks.Count() - 1) - { - await info.Copter.HoverAsync(); - } - } - - - private static bool CheckCrossing(List infos, int currentIndex) - { - var info = infos[currentIndex]; - for (int i = 0; i < currentIndex; i++) - { - var nextInfo = infos[i]; - if (GeographyUtils.CheckCrossing2D(info.Copter.Latitude, info.Copter.Longitude, info.TargetLat, info.TargetLng, - nextInfo.Copter.Latitude, nextInfo.Copter.Longitude, nextInfo.TargetLat, nextInfo.TargetLng)) - { - return true; - } - } - return false; - } - } -} +using Plane.Copters; +using Plane.Geography; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Plane.Windows.Messages; + +namespace Plane.FormationCreator.Formation +{ + public partial class FlightTask + { + private bool _StaggerRoutes = true; + + //是否有交错 + public bool StaggerRoutes + { + get { return _StaggerRoutes; } + set { Set(nameof(StaggerRoutes), ref _StaggerRoutes, value); } + } + + //同一个任务每一架飞机的FlytoTime和LoiterTime保持统一 + private int _FlytoTime = 10; + public int FlytoTime + { + get { return _FlytoTime; } + set + { + if (value > 4095) value = 4095; + if (value < 0) value = 0; + Set(nameof(FlytoTime), ref _FlytoTime, value); + } + } + private int _LoiterTime = 1; + public int LoiterTime + { + get { return _LoiterTime; } + set + { + if (value > 4095) value = 4095; + if (value < 0) value = 0; + Set(nameof(LoiterTime), ref _LoiterTime, value); + } + + } + + + private bool _VerticalLift = false; + public bool VerticalLift // 垂直升降标志位,后面需要加入即使拖动地图上的飞机,也不会变化经纬度. added by ZJF + { + get { return _VerticalLift; } + set + { + if (value) + { + int currentIndex = _flightTaskManager.SelectedTaskIndex; + var currentCopterInfos = _flightTaskManager.SelectedTask.SingleCopterInfos; + var previousCopterInfos = _flightTaskManager.Tasks[currentIndex - 1].SingleCopterInfos; + for (int i = 0; i < currentCopterInfos.Count; i++) + { + currentCopterInfos[i].TargetLat = previousCopterInfos[i].TargetLat; + currentCopterInfos[i].TargetLng = previousCopterInfos[i].TargetLng; + currentCopterInfos[i].TargetAlt = previousCopterInfos[i].TargetAlt; + } + } + + Set(nameof(VerticalLift), ref _VerticalLift, value); + } + } + + + + + + + + + public async Task RunFlyToTaskAsync() // 全部飞到指定航点 + { + //是否有交错 + if (StaggerRoutes) + { + var infos = SingleCopterInfos; + var tasks = new Task[infos.Count]; + for (int i = 0; i < infos.Count; i++) + { + var info = infos[i]; + //为每架飞机创建一个航点任务 + tasks[i] = await Task.Factory.StartNew(async () => + { + var internalInfo = info; + await FlyToTaskFlySingleCopterAsync(internalInfo); + }); + } + await Task.WhenAll(tasks).ConfigureAwait(false); + + } + else + { + await Task.WhenAll( + SingleCopterInfos.Select(info => FlyToTaskFlySingleCopterAsync(info)) + ).ConfigureAwait(false); + } + } + + + // private int RuningTaskRemaining = 0; + /// + /// 单独飞机执行飞行任务 + /// + /// + /// + private async Task FlyToTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info) + { + DateTime dtNow = DateTime.Now; + DateTime dtLastTime = DateTime.Now; + TimeSpan ts = dtNow - dtLastTime; + + + FlightTask task = _flightTaskManager.CurrentRunningTask; + int flyToTime = task.FlytoTime * 1000; + int loiterTime = task.LoiterTime * 1000; + int taskIndex = _flightTaskManager.CurrentRunningTaskIndex; + int copterIndex = SingleCopterInfos.IndexOf(info); + + + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } + + await info.Copter.SetShowLEDAsync(info.FlytoShowLED); + + if (info.Copter.State != Plane.Copters.CopterState.CommandMode) + await info.Copter.GuidAsync(); + + + double targetLat = info.TargetLat; + double targetLng = info.TargetLng; + if (info.IsLandWaypoint) + { + targetLat = info.Copter.TakeOffPoint.Latitude; + targetLng = info.Copter.TakeOffPoint.Longitude; + } + int flytype = _flightTaskManager.getflytype(taskIndex); + //指定目标位置 + await info.Copter.FlyToAsync(targetLat, targetLng, info.TargetAlt, task.FlytoTime, flytype); + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + //等待时间到达,并执行灯光模拟--不移动飞机,移动飞机是飞机自己计算的 + while (ts.TotalMilliseconds < (flyToTime + loiterTime)) //按时间轴飞:当前任务时间到达后自动飞往下个航点 + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(100).ConfigureAwait(false); //判断是否到达位置10hz + //执行灯光模拟 + if (info.LEDInfos.Count > 0) + { + string LEDRGB = ""; + List LedControl = info.LEDInfos.ToList(); + double time = 0; + for (int i = 0; i < LedControl.Count; i++) + { + + var led = LedControl[i]; + time += led.Delay * 1000; + if (ts.TotalMilliseconds >= time) + LEDRGB = info.LEDInfos[i].LEDRGB; + else + break; + } + info.Copter.LEDColor = LEDRGB; + } + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + } + // await info.Copter.HoverAsync(); + if (taskIndex == _flightTaskManager.Tasks.Count() - 1) + { + await info.Copter.HoverAsync(); + } + } + + + private static bool CheckCrossing(List infos, int currentIndex) + { + var info = infos[currentIndex]; + for (int i = 0; i < currentIndex; i++) + { + var nextInfo = infos[i]; + if (GeographyUtils.CheckCrossing2D(info.Copter.Latitude, info.Copter.Longitude, info.TargetLat, info.TargetLng, + nextInfo.Copter.Latitude, nextInfo.Copter.Longitude, nextInfo.TargetLat, nextInfo.TargetLng)) + { + return true; + } + } + return false; + } + } +} diff --git a/Plane.FormationCreator/Formation/FlightTask_TakeOff.cs b/Plane.FormationCreator/Formation/FlightTask_TakeOff.cs index a536192..9648002 100644 --- a/Plane.FormationCreator/Formation/FlightTask_TakeOff.cs +++ b/Plane.FormationCreator/Formation/FlightTask_TakeOff.cs @@ -1,487 +1,486 @@ -using Plane.Copters; -using Microsoft.Practices.ServiceLocation; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Plane.Geography; - -namespace Plane.FormationCreator.Formation -{ - public partial class FlightTask - { - - - //起飞到第一个航点高度的飞行时间 - private byte _TakeOffTime = 10; - public byte TakeOffTime - { - get { return _TakeOffTime; } - set { Set(nameof(TakeOffTime), ref _TakeOffTime, value); } - } - - //一架架起飞--未使用 - public async Task RunTakeOffTaskAsync() - { - // float takeOffAlt = 15; - int TaskCount = _flightTaskManager.Tasks.Count(); - if (TaskCount > 1) - { - var infos = SingleCopterInfos; - // var tasks = new Task[infos.Count]; - var tasksTmp = new Task[infos.Count]; - for (int i = 0; i < infos.Count; i++) - { - var info = infos[i]; - - if (info.takeOffStage == 0) // 第一阶段:起飞到10m - { - await TakeOffTaskFlySingleCopterAsync(info); - //if (_flightTaskManager.IsPaused == false) - //{ - // info.takeOffStage++; - //} - } - - tasksTmp[i] = TakeOffSecondTaskAsync(info); // 第二和第三阶段 - } - await Task.WhenAll(tasksTmp).ConfigureAwait(false); - if (_flightTaskManager.IsPaused == false) - { - for (int i = 0; i < infos.Count; i++) - { - var info = infos[i]; - info.takeOffStage = 0; - } - } - - } - } - - //新版的起飞方案 - public async Task NewMutilRunTakeOffTaskAsync() - { - var infos = SingleCopterInfos; - var tasksTakeOff = new Task[infos.Count]; - for (int i = 0; i < infos.Count; i++) - { - //tasksTakeOff[i] = NewSingleRunTaskOffTaskAsunc(infos[i]); - - - tasksTakeOff[i] = await Task.Factory.StartNew(async () => - { - var internalInfo = infos[i]; - - await NewSingleRunTaskOffTaskAsunc(internalInfo); - }); - } - await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); - //await Task.Delay(100); - } - - private async Task NewSingleRunTaskOffTaskAsunc(FlightTaskSingleCopterInfo info) - { - DateTime dtNow = DateTime.Now; - DateTime dtLastTime = DateTime.Now; - TimeSpan ts = dtNow - dtLastTime; - - int copterIndex = SingleCopterInfos.IndexOf(info); - var copter = info.Copter; - await copter.UnlockAsync(); - //等待起飞时间 - while ((int)ts.TotalMilliseconds < (int)info.TakeOffWaitTime * 1000) - { - if (_flightTaskManager.IsPaused == true) - { - await copter.UnlockAsync(); - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(100); - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - } - - //虚拟飞机5秒后不起飞会自动上锁 - await copter.UnlockAsync(); - await copter.TakeOffAsync(); - var copterNextTask = _flightTaskManager.Tasks[TaskIndex + 1].SingleCopterInfos[copterIndex]; - float takeOffAlt = copterNextTask.TargetAlt; - info.TargetLat = info.Copter.Latitude; - info.TargetLng = info.Copter.Longitude; - //info.Copter.takeOffTargetAltitude = takeOffAlt; - FlightTask task = _flightTaskManager.CurrentRunningTask; - float takeflytime = task.TakeOffTime - info.TakeOffWaitTime; - //开始往上飞 - await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt, takeflytime, 1); //秒 - //解锁起飞用暗紫色 - info.Copter.LEDColor = CopterManager.CopterTakeoffColor; - - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - - - while (ts.TotalMilliseconds < task.TakeOffTime * 1000) - { - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(100).ConfigureAwait(false); - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - //灯光控制 - if (info.LEDInfos.Count > 0) - { - string LEDRGB = ""; - List LedControl = info.LEDInfos.ToList(); - double time = 0; - for (int i = 0; i < LedControl.Count; i++) - { - - var led = LedControl[i]; - time += led.Delay * 1000; - if (ts.TotalMilliseconds >= time) - LEDRGB = info.LEDInfos[i].LEDRGB; - else - break; - } - info.Copter.LEDColor = LEDRGB; - ///灯光控制结束 - } - } - //起飞完成用默认颜色 - info.Copter.LEDColor = CopterManager.CopterFlyingColor; - - } - - - //老方案 ----- 按起飞数量起飞 - // 几架飞机同时起飞,参数为takeOffCount-----------------使用中 - //起飞分三个阶段: - //1阶段:分批起飞到15米(目前15米高度是飞控起飞航点决定),上一批起飞超过5米下一批开始起飞, - // 等待全部起飞完成后执行第二阶段, - //2阶段:等待高度超过9米(可能已到达15米)然后平飞到第一个航点位置,高度为15米的位置, - //3阶段:垂直上升到第一个航点指定高度 - // - //修改方案:针对高度 - //1.上升到起飞高度(目前没有地面站设置高度,高度在飞控中) - //2.直接飞往第一个航点的高度 - public async Task MutilRunTakeOffTaskAsync() - { - - int TaskCount = _flightTaskManager.Tasks.Count(); - if (TaskCount > 1) - { - var infos = SingleCopterInfos; - - //不再使用起飞数量 强制设置起飞总数等于所有飞机 - int takeOffCount = _copterManager.Copters.Count(); - int copterCount = infos.Count; - int integerPart = copterCount / takeOffCount; - int residualPart = copterCount % takeOffCount; - - // var tasks = new Task[infos.Count]; - var tasksTmp = new Task[infos.Count]; - for (int i = 0; i < integerPart; i++) - { - var tasksTakeOff = new Task[takeOffCount]; - //执行n架同时起飞 - for (int j = takeOffCount * i; j < takeOffCount * (i + 1); j++) - { - var info = infos[j]; - - int indexTmp = j - takeOffCount * i; - if (info.takeOffStage == 0) // 第一阶段:起飞到15m - { - tasksTakeOff[indexTmp] = TakeOffTaskFlySingleCopterAsync(info); - } - else - { - tasksTakeOff[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); }); - } - } - //等待多架起飞任务-起飞高度超过5米完成 - await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); - //加入已起飞飞机的第二第三阶段起飞任务--并不执行 - for (int j = takeOffCount * i; j < takeOffCount * (i + 1); j++) - { - var info = infos[j]; - tasksTmp[j] = TakeOffSecondTaskAsync(info); // 第二和第三阶段 - } - } - - // 余数架飞机同时起飞 - if (residualPart > 0) - { - var tasksTakeOff = new Task[residualPart]; - for (int j = integerPart * takeOffCount; j < takeOffCount * integerPart + residualPart; j++) - { - var info = infos[j]; - - int indexTmp = j - takeOffCount * integerPart; - if (info.takeOffStage == 0) // 第一阶段:起飞到15m - { - tasksTakeOff[indexTmp] = TakeOffTaskFlySingleCopterAsync(info); - } - else - { - tasksTakeOff[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); }); - } - } - //等待起飞超过5米 - await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); - - for (int j = integerPart * takeOffCount; j < takeOffCount * integerPart + residualPart; j++) - { - var info = infos[j]; - tasksTmp[j] = TakeOffSecondTaskAsync(info); // 加入第二和第三阶段 - } - } - //执行并等待所有的第二第三阶段起飞任务完成 - await Task.WhenAll(tasksTmp).ConfigureAwait(false); - if (_flightTaskManager.IsPaused == false) - { - for (int i = 0; i < infos.Count; i++) - { - var info = infos[i]; - info.takeOffStage = 0; - } - } - - } - } - - private CopterManager _copterManager = ServiceLocator.Current.GetInstance(); - - //执行第一阶段解锁起飞任务---使用中 - private async Task TakeOffTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info) - { - DateTime dtNow = DateTime.Now; - DateTime dtLastTime = DateTime.Now; - TimeSpan ts = dtNow - dtLastTime; - - int copterIndex = SingleCopterInfos.IndexOf(info); - var copter = info.Copter; - var copterNextTask = _flightTaskManager.Tasks[1].SingleCopterInfos[copterIndex]; - - if ((bool)_copterManager.CopterStatus[copterIndex]) - return; - - if (_flightTaskManager.IsPaused == true) - { - return; - } - - //设置灯光 - await copter.SetShowLEDAsync(true); - - //开始解锁 - await copter.UnlockAsync(); - for (int i = 0; !copter.IsUnlocked; i++) - { - //if (_flightTaskManager.IsPaused == true) - //{ - // return; - //} - //8秒内每1000毫秒尝试解锁一次 - //解锁间隔一定要超过1s否则导致飞控以后无法解锁 - - if (i > 320) - return; //无法解锁后面不用执行了 - if (i % (1000 / 25) == 1000 / 25 - 1) - { - await copter.UnlockAsync(); // 每 1000 毫秒重试一次。 - } - - await Task.Delay(25).ConfigureAwait(false); - } - //////解锁完成 - - // 为了返航,记录家的位置, 应该放在起飞命令 - info.TargetLat = info.Copter.Latitude; - info.TargetLng = info.Copter.Longitude; - - //等待起飞时间 - while (ts.TotalMilliseconds < info.TakeOffWaitTime * 1000 ) - { - await Task.Delay(100); - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - } - - //开始起飞 - for (int i = 0; i < 5; i++) // added by ZJF - { - await copter.TakeOffAsync(); - await Task.Delay(50).ConfigureAwait(false); - } - - // while (copter.Altitude < 4 || copter.State == Copters.CopterState.TakingOff) - //低于5米任务一直等待 - while (copter.Altitude < 5) // 修改起飞逻辑,当高度达到5米时,下一架开始起飞 - { - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(100).ConfigureAwait(false); - } - -/* //先不要这个控制看能否正常工作 - if (copter.Altitude > 8) - { - await info.Copter.GuidAsync(); - return; - } -*/ - } - - //执行第二第三阶段起飞任务-------------使用中 - private async Task TakeOffSecondTaskAsync(FlightTaskSingleCopterInfo info) - { - - int copterIndex = SingleCopterInfos.IndexOf(info); - var copterNextTask = _flightTaskManager.Tasks[1].SingleCopterInfos[copterIndex]; - float takeOffAlt = copterNextTask.TargetAlt;// 15; 起飞高度到下个任务的高度 - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } // await Task.Run(async () => - // { - // 小于9米时等待----按起飞高度算此时可能已到达15米起飞高度 - if (info.takeOffStage == 0) - { - while (info.Copter.Altitude < 9) - { - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(100).ConfigureAwait(false); - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } - } - if (_flightTaskManager.IsPaused == false) - { - info.takeOffStage++; - } - } - - DateTime dtNow = DateTime.Now; - DateTime dtLastTime = DateTime.Now; - TimeSpan ts = dtNow - dtLastTime; - - #region 屏蔽掉第二个阶段直接进入第三个阶 到达起飞高度直接飞往第一个航点 - - // 第二阶段:超过9米开始水平飞行 - if (info.takeOffStage == 1) - { - //切换到guided模式 - await info.Copter.GuidAsync(); - //设置灯光为航点要求的灯光 - await info.Copter.SetShowLEDAsync(copterNextTask.FlytoShowLED ); - //异步执行飞到第一个航点高度固定为15米的任务 - for (int j = 0; j < 3; j++) - { - await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt); - await Task.Delay(10).ConfigureAwait(false); - } - //直到到达第一个航点并高度15米 - while (!info.Copter.ArrivedTarget(info.TargetLat, info.TargetLng, takeOffAlt)) - { - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(25).ConfigureAwait(false); - - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - //每2秒再异步执行一次到航点高度15米的任务 - if (ts.TotalMilliseconds > 2000) - { - for (int j = 0; j < 2; j++) - { - await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt); - await Task.Delay(10).ConfigureAwait(false); - } - dtLastTime = dtNow; - } - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } - } - if (_flightTaskManager.IsPaused == false) - { - info.takeOffStage++; //当前变为2 - } - } - - dtNow = DateTime.Now; - dtLastTime = DateTime.Now; - ts = dtNow - dtLastTime; - - #endregion - - info.takeOffStage++; - - // 第三阶段:从第一个航点位置15米垂直飞行 - if (info.takeOffStage == 2) - { - //执行飞到第一个航点高度为设定目标高度 - for (int j = 0; j < 3; j++) - { - await info.Copter.FlyToAsync(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt); - await Task.Delay(10).ConfigureAwait(false); - } - //直到到达第一个航点 - while (!info.Copter.ArrivedTarget(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt)) - { - if (_flightTaskManager.IsPaused == true) - { - await info.Copter.HoverAsync(); - return; - } - await Task.Delay(25).ConfigureAwait(false); - - dtNow = DateTime.Now; - ts = dtNow - dtLastTime; - //每2秒发一次第一个航点飞行任务 - if (ts.TotalMilliseconds > 2000) - { - for (int j = 0; j < 2; j++) - { - await info.Copter.FlyToAsync(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt); - await Task.Delay(10).ConfigureAwait(false); - } - dtLastTime = dtNow; - } - // 当该飞机被标记时,悬停并跳过飞行任务 - if ((bool)_copterManager.CopterStatus[copterIndex]) - { - await info.Copter.HoverAsync(); - return; - } - } - } - - // }); - } - - } -} +using Plane.Copters; +using Microsoft.Practices.ServiceLocation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Plane.Geography; + +namespace Plane.FormationCreator.Formation +{ + public partial class FlightTask + { + + + //起飞到第一个航点高度的飞行时间 + private byte _TakeOffTime = 10; + public byte TakeOffTime + { + get { return _TakeOffTime; } + set { Set(nameof(TakeOffTime), ref _TakeOffTime, value); } + } + + //一架架起飞--未使用 + public async Task RunTakeOffTaskAsync() + { + // float takeOffAlt = 15; + int TaskCount = _flightTaskManager.Tasks.Count(); + if (TaskCount > 1) + { + var infos = SingleCopterInfos; + // var tasks = new Task[infos.Count]; + var tasksTmp = new Task[infos.Count]; + for (int i = 0; i < infos.Count; i++) + { + var info = infos[i]; + + if (info.takeOffStage == 0) // 第一阶段:起飞到10m + { + await TakeOffTaskFlySingleCopterAsync(info); + //if (_flightTaskManager.IsPaused == false) + //{ + // info.takeOffStage++; + //} + } + + tasksTmp[i] = TakeOffSecondTaskAsync(info); // 第二和第三阶段 + } + await Task.WhenAll(tasksTmp).ConfigureAwait(false); + if (_flightTaskManager.IsPaused == false) + { + for (int i = 0; i < infos.Count; i++) + { + var info = infos[i]; + info.takeOffStage = 0; + } + } + + } + } + + //新版的起飞方案 + public async Task NewMutilRunTakeOffTaskAsync() + { + var infos = SingleCopterInfos; + var tasksTakeOff = new Task[infos.Count]; + for (int i = 0; i < infos.Count; i++) + { + tasksTakeOff[i] = await Task.Factory.StartNew(async () => + { + var internalInfo = infos[i]; + await NewSingleRunTaskOffTaskAsunc(internalInfo); + }); + } + await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); + } + + /// + /// 单独飞机 执行起飞任务 + /// + /// + /// + private async Task NewSingleRunTaskOffTaskAsunc(FlightTaskSingleCopterInfo info) + { + DateTime dtNow = DateTime.Now; + DateTime dtLastTime = DateTime.Now; + TimeSpan ts = dtNow - dtLastTime; + + int copterIndex = SingleCopterInfos.IndexOf(info); + var copter = info.Copter; + await copter.UnlockAsync(); + //等待起飞时间 + while ((int)ts.TotalMilliseconds < (int)info.TakeOffWaitTime * 1000) + { + if (_flightTaskManager.IsPaused == true) + { + await copter.UnlockAsync(); + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(100); + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + } + + //虚拟飞机5秒后不起飞会自动上锁 + await copter.UnlockAsync(); + await copter.TakeOffAsync(); + var copterNextTask = _flightTaskManager.Tasks[TaskIndex + 1].SingleCopterInfos[copterIndex]; + float takeOffAlt = copterNextTask.TargetAlt; + info.TargetLat = info.Copter.Latitude; + info.TargetLng = info.Copter.Longitude; + //info.Copter.takeOffTargetAltitude = takeOffAlt; + FlightTask task = _flightTaskManager.CurrentRunningTask; + float takeflytime = task.TakeOffTime - info.TakeOffWaitTime; + //飞行目标,开始往上飞 + await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt, takeflytime, 1); //秒 + //解锁起飞用暗紫色 + info.Copter.LEDColor = CopterManager.CopterTakeoffColor; + + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + + //等待起飞时间完成,并模拟灯光--不移动飞机-飞机自己计算并移动位置 + while (ts.TotalMilliseconds < task.TakeOffTime * 1000) + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(100).ConfigureAwait(false); + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + //灯光控制 + if (info.LEDInfos.Count > 0) + { + string LEDRGB = ""; + List LedControl = info.LEDInfos.ToList(); + double time = 0; + for (int i = 0; i < LedControl.Count; i++) + { + + var led = LedControl[i]; + time += led.Delay * 1000; + if (ts.TotalMilliseconds >= time) + LEDRGB = info.LEDInfos[i].LEDRGB; + else + break; + } + info.Copter.LEDColor = LEDRGB; + ///灯光控制结束 + } + } + //起飞完成用默认颜色 + info.Copter.LEDColor = CopterManager.CopterFlyingColor; + } + + + //老方案 ----- 按起飞数量起飞 + // 几架飞机同时起飞,参数为takeOffCount-----------------使用中 + //起飞分三个阶段: + //1阶段:分批起飞到15米(目前15米高度是飞控起飞航点决定),上一批起飞超过5米下一批开始起飞, + // 等待全部起飞完成后执行第二阶段, + //2阶段:等待高度超过9米(可能已到达15米)然后平飞到第一个航点位置,高度为15米的位置, + //3阶段:垂直上升到第一个航点指定高度 + // + //修改方案:针对高度 + //1.上升到起飞高度(目前没有地面站设置高度,高度在飞控中) + //2.直接飞往第一个航点的高度 + public async Task MutilRunTakeOffTaskAsync() + { + + int TaskCount = _flightTaskManager.Tasks.Count(); + if (TaskCount > 1) + { + var infos = SingleCopterInfos; + + //不再使用起飞数量 强制设置起飞总数等于所有飞机 + int takeOffCount = _copterManager.Copters.Count(); + int copterCount = infos.Count; + int integerPart = copterCount / takeOffCount; + int residualPart = copterCount % takeOffCount; + + // var tasks = new Task[infos.Count]; + var tasksTmp = new Task[infos.Count]; + for (int i = 0; i < integerPart; i++) + { + var tasksTakeOff = new Task[takeOffCount]; + //执行n架同时起飞 + for (int j = takeOffCount * i; j < takeOffCount * (i + 1); j++) + { + var info = infos[j]; + + int indexTmp = j - takeOffCount * i; + if (info.takeOffStage == 0) // 第一阶段:起飞到15m + { + tasksTakeOff[indexTmp] = TakeOffTaskFlySingleCopterAsync(info); + } + else + { + tasksTakeOff[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); }); + } + } + //等待多架起飞任务-起飞高度超过5米完成 + await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); + //加入已起飞飞机的第二第三阶段起飞任务--并不执行 + for (int j = takeOffCount * i; j < takeOffCount * (i + 1); j++) + { + var info = infos[j]; + tasksTmp[j] = TakeOffSecondTaskAsync(info); // 第二和第三阶段 + } + } + + // 余数架飞机同时起飞 + if (residualPart > 0) + { + var tasksTakeOff = new Task[residualPart]; + for (int j = integerPart * takeOffCount; j < takeOffCount * integerPart + residualPart; j++) + { + var info = infos[j]; + + int indexTmp = j - takeOffCount * integerPart; + if (info.takeOffStage == 0) // 第一阶段:起飞到15m + { + tasksTakeOff[indexTmp] = TakeOffTaskFlySingleCopterAsync(info); + } + else + { + tasksTakeOff[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); }); + } + } + //等待起飞超过5米 + await Task.WhenAll(tasksTakeOff).ConfigureAwait(false); + + for (int j = integerPart * takeOffCount; j < takeOffCount * integerPart + residualPart; j++) + { + var info = infos[j]; + tasksTmp[j] = TakeOffSecondTaskAsync(info); // 加入第二和第三阶段 + } + } + //执行并等待所有的第二第三阶段起飞任务完成 + await Task.WhenAll(tasksTmp).ConfigureAwait(false); + if (_flightTaskManager.IsPaused == false) + { + for (int i = 0; i < infos.Count; i++) + { + var info = infos[i]; + info.takeOffStage = 0; + } + } + + } + } + + private CopterManager _copterManager = ServiceLocator.Current.GetInstance(); + + //执行第一阶段解锁起飞任务---使用中 + private async Task TakeOffTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info) + { + DateTime dtNow = DateTime.Now; + DateTime dtLastTime = DateTime.Now; + TimeSpan ts = dtNow - dtLastTime; + + int copterIndex = SingleCopterInfos.IndexOf(info); + var copter = info.Copter; + var copterNextTask = _flightTaskManager.Tasks[1].SingleCopterInfos[copterIndex]; + + if ((bool)_copterManager.CopterStatus[copterIndex]) + return; + + if (_flightTaskManager.IsPaused == true) + { + return; + } + + //设置灯光 + await copter.SetShowLEDAsync(true); + + //开始解锁 + await copter.UnlockAsync(); + for (int i = 0; !copter.IsUnlocked; i++) + { + //if (_flightTaskManager.IsPaused == true) + //{ + // return; + //} + //8秒内每1000毫秒尝试解锁一次 + //解锁间隔一定要超过1s否则导致飞控以后无法解锁 + + if (i > 320) + return; //无法解锁后面不用执行了 + if (i % (1000 / 25) == 1000 / 25 - 1) + { + await copter.UnlockAsync(); // 每 1000 毫秒重试一次。 + } + + await Task.Delay(25).ConfigureAwait(false); + } + //////解锁完成 + + // 为了返航,记录家的位置, 应该放在起飞命令 + info.TargetLat = info.Copter.Latitude; + info.TargetLng = info.Copter.Longitude; + + //等待起飞时间 + while (ts.TotalMilliseconds < info.TakeOffWaitTime * 1000 ) + { + await Task.Delay(100); + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + } + + //开始起飞 + for (int i = 0; i < 5; i++) // added by ZJF + { + await copter.TakeOffAsync(); + await Task.Delay(50).ConfigureAwait(false); + } + + // while (copter.Altitude < 4 || copter.State == Copters.CopterState.TakingOff) + //低于5米任务一直等待 + while (copter.Altitude < 5) // 修改起飞逻辑,当高度达到5米时,下一架开始起飞 + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(100).ConfigureAwait(false); + } + +/* //先不要这个控制看能否正常工作 + if (copter.Altitude > 8) + { + await info.Copter.GuidAsync(); + return; + } +*/ + } + + //执行第二第三阶段起飞任务-------------使用中 + private async Task TakeOffSecondTaskAsync(FlightTaskSingleCopterInfo info) + { + + int copterIndex = SingleCopterInfos.IndexOf(info); + var copterNextTask = _flightTaskManager.Tasks[1].SingleCopterInfos[copterIndex]; + float takeOffAlt = copterNextTask.TargetAlt;// 15; 起飞高度到下个任务的高度 + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } // await Task.Run(async () => + // { + // 小于9米时等待----按起飞高度算此时可能已到达15米起飞高度 + if (info.takeOffStage == 0) + { + while (info.Copter.Altitude < 9) + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(100).ConfigureAwait(false); + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } + } + if (_flightTaskManager.IsPaused == false) + { + info.takeOffStage++; + } + } + + DateTime dtNow = DateTime.Now; + DateTime dtLastTime = DateTime.Now; + TimeSpan ts = dtNow - dtLastTime; + + #region 屏蔽掉第二个阶段直接进入第三个阶 到达起飞高度直接飞往第一个航点 + + // 第二阶段:超过9米开始水平飞行 + if (info.takeOffStage == 1) + { + //切换到guided模式 + await info.Copter.GuidAsync(); + //设置灯光为航点要求的灯光 + await info.Copter.SetShowLEDAsync(copterNextTask.FlytoShowLED ); + //异步执行飞到第一个航点高度固定为15米的任务 + for (int j = 0; j < 3; j++) + { + await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt); + await Task.Delay(10).ConfigureAwait(false); + } + //直到到达第一个航点并高度15米 + while (!info.Copter.ArrivedTarget(info.TargetLat, info.TargetLng, takeOffAlt)) + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(25).ConfigureAwait(false); + + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + //每2秒再异步执行一次到航点高度15米的任务 + if (ts.TotalMilliseconds > 2000) + { + for (int j = 0; j < 2; j++) + { + await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt); + await Task.Delay(10).ConfigureAwait(false); + } + dtLastTime = dtNow; + } + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } + } + if (_flightTaskManager.IsPaused == false) + { + info.takeOffStage++; //当前变为2 + } + } + + dtNow = DateTime.Now; + dtLastTime = DateTime.Now; + ts = dtNow - dtLastTime; + + #endregion + + info.takeOffStage++; + + // 第三阶段:从第一个航点位置15米垂直飞行 + if (info.takeOffStage == 2) + { + //执行飞到第一个航点高度为设定目标高度 + for (int j = 0; j < 3; j++) + { + await info.Copter.FlyToAsync(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt); + await Task.Delay(10).ConfigureAwait(false); + } + //直到到达第一个航点 + while (!info.Copter.ArrivedTarget(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt)) + { + if (_flightTaskManager.IsPaused == true) + { + await info.Copter.HoverAsync(); + return; + } + await Task.Delay(25).ConfigureAwait(false); + + dtNow = DateTime.Now; + ts = dtNow - dtLastTime; + //每2秒发一次第一个航点飞行任务 + if (ts.TotalMilliseconds > 2000) + { + for (int j = 0; j < 2; j++) + { + await info.Copter.FlyToAsync(copterNextTask.TargetLat, copterNextTask.TargetLng, copterNextTask.TargetAlt); + await Task.Delay(10).ConfigureAwait(false); + } + dtLastTime = dtNow; + } + // 当该飞机被标记时,悬停并跳过飞行任务 + if ((bool)_copterManager.CopterStatus[copterIndex]) + { + await info.Copter.HoverAsync(); + return; + } + } + } + + // }); + } + + } +} diff --git a/Plane.FormationCreator/ViewModels/ControlPanelViewModel.cs b/Plane.FormationCreator/ViewModels/ControlPanelViewModel.cs index e58ce44..3dd44d9 100644 --- a/Plane.FormationCreator/ViewModels/ControlPanelViewModel.cs +++ b/Plane.FormationCreator/ViewModels/ControlPanelViewModel.cs @@ -1,2127 +1,2163 @@ -using Plane.Copters; -using Plane.FormationCreator.Formation; -using Plane.Geography; -using Plane.Logging; -using Plane.Windows.Messages; -using GalaSoft.MvvmLight; -using GalaSoft.MvvmLight.CommandWpf; -using Microsoft.Practices.ServiceLocation; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; -using Plane.Communication; -using Microsoft.Win32; -using Plane.Util; -using System.Windows.Media; -using Plane.CommunicationManagement; -using Plane.FormationCreator.Views; -using Plane.Windows.IniHelper; - -namespace Plane.FormationCreator.ViewModels -{ - public class ControlPanelViewModel : ViewModelBase - { - // serialport - internal static IConnection Rtkport ; - - private static bool trkthreadrun = false; - - private static bool rtcmthreadrun = false; - - - - public ControlPanelViewModel(FormationController formationController, CopterManager copterManager) - { - _formationController = formationController; - _copterManager = copterManager; - LoadRTKcomvalue(); - } - - private FormationController _formationController; - private CopterManager _copterManager; - private CommModuleManager _commModuleManager = CommModuleManager.Instance; - - private ILogger _logger = ServiceLocator.Current.GetInstance(); - - private float _AltP = 0.5f; - public float AltP - { - get { return _AltP; } - set { Set(nameof(AltP), ref _AltP, value); } - } - - private float _TaskOffAlt = 2; - public float TaskOffAlt - { - get { return _TaskOffAlt; } - set { Set(nameof(TaskOffAlt), ref _TaskOffAlt, value); } - } - - private string _RTKState = "RTK未发送"; - public string RTKState - { - get { return _RTKState; } - set { Set(nameof(RTKState), ref _RTKState, value); } - } - - private string _RTKbtntxt = "发送RTK"; - public string RTKbtntxt - { - get { return _RTKbtntxt; } - set { Set(nameof(RTKbtntxt), ref _RTKbtntxt, value); } - } - - private string _NTRIPbtntxt = "发送RTCM"; - public string NTRIPbtntxt - { - get { return _NTRIPbtntxt; } - set { Set(nameof(NTRIPbtntxt), ref _NTRIPbtntxt, value); } - } - - private ICommand _LockAllCommand; - public ICommand LockAllCommand - { - get - { - return _LockAllCommand ?? (_LockAllCommand = new RelayCommand(async () => - { - // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); - if (Alert.Show("您确定要上锁吗?所有飞行器将无视转速,立即强制停止运转!!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) - == MessageBoxResult.OK) - { - if (Alert.Show("再次确认上锁?请确认所有飞行器都在地面,否则将自由落体", "再次警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) - == MessageBoxResult.OK) - { - await _commModuleManager.LockAsync(); - /* - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - await c.LockAsync(); - })); - */ - } - } - })); - } - } - - - private static readonly object locker = new object(); - private ICommand _DetectionVoltage; - public ICommand DetectionVoltage - { - get - { - return _DetectionVoltage ?? (_DetectionVoltage = new RelayCommand(async () => - { - - float minVol; - InputDialog inputDialog = new InputDialog("最低检测电压( 0 恢复灯光):", "15.6"); - if (inputDialog.ShowDialog() == true) - minVol = float.Parse(inputDialog.Answer); - else return; - - //测试电池 - await _commModuleManager.TestBattery((short)0, minVol); - if (minVol == 0.0) return; - Message.Show("---请检查飞机灯光---"); - Message.Show(string.Format("---绿 色 电压高于 {0:F2}v (单节高于 {1:F2}v)--- ", minVol, minVol / 4.0f)); - Message.Show(string.Format("---黄 色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol, minVol / 4.0f)); - Message.Show(string.Format("---棕 色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.2, (minVol - 0.2) / 4.0f)); - Message.Show(string.Format("---洋红色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.4, (minVol - 0.4) / 4.0f)); - Message.Show(string.Format("---亮红色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.6, (minVol - 0.6) / 4.0f)); - Message.Show("---输入0恢复灯光---"); - - Message.Show("--------------开始检测单机电压--------------"); - Dictionary dic_voltage = new Dictionary(); - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - float voltageSum = 0.0f; - string name = c.Name; - - for (int i = 0; i < 5; i++) - { - - voltageSum += c.Voltage; - await Task.Delay(1000).ConfigureAwait(false); - } - float voltageAverage = voltageSum / 5; - if (name != null && name != "") - { - lock (locker) - { - dic_voltage.Add(name, voltageAverage); - } - } - })).ConfigureAwait(false); - - - Dictionary dic_voltage_Order = dic_voltage.OrderByDescending(o => o.Value).ToDictionary(o => o.Key, o => o.Value); - bool showch = false; - ICopter vcopter = null; - _copterManager.shiftkeydown = true; - //清除选择 - _copterManager.Select(null); - foreach (KeyValuePair kv in dic_voltage_Order) - { - if ((!showch) && (minVol > 0.00) && (kv.Value <= minVol)) - { - Message.Show(string.Format("以下飞机电压低于[{0}V,单节{1:F2}]", minVol, minVol / 4)); - showch = true; - } - Message.Show(string.Format("{0} --> 5秒平均电压:{1:F2},单节{2:F2}", kv.Key, kv.Value, kv.Value / 4)); - - - //选中低电压飞机 - if ((minVol > 0.00) && (kv.Value <= minVol)) - { - vcopter = _copterManager.Copters.FirstOrDefault(o => o.Name == kv.Key); - if (vcopter != null) - _copterManager.Select(vcopter); //需要访问UI线程 - } - await Task.Delay(5).ConfigureAwait(false); - } - await Task.Delay(500).ConfigureAwait(false); - _copterManager.shiftkeydown = false; - Message.Show(string.Format("----检测电压完成,检测总数:{0}----", dic_voltage.Count)); - //todo:增加电压阈值变成不同颜色灯 - })); - } - } - - private ICommand _DetectionMissionData; - public ICommand DetectionMissionData - { - get - { - return _DetectionMissionData ?? (_DetectionMissionData = new RelayCommand(async () => - { - var missionState = _commModuleManager.MissionWriteState.Where(i => i.Value.IsFailed); - if (missionState.Count() == 0) - Message.Show("航点全部写入成功"); - else - { - Message.Show("----统计失败航点写入失败----"); - foreach (KeyValuePair item in missionState) - { - CommWriteMissinState state = item.Value; - string msg = $"{item.Key}:飞机状态:{state.StateReturn}, 错误码:{state.ErrorCode}, 传输:{state.SendAchieved}, 写入:{state.WriteSucceed} "; - Message.Show(msg); - await Task.Delay(10); - } - } - })); - } - } - - private ICommand _DetectionReturnData; - public ICommand DetectionReturnData - { - get - { - return _DetectionReturnData ?? (_DetectionReturnData = new RelayCommand(async () => - { - Dictionary> dic_returnData = new Dictionary>(); - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - - string name = c.Name; - int return_data = BitConverter.ToInt32(c.Retain, 0); - - lock (locker) - { - List copterList; - if (!dic_returnData.ContainsKey(return_data)) - { - copterList = new List(); - dic_returnData.Add(return_data, copterList); - } - else - copterList = dic_returnData[return_data]; - - copterList.Add(name); - } - await Task.Delay(10).ConfigureAwait(false); - })).ConfigureAwait(false); - - await Task.Run(async () => - { - foreach (KeyValuePair> kv in dic_returnData) - { - byte[] test = BitConverter.GetBytes(kv.Key); - Array.Reverse(test); - string data = string.Join(".", test); - string copters = string.Join(",", kv.Value.ToArray()); - Message.Show(string.Format("返回数据{0}({1}):{2}", data, kv.Key,copters)); - await Task.Delay(5).ConfigureAwait(false); - } - Message.Show("----统计完成----"); - }).ConfigureAwait(false); - - })); - } - } - - private ICommand _ReportGPSTypeCommand; - public ICommand ReportGPSTypeCommand - { - get - { - return _ReportGPSTypeCommand ?? (_ReportGPSTypeCommand = new RelayCommand(async()=> - { - if (_copterManager.Copters.Count > 0) - { - Dictionary> GPSTypes = new Dictionary>(); - - Dictionary> Heading = new Dictionary>(); - - foreach (var copter in _copterManager.Copters) - { - string name = copter.Name; - if (!GPSTypes.Keys.Contains(copter.GpsFixType.ToString())) - { - List copterNames = new List(); - copterNames.Add(name); - GPSTypes.Add(copter.GpsFixType.ToString(), copterNames); - } - else - GPSTypes[copter.GpsFixType.ToString()].Add(name); - - - - - if (!Heading.Keys.Contains(copter.Heading.ToString())) - { - List copterNames = new List(); - copterNames.Add(name); - Heading.Add(copter.Heading.ToString(), copterNames); - } - else - Heading[copter.Heading.ToString()].Add(name); - - - } - Message.Show($"==定位状态=="); - - foreach (var item in GPSTypes) - { - Message.Show($"{item.Key}:{string.Join(",", item.Value)}"); - Message.Show($"------------"); - } - Message.Show($"==机头方向=="); - //从小到大排个序 - Dictionary> SortedHeading = Heading.OrderBy(p => p.Key).ToDictionary(p => p.Key, o => o.Value); - - foreach (var item in SortedHeading) - { - Message.Show($"{item.Key} 度:{string.Join(",", item.Value)}"); - Message.Show($"------------"); - - } - - } - await Task.Delay(10); - })); - } - } - - - - private ICommand _DetectionCommModuleVersion; - public ICommand DetectionCommModuleVersion - { - get - { - return _DetectionCommModuleVersion ?? (_DetectionCommModuleVersion = new RelayCommand(async () => - { - Dictionary> dic_version = new Dictionary>(); - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - string name = c.Name; - int version = c.CommModuleVersion; - - lock (locker) - { - List copterList; - if (!dic_version.ContainsKey(version)) - { - copterList = new List(); - dic_version.Add(version, copterList); - } - else - copterList = dic_version[version]; - - copterList.Add(name); - } - await Task.Delay(10).ConfigureAwait(false); - })).ConfigureAwait(false); - - await Task.Run(async () => - { - foreach (KeyValuePair> kv in dic_version) - { - string copters = string.Join(",", kv.Value.ToArray()); - Message.Show(string.Format("通信模块版本{0}:{1}", kv.Key, copters)); - await Task.Delay(5).ConfigureAwait(false); - } - Message.Show("----统计完成----"); - }).ConfigureAwait(false); - - })); - } - } - - private ICommand _AllLandCommand; - public ICommand AllLandCommand - { - get - { - return _AllLandCommand ?? (_AllLandCommand = new RelayCommand(async () => - { - _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - await _commModuleManager.LandAsync(); - /* - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - await c.LandAsync(); - })); - */ - })); - } - } - - private ICommand _LEDFlickerCommand; - public ICommand LEDFlickerCommand - { - get - { - return _LEDFlickerCommand ?? (_LEDFlickerCommand = new RelayCommand(() => - { - _commModuleManager.LED_FlickerAsync(_copterManager.AcceptingControlCopters); - })); - } - } - - - private ICommand _DelCommand; - public ICommand DelCommand - { - get - { - return _DelCommand ?? (_DelCommand = new RelayCommand(async () => - { - FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - { - if (_flightTaskManager.Tasks.Count > 0) - { - Alert.Show("有航点任务无法删除飞机,请先清除航点!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning); - return; - } - - await _copterManager.DelSelCopters(); - } - })); - } - } - - - private ICommand _MotorTestCommand; - public ICommand MotorTestCommand - { - get - { - return _MotorTestCommand ?? (_MotorTestCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - { - await _commModuleManager.MotorTestAsync(_copterManager.AcceptingControlCopters); - } - - /* - - await Task.WhenAll(_copterManager.Copters.Select(async c => - { - for (int i = 1; i <= 4; i++) - { - await c.MotorTestAsync(i).ConfigureAwait(false); - await Task.Delay(10); - } - - })).ConfigureAwait(false); - */ - })); - } - } - - private ICommand _GuidAsyncCommand; - public ICommand GuidAsyncCommand - { - get - { - return _GuidAsyncCommand ?? (_GuidAsyncCommand = new RelayCommand(async () => - { - if (TaskOffAlt <= 0) return; - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.TakeOffAsync(TaskOffAlt, _copterManager.AcceptingControlCopters); - /* - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async c => - { - await c.GuidAsync(); - await Task.Delay(100).ConfigureAwait(false); - await c.TakeOffAsync(1); - })); - */ - })); - } - } - - /// - /// 是否允许开始任务,全部解锁会在3秒内循环发送3次,该过程中不允许开始任务 - /// - private bool _AllowMissionStart = true; - public bool AllowMissionStart - { - get { return _AllowMissionStart; } - set { Set(nameof(AllowMissionStart), ref _AllowMissionStart, value); } - } - - - private ICommand _UnlockAllCommand; - public ICommand UnlockAllCommand - { - get - { - return _UnlockAllCommand ?? (_UnlockAllCommand = new RelayCommand(async () => - { - AllowMissionStart = false; - // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); - for (int i = 0; i < 3; i++) - { - _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - await _commModuleManager.UnlockAsync(); - await Task.Delay(1000).ConfigureAwait(false); - } - await Task.Delay(100); - AllowMissionStart = true; - - /* - await Task.WhenAll(_copterManager.Copters.Select(async c => { - await c.UnlockAsync(); - //解锁间隔一定要超过1s否则导致飞控以后无法解锁 - for (int i = 0; !c.IsUnlocked; i++) - { - if (i > 200) - break; - if (i % (1000 / 25) == 1000 / 25 - 1) - { - await c.UnlockAsync(); // 每 1000 毫秒重试一次。解锁间隔一定要超过1s否则导致飞控以后无法解锁 - } - await Task.Delay(25).ConfigureAwait(false); - } - })); - */ - })); - } - } - - private const string NTF_GROUPLED_OFF = "NTF_G_OFF"; - private ICommand _LEDOnOffCommand; - public ICommand LEDOnOffCommand - { - get - { - return _LEDOnOffCommand ?? (_LEDOnOffCommand = new RelayCommand(async onOff=> - { - string paramstr = NTF_GROUPLED_OFF; - float paramvalue = onOff; - await _commModuleManager.SetParamAsync(paramstr, paramvalue, _copterManager.AcceptingControlCopters); - /* - await Task.WhenAll( - _copterManager.AcceptingControlCopters.Select(async copter => - { - paramvalue = await copter.GetParamAsync(paramstr); - })); - - float newParamvalue = paramvalue == 0 ? 1 : 0; - - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select - (copter => copter.SetParamAsync(paramstr, newParamvalue))); - */ - })); - } - } - - private ICommand _UnlockCommand; - public ICommand UnlockCommand - { - get - { - return _UnlockCommand ?? (_UnlockCommand = new RelayCommand(async () => - { - // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.UnlockAsync(_copterManager.AcceptingControlCopters); - - /* - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select( async c => { - await c.UnlockAsync(); - //解锁间隔一定要超过1s否则导致飞控以后无法解锁 - for (int i = 0; !c.IsUnlocked; i++) - { - if (i > 200) - break; - if (i % (1000 / 25) == 1000 / 25 - 1) - { - await c.UnlockAsync(); // 每 1000 毫秒重试一次。解锁间隔一定要超过1s否则导致飞控以后无法解锁 - } - await Task.Delay(25).ConfigureAwait(false); - } - })); - */ - })); - } - } - - private float _LatOffset = 18.4023833f; - public float LatOffset - { - get { return _LatOffset; } - set { Set(nameof(LatOffset), ref _LatOffset, value); } - } - - private float _LngOffset = 109.799761f; - public float LngOffset - { - get { return _LngOffset; } - set { Set(nameof(LngOffset), ref _LngOffset, value); } - } - - - private ICommand _RLTOffsetCommand; - public ICommand RLTOffsetCommand - { - get - { - return _RLTOffsetCommand ?? (_RLTOffsetCommand = new RelayCommand(() => - { -// Message.Show($"偏移Lat = {LatOffset},Lng = {LngOffset}"); -// if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) -// await _commModuleManager.RLTOffsetAsync(LatOffset, LngOffset, _copterManager.AcceptingControlCopters); - - - })); - } - } - - private ICommand _LockCommand; - public ICommand LockCommand - { - get - { - return _LockCommand ?? (_LockCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - { - if (Alert.Show("您确定要上锁吗?飞行器将无视转速,立即强制停止运转!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) - == MessageBoxResult.OK) - { - _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - await _commModuleManager.LockAsync(_copterManager.AcceptingControlCopters); - //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.LockAsync())); - } - } - })); - } - } - - private ICommand _TakeOffCommand; - public ICommand TakeOffCommand - { - get - { - return _TakeOffCommand ?? (_TakeOffCommand = new RelayCommand(async () => - { - FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法开始任务!", "提示"); - return; - } - //飞机用UTC时间,日志用本地时间记录 - DateTime MissionTime = DateTime.UtcNow.AddSeconds(5); - DateTime MissionTime_log = DateTime.Now.AddSeconds(5); - Message.Show("任务开始:" + MissionTime_log.ToString()); - - IEnumerable selcopters = _copterManager.AcceptingControlCopters; - - //循环3次 发送起飞命令 避免通信问题 - for (int i = 0; i < 20; i++) - { - - /*await _commModuleManager.DoMissionStartAsync(_copterManager.Copters, - MissionTime.Hour, - MissionTime.Minute, - MissionTime.Second, - _flightTaskManager.OriginLng, - _flightTaskManager.OriginLat - ); - */ - - - await _commModuleManager.DoMissionStartAsync(selcopters, - MissionTime.Hour, - MissionTime.Minute, - MissionTime.Second, - _flightTaskManager.OriginLng, - _flightTaskManager.OriginLat - ); - - - - /* await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.MissionStartAsync( - MissionTime.Hour, - MissionTime.Minute, - MissionTime.Second, - _flightTaskManager.OriginLng, - _flightTaskManager.OriginLat - ))); - */ - - - await Task.Delay(20).ConfigureAwait(false); - - } - //_copterManager.Net_LogStartMission(MissionTime_log, _flightTaskManager.OriginLng, _flightTaskManager.OriginLat); - Alert.Show("所有选中飞机开始执行航点任务。请勿多次开始任务!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - })); - } - } - - private ICommand _ThrowoutCommand; - public ICommand ThrowoutCommand - { - get - { - return _ThrowoutCommand ?? (_ThrowoutCommand = new RelayCommand( () => - { - // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - _commModuleManager.ThrowoutAsync(_copterManager.AcceptingControlCopters); - })); - } - } - - private ICommand _HoverCommand; - public ICommand HoverCommand - { - get - { - return _HoverCommand ?? (_HoverCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.HoverAsync(_copterManager.AcceptingControlCopters); - //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.HoverAsync())); - })); - } - } - - private ICommand _FloatCommand; - public ICommand FloatCommand - { - get - { - return _FloatCommand ?? (_FloatCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.FloatAsync(_copterManager.AcceptingControlCopters); - //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.FloatAsync())); - })); - } - } - - private ICommand _ReturnToLaunchCommand; - public ICommand ReturnToLaunchCommand - { - get - { - return _ReturnToLaunchCommand ?? (_ReturnToLaunchCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.ReturnToLaunchAsync(_copterManager.AcceptingControlCopters); - //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.ReturnToLaunchAsync())); - })); - } - } - - - private ICommand _GetVersionsCommand; - public ICommand GetVersionsCommand - { - get - { - return _GetVersionsCommand ?? (_GetVersionsCommand = new RelayCommand(async () => - { - //if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.GetVersionsAsync(); - })); - } - } - private ICommand _GetCommsumCommand; - public ICommand GetCommsumCommand - { - get - { - return _GetCommsumCommand ?? (_GetCommsumCommand = new RelayCommand(async () => - { - //if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.GetCommsumAsync(); - })); - } - } - //打开校准界面 - private ICommand _CalibrationSingleCommand; - public ICommand CalibrationSingleCommand - { - get - { - return _CalibrationSingleCommand ?? (_CalibrationSingleCommand = new RelayCommand(async () => - { - CalibrationWindow calibrationWindow = new CalibrationWindow(); - calibrationWindow.ShowDialog(); - await Task.Delay(100); - })); - } - } - - private ICommand _LoadParamfile; - public ICommand LoadParamfile - { - get - { - return _LoadParamfile ?? (_LoadParamfile = new RelayCommand(async () => - { - - var dialog = new OpenFileDialog - { - DefaultExt = "param", - Filter = "飞行参数 (*.param)|*.param" - }; - if (dialog.ShowDialog() == true) - { - - bool ifallok = true; - var paramlist = ParamFile.loadParamFile(dialog.FileName); - - foreach (string name in paramlist.Keys) - { - float value = float.Parse( paramlist[name].ToString()); - //写5次 - for (int i = 0; i < 5; i++) - { - - if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) - await _commModuleManager.SetParamAsync(name, value, _copterManager.AcceptingControlCopters); - else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) - { - _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - await _commModuleManager.SetParamAsync(name, value); - } - - - - // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select - // (copter => copter.SetParamAsync(name, value))); - } - await Task.Delay(2000); - - //发送读取5次 - for (int i = 0; i < 5; i++) - { - if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) - await _commModuleManager.ReadParamAsnyc(name, _copterManager.AcceptingControlCopters); - else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) - await _commModuleManager.ReadParamAsnyc(name); - } - await Task.Delay(1000); - - //开始检查飞机返回参数是否正确 - - foreach (ICopter copter in _copterManager.AcceptingControlCopters) - { - if (value != copter.RetainInt) - { - ifallok = false; - Alert.Show(copter.Id + "参数[" + name + "]设置失败,读取的值是[" + copter.RetainInt + "]", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - - } - - - } - - - - - - /* - await Task.WhenAll( - - _copterManager.AcceptingControlCopters.Select(async copter => - { - float getvaule = await copter.GetParamAsync(name); - if (getvaule != value) - { - ifallok = false; - Alert.Show(copter.Id +"参数["+ name+ "]设置失败,读取的值是[" + getvaule+"]", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - } - } - - )); - */ - - - } - - if (ifallok) - Alert.Show("所有已选的飞机参数设置完成", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - else - Alert.Show("有部分飞机参数设置失败,请检查并再次设置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - } - })); - } - } - - - private ICommand _ParamModify; - public ICommand ParamModify - { - get - { - return _ParamModify ?? (_ParamModify = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - { - var ModifyParamWindow = new Plane.FormationCreator.ModifyParam(); - if (ModifyParamWindow.ShowDialog() == true) - { - bool isLoadParam = ModifyParamWindow.LoadParam; - string paramstr = ModifyParamWindow.textParamName.Text; - - if(!isLoadParam) - { - float paramvalue = Convert.ToSingle(ModifyParamWindow.textParamValue.Text); - int num = 0; - int writeTime = 0; - //连续写5次,为了都写成功 - for ( writeTime=0; writeTime<5; writeTime++) - { - - if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) - num = await _commModuleManager.SetParamAsync(paramstr, paramvalue, _copterManager.AcceptingControlCopters); - else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) - { - _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - num = await _commModuleManager.SetParamAsync(paramstr, paramvalue); - } - } - Alert.Show($"广播完成! 序列号从:{num-writeTime+1}到{num}"); - } - else - { - if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) - await _commModuleManager.ReadParamAsnyc(paramstr, _copterManager.AcceptingControlCopters); - else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) - await _commModuleManager.ReadParamAsnyc(paramstr); - } - - /* - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select - (copter => copter.SetParamAsync(paramstr, paramvalue))); - - bool ifallok = true; - await Task.WhenAll( - - _copterManager.AcceptingControlCopters.Select(async copter => - { - float getvaule = await copter.GetParamAsync(paramstr); - if (getvaule != paramvalue) - { - ifallok = false; - Alert.Show(copter.Id + "设置失败,读取的参数是" + getvaule, "提示", MessageBoxButton.OK, MessageBoxImage.Information); - } - } - - )); - if (ifallok) - Alert.Show("所有已选的飞机参数设置完成", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - else - Alert.Show("有部分飞机参数设置失败,请检查并再次设置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - - */ - - } - } - })); - } - } - - private ICommand _TurnOffTestLightsCommand; - public ICommand TurnOffTestLightsCommand - { - get - { - return _TurnOffTestLightsCommand ?? (_TurnOffTestLightsCommand = new RelayCommand(async () => - { - int num = 0; - //正式飞行 - num = await _commModuleManager.SetMultipleParamAsync( - "NTF_G_RTLOFF", "1", - "FS_GCS_ENABLE", "0", - "NTF_G_RTKTEST", "0", - "WAYPOINT_GLED", "0", - "FS_BATT_VOLTAGE", "14.2", - "RTL_ALT","3000", - "RTL_ALT_MAX","5000", - "FC_LOG_LEVEL", "0", - "FC_LOG_TYPE", "0", - "FS_GPS_RTL", "4"); - - //测试飞行 - /* - num = await _commModuleManager.SetMultipleParamAsync( - "NTF_G_RTLOFF", "0", - "FS_GCS_ENABLE", "1", - "NTF_G_RTKTEST", "1", - "WAYPOINT_GLED", "1", - "FS_BATT_VOLTAGE", "14.2", - "RTL_ALT", "3000", - "RTL_ALT_MAX", "5000", - "FC_LOG_LEVEL","3", - "FC_LOG_TYPE", "1", - "FS_GPS_RTL", "4" - ); - */ - - Alert.Show($"广播完成! 当前序列号:{num}"); - })); - } - } - - - private string _RTKcomvalue = "COM6"; - public string RTKcomvalue - { - get { return _RTKcomvalue; } - set { Set(nameof(RTKcomvalue), ref _RTKcomvalue, value); } - } - - //RTK收发线程 - private static void mainloop() - { - - - - } - - - private async Task ReadRTKPacketAsync() - { - if (!Rtkport.IsOpen) - { - return null; - } - - // limit to 110 byte packets - byte[] buffer; - int length = 0; - - try - { - length = Math.Min(180, Rtkport.BytesToRead()); - - if (length > 0)//while (Rtkport.BytesToRead() > 0) - - { - buffer = new byte[length]; - - int read = await Rtkport.ReadAsync(buffer, 0, Math.Min(buffer.Length, length)); - - // sendData(buffer, (byte)read); - - } - else - return null; - - /* - if (await Rtkport.ReadAsync(buffer, 0, 1) == 0) - { - // 做简单数据解析,得到协议类型,后续数据长度等 - } - //根据数据长度读取实际数据 - if (await Rtkport.ReadAsync(buffer, 1, 1) == 0) - { - - } - */ - - } - catch (Exception ex) - { - return null; - } - return buffer; - - } - - - - private ICommand _SendRTKCommand; - public ICommand SendRTKCommand - { - get - { - return _SendRTKCommand ?? (_SendRTKCommand = new RelayCommand(async () => - { - if (!trkthreadrun) - { - Rtkport = new SerialPortConnection(RTKcomvalue, 57600) as IConnection; - await Rtkport.OpenAsync(); - if (!Rtkport.IsOpen) - { - Alert.Show("无法打开" + RTKcomvalue, "警告", MessageBoxButton.OK, MessageBoxImage.Warning); - return; - } - trkthreadrun = true; //开始运行后台任务 - /* //线程方式后台运行rtk转发任务 - thrtk = new System.Threading.Thread(new System.Threading.ThreadStart(mainloop)) - { - IsBackground = true, - Name = "injectgps" - }; - thrtk.Start(); - */ - //后台任务方式运行rtk转发任务 - Alert.Show("RTK数据开始发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - RTKState = "RTK数据发送中"; - RTKbtntxt = "停止RTK"; - await SaveRTKcomvalue(); - await _commModuleManager.StartRtcmLoop(); - await Task.Run(async () => - { - Message.Show("RTK数据开始发送"); - //读取RTK数据循环 - rtcm3 rtcm3 = new rtcm3(); - while (trkthreadrun) - { - //读入RTK数据 - var packet = await ReadRTKPacketAsync().ConfigureAwait(false); - - if (packet != null && packet.Length > 0) - { - //Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---packet.length = {packet.Length}"); - //新方案的RTK发送,用于双频 - - int read = packet.Length; - if (read > 0) - { - for (int a = 0; a < read; a++) - { - int seenmsg = -1; - // rtcm - if ((seenmsg = rtcm3.Read(packet[a])) > 0) - { - Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---rtcm3.length = {rtcm3.length}"); - await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); - } - } - } - - - - //稳定方案的rtk发送,用于单频 - //_commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); - //await _commModuleManager.InjectGpsDataAsync(packet, (ushort)packet.Length); - } - await Task.Delay(10).ConfigureAwait(false); - - } - }).ConfigureAwait(false); - Alert.Show("RTK数据停止发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - } - else//停止RTK - { - await _commModuleManager.CloseRtcmLoop(); - - trkthreadrun = false; - Rtkport.Close(); - Rtkport = null; - - RTKState = "未发送RTK数据"; - RTKbtntxt = "发送RTK"; - } - })); - } - } - - - private ICommand _SendRTCMCommand; - public ICommand SendRTCMCommand - { - get - { - return _SendRTCMCommand ?? (_SendRTCMCommand = new RelayCommand(async () => - { - FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法发送RTCM!", "提示"); - return; - } - - rtcmthreadrun = !rtcmthreadrun; - if (rtcmthreadrun) - { - string messagetips = "格式:http://差分账号:差分密码@域名:端口/坐标系\r\n例如:http://account:password@rtk.ntrip.qxwz.com:8002/RTCM32_GGB"; - string url = ""; - IniFiles inifilse = new IniFiles(); - url = inifilse.IniReadvalue("Default","RTKurl"); - if (PlaneMessageBox.OnShow(messagetips, "发送RTK", ref url) == false) return; - inifilse.IniWritevalue("Default", "RTKurl", url); - - RTKState = "RTK数据发送中"; - NTRIPbtntxt = "停止RTCM"; - Alert.Show("RTCM数据开始发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - - await _commModuleManager.StartRtcmLoop(); - await Task.Run(async () => - { - Message.Show("RTK数据开始发送"); - //string url = "http://qxarpz003:1dc880b@rtk.ntrip.qxwz.com:8002/RTCM32_GGB"; - CommsNTRIP commNTRIP = new CommsNTRIP(url, _flightTaskManager.OriginLat, _flightTaskManager.OriginLng); - rtcm3 rtcm3 = new rtcm3(); - commNTRIP.Open(); - //读取RTK数据循环 - while (rtcmthreadrun) - { - byte[] buffer = new byte[180]; - - while (commNTRIP.BytesToRead > 0) - { - int read = commNTRIP.Read(buffer, 0, Math.Min(buffer.Length, commNTRIP.BytesToRead)); - - if (read > 0) - { - for (int a = 0; a < read; a++) - { - int seenmsg = -1; - // rtcm - if ((seenmsg = rtcm3.Read(buffer[a])) > 0) - { - //rtcmDatas.Add(rtcm3.packet); - //await SendRtcmData(); - //Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---rtcm3.length = {rtcm3.length}"); - await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); - } - } - } - } - await Task.Delay(10); - } - NTRIPbtntxt = "发送RTCM"; - RTKState = "未发送RTK数据"; - Alert.Show("RTCM数据停止发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - }); - } - })); - } - } - - private RtcmInfoView rtcmInfoView; - private ICommand _OpenRtcmManageCommand; - public ICommand OpenRtcmManageCommand - { - get - { - return _OpenRtcmManageCommand ?? (_OpenRtcmManageCommand = new RelayCommand(() => - { - RtcmInfoView.GetInstance().Show(); - RtcmInfoView.GetInstance().Activate(); - // if (rtcmInfoView == null) - // { - // rtcmInfoView = new RtcmInfoView(); - // } - // rtcmInfoView.Show(); - })); - } - } - - /* - rtcm3 rtcm3 = new rtcm3(); - private async Task AnalysisRendRrcmData(byte[] buffer, int length) - { - for (int a = 0; a < length; a++) - { - int seenmsg = -1; - // rtcm - if ((seenmsg = rtcm3.Read(buffer[a])) > 0) - { - await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); - } - } - await Task.Delay(1); - } - */ - - - private ICommand _LandCommand; - public ICommand LandCommand - { - get - { - return _LandCommand ?? (_LandCommand = new RelayCommand(async () => - { - if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) - await _commModuleManager.LandAsync(_copterManager.AcceptingControlCopters); - /* - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.LandAsync())); - */ - })); - } - } - - - - - private ICommand _ConnectCommand; - public ICommand ConnectCommand - { - get - { - return _ConnectCommand ?? (_ConnectCommand = new RelayCommand(async () => - { - //await ConnectAsync(); - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async copter => - { - //await commModule.ConnectAsync(); - await copter.ConnectAsync(); - //await copter.GetCopterDataAsync(); - })); - })); - } - } - - private ICommand _DisconnectCommand; - public ICommand DisconnectCommand - { - get - { - return _DisconnectCommand ?? (_DisconnectCommand = new RelayCommand(async () => - { - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.DisconnectAsync())); - })); - } - } - - private ICommand _FlyToAltitudeCommand; - public ICommand FlyToAltitudeCommand - { - get - { - return _FlyToAltitudeCommand ?? (_FlyToAltitudeCommand = new RelayCommand(async alt => - { - await _formationController.FlyToAltitudeAsync(_copterManager.AcceptingControlCopters, targetAlt: alt).ConfigureAwait(false); - })); - } - } - - private ICommand _FlyInCircleCommand; - public ICommand FlyInCircleCommand - { - get - { - return _FlyInCircleCommand ?? (_FlyInCircleCommand = new RelayCommand(async () => - { - await _formationController.FlyInCircleAsync(_copterManager.AcceptingControlCopters, centerDirection: 180, radius: 10, loop: true).ConfigureAwait(false); - })); - } - } - - private ICommand _FlyAroundCenterOfCoptersCommand; - public ICommand FlyAroundCenterOfCoptersCommand - { - get - { - return _FlyAroundCenterOfCoptersCommand ?? (_FlyAroundCenterOfCoptersCommand = new RelayCommand(async () => - { - await _formationController.FlyAroundCenterOfCoptersAsync(_copterManager.AcceptingControlCopters).ConfigureAwait(false); - })); - } - } - - private ICommand _FlyInRectangleCommand; - public ICommand FlyInRectangleCommand - { - get - { - return _FlyInRectangleCommand ?? (_FlyInRectangleCommand = new RelayCommand(async () => - { - await _formationController.FlyInRectangleAsync(_copterManager.AcceptingControlCopters, startDirection: 180, sideLength1: 15, sideLength2: 5, loop: true).ConfigureAwait(false); - })); - } - } - - private ICommand _FlyToVerticalLineAndMakeCircleCommand; - public ICommand FlyToVerticalLineAndMakeCircleCommand - { - get - { - return _FlyToVerticalLineAndMakeCircleCommand ?? (_FlyToVerticalLineAndMakeCircleCommand = new RelayCommand(async () => - { - await _formationController.FlyToVerticalLineAndMakeCircle( - _copterManager.AcceptingControlCopters, - centerDirection: 180, - radius: 10 - ).ConfigureAwait(false); - })); - } - } - - private ICommand _MissionStartCommand; - public ICommand MissionStartCommand - { - get - { - return _MissionStartCommand ?? (_MissionStartCommand = new RelayCommand(async () => - { - FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法开始任务!", "提示"); - return; - } - //飞机用UTC时间,日志用本地时间记录 - DateTime MissionTime = DateTime.UtcNow.AddSeconds(5); - DateTime MissionTime_log = DateTime.Now.AddSeconds(5); - Message.Show("任务开始:" + MissionTime_log.ToString()); - //循环3次 发送起飞命令 避免通信问题 - for (int i = 0; i < 20; i++) //20 - { - await _commModuleManager.DoMissionStartAsync(null, - MissionTime.Hour, - MissionTime.Minute, - MissionTime.Second, - _flightTaskManager.OriginLng, - _flightTaskManager.OriginLat - ); - - /* - foreach (var vcopter in _copterManager.Copters) - { - await vcopter.MissionStartAsync(utchour, - utcminute, - utcsecond, - _flightTaskManager.OriginLng, - _flightTaskManager.OriginLat - ); - } - */ - - await Task.Delay(20).ConfigureAwait(false); - - } - _copterManager.Net_LogStartMission(MissionTime_log, _flightTaskManager.OriginLng, _flightTaskManager.OriginLat); - Alert.Show("所有飞机开始执行航点任务。请勿多次开始任务!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); - })); - } - } - - private ICommand _MissionPauseCommand; - public ICommand MissionPauseCommand - { - get - { - return _MissionPauseCommand ?? (_MissionPauseCommand = new RelayCommand(async () => - { - for (int i = 0; i < 3; i++) - { - await _commModuleManager.DoMissionPauseAsync(); - } - })); - } - } - - private ICommand _MissionResumeCommand; - public ICommand MissionResumeCommand - { - get - { - return _MissionResumeCommand ?? (_MissionResumeCommand = new RelayCommand(async () => - { - int utchour = DateTime.UtcNow.AddSeconds(5).Hour; - int utcminute = DateTime.UtcNow.AddSeconds(5).Minute; - int utcsecond = DateTime.UtcNow.AddSeconds(5).Second; - for (int i = 0; i < 3; i++) - { - await _commModuleManager.DoMissionResumeAsync( - utchour, - utcminute, - utcsecond); - } - })); - } - } - - - // private ICommand _SetOriginalPointCommand; - // public ICommand SetOriginalPointCommand - // { - // get - // { - // return _SetOriginalPointCommand ?? (_SetOriginalPointCommand = new RelayCommand(() => - // { - // FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); - // _flightTaskManager.SetOriginal(); - // })); - // } - // } - private ICommand _WriteMissionSingleCommand; - public ICommand WriteMissionSingleCommand - { - get - { - return _WriteMissionSingleCommand ?? (_WriteMissionSingleCommand = new RelayCommand(async () => - { - var _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); - return; - } - var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); - if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) - { - Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); - await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); - } - - - int taskcount = _flightTaskManager.Tasks.Count; - if (taskcount < 2) return; - foreach (var copter in _copterManager.AcceptingControlCopters) - { - int i = _copterManager.Copters.IndexOf(copter); - await CollectMissions(i); - } - })); - } - } - - - private ICommand _WriteMissionFailedCommand; - public ICommand WriteMissionFailedCommand - { - get - { - return _WriteMissionFailedCommand ?? (_WriteMissionFailedCommand = new RelayCommand(async () => - { - var _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); - return; - } - var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); - if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) - { - Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); - await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); - } - - int coptercount = _copterManager.Copters.Count; - int taskcount = _flightTaskManager.Tasks.Count; - if (taskcount < 2) return; - foreach(KeyValuePair kv in _commModuleManager.MissionWriteState) - { - if (!kv.Value.SendAchieved || !kv.Value.WriteSucceed) - { - var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == kv.Key.ToString()); - int i = _copterManager.Copters.IndexOf(copter); - await CollectMissions(i); - } - } - })); - } - } - - private ICommand _WriteMissionCommand; - public ICommand WriteMissionCommand - { - get - { - return _WriteMissionCommand ?? (_WriteMissionCommand = new RelayCommand(async () => - { - var _flightTaskManager = ServiceLocator.Current.GetInstance(); - if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) - { - Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); - return; - } - - int coptercount = _copterManager.Copters.Count; - int taskcount = _flightTaskManager.Tasks.Count; - if (taskcount < 2) return; - - var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); - if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) - { - Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); - await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); - } - - Alert.Show("开始写入航点,飞机绿色成功红色失败!(先关灯再开灯可恢复飞机灯光)", "提示"); - _commModuleManager.ClearMissionWriteState(); - for (int i = 0; i < coptercount; i++) - { - ///写航线开始 - await CollectMissions(i).ConfigureAwait(false); - } - Alert.Show($"任务写入完成!请检测失败的飞机"); - })); - } - } - - /// - /// 用通讯模块 写入航点信息 - /// - /// copterIndex - /// - private async Task CollectMissions(int i) - { - int j = 0; - try - { - - - float groudAlt = _copterManager.Copters[i].GroundAlt; - var missions = new List(); - var _flightTaskManager = ServiceLocator.Current.GetInstance(); - for (j = 0; j < _flightTaskManager.Tasks.Count; j++) - { - switch (_flightTaskManager.Tasks[j].TaskType) - { - case FlightTaskType.TakeOff: - //int takeofftime = (int)(_flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetAlt / 2.5 + 5); - missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); - missions.Add(Mission.CreateTakeoffMission( - _flightTaskManager.Tasks[j].SingleCopterInfos[i].TakeOffWaitTime, //起飞等待时间 - _flightTaskManager.Tasks[j].TakeOffTime, //起飞时间 - _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetLat - _flightTaskManager.OriginLat, //位置没用 - _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetLng - _flightTaskManager.OriginLng, //位置没用 - _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetAlt - groudAlt) //下一个航点的高度 - ); - break; - - case FlightTaskType.FlyTo: - if (_flightTaskManager.Tasks[j].SingleCopterInfos[i].IsChangeSpeed) - { - missions.Add(Mission.CreateChangeSpeedMission( - _flightTaskManager.Tasks[j].SingleCopterInfos[i].LevelSpeed, - _flightTaskManager.Tasks[j].SingleCopterInfos[i].UpSpeed, - _flightTaskManager.Tasks[j].SingleCopterInfos[i].DownSpeed) - ); - } - missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); - - double Lat = _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetLat - _flightTaskManager.OriginLat; - double Lng = _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetLng - _flightTaskManager.OriginLng; - //如果是返航点,位置写入固定值,这样直接返回起飞点 - if (_flightTaskManager.Tasks[j].SingleCopterInfos[i].IsLandWaypoint) - { - Lat = 90; - Lng = 180; - } - - missions.Add(Mission.CreateWaypointMission( - _flightTaskManager.Tasks[j].LoiterTime, - _flightTaskManager.Tasks[j].FlytoTime, - Lat, - Lng, - _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetAlt - groudAlt) - ); - break; - - case FlightTaskType.Land: - missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); - - missions.Add(Mission.CreateLandMission( - _flightTaskManager.Tasks[j].SingleCopterInfos[i].LandWaitTime) - ); - break; - default: - break; - } - } - //186是通讯模块的限制--张伟那边 - if (missions.Count > 186) - { - Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 航点数量超过186,请减少再重写该飞机!"); - } - else - { - //虚拟ID在排序时已经变为ID了,直接按ID写入 - // var targetCopter = _copterManager.Copters.FirstOrDefault(o => o.VirtualId == (i+1)); - // bool result = await _commModuleManager.WriteMissionListAsync(targetCopter, missions); - bool result = await _commModuleManager.WriteMissionListAsync(_copterManager.Copters[i], missions); - - //CommWriteMissinState state = new CommWriteMissinState(result); - //_commModuleManager.missionWriteState.Add(int.Parse(_copterManager.Copters[i].Id), state); - if (!result) - { - - if (_copterManager.SortType == CopterManager.CopterSortType.ByVID) - Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 通信模块传输失败!"); - else - Message.Show($"飞机:{_copterManager.Copters[i].Id} 通信模块传输失败!"); - } - else - { - if (_copterManager.SortType == CopterManager.CopterSortType.ByVID) - Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 通信模块传输完成!"); - else - Message.Show($"飞机:{_copterManager.Copters[i].Id} 通信模块传输完成!"); - } - await Task.Delay(500).ConfigureAwait(false); - } - } - catch (Exception ex) - { - Message.Show(ex.ToString()); - } - - } - - private List CreateLEDMissions(IEnumerable LEDInfos) - { - List missions = new List(); - foreach (LEDInfo ledInfo in LEDInfos) - { - float ledinterval=0; - Color color = (Color)ColorConverter.ConvertFromString("#" + ledInfo.LEDRGB); - int ledMode = ledInfo.LEDMode; - //拉烟任务模式ID是50,需要改为50 - if (_copterManager.FC_VER_NO == 1) - { - //老版本是闪烁频率,且不能为小数 - ledinterval = ledInfo.LEDInterval; - //老版本ledMode == 8 对应拉烟,飞控对应50,ledinterval对应通道号 - if (ledMode==8) ledMode = 50; - } - else - { - //新版本飞控 是闪烁间隔单位是100ms,地面站还是频率可以有1位小数,用户输入0.5hz 飞控应该是(1/0.5)*10=20 - ledinterval = (1 / ledInfo.LEDInterval); - - //新版本 ledMode=16是抛物,飞控对应50,ledinterval对应10 --固定的 - if (ledMode == 16) - { - ledMode = 50; - ledinterval = 10; - } - else //新版本ledMode == 15 对应拉烟,飞控对应50,ledinterval对应通道号 - if (ledMode == 15) - { - ledMode = 50; - } - } - IMission LEDMission = Mission.CreateLEDControlMission( - (int)(ledInfo.Delay * 10), - ledMode, - ledinterval, - 0, //ledInfo.LEDTimes, - color.R, - color.G, - color.B - ); - missions.Add(LEDMission); - } - return missions; - } - - private ICommand _FlagCommand; - public ICommand FlagCommand - { - get - { - return _FlagCommand ?? (_FlagCommand = new RelayCommand(async () => - { - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => - { - - var copters = _copterManager.Copters; - int index = copters.IndexOf(copter); - _copterManager.CopterStatus[index] = true; - return Task.Run(()=> { }); - })); - })); - } - } - - private async Task UnlockTestSingleCopterAsync(ICopter SingleCopter) - { - await SingleCopter.UnlockAsync(); - await Task.Delay(25).ConfigureAwait(false); - - for (int i = 0; !SingleCopter.IsUnlocked; i++) - { - //8秒内每1000毫秒尝试解锁一次 - //解锁间隔一定要超过1s否则导致飞控以后无法解锁 - - if (i >320) - return; //无法解锁后面不用执行了 - if (i % (1000 / 25) == 1000 / 25 - 1) - { - await SingleCopter.UnlockAsync(); // 每 1000 毫秒重试一次。 - } - await Task.Delay(25).ConfigureAwait(false); - } - - - await Task.Delay(1000); - if (SingleCopter.IsUnlocked) - { - await SingleCopter.SetShowLEDAsync(true); - await Task.Delay(50); - await SingleCopter.SetShowLEDAsync(true); - } - - - await Task.Delay(5000); - - await SingleCopter.LockAsync(); - await Task.Delay(25).ConfigureAwait(false); - for (int i = 0; SingleCopter.IsUnlocked; i++) - { - //8秒内每1000毫秒尝试解锁一次 - //解锁间隔一定要超过1s否则导致飞控以后无法解锁 - - if (i > 320) - return; //无法解锁后面不用执行了 - if (i % (1000 / 25) == 1000 / 25 - 1) - { - await SingleCopter.LockAsync(); // 每 1000 毫秒重试一次。 - } - await Task.Delay(25).ConfigureAwait(false); - } - - await Task.Delay(1000); - if (!SingleCopter.IsUnlocked) - { - await SingleCopter.SetShowLEDAsync(false); - await Task.Delay(50); - await SingleCopter.SetShowLEDAsync(false); - } - } - - - - private ICommand _TestCommand; - public ICommand TestCommand - { - get - { - return _TestCommand ?? (_TestCommand = new RelayCommand(async () => - { - - - Message.Show("解锁测试--开始"); - int i = 0; - var tasksUnlockTest = new Task[_copterManager.Copters.Count]; - foreach (var vcopter in _copterManager.Copters) - { - tasksUnlockTest[i++] = UnlockTestSingleCopterAsync(vcopter); - //i++; - } - await Task.WhenAll(tasksUnlockTest).ConfigureAwait(false); - Message.Show("解锁测试--完成!"); - return; - - - - - - - - - - - foreach (var vcopter in _copterManager.Copters) - { - await vcopter.UnlockAsync(); - } - await Task.Delay(1000); - - foreach (var vcopter in _copterManager.Copters) - { - if (vcopter.IsUnlocked) - await vcopter.SetShowLEDAsync(true); - } - - await Task.Delay(5000); - - foreach (var vcopter in _copterManager.Copters) - { - await vcopter.LockAsync(); - await vcopter.SetShowLEDAsync(false); - - } - - - return; - - - - - - - - - - - - - var firstCopter = _copterManager.Copters.First(); - - // Test TurnAsync. - //var latLng = GeographyUtils.CalcLatLngSomeMetersAway(firstCopter.Latitude, firstCopter.Longitude, 135, 10); - //await _formationController.TurnAsync(_copterManager.AcceptingControlCopters, latLng.Item1, latLng.Item2); - - // Test FlyToLatLngAsync. - //var copters = _copterManager.AcceptingControlCopters; - //var centerLat = copters.Average(c => c.Latitude); - //var centerLng = copters.Average(c => c.Longitude); - //var latDelta = 10 * GeographyUtils.MetersToLocalLat; - //var lngDelta = 10 * GeographyUtils.GetMetersToLocalLon(copters.First().Latitude); - //var targetLat = centerLat + latDelta; - //var targetLng = centerLng + lngDelta; - //await _formationController.FlyToLatLngAsync(copters, targetLat, targetLng); - - // Test FlyInCircleAsync. - //await _formationController.FlyInCircleAsync(_copterManager.AcceptingControlCopters, centerDirection: 180, radius: 10, loop: false); - - // Test FlyAroundCenterOfCoptersAsync. - //await _formationController.FlyAroundCenterOfCoptersAsync(_copterManager.AcceptingControlCopters); - - // Test FlyToLatLngAsync. - //var targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway(firstCopter.Latitude, firstCopter.Longitude, 135, 20); - //await _formationController.FlyToLatLngAsync(firstCopter, targetLatLng.Item1, targetLatLng.Item2); - - //firstCopter.LoiterTurns(1, 10); - - //var radius = await firstCopter.GetParamAsync("CIRCLE_RADIUS"); - - ////await firstCopter.SetParamAsync("CIRCLE_RADIUS", 1500); - ////var param = await firstCopter.GetParamAsync("CIRCLE_RADIUS"); - //// Alert.Show($"半径设置成功啦: {param}"); - - ////await firstCopter.SetParamAsync("CIRCLE_RATE", 30); - //var rate = await firstCopter.GetParamAsync("CIRCLE_RATE"); - - //Alert.Show($"半径: {radius} 角速度: {rate}"); - - //await firstCopter.SetMobileControlAsync(yaw: 90); - - //if (!_listeningMissionItemReceived) - //{ - // firstCopter.MissionItemReceived += (sender, e) => Alert.Show($"{e.Index} {e.Total} {(Protocols.MAVLink.MAV_CMD)e.Details.id}"); - // _listeningMissionItemReceived = true; - //} - //await firstCopter.RequestMissionListAsync(); - - var copter = firstCopter; - - ///* 写航线 */ - //// 任务总数。 - //await copter.SetMissionCountAsync(6).ConfigureAwait(false); - //// 起飞前准备。 - //await copter.WritePreTakeOffMissionAsync().ConfigureAwait(false); - //// 起飞。 - //await copter.WriteTakeOffMissionAsync().ConfigureAwait(false); - //// 不断自增的编号。 - //ushort index = 2; - //// 航点。 - //await copter.WriteWaypointMissionAsync(new EHLocation(copter).AddLatLngAlt(0.001, 0.002, 2), index++).ConfigureAwait(false); - //// 航点。 - //await copter.WriteWaypointMissionAsync(new EHLocation(copter).AddLatLngAlt(0.003, 0.002, 2), index++).ConfigureAwait(false); - //// 返航。 - //await copter.WriteReturnToLaunchMissionAsync(index++).ConfigureAwait(false); - //// 降落。 - //await copter.WriteLandMissionAsync(index++).ConfigureAwait(false); - - ///* 读航线 */ - // 监听“任务项已接收”事件。 - //(copter as EHCopter).MissionItemReceived += (sender, e) => Alert.Show($"{e.Mission.Sequence} {e.Mission.Latitude} {e.Mission.Command}"); - // 请求任务列表。 - var missions = await copter.RequestMissionListAsync(); - // Alert.Show(string.Join(Environment.NewLine, missions.Select(m => $"{m.Sequence}\t{m.Command}\t\t{m.Latitude}"))); - - //ICopter previousCopter = firstCopter; - //foreach (var item in _copterManager.Copters.Where(c => c != firstCopter)) - //{ - // item.Follow(previousCopter, keepYawDifference: false, keepFacingTarget: false); - // previousCopter = item; - //} - - //var missions = new Mission[] - //{ - // Mission.CreateWaypointMission(new EHLocation(firstCopter).AddLatLngAlt(0.0001, 0, 10)), - // Mission.CreateReturnToLaunchMission(), - // Mission.CreateLandMission() - //}; - //var result = await firstCopter.WriteMissionsAsync(missions); - //var result2 = await firstCopter.WriteMissionsAsync(missions); - //Debug.WriteLine($"{result1} {result2}"); - - //var missions = new Mission[] - //{ - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateWaypointMission(23.123, 113.123, 10), - // Mission.CreateReturnToLaunchMission(), - // Mission.CreateLandMission() - //}; - //var result = await firstCopter.WriteMissionListAsync(missions); - //MessageBox.Show($"The result of WriteMissions: {result}"); - - // 跟随测试 - /* - ICopter previousCopter = firstCopter; - foreach (var item in _copterManager.Copters.Where(c => c != firstCopter)) - { - item.Follow(previousCopter, keepYawDifference: false, keepFacingTarget: false); - previousCopter = item; - } - */ - await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async c => - { - - float gpsLed = await c.GetParamAsync("NOTI_GPSLED"); - if (gpsLed == 0.0f) - { - await LEDFlashAsync(c, true); - } - else - { - await LEDFlashAsync(c, false); - } - - // for (int jj = 0; jj < 5; jj++) - { - // await LEDFlashAsync(c, true); - // await c.SetParamAsync("THR_ALT_P", AltP); - // await c.SetParamAsync("WPNAV_ACCEL_Z", AltP); - // await c.SetParamAsync("WPNAV_ACCEL", AltP); - // await c.SetParamAsync("WPNAV_SPEED", AltP); - // await c.SetParamAsync("WPNAV_SPEED_DN", AltP); - // await c.SetParamAsync("WPNAV_SPEED_UP", AltP); - // await LEDFlashAsync(c, false); - // await LEDFlashAsync(c, true); - // await Task.Delay(500).ConfigureAwait(false); - - // await Task.Delay(1000).ConfigureAwait(false); - - // await LEDFlashAsync(c, true); - // await Task.Delay(1000).ConfigureAwait(false); - } - })); - })); - } - } - - /// - /// 读取串口号 - /// - private void LoadRTKcomvalue() - { - IniFiles inifilse = new IniFiles(); - RTKcomvalue = inifilse.IniReadvalue("Default", "RTKcomvalue"); - if (RTKcomvalue == "") RTKcomvalue = "COM6"; - } - - - /// - /// 保存上次成功的串口号 - /// - /// - private async Task SaveRTKcomvalue() - { - IniFiles inifilse = new IniFiles(); - inifilse.IniWritevalue("Default", "RTKcomvalue", RTKcomvalue); - await Task.Delay(1); - } - - private async Task LEDFlashAsync(ICopter copter, bool isOn) - { - // float gpsLed = await c.GetParamAsync("NOTI_GPSLED"); - float ledControl = 0.0f; - if (isOn) - { - ledControl = 1.0f; - } - var tasks = new Task[2]; - //tasks[0] = copter.SetParamAsync("NOTI_GPSLED", ledControl); - //tasks[1] = copter.SetParamAsync("NOTI_ARMLED", ledControl); - tasks[0] = Task.Run(async () => - { - try - { - await copter.SetParamAsync("NOTI_GPSLED", ledControl, 5000); - } - catch (TimeoutException e) - { - _logger.Log($"NOTI_GPSLED 超时, CopterId: {copter.Id}。"); - } - }); - tasks[1] = Task.Run(async () => - { - try - { - await copter.SetParamAsync("NOTI_ARMLED", ledControl, 5000); - } - catch (TimeoutException e) - { - _logger.Log($"NOTI_ARMLED 超时, CopterId: {copter.Id}。"); - } - }); - await Task.WhenAll(tasks).ConfigureAwait(false); - - } - - private bool _listeningMissionItemReceived; - - private ICommand _StopTaskCommand; - public ICommand StopTaskCommand - { - get - { - return _StopTaskCommand ?? (_StopTaskCommand = new RelayCommand(async () => - { - await _formationController.AllStop().ConfigureAwait(false); - })); - } - } - - - } -} +using Plane.Copters; +using Plane.FormationCreator.Formation; +using Plane.Geography; +using Plane.Logging; +using Plane.Windows.Messages; +using GalaSoft.MvvmLight; +using GalaSoft.MvvmLight.CommandWpf; +using Microsoft.Practices.ServiceLocation; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using Plane.Communication; +using Microsoft.Win32; +using Plane.Util; +using System.Windows.Media; +using Plane.CommunicationManagement; +using Plane.FormationCreator.Views; +using Plane.Windows.IniHelper; + +namespace Plane.FormationCreator.ViewModels +{ + public class ControlPanelViewModel : ViewModelBase + { + // serialport + internal static IConnection Rtkport ; + + private static bool trkthreadrun = false; + + private static bool rtcmthreadrun = false; + + + + public ControlPanelViewModel(FormationController formationController, CopterManager copterManager) + { + _formationController = formationController; + _copterManager = copterManager; + LoadRTKcomvalue(); + } + + private FormationController _formationController; + private CopterManager _copterManager; + private CommModuleManager _commModuleManager = CommModuleManager.Instance; + + private ILogger _logger = ServiceLocator.Current.GetInstance(); + + private float _AltP = 0.5f; + public float AltP + { + get { return _AltP; } + set { Set(nameof(AltP), ref _AltP, value); } + } + + private float _TaskOffAlt = 2; + public float TaskOffAlt + { + get { return _TaskOffAlt; } + set { Set(nameof(TaskOffAlt), ref _TaskOffAlt, value); } + } + + private string _RTKState = "RTK未发送"; + public string RTKState + { + get { return _RTKState; } + set { Set(nameof(RTKState), ref _RTKState, value); } + } + + private string _RTKbtntxt = "发送RTK"; + public string RTKbtntxt + { + get { return _RTKbtntxt; } + set { Set(nameof(RTKbtntxt), ref _RTKbtntxt, value); } + } + + private string _NTRIPbtntxt = "发送RTCM"; + public string NTRIPbtntxt + { + get { return _NTRIPbtntxt; } + set { Set(nameof(NTRIPbtntxt), ref _NTRIPbtntxt, value); } + } + + private ICommand _LockAllCommand; + public ICommand LockAllCommand + { + get + { + return _LockAllCommand ?? (_LockAllCommand = new RelayCommand(async () => + { + // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); + if (Alert.Show("您确定要上锁吗?所有飞行器将无视转速,立即强制停止运转!!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) + == MessageBoxResult.OK) + { + if (Alert.Show("再次确认上锁?请确认所有飞行器都在地面,否则将自由落体", "再次警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) + == MessageBoxResult.OK) + { + await _commModuleManager.LockAsync(); + /* + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + await c.LockAsync(); + })); + */ + } + } + })); + } + } + + + private static readonly object locker = new object(); + private ICommand _DetectionVoltage; + public ICommand DetectionVoltage + { + get + { + return _DetectionVoltage ?? (_DetectionVoltage = new RelayCommand(async () => + { + + float minVol; + InputDialog inputDialog = new InputDialog("最低检测电压( 0 恢复灯光):", "15.6"); + if (inputDialog.ShowDialog() == true) + minVol = float.Parse(inputDialog.Answer); + else return; + + //测试电池 + await _commModuleManager.TestBattery((short)0, minVol); + if (minVol == 0.0) return; + Message.Show("---请检查飞机灯光---"); + Message.Show(string.Format("---绿 色 电压高于 {0:F2}v (单节高于 {1:F2}v)--- ", minVol, minVol / 4.0f)); + Message.Show(string.Format("---黄 色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol, minVol / 4.0f)); + Message.Show(string.Format("---棕 色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.2, (minVol - 0.2) / 4.0f)); + Message.Show(string.Format("---洋红色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.4, (minVol - 0.4) / 4.0f)); + Message.Show(string.Format("---亮红色 电压低于 {0:F2}v (单节低于 {1:F2}v)--- ", minVol - 0.6, (minVol - 0.6) / 4.0f)); + Message.Show("---输入0恢复灯光---"); + + Message.Show("--------------开始检测单机电压--------------"); + Dictionary dic_voltage = new Dictionary(); + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + float voltageSum = 0.0f; + string name = c.Name; + + for (int i = 0; i < 5; i++) + { + + voltageSum += c.Voltage; + await Task.Delay(1000).ConfigureAwait(false); + } + float voltageAverage = voltageSum / 5; + if (name != null && name != "") + { + lock (locker) + { + dic_voltage.Add(name, voltageAverage); + } + } + })).ConfigureAwait(false); + + + Dictionary dic_voltage_Order = dic_voltage.OrderByDescending(o => o.Value).ToDictionary(o => o.Key, o => o.Value); + bool showch = false; + ICopter vcopter = null; + _copterManager.shiftkeydown = true; + //清除选择 + _copterManager.Select(null); + foreach (KeyValuePair kv in dic_voltage_Order) + { + if ((!showch) && (minVol > 0.00) && (kv.Value <= minVol)) + { + Message.Show(string.Format("以下飞机电压低于[{0}V,单节{1:F2}]", minVol, minVol / 4)); + showch = true; + } + Message.Show(string.Format("{0} --> 5秒平均电压:{1:F2},单节{2:F2}", kv.Key, kv.Value, kv.Value / 4)); + + + //选中低电压飞机 + if ((minVol > 0.00) && (kv.Value <= minVol)) + { + vcopter = _copterManager.Copters.FirstOrDefault(o => o.Name == kv.Key); + if (vcopter != null) + _copterManager.Select(vcopter); //需要访问UI线程 + } + await Task.Delay(5).ConfigureAwait(false); + } + await Task.Delay(500).ConfigureAwait(false); + _copterManager.shiftkeydown = false; + Message.Show(string.Format("----检测电压完成,检测总数:{0}----", dic_voltage.Count)); + //todo:增加电压阈值变成不同颜色灯 + })); + } + } + + private ICommand _DetectionMissionData; + public ICommand DetectionMissionData + { + get + { + return _DetectionMissionData ?? (_DetectionMissionData = new RelayCommand(async () => + { + var missionState = _commModuleManager.MissionWriteState.Where(i => i.Value.IsFailed); + if (missionState.Count() == 0) + Message.Show("航点全部写入成功"); + else + { + Message.Show("----统计失败航点写入失败----"); + foreach (KeyValuePair item in missionState) + { + CommWriteMissinState state = item.Value; + string msg = $"{item.Key}:飞机状态:{state.StateReturn}, 错误码:{state.ErrorCode}, 传输:{state.SendAchieved}, 写入:{state.WriteSucceed} "; + Message.Show(msg); + await Task.Delay(10); + } + } + })); + } + } + + private ICommand _DetectionReturnData; + public ICommand DetectionReturnData + { + get + { + return _DetectionReturnData ?? (_DetectionReturnData = new RelayCommand(async () => + { + Dictionary> dic_returnData = new Dictionary>(); + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + + string name = c.Name; + int return_data = BitConverter.ToInt32(c.Retain, 0); + + lock (locker) + { + List copterList; + if (!dic_returnData.ContainsKey(return_data)) + { + copterList = new List(); + dic_returnData.Add(return_data, copterList); + } + else + copterList = dic_returnData[return_data]; + + copterList.Add(name); + } + await Task.Delay(10).ConfigureAwait(false); + })).ConfigureAwait(false); + + await Task.Run(async () => + { + foreach (KeyValuePair> kv in dic_returnData) + { + byte[] test = BitConverter.GetBytes(kv.Key); + Array.Reverse(test); + string data = string.Join(".", test); + string copters = string.Join(",", kv.Value.ToArray()); + Message.Show(string.Format("返回数据{0}({1}):{2}", data, kv.Key,copters)); + await Task.Delay(5).ConfigureAwait(false); + } + Message.Show("----统计完成----"); + }).ConfigureAwait(false); + + })); + } + } + + private ICommand _ReportGPSTypeCommand; + public ICommand ReportGPSTypeCommand + { + get + { + return _ReportGPSTypeCommand ?? (_ReportGPSTypeCommand = new RelayCommand(async()=> + { + if (_copterManager.Copters.Count > 0) + { + Dictionary> GPSTypes = new Dictionary>(); + + Dictionary> Heading = new Dictionary>(); + + foreach (var copter in _copterManager.Copters) + { + string name = copter.Name; + if (!GPSTypes.Keys.Contains(copter.GpsFixType.ToString())) + { + List copterNames = new List(); + copterNames.Add(name); + GPSTypes.Add(copter.GpsFixType.ToString(), copterNames); + } + else + GPSTypes[copter.GpsFixType.ToString()].Add(name); + + + + + if (!Heading.Keys.Contains(copter.Heading.ToString())) + { + List copterNames = new List(); + copterNames.Add(name); + Heading.Add(copter.Heading.ToString(), copterNames); + } + else + Heading[copter.Heading.ToString()].Add(name); + + + } + Message.Show($"==定位状态=="); + + foreach (var item in GPSTypes) + { + Message.Show($"{item.Key}:{string.Join(",", item.Value)}"); + Message.Show($"------------"); + } + Message.Show($"==机头方向=="); + //从小到大排个序 + Dictionary> SortedHeading = Heading.OrderBy(p => p.Key).ToDictionary(p => p.Key, o => o.Value); + + foreach (var item in SortedHeading) + { + Message.Show($"{item.Key} 度:{string.Join(",", item.Value)}"); + Message.Show($"------------"); + + } + + } + await Task.Delay(10); + })); + } + } + + + + private ICommand _DetectionCommModuleVersion; + public ICommand DetectionCommModuleVersion + { + get + { + return _DetectionCommModuleVersion ?? (_DetectionCommModuleVersion = new RelayCommand(async () => + { + Dictionary> dic_version = new Dictionary>(); + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + string name = c.Name; + int version = c.CommModuleVersion; + + lock (locker) + { + List copterList; + if (!dic_version.ContainsKey(version)) + { + copterList = new List(); + dic_version.Add(version, copterList); + } + else + copterList = dic_version[version]; + + copterList.Add(name); + } + await Task.Delay(10).ConfigureAwait(false); + })).ConfigureAwait(false); + + await Task.Run(async () => + { + foreach (KeyValuePair> kv in dic_version) + { + string copters = string.Join(",", kv.Value.ToArray()); + Message.Show(string.Format("通信模块版本{0}:{1}", kv.Key, copters)); + await Task.Delay(5).ConfigureAwait(false); + } + Message.Show("----统计完成----"); + }).ConfigureAwait(false); + + })); + } + } + + private ICommand _AllLandCommand; + public ICommand AllLandCommand + { + get + { + return _AllLandCommand ?? (_AllLandCommand = new RelayCommand(async () => + { + _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + await _commModuleManager.LandAsync(); + /* + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + await c.LandAsync(); + })); + */ + })); + } + } + + private ICommand _EmergencyRetCommand; + public ICommand EmergencyRetCommand + { + get + { + return _EmergencyRetCommand ?? (_EmergencyRetCommand = new RelayCommand(async () => + { + if (Alert.Show("您确定要紧急返航吗?紧急返航可能导致飞行器碰撞!!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) + != MessageBoxResult.OK) + return; //计算当前图案中心点,起飞图案中心点,图案距离起飞图案中心点最近距离 + FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + //计算无人机返航方向和最近的飞机距离 + PLLocation takeoffcentloc; + PLLocation taskcentloc; + double mindistance; //单位米 + bool overlapping; //图案否重叠 + int rettime= (int)(DateTime.Now - _flightTaskManager.taskStartTime).TotalSeconds; + if (!_flightTaskManager.EmergencyRet(rettime,out takeoffcentloc,out taskcentloc, out mindistance,out overlapping)) + { + Alert.Show("紧急返航数据计算失败!", "提示"); + return; + } + rettime += 5; //加5秒延迟用于通讯重复,有些飞机通讯不成功多次发送才收到,比别的飞机慢 + + //模拟测试 + if (_flightTaskManager.TaskState != TasksStatus.Stop) + await _flightTaskManager.sim_DoMissionEmergencyRetAsync(takeoffcentloc, taskcentloc, (float)mindistance, rettime, overlapping); + for (int i = 0; i < 10; i++) + { + await _commModuleManager.DoMissionEmergencyRetAsync(takeoffcentloc,taskcentloc,(float)mindistance, rettime, overlapping); + } + })); + } + } + + + private ICommand _LEDFlickerCommand; + public ICommand LEDFlickerCommand + { + get + { + return _LEDFlickerCommand ?? (_LEDFlickerCommand = new RelayCommand(() => + { + _commModuleManager.LED_FlickerAsync(_copterManager.AcceptingControlCopters); + })); + } + } + + + private ICommand _DelCommand; + public ICommand DelCommand + { + get + { + return _DelCommand ?? (_DelCommand = new RelayCommand(async () => + { + FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + { + if (_flightTaskManager.Tasks.Count > 0) + { + Alert.Show("有航点任务无法删除飞机,请先清除航点!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + await _copterManager.DelSelCopters(); + } + })); + } + } + + + private ICommand _MotorTestCommand; + public ICommand MotorTestCommand + { + get + { + return _MotorTestCommand ?? (_MotorTestCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + { + await _commModuleManager.MotorTestAsync(_copterManager.AcceptingControlCopters); + } + + /* + + await Task.WhenAll(_copterManager.Copters.Select(async c => + { + for (int i = 1; i <= 4; i++) + { + await c.MotorTestAsync(i).ConfigureAwait(false); + await Task.Delay(10); + } + + })).ConfigureAwait(false); + */ + })); + } + } + + private ICommand _GuidAsyncCommand; + public ICommand GuidAsyncCommand + { + get + { + return _GuidAsyncCommand ?? (_GuidAsyncCommand = new RelayCommand(async () => + { + if (TaskOffAlt <= 0) return; + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.TakeOffAsync(TaskOffAlt, _copterManager.AcceptingControlCopters); + /* + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async c => + { + await c.GuidAsync(); + await Task.Delay(100).ConfigureAwait(false); + await c.TakeOffAsync(1); + })); + */ + })); + } + } + + /// + /// 是否允许开始任务,全部解锁会在3秒内循环发送3次,该过程中不允许开始任务 + /// + private bool _AllowMissionStart = true; + public bool AllowMissionStart + { + get { return _AllowMissionStart; } + set { Set(nameof(AllowMissionStart), ref _AllowMissionStart, value); } + } + + + private ICommand _UnlockAllCommand; + public ICommand UnlockAllCommand + { + get + { + return _UnlockAllCommand ?? (_UnlockAllCommand = new RelayCommand(async () => + { + AllowMissionStart = false; + // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); + for (int i = 0; i < 3; i++) + { + _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + await _commModuleManager.UnlockAsync(); + await Task.Delay(1000).ConfigureAwait(false); + } + await Task.Delay(100); + AllowMissionStart = true; + + /* + await Task.WhenAll(_copterManager.Copters.Select(async c => { + await c.UnlockAsync(); + //解锁间隔一定要超过1s否则导致飞控以后无法解锁 + for (int i = 0; !c.IsUnlocked; i++) + { + if (i > 200) + break; + if (i % (1000 / 25) == 1000 / 25 - 1) + { + await c.UnlockAsync(); // 每 1000 毫秒重试一次。解锁间隔一定要超过1s否则导致飞控以后无法解锁 + } + await Task.Delay(25).ConfigureAwait(false); + } + })); + */ + })); + } + } + + private const string NTF_GROUPLED_OFF = "NTF_G_OFF"; + private ICommand _LEDOnOffCommand; + public ICommand LEDOnOffCommand + { + get + { + return _LEDOnOffCommand ?? (_LEDOnOffCommand = new RelayCommand(async onOff=> + { + string paramstr = NTF_GROUPLED_OFF; + float paramvalue = onOff; + await _commModuleManager.SetParamAsync(paramstr, paramvalue, _copterManager.AcceptingControlCopters); + /* + await Task.WhenAll( + _copterManager.AcceptingControlCopters.Select(async copter => + { + paramvalue = await copter.GetParamAsync(paramstr); + })); + + float newParamvalue = paramvalue == 0 ? 1 : 0; + + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select + (copter => copter.SetParamAsync(paramstr, newParamvalue))); + */ + })); + } + } + + private ICommand _UnlockCommand; + public ICommand UnlockCommand + { + get + { + return _UnlockCommand ?? (_UnlockCommand = new RelayCommand(async () => + { + // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.UnlockAsync(_copterManager.AcceptingControlCopters); + + /* + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select( async c => { + await c.UnlockAsync(); + //解锁间隔一定要超过1s否则导致飞控以后无法解锁 + for (int i = 0; !c.IsUnlocked; i++) + { + if (i > 200) + break; + if (i % (1000 / 25) == 1000 / 25 - 1) + { + await c.UnlockAsync(); // 每 1000 毫秒重试一次。解锁间隔一定要超过1s否则导致飞控以后无法解锁 + } + await Task.Delay(25).ConfigureAwait(false); + } + })); + */ + })); + } + } + + private float _LatOffset = 18.4023833f; + public float LatOffset + { + get { return _LatOffset; } + set { Set(nameof(LatOffset), ref _LatOffset, value); } + } + + private float _LngOffset = 109.799761f; + public float LngOffset + { + get { return _LngOffset; } + set { Set(nameof(LngOffset), ref _LngOffset, value); } + } + + + private ICommand _RLTOffsetCommand; + public ICommand RLTOffsetCommand + { + get + { + return _RLTOffsetCommand ?? (_RLTOffsetCommand = new RelayCommand(() => + { +// Message.Show($"偏移Lat = {LatOffset},Lng = {LngOffset}"); +// if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) +// await _commModuleManager.RLTOffsetAsync(LatOffset, LngOffset, _copterManager.AcceptingControlCopters); + + + })); + } + } + + private ICommand _LockCommand; + public ICommand LockCommand + { + get + { + return _LockCommand ?? (_LockCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + { + if (Alert.Show("您确定要上锁吗?飞行器将无视转速,立即强制停止运转!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) + == MessageBoxResult.OK) + { + _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + await _commModuleManager.LockAsync(_copterManager.AcceptingControlCopters); + //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.LockAsync())); + } + } + })); + } + } + + private ICommand _TakeOffCommand; + public ICommand TakeOffCommand + { + get + { + return _TakeOffCommand ?? (_TakeOffCommand = new RelayCommand(async () => + { + FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法开始任务!", "提示"); + return; + } + //飞机用UTC时间,日志用本地时间记录 + DateTime MissionTime = DateTime.UtcNow.AddSeconds(5); + DateTime MissionTime_log = DateTime.Now.AddSeconds(5); + Message.Show("任务开始:" + MissionTime_log.ToString()); + + IEnumerable selcopters = _copterManager.AcceptingControlCopters; + + //循环3次 发送起飞命令 避免通信问题 + for (int i = 0; i < 20; i++) + { + + /*await _commModuleManager.DoMissionStartAsync(_copterManager.Copters, + MissionTime.Hour, + MissionTime.Minute, + MissionTime.Second, + _flightTaskManager.OriginLng, + _flightTaskManager.OriginLat + ); + */ + + + await _commModuleManager.DoMissionStartAsync(selcopters, + MissionTime.Hour, + MissionTime.Minute, + MissionTime.Second, + _flightTaskManager.OriginLng, + _flightTaskManager.OriginLat + ); + + + + /* await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.MissionStartAsync( + MissionTime.Hour, + MissionTime.Minute, + MissionTime.Second, + _flightTaskManager.OriginLng, + _flightTaskManager.OriginLat + ))); + */ + + + await Task.Delay(20).ConfigureAwait(false); + + } + //_copterManager.Net_LogStartMission(MissionTime_log, _flightTaskManager.OriginLng, _flightTaskManager.OriginLat); + Alert.Show("所有选中飞机开始执行航点任务。请勿多次开始任务!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + })); + } + } + + private ICommand _ThrowoutCommand; + public ICommand ThrowoutCommand + { + get + { + return _ThrowoutCommand ?? (_ThrowoutCommand = new RelayCommand( () => + { + // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.UnlockAsync())); + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + _commModuleManager.ThrowoutAsync(_copterManager.AcceptingControlCopters); + })); + } + } + + private ICommand _HoverCommand; + public ICommand HoverCommand + { + get + { + return _HoverCommand ?? (_HoverCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.HoverAsync(_copterManager.AcceptingControlCopters); + //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.HoverAsync())); + })); + } + } + + private ICommand _FloatCommand; + public ICommand FloatCommand + { + get + { + return _FloatCommand ?? (_FloatCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.FloatAsync(_copterManager.AcceptingControlCopters); + //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.FloatAsync())); + })); + } + } + + private ICommand _ReturnToLaunchCommand; + public ICommand ReturnToLaunchCommand + { + get + { + return _ReturnToLaunchCommand ?? (_ReturnToLaunchCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.ReturnToLaunchAsync(_copterManager.AcceptingControlCopters); + //await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.ReturnToLaunchAsync())); + })); + } + } + + + private ICommand _GetVersionsCommand; + public ICommand GetVersionsCommand + { + get + { + return _GetVersionsCommand ?? (_GetVersionsCommand = new RelayCommand(async () => + { + //if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.GetVersionsAsync(); + })); + } + } + private ICommand _GetCommsumCommand; + public ICommand GetCommsumCommand + { + get + { + return _GetCommsumCommand ?? (_GetCommsumCommand = new RelayCommand(async () => + { + //if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.GetCommsumAsync(); + })); + } + } + //打开校准界面 + private ICommand _CalibrationSingleCommand; + public ICommand CalibrationSingleCommand + { + get + { + return _CalibrationSingleCommand ?? (_CalibrationSingleCommand = new RelayCommand(async () => + { + CalibrationWindow calibrationWindow = new CalibrationWindow(); + calibrationWindow.ShowDialog(); + await Task.Delay(100); + })); + } + } + + private ICommand _LoadParamfile; + public ICommand LoadParamfile + { + get + { + return _LoadParamfile ?? (_LoadParamfile = new RelayCommand(async () => + { + + var dialog = new OpenFileDialog + { + DefaultExt = "param", + Filter = "飞行参数 (*.param)|*.param" + }; + if (dialog.ShowDialog() == true) + { + + bool ifallok = true; + var paramlist = ParamFile.loadParamFile(dialog.FileName); + + foreach (string name in paramlist.Keys) + { + float value = float.Parse( paramlist[name].ToString()); + //写5次 + for (int i = 0; i < 5; i++) + { + + if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) + await _commModuleManager.SetParamAsync(name, value, _copterManager.AcceptingControlCopters); + else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) + { + _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + await _commModuleManager.SetParamAsync(name, value); + } + + + + // await Task.WhenAll(_copterManager.AcceptingControlCopters.Select + // (copter => copter.SetParamAsync(name, value))); + } + await Task.Delay(2000); + + //发送读取5次 + for (int i = 0; i < 5; i++) + { + if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) + await _commModuleManager.ReadParamAsnyc(name, _copterManager.AcceptingControlCopters); + else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) + await _commModuleManager.ReadParamAsnyc(name); + } + await Task.Delay(1000); + + //开始检查飞机返回参数是否正确 + + foreach (ICopter copter in _copterManager.AcceptingControlCopters) + { + if (value != copter.RetainInt) + { + ifallok = false; + Alert.Show(copter.Id + "参数[" + name + "]设置失败,读取的值是[" + copter.RetainInt + "]", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + + } + + + } + + + + + + /* + await Task.WhenAll( + + _copterManager.AcceptingControlCopters.Select(async copter => + { + float getvaule = await copter.GetParamAsync(name); + if (getvaule != value) + { + ifallok = false; + Alert.Show(copter.Id +"参数["+ name+ "]设置失败,读取的值是[" + getvaule+"]", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + } + } + + )); + */ + + + } + + if (ifallok) + Alert.Show("所有已选的飞机参数设置完成", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + else + Alert.Show("有部分飞机参数设置失败,请检查并再次设置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + } + })); + } + } + + + private ICommand _ParamModify; + public ICommand ParamModify + { + get + { + return _ParamModify ?? (_ParamModify = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + { + var ModifyParamWindow = new Plane.FormationCreator.ModifyParam(); + if (ModifyParamWindow.ShowDialog() == true) + { + bool isLoadParam = ModifyParamWindow.LoadParam; + string paramstr = ModifyParamWindow.textParamName.Text; + + if(!isLoadParam) + { + float paramvalue = Convert.ToSingle(ModifyParamWindow.textParamValue.Text); + int num = 0; + int writeTime = 0; + //连续写5次,为了都写成功 + for ( writeTime=0; writeTime<5; writeTime++) + { + + if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) + num = await _commModuleManager.SetParamAsync(paramstr, paramvalue, _copterManager.AcceptingControlCopters); + else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) + { + _commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + num = await _commModuleManager.SetParamAsync(paramstr, paramvalue); + } + } + Alert.Show($"广播完成! 序列号从:{num-writeTime+1}到{num}"); + } + else + { + if (_copterManager.AcceptingControlCopters.Count() < _copterManager.Copters.Count) + await _commModuleManager.ReadParamAsnyc(paramstr, _copterManager.AcceptingControlCopters); + else if (_copterManager.AcceptingControlCopters.Count() == _copterManager.Copters.Count) + await _commModuleManager.ReadParamAsnyc(paramstr); + } + + /* + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select + (copter => copter.SetParamAsync(paramstr, paramvalue))); + + bool ifallok = true; + await Task.WhenAll( + + _copterManager.AcceptingControlCopters.Select(async copter => + { + float getvaule = await copter.GetParamAsync(paramstr); + if (getvaule != paramvalue) + { + ifallok = false; + Alert.Show(copter.Id + "设置失败,读取的参数是" + getvaule, "提示", MessageBoxButton.OK, MessageBoxImage.Information); + } + } + + )); + if (ifallok) + Alert.Show("所有已选的飞机参数设置完成", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + else + Alert.Show("有部分飞机参数设置失败,请检查并再次设置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + + */ + + } + } + })); + } + } + + private ICommand _TurnOffTestLightsCommand; + public ICommand TurnOffTestLightsCommand + { + get + { + return _TurnOffTestLightsCommand ?? (_TurnOffTestLightsCommand = new RelayCommand(async () => + { + int num = 0; + //正式飞行 + num = await _commModuleManager.SetMultipleParamAsync( + "NTF_G_RTLOFF", "1", + "FS_GCS_ENABLE", "0", + "NTF_G_RTKTEST", "0", + "WAYPOINT_GLED", "0", + "FS_BATT_VOLTAGE", "14.2", + "RTL_ALT","3000", + "RTL_ALT_MAX","5000", + "FC_LOG_LEVEL", "0", + "FC_LOG_TYPE", "0", + "FS_GPS_RTL", "4"); + + //测试飞行 + /* + num = await _commModuleManager.SetMultipleParamAsync( + "NTF_G_RTLOFF", "0", + "FS_GCS_ENABLE", "1", + "NTF_G_RTKTEST", "1", + "WAYPOINT_GLED", "1", + "FS_BATT_VOLTAGE", "14.2", + "RTL_ALT", "3000", + "RTL_ALT_MAX", "5000", + "FC_LOG_LEVEL","3", + "FC_LOG_TYPE", "1", + "FS_GPS_RTL", "4" + ); + */ + + Alert.Show($"广播完成! 当前序列号:{num}"); + })); + } + } + + + private string _RTKcomvalue = "COM6"; + public string RTKcomvalue + { + get { return _RTKcomvalue; } + set { Set(nameof(RTKcomvalue), ref _RTKcomvalue, value); } + } + + //RTK收发线程 + private static void mainloop() + { + + + + } + + + private async Task ReadRTKPacketAsync() + { + if (!Rtkport.IsOpen) + { + return null; + } + + // limit to 110 byte packets + byte[] buffer; + int length = 0; + + try + { + length = Math.Min(180, Rtkport.BytesToRead()); + + if (length > 0)//while (Rtkport.BytesToRead() > 0) + + { + buffer = new byte[length]; + + int read = await Rtkport.ReadAsync(buffer, 0, Math.Min(buffer.Length, length)); + + // sendData(buffer, (byte)read); + + } + else + return null; + + /* + if (await Rtkport.ReadAsync(buffer, 0, 1) == 0) + { + // 做简单数据解析,得到协议类型,后续数据长度等 + } + //根据数据长度读取实际数据 + if (await Rtkport.ReadAsync(buffer, 1, 1) == 0) + { + + } + */ + + } + catch (Exception ex) + { + return null; + } + return buffer; + + } + + + + private ICommand _SendRTKCommand; + public ICommand SendRTKCommand + { + get + { + return _SendRTKCommand ?? (_SendRTKCommand = new RelayCommand(async () => + { + if (!trkthreadrun) + { + Rtkport = new SerialPortConnection(RTKcomvalue, 57600) as IConnection; + await Rtkport.OpenAsync(); + if (!Rtkport.IsOpen) + { + Alert.Show("无法打开" + RTKcomvalue, "警告", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + trkthreadrun = true; //开始运行后台任务 + /* //线程方式后台运行rtk转发任务 + thrtk = new System.Threading.Thread(new System.Threading.ThreadStart(mainloop)) + { + IsBackground = true, + Name = "injectgps" + }; + thrtk.Start(); + */ + //后台任务方式运行rtk转发任务 + Alert.Show("RTK数据开始发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + RTKState = "RTK数据发送中"; + RTKbtntxt = "停止RTK"; + await SaveRTKcomvalue(); + await _commModuleManager.StartRtcmLoop(); + await Task.Run(async () => + { + Message.Show("RTK数据开始发送"); + //读取RTK数据循环 + rtcm3 rtcm3 = new rtcm3(); + while (trkthreadrun) + { + //读入RTK数据 + var packet = await ReadRTKPacketAsync().ConfigureAwait(false); + + if (packet != null && packet.Length > 0) + { + //Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---packet.length = {packet.Length}"); + //新方案的RTK发送,用于双频 + + int read = packet.Length; + if (read > 0) + { + for (int a = 0; a < read; a++) + { + int seenmsg = -1; + // rtcm + if ((seenmsg = rtcm3.Read(packet[a])) > 0) + { + Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---rtcm3.length = {rtcm3.length}"); + await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); + } + } + } + + + + //稳定方案的rtk发送,用于单频 + //_commModuleManager.SetAllCoptersForWifi(_copterManager.Copters); + //await _commModuleManager.InjectGpsDataAsync(packet, (ushort)packet.Length); + } + await Task.Delay(10).ConfigureAwait(false); + + } + }).ConfigureAwait(false); + Alert.Show("RTK数据停止发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + } + else//停止RTK + { + await _commModuleManager.CloseRtcmLoop(); + + trkthreadrun = false; + Rtkport.Close(); + Rtkport = null; + + RTKState = "未发送RTK数据"; + RTKbtntxt = "发送RTK"; + } + })); + } + } + + + private ICommand _SendRTCMCommand; + public ICommand SendRTCMCommand + { + get + { + return _SendRTCMCommand ?? (_SendRTCMCommand = new RelayCommand(async () => + { + FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法发送RTCM!", "提示"); + return; + } + + rtcmthreadrun = !rtcmthreadrun; + if (rtcmthreadrun) + { + string messagetips = "格式:http://差分账号:差分密码@域名:端口/坐标系\r\n例如:http://account:password@rtk.ntrip.qxwz.com:8002/RTCM32_GGB"; + string url = ""; + IniFiles inifilse = new IniFiles(); + url = inifilse.IniReadvalue("Default","RTKurl"); + if (PlaneMessageBox.OnShow(messagetips, "发送RTK", ref url) == false) return; + inifilse.IniWritevalue("Default", "RTKurl", url); + + RTKState = "RTK数据发送中"; + NTRIPbtntxt = "停止RTCM"; + Alert.Show("RTCM数据开始发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + + await _commModuleManager.StartRtcmLoop(); + await Task.Run(async () => + { + Message.Show("RTK数据开始发送"); + //string url = "http://qxarpz003:1dc880b@rtk.ntrip.qxwz.com:8002/RTCM32_GGB"; + CommsNTRIP commNTRIP = new CommsNTRIP(url, _flightTaskManager.OriginLat, _flightTaskManager.OriginLng); + rtcm3 rtcm3 = new rtcm3(); + commNTRIP.Open(); + //读取RTK数据循环 + while (rtcmthreadrun) + { + byte[] buffer = new byte[180]; + + while (commNTRIP.BytesToRead > 0) + { + int read = commNTRIP.Read(buffer, 0, Math.Min(buffer.Length, commNTRIP.BytesToRead)); + + if (read > 0) + { + for (int a = 0; a < read; a++) + { + int seenmsg = -1; + // rtcm + if ((seenmsg = rtcm3.Read(buffer[a])) > 0) + { + //rtcmDatas.Add(rtcm3.packet); + //await SendRtcmData(); + //Message.Show($"{DateTime.Now.ToString("HH:mm:ss fff")}---rtcm3.length = {rtcm3.length}"); + await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); + } + } + } + } + await Task.Delay(10); + } + NTRIPbtntxt = "发送RTCM"; + RTKState = "未发送RTK数据"; + Alert.Show("RTCM数据停止发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + }); + } + })); + } + } + + private RtcmInfoView rtcmInfoView; + private ICommand _OpenRtcmManageCommand; + public ICommand OpenRtcmManageCommand + { + get + { + return _OpenRtcmManageCommand ?? (_OpenRtcmManageCommand = new RelayCommand(() => + { + RtcmInfoView.GetInstance().Show(); + RtcmInfoView.GetInstance().Activate(); + // if (rtcmInfoView == null) + // { + // rtcmInfoView = new RtcmInfoView(); + // } + // rtcmInfoView.Show(); + })); + } + } + + /* + rtcm3 rtcm3 = new rtcm3(); + private async Task AnalysisRendRrcmData(byte[] buffer, int length) + { + for (int a = 0; a < length; a++) + { + int seenmsg = -1; + // rtcm + if ((seenmsg = rtcm3.Read(buffer[a])) > 0) + { + await _commModuleManager.InjectGpsRTCMDataAsync(rtcm3.packet, rtcm3.length); + } + } + await Task.Delay(1); + } + */ + + + private ICommand _LandCommand; + public ICommand LandCommand + { + get + { + return _LandCommand ?? (_LandCommand = new RelayCommand(async () => + { + if (_copterManager.AcceptingControlCopters != null && _copterManager.AcceptingControlCopters.Count() > 0) + await _commModuleManager.LandAsync(_copterManager.AcceptingControlCopters); + /* + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.LandAsync())); + */ + })); + } + } + + + + + private ICommand _ConnectCommand; + public ICommand ConnectCommand + { + get + { + return _ConnectCommand ?? (_ConnectCommand = new RelayCommand(async () => + { + //await ConnectAsync(); + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async copter => + { + //await commModule.ConnectAsync(); + await copter.ConnectAsync(); + //await copter.GetCopterDataAsync(); + })); + })); + } + } + + private ICommand _DisconnectCommand; + public ICommand DisconnectCommand + { + get + { + return _DisconnectCommand ?? (_DisconnectCommand = new RelayCommand(async () => + { + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => copter.DisconnectAsync())); + })); + } + } + + private ICommand _FlyToAltitudeCommand; + public ICommand FlyToAltitudeCommand + { + get + { + return _FlyToAltitudeCommand ?? (_FlyToAltitudeCommand = new RelayCommand(async alt => + { + await _formationController.FlyToAltitudeAsync(_copterManager.AcceptingControlCopters, targetAlt: alt).ConfigureAwait(false); + })); + } + } + + private ICommand _FlyInCircleCommand; + public ICommand FlyInCircleCommand + { + get + { + return _FlyInCircleCommand ?? (_FlyInCircleCommand = new RelayCommand(async () => + { + await _formationController.FlyInCircleAsync(_copterManager.AcceptingControlCopters, centerDirection: 180, radius: 10, loop: true).ConfigureAwait(false); + })); + } + } + + private ICommand _FlyAroundCenterOfCoptersCommand; + public ICommand FlyAroundCenterOfCoptersCommand + { + get + { + return _FlyAroundCenterOfCoptersCommand ?? (_FlyAroundCenterOfCoptersCommand = new RelayCommand(async () => + { + await _formationController.FlyAroundCenterOfCoptersAsync(_copterManager.AcceptingControlCopters).ConfigureAwait(false); + })); + } + } + + private ICommand _FlyInRectangleCommand; + public ICommand FlyInRectangleCommand + { + get + { + return _FlyInRectangleCommand ?? (_FlyInRectangleCommand = new RelayCommand(async () => + { + await _formationController.FlyInRectangleAsync(_copterManager.AcceptingControlCopters, startDirection: 180, sideLength1: 15, sideLength2: 5, loop: true).ConfigureAwait(false); + })); + } + } + + private ICommand _FlyToVerticalLineAndMakeCircleCommand; + public ICommand FlyToVerticalLineAndMakeCircleCommand + { + get + { + return _FlyToVerticalLineAndMakeCircleCommand ?? (_FlyToVerticalLineAndMakeCircleCommand = new RelayCommand(async () => + { + await _formationController.FlyToVerticalLineAndMakeCircle( + _copterManager.AcceptingControlCopters, + centerDirection: 180, + radius: 10 + ).ConfigureAwait(false); + })); + } + } + + private ICommand _MissionStartCommand; + public ICommand MissionStartCommand + { + get + { + return _MissionStartCommand ?? (_MissionStartCommand = new RelayCommand(async () => + { + FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法开始任务!", "提示"); + return; + } + //飞机用UTC时间,日志用本地时间记录 + DateTime MissionTime = DateTime.UtcNow.AddSeconds(5); + DateTime MissionTime_log = DateTime.Now.AddSeconds(5); + Message.Show("任务开始:" + MissionTime_log.ToString()); + //循环3次 发送起飞命令 避免通信问题 + for (int i = 0; i < 20; i++) //20 + { + await _commModuleManager.DoMissionStartAsync(null, + MissionTime.Hour, + MissionTime.Minute, + MissionTime.Second, + _flightTaskManager.OriginLng, + _flightTaskManager.OriginLat + ); + + /* + foreach (var vcopter in _copterManager.Copters) + { + await vcopter.MissionStartAsync(utchour, + utcminute, + utcsecond, + _flightTaskManager.OriginLng, + _flightTaskManager.OriginLat + ); + } + */ + + await Task.Delay(20).ConfigureAwait(false); + + } + _copterManager.Net_LogStartMission(MissionTime_log, _flightTaskManager.OriginLng, _flightTaskManager.OriginLat); + Alert.Show("所有飞机开始执行航点任务。请勿多次开始任务!", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + })); + } + } + + private ICommand _MissionPauseCommand; + public ICommand MissionPauseCommand + { + get + { + return _MissionPauseCommand ?? (_MissionPauseCommand = new RelayCommand(async () => + { + for (int i = 0; i < 3; i++) + { + await _commModuleManager.DoMissionPauseAsync(); + } + })); + } + } + + private ICommand _MissionResumeCommand; + public ICommand MissionResumeCommand + { + get + { + return _MissionResumeCommand ?? (_MissionResumeCommand = new RelayCommand(async () => + { + int utchour = DateTime.UtcNow.AddSeconds(5).Hour; + int utcminute = DateTime.UtcNow.AddSeconds(5).Minute; + int utcsecond = DateTime.UtcNow.AddSeconds(5).Second; + for (int i = 0; i < 3; i++) + { + await _commModuleManager.DoMissionResumeAsync( + utchour, + utcminute, + utcsecond); + } + })); + } + } + + + // private ICommand _SetOriginalPointCommand; + // public ICommand SetOriginalPointCommand + // { + // get + // { + // return _SetOriginalPointCommand ?? (_SetOriginalPointCommand = new RelayCommand(() => + // { + // FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance(); + // _flightTaskManager.SetOriginal(); + // })); + // } + // } + private ICommand _WriteMissionSingleCommand; + public ICommand WriteMissionSingleCommand + { + get + { + return _WriteMissionSingleCommand ?? (_WriteMissionSingleCommand = new RelayCommand(async () => + { + var _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); + return; + } + var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); + if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) + { + Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); + await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); + } + + + int taskcount = _flightTaskManager.Tasks.Count; + if (taskcount < 2) return; + foreach (var copter in _copterManager.AcceptingControlCopters) + { + int i = _copterManager.Copters.IndexOf(copter); + await CollectMissions(i); + } + })); + } + } + + + private ICommand _WriteMissionFailedCommand; + public ICommand WriteMissionFailedCommand + { + get + { + return _WriteMissionFailedCommand ?? (_WriteMissionFailedCommand = new RelayCommand(async () => + { + var _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); + return; + } + var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); + if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) + { + Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); + await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); + } + + int coptercount = _copterManager.Copters.Count; + int taskcount = _flightTaskManager.Tasks.Count; + if (taskcount < 2) return; + foreach(KeyValuePair kv in _commModuleManager.MissionWriteState) + { + if (!kv.Value.SendAchieved || !kv.Value.WriteSucceed) + { + var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == kv.Key.ToString()); + int i = _copterManager.Copters.IndexOf(copter); + await CollectMissions(i); + } + } + })); + } + } + + private ICommand _WriteMissionCommand; + public ICommand WriteMissionCommand + { + get + { + return _WriteMissionCommand ?? (_WriteMissionCommand = new RelayCommand(async () => + { + var _flightTaskManager = ServiceLocator.Current.GetInstance(); + if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0) + { + Alert.Show("作为参照的原点未设置,无法写入相对位置!", "提示"); + return; + } + + int coptercount = _copterManager.Copters.Count; + int taskcount = _flightTaskManager.Tasks.Count; + if (taskcount < 2) return; + + var _RtcmInfoViewModel = ServiceLocator.Current.GetInstance(); + if (_RtcmInfoViewModel.RtcmManager.Rtcmthreadrun) + { + Alert.Show("RTK数据正在发送,将自动关闭!", "提示"); + await _RtcmInfoViewModel.RtcmManager.Close(_RtcmInfoViewModel.SerialPortsSelectdValue); + } + + Alert.Show("开始写入航点,飞机绿色成功红色失败!(先关灯再开灯可恢复飞机灯光)", "提示"); + _commModuleManager.ClearMissionWriteState(); + for (int i = 0; i < coptercount; i++) + { + ///写航线开始 + await CollectMissions(i).ConfigureAwait(false); + } + Alert.Show($"任务写入完成!请检测失败的飞机"); + })); + } + } + + /// + /// 用通讯模块 写入航点信息 + /// + /// copterIndex + /// + private async Task CollectMissions(int i) + { + int j = 0; + try + { + + + float groudAlt = _copterManager.Copters[i].GroundAlt; + var missions = new List(); + var _flightTaskManager = ServiceLocator.Current.GetInstance(); + for (j = 0; j < _flightTaskManager.Tasks.Count; j++) + { + switch (_flightTaskManager.Tasks[j].TaskType) + { + case FlightTaskType.TakeOff: + //int takeofftime = (int)(_flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetAlt / 2.5 + 5); + missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); + missions.Add(Mission.CreateTakeoffMission( + _flightTaskManager.Tasks[j].SingleCopterInfos[i].TakeOffWaitTime, //起飞等待时间 + _flightTaskManager.Tasks[j].TakeOffTime, //起飞时间 + _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetLat - _flightTaskManager.OriginLat, //位置没用 + _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetLng - _flightTaskManager.OriginLng, //位置没用 + _flightTaskManager.Tasks[j + 1].SingleCopterInfos[i].TargetAlt - groudAlt) //下一个航点的高度 + ); + break; + + case FlightTaskType.FlyTo: + if (_flightTaskManager.Tasks[j].SingleCopterInfos[i].IsChangeSpeed) + { + missions.Add(Mission.CreateChangeSpeedMission( + _flightTaskManager.Tasks[j].SingleCopterInfos[i].LevelSpeed, + _flightTaskManager.Tasks[j].SingleCopterInfos[i].UpSpeed, + _flightTaskManager.Tasks[j].SingleCopterInfos[i].DownSpeed) + ); + } + missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); + + double Lat = _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetLat - _flightTaskManager.OriginLat; + double Lng = _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetLng - _flightTaskManager.OriginLng; + //如果是返航点,位置写入固定值,这样直接返回起飞点 + if (_flightTaskManager.Tasks[j].SingleCopterInfos[i].IsLandWaypoint) + { + Lat = 90; + Lng = 180; + } + + missions.Add(Mission.CreateWaypointMission( + _flightTaskManager.Tasks[j].LoiterTime, + _flightTaskManager.Tasks[j].FlytoTime, + Lat, + Lng, + _flightTaskManager.Tasks[j].SingleCopterInfos[i].TargetAlt - groudAlt) + ); + break; + + case FlightTaskType.Land: + missions.AddRange(CreateLEDMissions(_flightTaskManager.Tasks[j].SingleCopterInfos[i].LEDInfos)); + + missions.Add(Mission.CreateLandMission( + _flightTaskManager.Tasks[j].SingleCopterInfos[i].LandWaitTime) + ); + break; + default: + break; + } + } + //186是通讯模块的限制--张伟那边 + if (missions.Count > 186) + { + Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 航点数量超过186,请减少再重写该飞机!"); + } + else + { + //虚拟ID在排序时已经变为ID了,直接按ID写入 + // var targetCopter = _copterManager.Copters.FirstOrDefault(o => o.VirtualId == (i+1)); + // bool result = await _commModuleManager.WriteMissionListAsync(targetCopter, missions); + bool result = await _commModuleManager.WriteMissionListAsync(_copterManager.Copters[i], missions); + + //CommWriteMissinState state = new CommWriteMissinState(result); + //_commModuleManager.missionWriteState.Add(int.Parse(_copterManager.Copters[i].Id), state); + if (!result) + { + + if (_copterManager.SortType == CopterManager.CopterSortType.ByVID) + Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 通信模块传输失败!"); + else + Message.Show($"飞机:{_copterManager.Copters[i].Id} 通信模块传输失败!"); + } + else + { + if (_copterManager.SortType == CopterManager.CopterSortType.ByVID) + Message.Show($"飞机:{_copterManager.Copters[i].VirtualId} 通信模块传输完成!"); + else + Message.Show($"飞机:{_copterManager.Copters[i].Id} 通信模块传输完成!"); + } + await Task.Delay(500).ConfigureAwait(false); + } + } + catch (Exception ex) + { + Message.Show(ex.ToString()); + } + + } + + private List CreateLEDMissions(IEnumerable LEDInfos) + { + List missions = new List(); + foreach (LEDInfo ledInfo in LEDInfos) + { + float ledinterval=0; + Color color = (Color)ColorConverter.ConvertFromString("#" + ledInfo.LEDRGB); + int ledMode = ledInfo.LEDMode; + //拉烟任务模式ID是50,需要改为50 + if (_copterManager.FC_VER_NO == 1) + { + //老版本是闪烁频率,且不能为小数 + ledinterval = ledInfo.LEDInterval; + //老版本ledMode == 8 对应拉烟,飞控对应50,ledinterval对应通道号 + if (ledMode==8) ledMode = 50; + } + else + { + //新版本飞控 是闪烁间隔单位是100ms,地面站还是频率可以有1位小数,用户输入0.5hz 飞控应该是(1/0.5)*10=20 + ledinterval = (1 / ledInfo.LEDInterval); + + //新版本 ledMode=16是抛物,飞控对应50,ledinterval对应10 --固定的 + if (ledMode == 16) + { + ledMode = 50; + ledinterval = 10; + } + else //新版本ledMode == 15 对应拉烟,飞控对应50,ledinterval对应通道号 + if (ledMode == 15) + { + ledMode = 50; + } + } + IMission LEDMission = Mission.CreateLEDControlMission( + (int)(ledInfo.Delay * 10), + ledMode, + ledinterval, + 0, //ledInfo.LEDTimes, + color.R, + color.G, + color.B + ); + missions.Add(LEDMission); + } + return missions; + } + + private ICommand _FlagCommand; + public ICommand FlagCommand + { + get + { + return _FlagCommand ?? (_FlagCommand = new RelayCommand(async () => + { + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(copter => + { + + var copters = _copterManager.Copters; + int index = copters.IndexOf(copter); + _copterManager.CopterStatus[index] = true; + return Task.Run(()=> { }); + })); + })); + } + } + + private async Task UnlockTestSingleCopterAsync(ICopter SingleCopter) + { + await SingleCopter.UnlockAsync(); + await Task.Delay(25).ConfigureAwait(false); + + for (int i = 0; !SingleCopter.IsUnlocked; i++) + { + //8秒内每1000毫秒尝试解锁一次 + //解锁间隔一定要超过1s否则导致飞控以后无法解锁 + + if (i >320) + return; //无法解锁后面不用执行了 + if (i % (1000 / 25) == 1000 / 25 - 1) + { + await SingleCopter.UnlockAsync(); // 每 1000 毫秒重试一次。 + } + await Task.Delay(25).ConfigureAwait(false); + } + + + await Task.Delay(1000); + if (SingleCopter.IsUnlocked) + { + await SingleCopter.SetShowLEDAsync(true); + await Task.Delay(50); + await SingleCopter.SetShowLEDAsync(true); + } + + + await Task.Delay(5000); + + await SingleCopter.LockAsync(); + await Task.Delay(25).ConfigureAwait(false); + for (int i = 0; SingleCopter.IsUnlocked; i++) + { + //8秒内每1000毫秒尝试解锁一次 + //解锁间隔一定要超过1s否则导致飞控以后无法解锁 + + if (i > 320) + return; //无法解锁后面不用执行了 + if (i % (1000 / 25) == 1000 / 25 - 1) + { + await SingleCopter.LockAsync(); // 每 1000 毫秒重试一次。 + } + await Task.Delay(25).ConfigureAwait(false); + } + + await Task.Delay(1000); + if (!SingleCopter.IsUnlocked) + { + await SingleCopter.SetShowLEDAsync(false); + await Task.Delay(50); + await SingleCopter.SetShowLEDAsync(false); + } + } + + + + private ICommand _TestCommand; + public ICommand TestCommand + { + get + { + return _TestCommand ?? (_TestCommand = new RelayCommand(async () => + { + + + Message.Show("解锁测试--开始"); + int i = 0; + var tasksUnlockTest = new Task[_copterManager.Copters.Count]; + foreach (var vcopter in _copterManager.Copters) + { + tasksUnlockTest[i++] = UnlockTestSingleCopterAsync(vcopter); + //i++; + } + await Task.WhenAll(tasksUnlockTest).ConfigureAwait(false); + Message.Show("解锁测试--完成!"); + return; + + + + + + + + + + + foreach (var vcopter in _copterManager.Copters) + { + await vcopter.UnlockAsync(); + } + await Task.Delay(1000); + + foreach (var vcopter in _copterManager.Copters) + { + if (vcopter.IsUnlocked) + await vcopter.SetShowLEDAsync(true); + } + + await Task.Delay(5000); + + foreach (var vcopter in _copterManager.Copters) + { + await vcopter.LockAsync(); + await vcopter.SetShowLEDAsync(false); + + } + + + return; + + + + + + + + + + + + + var firstCopter = _copterManager.Copters.First(); + + // Test TurnAsync. + //var latLng = GeographyUtils.CalcLatLngSomeMetersAway(firstCopter.Latitude, firstCopter.Longitude, 135, 10); + //await _formationController.TurnAsync(_copterManager.AcceptingControlCopters, latLng.Item1, latLng.Item2); + + // Test FlyToLatLngAsync. + //var copters = _copterManager.AcceptingControlCopters; + //var centerLat = copters.Average(c => c.Latitude); + //var centerLng = copters.Average(c => c.Longitude); + //var latDelta = 10 * GeographyUtils.MetersToLocalLat; + //var lngDelta = 10 * GeographyUtils.GetMetersToLocalLon(copters.First().Latitude); + //var targetLat = centerLat + latDelta; + //var targetLng = centerLng + lngDelta; + //await _formationController.FlyToLatLngAsync(copters, targetLat, targetLng); + + // Test FlyInCircleAsync. + //await _formationController.FlyInCircleAsync(_copterManager.AcceptingControlCopters, centerDirection: 180, radius: 10, loop: false); + + // Test FlyAroundCenterOfCoptersAsync. + //await _formationController.FlyAroundCenterOfCoptersAsync(_copterManager.AcceptingControlCopters); + + // Test FlyToLatLngAsync. + //var targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway(firstCopter.Latitude, firstCopter.Longitude, 135, 20); + //await _formationController.FlyToLatLngAsync(firstCopter, targetLatLng.Item1, targetLatLng.Item2); + + //firstCopter.LoiterTurns(1, 10); + + //var radius = await firstCopter.GetParamAsync("CIRCLE_RADIUS"); + + ////await firstCopter.SetParamAsync("CIRCLE_RADIUS", 1500); + ////var param = await firstCopter.GetParamAsync("CIRCLE_RADIUS"); + //// Alert.Show($"半径设置成功啦: {param}"); + + ////await firstCopter.SetParamAsync("CIRCLE_RATE", 30); + //var rate = await firstCopter.GetParamAsync("CIRCLE_RATE"); + + //Alert.Show($"半径: {radius} 角速度: {rate}"); + + //await firstCopter.SetMobileControlAsync(yaw: 90); + + //if (!_listeningMissionItemReceived) + //{ + // firstCopter.MissionItemReceived += (sender, e) => Alert.Show($"{e.Index} {e.Total} {(Protocols.MAVLink.MAV_CMD)e.Details.id}"); + // _listeningMissionItemReceived = true; + //} + //await firstCopter.RequestMissionListAsync(); + + var copter = firstCopter; + + ///* 写航线 */ + //// 任务总数。 + //await copter.SetMissionCountAsync(6).ConfigureAwait(false); + //// 起飞前准备。 + //await copter.WritePreTakeOffMissionAsync().ConfigureAwait(false); + //// 起飞。 + //await copter.WriteTakeOffMissionAsync().ConfigureAwait(false); + //// 不断自增的编号。 + //ushort index = 2; + //// 航点。 + //await copter.WriteWaypointMissionAsync(new EHLocation(copter).AddLatLngAlt(0.001, 0.002, 2), index++).ConfigureAwait(false); + //// 航点。 + //await copter.WriteWaypointMissionAsync(new EHLocation(copter).AddLatLngAlt(0.003, 0.002, 2), index++).ConfigureAwait(false); + //// 返航。 + //await copter.WriteReturnToLaunchMissionAsync(index++).ConfigureAwait(false); + //// 降落。 + //await copter.WriteLandMissionAsync(index++).ConfigureAwait(false); + + ///* 读航线 */ + // 监听“任务项已接收”事件。 + //(copter as EHCopter).MissionItemReceived += (sender, e) => Alert.Show($"{e.Mission.Sequence} {e.Mission.Latitude} {e.Mission.Command}"); + // 请求任务列表。 + var missions = await copter.RequestMissionListAsync(); + // Alert.Show(string.Join(Environment.NewLine, missions.Select(m => $"{m.Sequence}\t{m.Command}\t\t{m.Latitude}"))); + + //ICopter previousCopter = firstCopter; + //foreach (var item in _copterManager.Copters.Where(c => c != firstCopter)) + //{ + // item.Follow(previousCopter, keepYawDifference: false, keepFacingTarget: false); + // previousCopter = item; + //} + + //var missions = new Mission[] + //{ + // Mission.CreateWaypointMission(new EHLocation(firstCopter).AddLatLngAlt(0.0001, 0, 10)), + // Mission.CreateReturnToLaunchMission(), + // Mission.CreateLandMission() + //}; + //var result = await firstCopter.WriteMissionsAsync(missions); + //var result2 = await firstCopter.WriteMissionsAsync(missions); + //Debug.WriteLine($"{result1} {result2}"); + + //var missions = new Mission[] + //{ + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateWaypointMission(23.123, 113.123, 10), + // Mission.CreateReturnToLaunchMission(), + // Mission.CreateLandMission() + //}; + //var result = await firstCopter.WriteMissionListAsync(missions); + //MessageBox.Show($"The result of WriteMissions: {result}"); + + // 跟随测试 + /* + ICopter previousCopter = firstCopter; + foreach (var item in _copterManager.Copters.Where(c => c != firstCopter)) + { + item.Follow(previousCopter, keepYawDifference: false, keepFacingTarget: false); + previousCopter = item; + } + */ + await Task.WhenAll(_copterManager.AcceptingControlCopters.Select(async c => + { + + float gpsLed = await c.GetParamAsync("NOTI_GPSLED"); + if (gpsLed == 0.0f) + { + await LEDFlashAsync(c, true); + } + else + { + await LEDFlashAsync(c, false); + } + + // for (int jj = 0; jj < 5; jj++) + { + // await LEDFlashAsync(c, true); + // await c.SetParamAsync("THR_ALT_P", AltP); + // await c.SetParamAsync("WPNAV_ACCEL_Z", AltP); + // await c.SetParamAsync("WPNAV_ACCEL", AltP); + // await c.SetParamAsync("WPNAV_SPEED", AltP); + // await c.SetParamAsync("WPNAV_SPEED_DN", AltP); + // await c.SetParamAsync("WPNAV_SPEED_UP", AltP); + // await LEDFlashAsync(c, false); + // await LEDFlashAsync(c, true); + // await Task.Delay(500).ConfigureAwait(false); + + // await Task.Delay(1000).ConfigureAwait(false); + + // await LEDFlashAsync(c, true); + // await Task.Delay(1000).ConfigureAwait(false); + } + })); + })); + } + } + + /// + /// 读取串口号 + /// + private void LoadRTKcomvalue() + { + IniFiles inifilse = new IniFiles(); + RTKcomvalue = inifilse.IniReadvalue("Default", "RTKcomvalue"); + if (RTKcomvalue == "") RTKcomvalue = "COM6"; + } + + + /// + /// 保存上次成功的串口号 + /// + /// + private async Task SaveRTKcomvalue() + { + IniFiles inifilse = new IniFiles(); + inifilse.IniWritevalue("Default", "RTKcomvalue", RTKcomvalue); + await Task.Delay(1); + } + + private async Task LEDFlashAsync(ICopter copter, bool isOn) + { + // float gpsLed = await c.GetParamAsync("NOTI_GPSLED"); + float ledControl = 0.0f; + if (isOn) + { + ledControl = 1.0f; + } + var tasks = new Task[2]; + //tasks[0] = copter.SetParamAsync("NOTI_GPSLED", ledControl); + //tasks[1] = copter.SetParamAsync("NOTI_ARMLED", ledControl); + tasks[0] = Task.Run(async () => + { + try + { + await copter.SetParamAsync("NOTI_GPSLED", ledControl, 5000); + } + catch (TimeoutException e) + { + _logger.Log($"NOTI_GPSLED 超时, CopterId: {copter.Id}。"); + } + }); + tasks[1] = Task.Run(async () => + { + try + { + await copter.SetParamAsync("NOTI_ARMLED", ledControl, 5000); + } + catch (TimeoutException e) + { + _logger.Log($"NOTI_ARMLED 超时, CopterId: {copter.Id}。"); + } + }); + await Task.WhenAll(tasks).ConfigureAwait(false); + + } + + private bool _listeningMissionItemReceived; + + private ICommand _StopTaskCommand; + public ICommand StopTaskCommand + { + get + { + return _StopTaskCommand ?? (_StopTaskCommand = new RelayCommand(async () => + { + await _formationController.AllStop().ConfigureAwait(false); + })); + } + } + + + } +} diff --git a/Plane.FormationCreator/Views/ControlPanelView.xaml b/Plane.FormationCreator/Views/ControlPanelView.xaml index cf08c2e..0105a49 100644 --- a/Plane.FormationCreator/Views/ControlPanelView.xaml +++ b/Plane.FormationCreator/Views/ControlPanelView.xaml @@ -1,235 +1,238 @@ - - - - - - - - - - - - - - - - -