支持紧急返航

支持返回飞机错误
飞机有预解锁错误回显示黄色
支持新版低电电压参数
支持重启飞控
支持陀螺仪校准
This commit is contained in:
pxzleo 2024-03-26 22:06:52 +08:00
parent 36875bcdc2
commit af9a86dffd
16 changed files with 1889 additions and 1648 deletions

View File

@ -75,9 +75,16 @@
<lcnv:HeartbeatCountToBrushConverter x:Key="HeartbeatCountToBrushConverter" />
<lcnv:AppModeToVisibilityConverter x:Key="AppModeToVisibilityConverter" />
<lcnv:FlightTaskStatusToFillConverter x:Key="FlightTaskStatusToFillConverter" />
<lcnv:ErrorCodeToColorConverter x:Key="ErrorCodeToColorConverter" />
<lcnv:PrecheckToColorConverter x:Key="PrecheckToColorConverter" />
<lcnv:FlightTaskStatusAndTransitionToFillConverter x:Key="FlightTaskStatusAndTransitionToFillConverter" />
<lcnv:FlightTaskIsSelectedToEffectConverter x:Key="FlightTaskIsSelectedToEffectConverter" />
</Application.Resources>
</Application>

View File

@ -1,44 +1,87 @@
using Plane.Copters;
using Plane.FormationCreator.Formation;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace Plane.FormationCreator.Converters
{
public class HeartbeatCountToBrushConverter : IMultiValueConverter
{
private static SolidColorBrush _zeroBrush = new SolidColorBrush(Color.FromArgb(125, 125, 125, 125));
private static SolidColorBrush _oneBrush = Copter.DefaultBrush;
private static SolidColorBrush _FakeCopterBrush = Copter.DefaultFakeBrush;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == DependencyProperty.UnsetValue) return _zeroBrush;
var heartbeatCount = (ulong)values[0];
if (heartbeatCount % 2 == 0) return _zeroBrush;
if (values[1] is FakeCopter)
return _FakeCopterBrush;
if (values[1] is PLCopter)
return _oneBrush;
var copter = values[1] as Copter;
return copter == null ? _oneBrush : copter.Brush;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
using Plane.Copters;
using Plane.FormationCreator.Formation;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
namespace Plane.FormationCreator.Converters
{
public class HeartbeatCountToBrushConverter : IMultiValueConverter
{
private static SolidColorBrush _zeroBrush = new SolidColorBrush(Color.FromArgb(125, 125, 125, 125));
private static SolidColorBrush _zeroBrush_fault = new SolidColorBrush(Color.FromRgb(160, 140, 0));
private static SolidColorBrush _oneBrush = Copter.DefaultBrush;
private static SolidColorBrush _FakeCopterBrush = Copter.DefaultFakeBrush;
private static SolidColorBrush _PreCheckNopassBrush = Copter.YellowBrush;
private static SolidColorBrush _NoconnectedBrush = Copter.RedBrush;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == DependencyProperty.UnsetValue) return _zeroBrush;
var heartbeatCount = (ulong)values[0];
/* //绑定的是心跳,所以连接断开时不会调用这个转换器
//如果是真飞机,并且断开了,直接显示红色
if (values[1] is PLCopter)
{
var plcopter = values[1] as PLCopter;
if (!plcopter.CommModuleConnected)
return _NoconnectedBrush;
}
*/
//用于显示收到心跳的闪烁
if (heartbeatCount % 2 == 0)
{
//真飞机如果异常显示暗淡黄色
if (values[1] is PLCopter)
{
var plcopter = values[1] as PLCopter;
if (plcopter.CopterPreCheckPass)
return _zeroBrush;
else return _zeroBrush_fault;
}
else
return _zeroBrush;
}
if (values[1] is FakeCopter)
{
var fkcopter = values[1] as FakeCopter;
if (fkcopter.CopterPreCheckPass)
return _FakeCopterBrush;
else return _PreCheckNopassBrush;
}
if (values[1] is PLCopter)
{
var plcopter = values[1] as PLCopter;
if (plcopter.CopterPreCheckPass)
return _oneBrush;
else return _PreCheckNopassBrush;
}
var copter = values[1] as Copter;
return copter == null ? _oneBrush : copter.Brush;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View File

@ -1,69 +1,75 @@
using Plane.Copters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Communication;
using System.Threading;
using System.Windows.Media;
namespace Plane.FormationCreator.Formation
{
class Copter : PLCopter
{
public Copter(IConnection Connection, SynchronizationContext uiThreadContext) : base(Connection, uiThreadContext,false)
{
Brush = _brushes[NextBrushIndex()];
}
public Copter(IConnection Connection, SynchronizationContext uiThreadContext, double lat, double lng) : base(Connection, uiThreadContext, false)
{
Brush = _brushes[NextBrushIndex()];
RecordLat = lat;
RecordLng = lng;
Latitude = lat;
Longitude = lng;
//RaiseLocationChangedIfNeeded();
}
internal static SolidColorBrush BlueBrush { get; } = new SolidColorBrush(Color.FromRgb(28, 151, 234));
internal static SolidColorBrush RedBrush { get; } = new SolidColorBrush(Color.FromRgb(255, 100, 100));
internal static SolidColorBrush GreenBrush { get; } = new SolidColorBrush(Color.FromRgb(100, 255, 100));
internal static SolidColorBrush YellowBrush { get; } = new SolidColorBrush(Color.FromRgb(255, 215, 0));
static SolidColorBrush[] _brushes = new[]
{
new SolidColorBrush(Color.FromArgb(180, 255, 0, 0)),
new SolidColorBrush(Color.FromArgb(180, 235, 97, 0)),
new SolidColorBrush(Color.FromArgb(180, 255, 255, 0)),
new SolidColorBrush(Color.FromArgb(180, 0, 255, 0)),
new SolidColorBrush(Color.FromArgb(180, 0, 198, 255)),
new SolidColorBrush(Color.FromArgb(180, 0, 122, 204)),
new SolidColorBrush(Color.FromArgb(180, 174, 0, 255))
};
static int _brushIndex = 0;
static int NextBrushIndex()
{
return _brushIndex++ % _brushes.Length;
}
//真实飞机列表默认颜色
internal static SolidColorBrush DefaultBrush { get; } = GreenBrush;// new SolidColorBrush(Color.FromRgb(50, 205, 50));
//虚拟飞机列表默认颜色
internal static SolidColorBrush DefaultFakeBrush { get; } = BlueBrush;
private SolidColorBrush _Brush;
public SolidColorBrush Brush
{
get { return _Brush ?? DefaultBrush; }
set { Set(nameof(Brush), ref _Brush, value); }
}
}
}
using Plane.Copters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Communication;
using System.Threading;
using System.Windows.Media;
namespace Plane.FormationCreator.Formation
{
class Copter : PLCopter
{
public Copter(IConnection Connection, SynchronizationContext uiThreadContext) : base(Connection, uiThreadContext,false)
{
Brush = _brushes[NextBrushIndex()];
}
public Copter(IConnection Connection, SynchronizationContext uiThreadContext, double lat, double lng) : base(Connection, uiThreadContext, false)
{
Brush = _brushes[NextBrushIndex()];
RecordLat = lat;
RecordLng = lng;
Latitude = lat;
Longitude = lng;
//RaiseLocationChangedIfNeeded();
}
internal static SolidColorBrush BlueBrush { get; } = new SolidColorBrush(Color.FromRgb(28, 151, 234));
internal static SolidColorBrush RedBrush { get; } = new SolidColorBrush(Color.FromRgb(255, 100, 100));
internal static SolidColorBrush GreenBrush { get; } = new SolidColorBrush(Color.FromRgb(100, 255, 100));
internal static SolidColorBrush YellowBrush { get; } = new SolidColorBrush(Color.FromRgb(255, 215, 0));
static SolidColorBrush[] _brushes = new[]
{
new SolidColorBrush(Color.FromArgb(180, 255, 0, 0)),
new SolidColorBrush(Color.FromArgb(180, 235, 97, 0)),
new SolidColorBrush(Color.FromArgb(180, 255, 255, 0)),
new SolidColorBrush(Color.FromArgb(180, 0, 255, 0)),
new SolidColorBrush(Color.FromArgb(180, 0, 198, 255)),
new SolidColorBrush(Color.FromArgb(180, 0, 122, 204)),
new SolidColorBrush(Color.FromArgb(180, 174, 0, 255))
};
static int _brushIndex = 0;
static int NextBrushIndex()
{
return _brushIndex++ % _brushes.Length;
}
//真实飞机列表默认颜色
internal static SolidColorBrush DefaultBrush { get; } = GreenBrush;// new SolidColorBrush(Color.FromRgb(50, 205, 50));
//虚拟飞机列表默认颜色
internal static SolidColorBrush DefaultFakeBrush { get; } = BlueBrush;
private SolidColorBrush _Brush;
public SolidColorBrush Brush
{
get {
if (CopterPreCheckPass)
return _Brush ?? DefaultBrush;
else
return _Brush ?? YellowBrush;
}
set { Set(nameof(Brush), ref _Brush, value); }
}
}
}

View File

@ -26,6 +26,7 @@ using Newtonsoft.Json.Linq;
using GMap.NET.MapProviders;
using GMap.NET;
using static Plane.FormationCreator.CalculationLogLatDistance;
using Plane.CopterManagement;
namespace Plane.FormationCreator.Formation
{
@ -412,6 +413,13 @@ namespace Plane.FormationCreator.Formation
get { return _TaskState; }
private set { Set(nameof(TaskState), ref _TaskState, value); }
}
//真实飞行任务状态
private TasksStatus _TaskState_real = TasksStatus.Stop;
public TasksStatus TaskState_real
{
get { return _TaskState_real; }
private set { Set(nameof(TaskState_real), ref _TaskState_real, value);}
}
public event EventHandler<FlightTaskAddedEventArgs> TaskAdded;
public event EventHandler<FlightTaskDeledEventArgs> TaskDeled;
@ -601,6 +609,7 @@ namespace Plane.FormationCreator.Formation
/// <summary>
/// 起始点作为参考,设置起始点后飞行写入的数据将为相对坐标
/// </summary>
@ -796,7 +805,7 @@ namespace Plane.FormationCreator.Formation
Pause();
//等待暂停或2s超时(80*25ms)
int k = 0;
while ((TaskState != TasksStatus.Paused) || (k > 80))
while ((TaskState != TasksStatus.Paused) && (k < 80))
{
await Task.Delay(25).ConfigureAwait(false);
k++;
@ -2227,7 +2236,7 @@ namespace Plane.FormationCreator.Formation
}
//新开线程异步调用ABypassB并等待返回
public async Task<(List<List<FlightRouteV2.Vector3>>,bool)> ABypassBAsync(FlightRouteV2.Vector3[] aVecs, FlightRouteV2.Vector3[] bVecs)
public async Task<(List<List<FlightRouteV2.Vector3>>,bool)> ABypassBAsync(FlightRouteV2.Vector3[] aVecs, FlightRouteV2.Vector3[] bVecs, List<int> mappingId = null)
{
List<List<FlightRouteV2.Vector3>> ret = null;
bool isPasstmp = false;
@ -2235,7 +2244,7 @@ namespace Plane.FormationCreator.Formation
var task = Task.Run(() =>
{
cts = new CancellationTokenSource();
ret = FlyVecFun.ABypassB(aVecs, bVecs, Routecallback, Cronograma, cts.Token, out isPasstmp);
ret = FlyVecFun.ABypassB(aVecs, bVecs, Routecallback, Cronograma, cts.Token, out isPasstmp, mappingId);
});
try
{
@ -2277,7 +2286,7 @@ namespace Plane.FormationCreator.Formation
var task = Task.Run(() =>
{
ret = FlyVecFun.CollisionLayer(aVecs, bVecs, taskname_a, taskname_b, Routecallback);
ret = FlyVecFun.CollisionLayer(aVecs, bVecs, Routecallback);
});
try
{
@ -2408,7 +2417,7 @@ namespace Plane.FormationCreator.Formation
/// <summary>
/// 自动生成航线2D和3D都用这个-------V2版使用新的碰撞检测和绕行用flybase.cs库只用于新版固件--------------
/// </summary>
/// <param name="Is3d">3D计算</param>
/// <param name="Is3d">2D/3D计算</param>
/// <param name="Ischange">是否改变线路的结束点顺序--返回起飞点航线不能交换</param>
/// <param name="Is3dstagger">3D是否自动插入拉开层用于2D画面回起飞矩阵拉开2D画面</param>
public async Task OptimizeRouteMeterV2(bool Is3d = false, bool Ischange = true,bool Is3dstagger=false)
@ -2417,6 +2426,10 @@ namespace Plane.FormationCreator.Formation
Dictionary<int, Point3D> prevTaskPoint = new Dictionary<int, Point3D>();
var stopWatch = new Stopwatch();
stopWatch.Start();
//ID映射列表
List<int> mappingId = new List<int>();
//设置随机数种子
FlyVecFun.RandomSeed = (int)DateTime.Now.Ticks;
@ -2435,6 +2448,8 @@ namespace Plane.FormationCreator.Formation
var prevInfo = Tasks[SelectedTaskIndex - 1].SingleCopterInfos[i];
Point3D prevLoc = new Point3D(prevInfo.X * 100, prevInfo.TargetAlt * 100, prevInfo.Y * 100);
prevTaskPoint.Add(i, prevLoc);
//3D计算需要ID映射
mappingId.Add(int.Parse(_copterManager.Copters[i].Id));
}
string taskname_a = SelectedTaskIndex.ToString() + Tasks[SelectedTaskIndex - 1].TaskCnName;
string taskname_b = (SelectedTaskIndex+1).ToString()+SelectedTask.TaskCnName;
@ -2473,7 +2488,9 @@ namespace Plane.FormationCreator.Formation
if (Is3d)
{
bool isPass = false;
var result= await ABypassBAsync(aVecs, bVecs);
var result= await ABypassBAsync(aVecs, bVecs, mappingId);
List<List<FlightRouteV2.Vector3>> flyret = result.Item1;
isPass= result.Item2;
if ((flyret.Count == 0)&&(!isPass))
@ -2483,6 +2500,12 @@ namespace Plane.FormationCreator.Formation
{
Message.Show($"任务{SelectedTaskIndex + 1}无法直接生成3D航线尝试拉开画面");
cVecs = await NormalPullsync(aVecs, bVecs);
if (cVecs == null)
{
Message.Show($"任务不满足拉开条件,退出");
return;
}
Message.Show($"任务{SelectedTaskIndex + 1}后插入拉开层...");
//插入错层航点
SelectTask(SelectedTaskIndex - 1);
@ -2498,7 +2521,7 @@ namespace Plane.FormationCreator.Formation
SetTaskFlytime(SelectedTaskIndex);
//选到最后一个航点
SelectTask(SelectedTaskIndex + 1);
var result1= await ABypassBAsync(cVecs, bVecs);
var result1= await ABypassBAsync(cVecs, bVecs, mappingId);
flyret = result1.Item1;
isPass = result1.Item2;
}
@ -3260,9 +3283,64 @@ namespace Plane.FormationCreator.Formation
}
}
//任务飞行时长ms
private TimeSpan _taskflyTime ;
public TimeSpan taskflyTime
{
get { return _taskflyTime; }
set { Set(nameof(taskflyTime), ref _taskflyTime, value); }
}
//真实任务飞行时长ms
private TimeSpan _taskflyTime_real;
public TimeSpan taskflyTime_real
{
get { return _taskflyTime_real; }
set { Set(nameof(taskflyTime_real), ref _taskflyTime_real, value); }
}
private DateTime _taskStartTime;
private DateTime _taskStartTime_real;
public DateTime TaskStartTime_real
{
get { return _taskStartTime_real; }
}
public bool RealRunTask(DateTime taskStartTime)
{
if (TaskState_real == TasksStatus.Stop)
//根据传入时间设置真实起飞时间
{
_taskStartTime_real = taskStartTime;
TaskState_real = TasksStatus.Running;
Message.Show($"{taskStartTime.ToString("HH:mm:ss")}:真实任务开始");
return true;
}else
Message.Show($"任务已经开始");
return false;
}
public void RealResetTask()
{
TaskState_real = TasksStatus.Stop;
}
public bool SimRunTask(DateTime taskStartTime)
{
if (TaskState== TasksStatus.Stop)
//根据传入时间设置真实起飞时间
{
_taskStartTime = taskStartTime;
Message.Show($"{taskStartTime.ToString("HH:mm:ss")}:默认任务开始");
return true;
} else
Message.Show($"任务已经开始");
return false;
}
TimeSpan timeSpan;
public DateTime taskStartTime;
public async Task RunTaskAsync()
{
if (Tasks.Count == 0) return;
@ -3290,7 +3368,12 @@ namespace Plane.FormationCreator.Formation
if (CurrentRunningTaskIndex == 0)
{
taskStartTime = DateTime.Now;
if (!SimRunTask(DateTime.Now))
{
Alert.Show($"模拟任务已经开始,请先停止任务!");
return;
}
Message.Show($"{DateTime.Now.ToString("HH:mm:ss")}:任务开始");
}
@ -3307,13 +3390,16 @@ namespace Plane.FormationCreator.Formation
await RunAsync();
taskflyTime = DateTime.Now - _taskStartTime;
if ((IsPaused ?? false) == false)
{
timeSpan = DateTime.Now - taskStartTime;
Message.Show($"{DateTime.Now.ToString("HH:mm:ss")}:任务结束");
Message.Show($"总时长 = {timeSpan.Minutes}分{timeSpan.Seconds}秒");
Message.Show($"总时长 = {taskflyTime.Minutes}分{taskflyTime.Seconds}秒");
}
else
Message.Show($"任务暂停,总时长 = {taskflyTime.TotalSeconds}秒");
}
/// <summary>
/// 开始运行模拟任务
@ -3330,12 +3416,13 @@ namespace Plane.FormationCreator.Formation
task.Status = FlightTaskStatus.Stop;
}
AppEx.Current.AppMode = AppMode.RunningTasks;
StartAvoidingCrash(); //开始碰撞检测
//告诉所有飞机开始任务--模拟飞机不计算起飞延迟直接传0
foreach (var copter in _copterManager.Copters)
await copter.MissionStartAsync(0, 0, 0, 0, 0);
TaskState = TasksStatus.Running;
TaskState = TasksStatus.Running;
StartAvoidingCrash(); //开始碰撞检测
for (int i = CurrentRunningTaskIndex; i < Tasks.Count; i++)
{
var task = Tasks[i];
@ -3474,6 +3561,7 @@ namespace Plane.FormationCreator.Formation
{
rettaskindex = i;
taskflytime = rettime - starttime;
break;
}
starttime += flyedtasktime;
}
@ -3495,7 +3583,7 @@ namespace Plane.FormationCreator.Formation
curLoc = TaskFlyLoc(copterprvLoc, coptercurLoc, taskflytime, Tasks[rettaskindex].FlytoTime);
}
else //正在悬停
curLoc = new PLLocation(curinfo.TargetLat, curinfo.TargetLng, 0);
curLoc = new PLLocation(curinfo.TargetLat, curinfo.TargetLng, curinfo.TargetAlt);
curTaskPoint.Add(i, curLoc);
if (curinfo.TargetLat > taskmaxlat)
@ -3557,15 +3645,22 @@ namespace Plane.FormationCreator.Formation
/// <summary>
/// 开始碰撞检测
/// </summary>
private async void StartAvoidingCrash()
{
await Task.Factory.StartNew(AvoidCrashtoshow);
await Task.Factory.StartNew(LoopToAvoidCrash);
}
/// <summary>
/// 将碰撞显示到UI
/// </summary>
private async void AvoidCrashtoshow()
{
while (IsPaused == false)
Message.Show("开始碰撞检测");
while (TaskState != TasksStatus.Stop) //IsPaused == false
{
try
{
@ -3585,10 +3680,14 @@ namespace Plane.FormationCreator.Formation
await Task.Delay(100).ConfigureAwait(false);
}
}
Message.Show("开始碰撞检测停止");
}
/// <summary>
/// 循环检测碰撞
/// </summary>
private async void LoopToAvoidCrash()
{
while (IsPaused == false)
while (TaskState != TasksStatus.Stop)
{
try
{

View File

@ -183,6 +183,10 @@ namespace Plane.FormationCreator.Formation
await info.Copter.HoverAsync();
return;
}
if (_flightTaskManager.IsEmergencyRet == true)
{
return;
}
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
}

View File

@ -112,6 +112,8 @@ namespace Plane.FormationCreator.Formation
info.TargetLng = info.Copter.Longitude;
//info.Copter.takeOffTargetAltitude = takeOffAlt;
FlightTask task = _flightTaskManager.CurrentRunningTask;
if (task==null)
return;
float takeflytime = task.TakeOffTime - info.TakeOffWaitTime;
//飞行目标,开始往上飞
await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt, takeflytime, 1); //秒

View File

@ -1,56 +1,65 @@
using Plane.FormationCreator.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Plane.FormationCreator
{
/// <summary>
/// ModifyParam.xaml 的交互逻辑
/// </summary>
public partial class ModifyParam : Window
{
public bool LoadParam = false;
public ModifyParam()
{
InitializeComponent();
// if (!VersionControl.IsFullVersion)
// {
// hide_panel.Visibility = Visibility.Collapsed;
// textParamName.IsReadOnly = true;
// btnLoad.Visibility = Visibility.Collapsed;
//
// label.Visibility = Visibility.Collapsed;
// textParamName.Visibility = Visibility.Collapsed;
// }
}
private void btnModify_Click(object sender, RoutedEventArgs e)
{
LoadParam = false;
this.DialogResult = true;
}
private void Modify_Select(object sender, RoutedEventArgs e)
{
textParamName.Text = ((Button)sender).Tag.ToString();
textParamName_cn.Text = ((Button)sender).Content.ToString();
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
LoadParam = true;
this.DialogResult = true;
}
}
}
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Plane.FormationCreator
{
/// <summary>
/// ModifyParam.xaml 的交互逻辑
/// </summary>
public partial class ModifyParam : Window
{
public bool LoadParam = false;
public ModifyParam()
{
InitializeComponent();
// if (!VersionControl.IsFullVersion)
// {
// hide_panel.Visibility = Visibility.Collapsed;
// textParamName.IsReadOnly = true;
// btnLoad.Visibility = Visibility.Collapsed;
//
// label.Visibility = Visibility.Collapsed;
// textParamName.Visibility = Visibility.Collapsed;
// }
}
private void btnModify_Click(object sender, RoutedEventArgs e)
{
LoadParam = false;
this.DialogResult = true;
}
private void Modify_Select(object sender, RoutedEventArgs e)
{
Formation.CopterManager _copterManager = ServiceLocator.Current.GetInstance<Formation.CopterManager>();
String strParamName = ((Button)sender).Tag.ToString();
if (strParamName == "FS_BATT_VOLTAGE")
{
if (_copterManager.FC_VER_NO >= 3)
strParamName = "BATT_LOW_VOLT";
}
textParamName.Text = strParamName;
textParamName_cn.Text = ((Button)sender).Content.ToString();
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
LoadParam = true;
this.DialogResult = true;
}
}
}

View File

@ -166,6 +166,8 @@
<Compile Include="AppEx.cs" />
<Compile Include="AppConfig.cs" />
<Compile Include="Converters\AppModeToVisibilityConverter.cs" />
<Compile Include="Converters\PrecheckToColorConverter.cs" />
<Compile Include="Converters\ErrorCodeToColorConverter.cs" />
<Compile Include="Converters\FlightTaskIsSelectedToEffectConverter.cs" />
<Compile Include="Converters\FlightTaskStatusAndTransitionToFillConverter.cs" />
<Compile Include="Converters\FlightTaskStatusToFillConverter.cs" />

View File

@ -1,222 +1,263 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Plane.CommunicationManagement;
using Plane.CopterManagement;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Windows.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Plane.FormationCreator.ViewModels
{
public class CalibrationViewModel : ViewModelBase
{
CommModuleManager commModule = CommModuleManager.Instance;
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private string _AccelerometerTips;
public string AccelerometerTips
{
get
{
switch (AccelerometerState)
{
case AccelerometerStates.Idle:
_AccelerometerTips = "点击“开始校准”后,开始校准加速计";
break;
case AccelerometerStates.Front:
_AccelerometerTips = "亮紫色: 飞机水平放置(Front)";
break;
case AccelerometerStates.Left:
_AccelerometerTips = "亮黄色:飞机左侧接触地面竖立放置(Left)";
break;
case AccelerometerStates.Right:
_AccelerometerTips = "亮青色:飞机右侧接触地面竖立放置(Right)";
break;
case AccelerometerStates.Down:
_AccelerometerTips = "紫色:飞机机头向下接触地面竖立放置(Down)";
break;
case AccelerometerStates.Up:
_AccelerometerTips = "黄色:飞机机尾向下接触地面竖立放置(Up)";
break;
case AccelerometerStates.Back:
_AccelerometerTips = "青色:飞机翻过来水平放置(Back)";
break;
}
return _AccelerometerTips;
}
}
private string _AccelerometerBtnText = "开始校准";
public string AccelerometerBtnText
{
get
{
switch (AccelerometerState)
{
case AccelerometerStates.Idle:
_AccelerometerBtnText = "开始校准";
break;
default:
_AccelerometerBtnText = "完成";
break;
}
return _AccelerometerBtnText;
}
}
//校准加速计的状态
public enum AccelerometerStates
{
Idle = 0,
Front = 1,
Left = 2,
Right = 3,
Down = 4,
Up = 5,
Back = 6
}
private AccelerometerStates _AccelerometerState = AccelerometerStates.Idle;
public AccelerometerStates AccelerometerState
{
get { return _AccelerometerState; }
set
{
Set(nameof(AccelerometerState), ref _AccelerometerState, value);
RaisePropertyChanged(nameof(AccelerometerBtnText));
RaisePropertyChanged(nameof(AccelerometerTips));
}
}
/// <summary>
/// 开始校准加速计
/// </summary>
private ICommand _CalibrationAccelerometerStartCommand;
public ICommand CalibrationAccelerometerStartCommand
{
get
{
return _CalibrationAccelerometerStartCommand ?? (_CalibrationAccelerometerStartCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
await commModule.DoStartPreflightCompassAsync(_copterManager.SelectedCopters);
}));
}
}
/// <summary>
/// 校准加速计下一步
/// </summary>
private ICommand _CalibrationAccelerometerNextCommand;
public ICommand CalibrationAccelerometerNextCommand
{
get
{
return _CalibrationAccelerometerNextCommand ?? (_CalibrationAccelerometerNextCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
await commModule.DoNextPreflightCompassAsync(_copterManager.SelectedCopters);
}));
}
}
private int _CompassPercent;
public int CompassPercent
{
get { return _CompassPercent; }
set
{
Set(nameof(CompassPercent), ref _CompassPercent, value);
}
}
public bool IsCalibration { get; set; }
/// <summary>
/// 校准指南针
/// </summary>
private ICommand _CalibrationCompassCommand;
public ICommand CalibrationCompassCommand
{
get
{
return _CalibrationCompassCommand ?? (_CalibrationCompassCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
// ICopter copter = _copterManager.SelectedCopters.FirstOrDefault();
//
// short copterId = short.Parse(copter.Name);
Message.Show("开始校准指南针");
await commModule.DoCalibrationCompassAsync(_copterManager.SelectedCopters);
await Task.Delay(50).ConfigureAwait(false);
/*
IsCalibration = true;
CompassPercent = 0;
int State = 0; //4成功 5失败 todo 改为枚举
while (IsCalibration && CompassPercent <= 100)
{
//两个255的时候表示 当前预留字节代表的意思是校准
if (copter.Retain[2] == 255 && copter.Retain[3] == 255)
{
CompassPercent = copter.Retain[0];
State = copter.Retain[1];
if (State == 4 || State == 5)
break;
}
await Task.Delay(100);
}
switch (State)
{
case 4:
Alert.Show($"校准成功,请重新上电{copterId}号", "指南针");
break;
case 5:
Alert.Show("校准失败", "指南针");
break;
default:
break;
}
IsCalibration = false;
*/
}));
}
}
private ICommand _CancelCalibrationCompassCommand;
public ICommand CancelCalibrationCompassCommand
{
get
{
return _CancelCalibrationCompassCommand ?? (_CancelCalibrationCompassCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 1) return;
ICopter copter = _copterManager.SelectedCopters.FirstOrDefault();
short copterId = short.Parse(copter.Name);
await commModule.DoCancelCalibrationCompassAsync(copterId);
IsCalibration = false;
Alert.Show("放弃校准", "指南针");
}));
}
}
}
}
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Plane.CommunicationManagement;
using Plane.CopterManagement;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Windows.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Plane.FormationCreator.ViewModels
{
public class CalibrationViewModel : ViewModelBase
{
CommModuleManager commModule = CommModuleManager.Instance;
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private string _AccelerometerTips;
public string AccelerometerTips
{
get
{
switch (AccelerometerState)
{
case AccelerometerStates.Idle:
_AccelerometerTips = "点击“开始校准”后,开始校准加速计";
break;
case AccelerometerStates.Front:
_AccelerometerTips = "亮紫色: 飞机水平放置(Front)";
break;
case AccelerometerStates.Left:
_AccelerometerTips = "亮黄色:飞机左侧接触地面竖立放置(Left)";
break;
case AccelerometerStates.Right:
_AccelerometerTips = "亮青色:飞机右侧接触地面竖立放置(Right)";
break;
case AccelerometerStates.Down:
_AccelerometerTips = "紫色:飞机机头向下接触地面竖立放置(Down)";
break;
case AccelerometerStates.Up:
_AccelerometerTips = "黄色:飞机机尾向下接触地面竖立放置(Up)";
break;
case AccelerometerStates.Back:
_AccelerometerTips = "青色:飞机翻过来水平放置(Back)";
break;
}
return _AccelerometerTips;
}
}
private string _AccelerometerBtnText = "开始校准";
public string AccelerometerBtnText
{
get
{
switch (AccelerometerState)
{
case AccelerometerStates.Idle:
_AccelerometerBtnText = "开始校准";
break;
default:
_AccelerometerBtnText = "完成";
break;
}
return _AccelerometerBtnText;
}
}
//校准加速计的状态
public enum AccelerometerStates
{
Idle = 0,
Front = 1,
Left = 2,
Right = 3,
Down = 4,
Up = 5,
Back = 6
}
private AccelerometerStates _AccelerometerState = AccelerometerStates.Idle;
public AccelerometerStates AccelerometerState
{
get { return _AccelerometerState; }
set
{
Set(nameof(AccelerometerState), ref _AccelerometerState, value);
RaisePropertyChanged(nameof(AccelerometerBtnText));
RaisePropertyChanged(nameof(AccelerometerTips));
}
}
/// <summary>
/// 开始校准加速计
/// </summary>
private ICommand _CalibrationAccelerometerStartCommand;
public ICommand CalibrationAccelerometerStartCommand
{
get
{
return _CalibrationAccelerometerStartCommand ?? (_CalibrationAccelerometerStartCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
await commModule.DoStartPreflightCompassAsync(_copterManager.SelectedCopters);
}));
}
}
/// <summary>
/// 校准加速计下一步
/// </summary>
private ICommand _CalibrationAccelerometerNextCommand;
public ICommand CalibrationAccelerometerNextCommand
{
get
{
return _CalibrationAccelerometerNextCommand ?? (_CalibrationAccelerometerNextCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
await commModule.DoNextPreflightCompassAsync(_copterManager.SelectedCopters);
}));
}
}
private int _CompassPercent;
public int CompassPercent
{
get { return _CompassPercent; }
set
{
Set(nameof(CompassPercent), ref _CompassPercent, value);
}
}
public bool IsCalibration { get; set; }
/// <summary>
/// 重启飞控
/// </summary>
private ICommand _RestartFCCommand;
public ICommand RestartFCCommand
{
get
{
return _RestartFCCommand ?? (_RestartFCCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
Message.Show("重启飞控");
await commModule.DoRestartFCAsync(_copterManager.SelectedCopters);
await Task.Delay(50).ConfigureAwait(false);
}));
}
}
/// <summary>
/// 陀螺仪校准
/// </summary>
private ICommand _CalibrationPreflightCommand;
public ICommand CalibrationPreflightCommand
{
get
{
return _CalibrationPreflightCommand ?? (_CalibrationPreflightCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
Message.Show("开始校准陀螺仪");
await commModule.DoCalibrationPreflightAsync(_copterManager.SelectedCopters);
await Task.Delay(50).ConfigureAwait(false);
}));
}
}
/// <summary>
/// 校准指南针
/// </summary>
private ICommand _CalibrationCompassCommand;
public ICommand CalibrationCompassCommand
{
get
{
return _CalibrationCompassCommand ?? (_CalibrationCompassCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 0) return;
// ICopter copter = _copterManager.SelectedCopters.FirstOrDefault();
//
// short copterId = short.Parse(copter.Name);
Message.Show("开始校准指南针");
await commModule.DoCalibrationCompassAsync(_copterManager.SelectedCopters);
await Task.Delay(50).ConfigureAwait(false);
/*
IsCalibration = true;
CompassPercent = 0;
int State = 0; //4成功 5失败 todo 改为枚举
while (IsCalibration && CompassPercent <= 100)
{
//两个255的时候表示 当前预留字节代表的意思是校准
if (copter.Retain[2] == 255 && copter.Retain[3] == 255)
{
CompassPercent = copter.Retain[0];
State = copter.Retain[1];
if (State == 4 || State == 5)
break;
}
await Task.Delay(100);
}
switch (State)
{
case 4:
Alert.Show($"校准成功,请重新上电{copterId}号", "指南针");
break;
case 5:
Alert.Show("校准失败", "指南针");
break;
default:
break;
}
IsCalibration = false;
*/
}));
}
}
private ICommand _CancelCalibrationCompassCommand;
public ICommand CancelCalibrationCompassCommand
{
get
{
return _CancelCalibrationCompassCommand ?? (_CancelCalibrationCompassCommand = new RelayCommand(async () =>
{
if (_copterManager.SelectedCopters.Count() == 1) return;
ICopter copter = _copterManager.SelectedCopters.FirstOrDefault();
short copterId = short.Parse(copter.Name);
await commModule.DoCancelCalibrationCompassAsync(copterId);
IsCalibration = false;
Alert.Show("放弃校准", "指南针");
}));
}
}
}
}

View File

@ -394,7 +394,21 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private ICommand _ResetRealMissionCommand;
public ICommand ResetRealMissionCommand
{
get
{
return _ResetRealMissionCommand ?? (_ResetRealMissionCommand = new RelayCommand(async () =>
{
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
_flightTaskManager.RealResetTask();
AllowMissionStart = true;
}));
}
}
private ICommand _EmergencyRetCommand;
public ICommand EmergencyRetCommand
{
@ -402,23 +416,45 @@ namespace Plane.FormationCreator.ViewModels
{
return _EmergencyRetCommand ?? (_EmergencyRetCommand = new RelayCommand(async () =>
{
if (Alert.Show("您确定要紧急返航吗?紧急返航可能导致飞行器碰撞!!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
!= MessageBoxResult.OK)
return; //计算当前图案中心点,起飞图案中心点,图案距离起飞图案中心点最近距离
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
if (_flightTaskManager.Tasks.Count==0)
{
Alert.Show("没有航点无法紧急返航!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if ((_flightTaskManager.TaskState_real == TasksStatus.Stop)
&&((_flightTaskManager.IsPaused ?? false) == false))
{
Alert.Show("先暂停任务!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
//if (Alert.Show("您确定要紧急返航吗?紧急返航可能导致飞行器碰撞!!!!", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
// != MessageBoxResult.OK)
// return;
//计算当前图案中心点,起飞图案中心点,图案距离起飞图案中心点最近距离
//计算无人机返航方向和最近的飞机距离
PLLocation takeoffcentloc;
PLLocation taskcentloc;
double mindistance; //单位米
bool overlapping; //图案否重叠
int rettime= (int)(DateTime.Now - _flightTaskManager.taskStartTime).TotalSeconds;
int rettime=0;
if (_flightTaskManager.TaskState_real!= TasksStatus.Stop)
//计算实际飞行时间
rettime = (int)(DateTime.UtcNow - _flightTaskManager.TaskStartTime_real).TotalSeconds;
else
if (_flightTaskManager.TaskState!= TasksStatus.Stop)
//计算模拟飞行时间
rettime = (int)_flightTaskManager.taskflyTime.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);
@ -544,7 +580,8 @@ namespace Plane.FormationCreator.ViewModels
await Task.Delay(1000).ConfigureAwait(false);
}
await Task.Delay(100);
AllowMissionStart = true;
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
AllowMissionStart = (_flightTaskManager.TaskState_real == TasksStatus.Stop);
/*
await Task.WhenAll(_copterManager.Copters.Select(async c => {
@ -1440,9 +1477,22 @@ namespace Plane.FormationCreator.ViewModels
Alert.Show("作为参照的原点未设置,无法开始任务!", "提示");
return;
}
if (_flightTaskManager.Tasks.Count == 0 )
{
if (Alert.Show("没有导入任务,紧急返航功能不能使用,继续吗?", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
!= MessageBoxResult.OK)
return;
}
//飞机用UTC时间日志用本地时间记录
DateTime MissionTime = DateTime.UtcNow.AddSeconds(5);
DateTime MissionTime_log = DateTime.Now.AddSeconds(5);
if (!_flightTaskManager.RealRunTask(MissionTime))
{
Alert.Show("任务已经开始,请先重设任务!", "提示");
return;
}
AllowMissionStart = false;
Message.Show("任务开始:" + MissionTime_log.ToString());
//循环3次 发送起飞命令 避免通信问题
for (int i = 0; i < 20; i++) //20

View File

@ -959,8 +959,8 @@ namespace Plane.FormationCreator.ViewModels
return _OptimizeRouteCommandRet ?? (_OptimizeRouteCommandRet = new RelayCommand<int>(async =>
{
if (_copterManager.FC_VER_NO >= 3)
//3D计算不改变ID可以错层
_flightTaskManager.OptimizeRouteMeter(false, false, true); //采用米计算逻辑用3D生成不改变ID可拉开层(2D回起飞矩阵专用)
//2D计算不改变ID不用错层
_flightTaskManager.OptimizeRouteMeter(false, false, false); //采用米计算逻辑用3D生成不改变ID可拉开层(2D回起飞矩阵专用)
else
_flightTaskManager.OptimizeRouteMeter(false, false); //采用米计算逻辑用2D生成不改变ID不拉开层
@ -978,7 +978,7 @@ namespace Plane.FormationCreator.ViewModels
{
if (_copterManager.FC_VER_NO >= 3)
//3D计算不改变ID可以错层
_flightTaskManager.OptimizeRouteMeter(true, false, false); //采用米计算逻辑用3D生成不改变ID拉开层(3D回起飞矩阵专用)
_flightTaskManager.OptimizeRouteMeter(true, false, true); //采用米计算逻辑用3D生成不改变ID拉开层(3D回起飞矩阵专用,结束必须是矩阵)
else
_flightTaskManager.OptimizeRouteMeter(false, false); //采用米计算逻辑用2D生成不改变ID不拉开层

View File

@ -1,40 +1,44 @@
<Window x:Class="Plane.FormationCreator.Views.CalibrationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="校准" Height="320" Width="450">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70*"/>
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<StackPanel Margin="10" >
<Label Content="加速计" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="开始校准" Width="100" Margin="10, 0"
Command="{Binding CalibrationAccelerometerStartCommand}"/>
<Button Content="下一步" Width="100" Margin="10, 0"
Command="{Binding CalibrationAccelerometerNextCommand}"/>
</WrapPanel>
<Label Margin="0,10" Content="亮紫色:飞机水平放置(Front)&#13;亮黄色:飞机左侧接触地面竖立放置(Left)&#13;亮青色:飞机右侧接触地面竖立放置(Right)&#13;紫色:飞机机头向下接触地面竖立放置(Down)&#13;黄色:飞机机尾向下接触地面竖立放置(Up)&#13;青色:飞机翻过来水平放置(Back)" HorizontalContentAlignment="Center"/>
</StackPanel>
<StackPanel Grid.Row="1" Margin="10,0,10,10">
<Label Content="指南针" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="开始校准" Width="100" Margin="10, 0"
Command="{Binding CalibrationCompassCommand}"/>
<Button Content="放弃校准" Width="100" Margin="10, 0"
Command="{Binding CancelCalibrationCompassCommand}" Visibility="Collapsed"/>
</WrapPanel>
<ProgressBar Margin="0,20" Height="18" Width="220" Value="{Binding CompassPercent, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Grid>
</Window>
<Window x:Class="Plane.FormationCreator.Views.CalibrationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
mc:Ignorable="d"
WindowStartupLocation="CenterScreen"
Title="校准" Height="329" Width="455">
<Grid Margin="0,0,0,7">
<Grid.RowDefinitions>
<RowDefinition Height="70*"/>
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<StackPanel Margin="10" >
<Label Content="加速计" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="开始校准" Width="100" Margin="10, 0"
Command="{Binding CalibrationAccelerometerStartCommand}"/>
<Button Content="下一步" Width="100" Margin="10, 0"
Command="{Binding CalibrationAccelerometerNextCommand}"/>
</WrapPanel>
<Label Margin="0,10" Content="亮紫色:飞机水平放置(Front)&#13;亮黄色:飞机左侧接触地面竖立放置(Left)&#13;亮青色:飞机右侧接触地面竖立放置(Right)&#13;紫色:飞机机头向下接触地面竖立放置(Down)&#13;黄色:飞机机尾向下接触地面竖立放置(Up)&#13;青色:飞机翻过来水平放置(Back)" HorizontalContentAlignment="Center"/>
</StackPanel>
<StackPanel Grid.Row="1" Margin="10,0,10,10">
<Label Content="其他" Margin="0,0,0,10" FontWeight="Bold" FontSize="14"/>
<WrapPanel HorizontalAlignment="Center">
<Button Content="放弃校准" Width="100" Margin="10, 0"
Command="{Binding CancelCalibrationCompassCommand}" Visibility="Collapsed"/>
<Button Content="校准指南针" Width="120"
Command="{Binding CalibrationCompassCommand}"/>
<Button Content="校准陀螺仪" Width="120" Margin="20, 0"
Command="{Binding CalibrationPreflightCommand}"/>
<Button Content="重启飞控" Width="100" Margin="10, 0"
Command="{Binding RestartFCCommand}"/>
</WrapPanel>
<ProgressBar Margin="0,20" Height="18" Width="220" Value="{Binding CompassPercent, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Grid>
</Window>

View File

@ -202,7 +202,9 @@
Command="{Binding AllLandCommand}" />
<Button Content="紧急返航"
Command="{Binding EmergencyRetCommand}" />
<Button Content="重设任务"
Command="{Binding ResetRealMissionCommand}" />
</WrapPanel>
</StackPanel>

View File

@ -1,359 +1,331 @@
<UserControl x:Class="Plane.FormationCreator.Views.CopterInfoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
xmlns:ec="clr-namespace:Plane.Copters;assembly=PlaneGcsSdk_Private_NET46"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
d:DataContext="{d:DesignInstance Type=ec:FakeCopter, IsDesignTimeCreatable=True}">
<UserControl.Resources>
<!--笔刷-->
<LinearGradientBrush x:Key="SliderBackground" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#59ccfc"/>
<GradientStop Offset="0.5" Color="#00b3fe"/>
<GradientStop Offset="1" Color="#59ccfc"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="SliderThumb" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFD9D3E8"/>
<!--<GradientStop Offset="1" Color="#dfdfdf"/>-->
</LinearGradientBrush>
<LinearGradientBrush x:Key="SliderText" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#7cce45"/>
<GradientStop Offset="1" Color="#4ea017"/>
</LinearGradientBrush>
<!--Slider模板-->
<Style x:Key="Slider_RepeatButton" TargetType="RepeatButton">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="{StaticResource SliderBackground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_RepeatButton1" TargetType="RepeatButton">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_Thumb" TargetType="Thumb">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource SliderBackground}"/>
<Border Grid.ColumnSpan="2" CornerRadius="4" Background="{StaticResource SliderThumb}" Width="15">
<!--<TextBlock Text="||" HorizontalAlignment="Center" VerticalAlignment="Center"/>-->
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_CustomStyle" TargetType="Slider">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid>
<!--<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>-->
<Grid.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="1" />
</Grid.Effect>
<!--<Border HorizontalAlignment="Right" BorderBrush="Gray" BorderThickness="1,1,0,1" Background="{StaticResource SliderText}" Width="80" CornerRadius="8,0,0,8"/>-->
<!--<Border Grid.Column="2" HorizontalAlignment="Right" BorderBrush="Gray" BorderThickness="0,1,1,1" Background="{StaticResource SliderText}" Width="40" CornerRadius="0,8,8,0"/>-->
<!--<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Tag}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding ElementName=PART_Track,Path=Value,StringFormat=\{0:N0\}}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" DataContext="{Binding}" />-->
<Border Grid.Column="1" BorderBrush="Gray" BorderThickness="1" CornerRadius="8,0,0,8">
<Track Grid.Column="1" Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource Slider_RepeatButton}"
Command="Slider.DecreaseLarge"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource Slider_RepeatButton1}"
Command="Slider.IncreaseLarge"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource Slider_Thumb}"/>
</Track.Thumb>
</Track>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel>
<TextBlock Text="飞行信息" />
<Grid>
<Grid.Resources>
<Style x:Key="CopterInfo_ComboBox"
TargetType="ComboBox"
BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="MinWidth"
Value="120" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>
<Style x:Key="CopterInfo_StackPanel"
TargetType="StackPanel">
<Setter Property="Orientation"
Value="Horizontal" />
<Setter Property="Margin"
Value="0,2" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="ComboBox"
BasedOn="{StaticResource CopterInfo_ComboBox}" />
<Style TargetType="StackPanel"
BasedOn="{StaticResource CopterInfo_StackPanel}" />
</StackPanel.Resources>
<StackPanel>
<TextBlock Text="ID" />
<TextBlock Width="30" Text="{Binding Path=Id}" />
<TextBlock Text="VID" />
<TextBlock Width="30" Text="{Binding Path=VirtualId}" />
</StackPanel>
<StackPanel>
<TextBlock Text="已连接:" />
<ContentPresenter Content="{Binding CommModuleConnected, Converter={StaticResource CheckSignConverter}, Mode=OneWay}" />
</StackPanel>
<StackPanel>
<TextBlock Text="已解锁:" />
<ContentPresenter Content="{Binding IsUnlocked, Converter={StaticResource CheckSignConverter}, Mode=OneWay}" />
</StackPanel>
<StackPanel>
<TextBlock Text="心跳数:" />
<TextBlock Text="{Binding Path=HeartbeatCount}" />
</StackPanel>
<StackPanel>
<TextBlock Text="卫星数:" />
<TextBlock Text="{Binding Path=SatCount}" />
</StackPanel>
<StackPanel>
<TextBlock Text="方向:" />
<TextBlock Text="{Binding Path=Heading}" />
</StackPanel>
<!--<StackPanel>
<TextBlock Text="Yaw" />
<TextBlock Text="{Binding Path=Yaw, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="纬度:" />
<TextBlock Text="{Binding Path=Latitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="经度:" />
<TextBlock Text="{Binding Path=Longitude}" />
</StackPanel>-->
<StackPanel>
<TextBlock Text="高度:" />
<TextBlock Text="{Binding Altitude, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="距离:" />
<TextBlock Text="{Binding FlightDistance, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="锁定类型:" />
<TextBlock Text="{Binding GpsFixType}" />
</StackPanel>
<StackPanel>
<TextBlock Text="返回数据:" />
<StackPanel ToolTip="{Binding RetainInt}">
<TextBlock Text="{Binding Retain[3]}" />
<TextBlock Text="." />
<TextBlock Text="{Binding Retain[2]}" />
<TextBlock Text="." />
<TextBlock Text="{Binding Retain[1]}" />
<TextBlock Text="." />
<TextBlock Text="{Binding Retain[0]}" />
</StackPanel>
</StackPanel>
<!--
<StackPanel>
<TextBlock Text="固件版本:" />
<TextBlock Text="{Binding FirmwareVersionText}" />
</StackPanel>-->
</StackPanel>
<StackPanel Grid.Row="1"
Grid.Column="1"
Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="ComboBox"
BasedOn="{StaticResource CopterInfo_ComboBox}" />
<Style TargetType="StackPanel"
BasedOn="{StaticResource CopterInfo_StackPanel}" />
</StackPanel.Resources>
<StackPanel>
<TextBlock Text="电压:" />
<Slider x:Name="sldChannel3"
Width="75"
Minimum="1100"
Maximum="1900"
Value="{Binding Channel3, Mode=OneWay}"
ValueChanged="sldChannel3_ValueChanged">
<Slider.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Slider.Resources>
</Slider>
</StackPanel>
<StackPanel>
<TextBlock Text="电压值:" />
<TextBlock Text="{Binding Path=Voltage}" />
</StackPanel>
<StackPanel>
<TextBlock Text="剩余电量:" />
<TextBlock Text="{Binding Path=BatteryPer}" />
<TextBlock Text="%" />
</StackPanel>
<StackPanel>
<TextBlock Text="状态:" />
<TextBlock Text="{Binding Path=CommModuleMode}" />
</StackPanel>
<StackPanel>
<TextBlock Text="纬度:" />
<TextBlock Text="{Binding Latitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="经度:" />
<TextBlock Text="{Binding Longitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="通道3" />
<TextBlock Text="{Binding Channel3}" />
</StackPanel>
<StackPanel>
<TextBlock Text="通道4" />
<TextBlock Text="{Binding Channel4}" />
</StackPanel>
<StackPanel>
<TextBlock Text="定位精度:" />
<TextBlock Text="{Binding GpsHdop, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="通信模块版本:" />
<TextBlock Text="{Binding CommModuleVersion}" />
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
</UserControl>
<UserControl x:Class="Plane.FormationCreator.Views.CopterInfoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
xmlns:ec="clr-namespace:Plane.Copters;assembly=PlaneGcsSdk_Private_NET46"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300"
d:DataContext="{d:DesignInstance Type=ec:FakeCopter, IsDesignTimeCreatable=True}">
<UserControl.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14" />
</Style>
<!--笔刷-->
<LinearGradientBrush x:Key="SliderBackground" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#59ccfc"/>
<GradientStop Offset="0.5" Color="#00b3fe"/>
<GradientStop Offset="1" Color="#59ccfc"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="SliderThumb" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFD9D3E8"/>
<!--<GradientStop Offset="1" Color="#dfdfdf"/>-->
</LinearGradientBrush>
<LinearGradientBrush x:Key="SliderText" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#7cce45"/>
<GradientStop Offset="1" Color="#4ea017"/>
</LinearGradientBrush>
<!--Slider模板-->
<Style x:Key="Slider_RepeatButton" TargetType="RepeatButton">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="{StaticResource SliderBackground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_RepeatButton1" TargetType="RepeatButton">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RepeatButton">
<Border Background="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_Thumb" TargetType="Thumb">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Background="{StaticResource SliderBackground}"/>
<Border Grid.ColumnSpan="2" CornerRadius="4" Background="{StaticResource SliderThumb}" Width="15">
<!--<TextBlock Text="||" HorizontalAlignment="Center" VerticalAlignment="Center"/>-->
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Slider_CustomStyle" TargetType="Slider">
<Setter Property="Focusable" Value="false" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid>
<!--<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>-->
<Grid.Effect>
<DropShadowEffect BlurRadius="10" ShadowDepth="1" />
</Grid.Effect>
<!--<Border HorizontalAlignment="Right" BorderBrush="Gray" BorderThickness="1,1,0,1" Background="{StaticResource SliderText}" Width="80" CornerRadius="8,0,0,8"/>-->
<!--<Border Grid.Column="2" HorizontalAlignment="Right" BorderBrush="Gray" BorderThickness="0,1,1,1" Background="{StaticResource SliderText}" Width="40" CornerRadius="0,8,8,0"/>-->
<!--<TextBlock Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Tag}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14"/>-->
<!--<TextBlock Grid.Column="2" Text="{Binding ElementName=PART_Track,Path=Value,StringFormat=\{0:N0\}}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="14" DataContext="{Binding}" />-->
<Border Grid.Column="1" BorderBrush="Gray" BorderThickness="1" CornerRadius="8,0,0,8">
<Track Grid.Column="1" Name="PART_Track">
<Track.DecreaseRepeatButton>
<RepeatButton Style="{StaticResource Slider_RepeatButton}"
Command="Slider.DecreaseLarge"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Style="{StaticResource Slider_RepeatButton1}"
Command="Slider.IncreaseLarge"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb Style="{StaticResource Slider_Thumb}"/>
</Track.Thumb>
</Track>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel>
<TextBlock Text="飞行信息" />
<Grid>
<Grid.Resources>
<Style x:Key="CopterInfo_ComboBox"
TargetType="ComboBox"
BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="MinWidth"
Value="120" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>
<Style x:Key="CopterInfo_StackPanel"
TargetType="StackPanel">
<Setter Property="Orientation"
Value="Horizontal" />
<Setter Property="Margin"
Value="0,2" />
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" >
<StackPanel.Resources>
<Style TargetType="ComboBox"
BasedOn="{StaticResource CopterInfo_ComboBox}" />
<Style TargetType="StackPanel"
BasedOn="{StaticResource CopterInfo_StackPanel}" />
</StackPanel.Resources>
<StackPanel>
<TextBlock Text="ID" />
<TextBlock Width="30" Text="{Binding Path=Id}" />
<TextBlock Text="VID" />
<TextBlock Width="30" Text="{Binding Path=VirtualId}" />
</StackPanel>
<StackPanel>
<TextBlock Text="已连接:" />
<ContentPresenter Content="{Binding CommModuleConnected, Converter={StaticResource CheckSignConverter}, Mode=OneWay}" />
</StackPanel>
<StackPanel>
<TextBlock Text="已解锁:" />
<ContentPresenter Content="{Binding IsUnlocked, Converter={StaticResource CheckSignConverter}, Mode=OneWay}" />
</StackPanel>
<StackPanel>
<TextBlock Text="心跳数:" />
<TextBlock Text="{Binding Path=HeartbeatCount}" />
</StackPanel>
<StackPanel>
<TextBlock Text="卫星数:" />
<TextBlock Text="{Binding Path=SatCount}" />
</StackPanel>
<StackPanel>
<TextBlock Text="方向:" />
<TextBlock Text="{Binding Path=Heading}" />
</StackPanel>
<!--<StackPanel>
<TextBlock Text="Yaw" />
<TextBlock Text="{Binding Path=Yaw, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="纬度:" />
<TextBlock Text="{Binding Path=Latitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="经度:" />
<TextBlock Text="{Binding Path=Longitude}" />
</StackPanel>-->
<StackPanel>
<TextBlock Text="高度:" />
<TextBlock Text="{Binding Altitude, StringFormat=0.##}" />
</StackPanel>
<StackPanel>
<TextBlock Text="锁定类型:" />
<TextBlock Text="{Binding GpsFixType}" />
</StackPanel>
<StackPanel>
<TextBlock Text="预检查状态:" />
<TextBlock Text="{Binding CopterPreCheckPassStr}"
Foreground="{Binding CopterPreCheckPass, Converter={StaticResource PrecheckToColorConverter}}" />
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1"
Grid.Column="1"
Orientation="Vertical">
<StackPanel.Resources>
<Style TargetType="ComboBox"
BasedOn="{StaticResource CopterInfo_ComboBox}" />
<Style TargetType="StackPanel"
BasedOn="{StaticResource CopterInfo_StackPanel}" />
</StackPanel.Resources>
<StackPanel Visibility="Hidden">
<TextBlock Text="电压值:" />
<TextBlock Text="{Binding Path=Voltage}" />
</StackPanel>
<StackPanel>
<TextBlock Text="电压值:" />
<TextBlock Text="{Binding Path=Voltage}" />
</StackPanel>
<StackPanel>
<TextBlock Text="剩余电量:" />
<TextBlock Text="{Binding Path=BatteryPer}" />
<TextBlock Text="%" />
</StackPanel>
<StackPanel>
<TextBlock Text="状态:" />
<TextBlock Text="{Binding Path=CommModuleMode}" />
</StackPanel>
<StackPanel>
<TextBlock Text="纬度:" />
<TextBlock Text="{Binding Latitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="经度:" />
<TextBlock Text="{Binding Longitude}" />
</StackPanel>
<StackPanel>
<TextBlock Text="通信模块版本:" />
<TextBlock Text="{Binding CommModuleVersion}" />
</StackPanel>
<StackPanel>
<TextBlock Text="返回数据:" />
<StackPanel Margin="0,0,0,0" Height="14" ToolTip="{Binding RetainInt}">
<TextBlock Margin="0,-1,0,0" Text="{Binding Retain[3]}" />
<TextBlock Margin="0,-1,0,0" Text="." />
<TextBlock Margin="0,-1,0,0" Text="{Binding Retain[2]}" />
<TextBlock Margin="0,-1,0,0" Text="." />
<TextBlock Margin="0,-1,0,0" Text="{Binding Retain[1]}" />
<TextBlock Margin="0,-1,0,0" Text="." />
<TextBlock Margin="0,-1,0,0" Text="{Binding Retain[0]}" />
</StackPanel>
</StackPanel>
<StackPanel >
<TextBlock Text="最后异常:" />
<TextBlock Text="{Binding CopterErrorString}"/>
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
</UserControl>

File diff suppressed because it is too large Load Diff

View File

@ -74,9 +74,9 @@
/>
<Button Margin="0,5,5,0" Content="3D航线" Width="82" Command="{Binding OptimizeRouteCommand3D}"
/>
<Button Margin="0,5,5,0" Content="2D返航" Width="82" Command="{Binding OptimizeRouteCommandRet}"
<Button Margin="0,5,5,0" Content="2D对应" Width="82" Command="{Binding OptimizeRouteCommandRet}"
/>
<Button Margin="0,5,5,0" Content="3D返航" Width="82" Command="{Binding OptimizeRouteCommandRet3D}"
<Button Margin="0,5,5,0" Content="3D对应" Width="82" Command="{Binding OptimizeRouteCommandRet3D}"
/>