Compare commits

..

92 Commits

Author SHA1 Message Date
xu
7b024ed726 [fix] 调整发送提示
详细描述

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-07-02 14:58:54 +08:00
xu
92a56a247f [feat] 调整界面,关键指令同时发送到广播通道
调整界面,RTCM默认双通道发送,只要打开广播通道,rtcm自动同时通过广播发送

增加紧急返航的注释,要不不清除功能怎么用
        /// 紧急返航:计算当前图案中心点,起飞图案中心点,图案距离起飞图案中心点最近距离
        /// 条件:任务已经开始,且飞行器已经飞行
        /// 可用于模拟和实际飞行,
        /// 1首先需要导入最后的飞行任务文件,
        /// 2实际飞机需要执行解锁和开始任务
        /// 3模拟任务需要开始任务并且暂停任务才能计算

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-30 11:18:27 +08:00
xu
a9cf0fdc8a [feat] 修改图标和版本
版本改为 2.2.0
  主要修改双通道同时发送rtk和所有广播命令

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-28 23:17:01 +08:00
xu
32110aab07 [feat] 调整双通道发送框架和界面
为了广播通道能服务于所有广播命令,调整广播发送框架,
 将通道选择从rtk发送界面移到设置界面
 右下角加入广播通道是否打开的提示
 RTK发送状态的提示从按钮旁边移动到主界面状态栏,并加入更多信息
 调整连接状态图标

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-28 18:29:06 +08:00
xu
12262ff53d [docs] 修改版本号2.1.0.X
详细描述

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-26 14:41:29 +08:00
xu
3491f87832 [fix] 导入老版本的航线生成库
修改函数名

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-24 20:42:54 +08:00
xu
7402ace3f8 [feat] 增加RTCM双频信号强度
详细描述

# 类型 包含:
# feat:新功能(feature)
# fix:修补bug
# docs:文档(documentation)
# style: 格式(不影响代码运行的变动)
# refactor:重构(即不是新增功能,也不是修改bug的代码变动)
# test:增加测试
# chore:构建过程或辅助工具的变动
2024-06-24 15:37:19 +08:00
xu
77afef5ee1 RTCM发送中遇到端口被关闭的情况,自动再次打开,走虚拟基站经常有这种情况(30分钟被服务器断开一次) 2024-04-27 15:33:11 +08:00
xu
9bc7a66831 虚拟飞机不用写航点 2024-04-08 19:38:15 +08:00
af9a86dffd 支持紧急返航
支持返回飞机错误
飞机有预解锁错误回显示黄色
支持新版低电电压参数
支持重启飞控
支持陀螺仪校准
2024-03-26 22:06:52 +08:00
36875bcdc2 紧急返航功能,策略不对,临时保存 2024-01-17 22:37:25 +08:00
2614dc2f59 增加过度航点属性,通过颜色区分
加入起飞检测额外时间,默认4秒,加入参数控制时间和高度
加入自动计算航线碰撞检测间距参数
加入2D计算返航
2024-01-16 21:43:44 +08:00
17e4c8bd97 1修复开网络RTK后,界面卡顿bug,rtkloop增加关键延迟
2将now改为utcnow,减少系统占用
2024-01-10 16:15:33 +08:00
9cfd7db051 采用新的算法计算航线,可以全流程生成,起飞到图案(用3d生成),2d图案到2d图案(用2d错层生成),2d或3d回起飞矩阵(用3d,加2d拉开层,对应ID生成) 2024-01-08 20:39:33 +08:00
ff37f4fa04 更新使用Vs2022编译
增加新的自动航线计算模块
任务时间检测调整
2023-12-25 18:51:42 +08:00
f8f3f36304 小航点计算飞行路径,计算4种情况,匀速。加速匀速减速,加速匀速,匀速减速 2023-12-04 23:48:27 +08:00
b289618a87 1c4D导入V3版自动导入时间,第一个航点不计算时间
2添加的第一个飞行航点自动和起飞点在一起
2023-11-22 15:42:39 +08:00
c2d26dd62c 1增加观测者位置图标,修改后直接可以使用
2增加配置FC_VER_NO = 3 使用小航点同时达到模式计算模拟飞行
3增加灯光框架,可实现闪烁等,但实际使用太慢,暂时不用
2023-11-21 21:16:32 +08:00
b729f6b78e 加入时间估计,兼容新飞机固件
配置文件加入默认加速度,速度等参数
2023-11-16 23:34:55 +08:00
79669581f1 1加入RTCM数据广播到指定端口功能
2将降低广播数据作为可选项在发送界面(只影响通讯模块,不影响端口转发)
3修改一个严重BUG:
   RTCM协议解析BUG,这个BUG是因为F9P地面站有UBX协议数据和RTCM协议数据,由于之前没有解析UBX数据导致RTCM数据也解析不了,导致3秒才发一次RTCM数据到飞机
2023-10-19 22:12:53 +08:00
1403000ef9 加入RTK转发的广播端口 2023-10-15 11:09:53 +08:00
c3a3877323 修改RTK发送部分,限制数据量和封包,通过常量支持以前方式发送,兼容没有修改的固件 2023-05-01 13:55:44 +08:00
xu
aea10b8382 无法编译bug 2022-09-15 01:01:07 +08:00
xu
ca07ddd155 增加通讯统计
修改一架飞机不能修改起飞任务参数的bug
增加抛物功能
增加机头统计排序功能
2022-09-15 00:59:20 +08:00
xu
09da3f24ba 1,加入回传功率设置,在设置窗口里面
2. 增加删除按钮,可以删除不存在的飞机
3. 发送起飞从10次变为20次重复
4.加入256个航点的任务限制提示
5.加入计算任务数按钮
2021-12-27 12:39:28 +08:00
xu
512d9e5386 修改全屏bug 2021-07-22 17:06:24 +08:00
xu
3a8662548f 增加抛物测试功能,(测试可以,但功能未完成)
自适应屏幕分辨率
2021-07-22 15:37:53 +08:00
xu
4b54e56ebc 改回飞行魔方 2021-07-11 23:58:51 +08:00
xu
63c9372550 中科浩电OEM版本V1.0 到期时间2021.8.10 2021-07-11 23:49:20 +08:00
xu
cb2a672c44 修改时间为2022-6-10日 2021-07-11 12:57:45 +08:00
xu
7dfe36a7f8 1.自动计算模拟飞机更新间隔
2.增加通讯模块测试功能
3.增加检测电池电压功能
4.间隔选中飞机每行重新计算
5.计算飞机距离,增加所有任务的,并计算最大距离
6.整体旋转增加起始结束任务号
2021-04-02 01:26:12 +08:00
xu
ba8eb6b2e2 定位统计改为状态统计,增加机头统计,用于检测是否需要校验磁罗盘 2020-11-27 00:27:35 +08:00
xu
4dba5da8fd 1.兼容版和新飞控版用同样的软件,配置文件不同
2.飞行时间计算,每一个判断是否修改速度,有修改就按新速度计算时间
3.加入魔方基站支持
4.支持部分任务
2020-09-20 11:42:07 +08:00
xu
3719c74753 导入外部起飞形状 2020-05-28 15:05:18 +08:00
xu
417f761e40 不再预先分配VID
自动分配后自动排序
2020-05-22 22:52:45 +08:00
xu
bbb7804831 修改添加新飞机排序和显示id可能和之前不一致问题 2020-05-22 21:50:42 +08:00
xu
7c71016e0c 虚拟飞机用蓝色,真实飞机绿色
灯光模拟间隔不能低于1秒的bug
真实飞机替代虚拟飞机,虚拟飞机不能替代真实飞机
2020-05-22 20:47:20 +08:00
xu
3efb9b719d 选写航点加入,自动关闭rtk功能 2020-05-20 00:43:04 +08:00
xu
62cde39a91 加入计算返航的功能,可以完整计算整个2d飞行任务 2020-05-13 00:44:52 +08:00
xu
d547c7ab5c 移动flybase项目到平级目录 2020-05-12 11:00:55 +08:00
xu
8fbb41928d Flybase库加入工程
加入2d自动计算航线--待测试
加入3d自动计算航线--未完成
主界面顶部调整
导入检测飞机数量并提示
加入多个任务垂直旋转用于自动计算的航线
2020-05-12 10:54:54 +08:00
xu
c1db1e3525 加入变色灯光
加入多次关闭测试灯光
2020-05-08 22:46:17 +08:00
xu
f0ef8134d5 加入导入飞机位置选项
导出以前只是经纬差,改为距离差
加入文件标识和版本目前为2.0
加入文件飞机数量和实际数量不一致提醒
修改灯光设计的按钮在选中1架时会报错的bug
2020-05-06 03:13:51 +08:00
xu
c27138d0e3 登录添加版本号 2020-05-05 19:33:57 +08:00
xu
8938e3aaaa 兼容老版本航点文件
间隔保留1位小数
2020-05-05 16:18:23 +08:00
xu
59b4669a7d 灯光列表改为单独页面
跑马灯和灯带加入方向
加入对齐灯光时间
加入灯光新类型
拉烟ID之前是8改为11,到固件任然为50
2020-05-05 13:29:14 +08:00
xu
62a7b8b028 灯光频率改为间隔
可以选择颜色
2020-05-04 11:08:00 +08:00
xu
e1c81f28ff 增加保存读取虚拟编号
多次写入参数
加入测试灯光和灯光频率可以为小数---需要升级飞控

修改3D颜色和编号刷新的bug
2020-05-03 12:14:27 +08:00
xu
9b5b3bb22c 快速航点和普通航点同样处理,否则灯光和重设都有bug 2020-04-28 00:35:50 +08:00
xu
441cbe953d 修改任务区多次点击,或双击,右键乱点容易异常退出bug 2020-04-22 02:37:45 +08:00
xu
23c1390758 修改3D默认飞机颜色
修复任务双击快进自动退出的bug
2D/3D切换飞机如果不动就没刷新位置的bug
2020-04-22 01:10:02 +08:00
xu
d525f00222 可模拟起飞灯光 2020-04-21 15:36:17 +08:00
xu
f787069624 修改任务选中颜色,更明显
可导入ai和obj模型文件
增加删除任务和在任务中插入任务功能(添加改为选中任务后一个添加)
航线改为默认显示,优化右键隐藏航点功能
更改飞机和航点默认颜色
界面加入“飞行前准备”等分组页面,更方便操作
修改bug:清除飞机重新添加后飞行航线发虚,右键隐藏状态没有重置,
2020-04-20 00:12:11 +08:00
xu
84c12a1eb7 写入航点时停止发送RTK
调整按钮位置,分开选中和整体的操作
修改电压后面信息无法显示的bug
加入显示所有航点功能
2020-03-27 17:05:48 +08:00
xu
8facb729f7 修改双频不能发送rtk的bug,原因是用的新打包方式发送,暂时改回180字节单独发送模式 2020-03-16 14:12:15 +08:00
xu
3aa4879511 继续修改wifi,可以批量起飞等功能 2020-03-11 15:34:31 +08:00
xu
da086831bf RTK按钮取消 2020-03-06 17:43:33 +08:00
xu
911024c0ad 1.修改使用单频RTK的函数,
2.加入可保存飞行日志到临时本地,下次登录再提交
2020-03-05 17:59:11 +08:00
xu
3d2a3b10fb 加入通讯模块类型,初步支持wifi通讯 2020-03-03 11:21:29 +08:00
xu
776b9cfe62 写航点时不用虚拟ID而用实际序号ID,因为在排序时已经重新按VID排列 2020-03-02 19:22:58 +08:00
xu
57fc99c434 去掉起飞数量 2020-03-02 17:05:09 +08:00
xu
9a1fd805b9 把编译和运行需要的依赖项加入,没有models目录无法运行,没有packages目录无法编译 2020-02-29 02:46:43 +08:00
xu
d4a9dc5bf3 添加的文件 2020-02-26 02:06:30 +08:00
xu
3362a1b47c 加入登录和修改密码 2020-02-26 02:02:12 +08:00
xu
2f26de2196 密码加密保存
服务器地址可以通过ini修改,默认写入程序
2020-02-26 00:49:56 +08:00
xu
b728584628 启动先开打登录界面,可以取消
退出延时1秒,更好的注销
2020-02-25 04:21:21 +08:00
xu
92044ae56b 加入和服务器交互,必须登录服务器账号才能允许加入飞机
飞机数量控制以前的ini方式去掉,改为仅仅账号控制
加入登录登出服务器日志
加入飞行任务服务器日志
加入修改密码功能
用户级别也只能用账号方式控制
超级用户硬编码到代码里,不用登录服务器:admin 密码 fxmf0622
2020-02-25 03:50:34 +08:00
xu
6cb44d5401 开始加入登录,功能还没实现,加入工具类
日志窗口可拖动宽度
2020-02-23 16:05:27 +08:00
xu
7fb0bcf60e 加入立体缩放比例设置,用于立体视图显示超出范围的航点
修复自动编号寻找的bug
开始修改通讯了---还没改完
2020-02-21 23:58:14 +08:00
xu
e3f4e557dd 去掉不用的任务类型,只保留起飞,飞向和降落 2020-02-08 23:23:53 +08:00
xu
d7df82f667 修改bug,起飞不画轨迹线 2020-02-08 22:54:49 +08:00
xu
e8d17e29d1 飞机列表右键增加显示虚拟编号和飞机编号的切换,同时自动排序 2020-02-05 04:57:47 +08:00
xu
ffe6b466fe 修改界面小bug 2020-02-05 02:47:57 +08:00
xu
f9428fbad2 改名按钮去掉,改成双击页头
页头自动显示选中的任务
2020-02-05 02:09:45 +08:00
xu
d334442d62 调整任务设置界面 2020-02-04 03:27:05 +08:00
xu
08ff8c7772 调整设置界面
任务右键改为隐藏\显示航点
2020-02-04 03:04:14 +08:00
xu
5c6cf9ecdb 设置窗口显示版本号和编译时间 2020-02-04 02:10:15 +08:00
xu
1e38390fc6 按VID排序
修改自动编号逻辑
//目前方案是
                //1.保证所有没有正确定位的飞机都人工编号,
                //2.然后选中2-3架飞机,1号飞机,第一排任意飞机,第一列任意飞机(尽量远离1号机),
                //3.开始计算
修改3飞机信息通道数据改为电池图标,并且不让拖动修改
显示VID变换黄色,以前是红色
2020-02-03 23:44:55 +08:00
xu
00d03a0025 修改自动编号逻辑前 2020-02-01 22:02:25 +08:00
xu
8990d57212 修改模拟飞行时降落不能多次双击模拟bug
修改前一个是返航点时,双击模拟时飞机位置不正确bug
3d地面飞机改为白色
修改启动界面更好看点
2020-01-31 02:18:28 +08:00
xu
6f33c3867c 任务时间提示
防止修改任务为起飞任务
下方添加状态提示信息
任务块,在任务模拟中双击是马上执行该任务,右键改名
调整界面,去掉不必要的元素
2020-01-30 20:35:41 +08:00
xu
b80026ff8c 界面小调整,选中任务更明显
双击任务可直接运行到这个任务,改名可右键单击
修改小bug
2020-01-30 15:32:06 +08:00
xu
f7a638159e 修改bug 2020-01-29 22:08:57 +08:00
xu
694472c9b7 去掉地图上方的蓝色小条 2020-01-29 16:28:58 +08:00
xu
fc3b2cae02 修改启动界面和标题 2020-01-29 03:45:52 +08:00
xu
beb927a08c 修改删除飞机没有吧原点清空的bug
地图切换后操作不同的bug
2020-01-29 02:42:26 +08:00
xu
7ea00c6855 去掉飞行时间,飞行距离,姿态计算和更新,提高效率
碰撞检测改为异步提示,检测间隔缩小为50ms
修改任务无法停止的bug
不多次发送目标航点
地图上选中变为红色
地图中间加入十字标记,用于精确确定添加飞机位置
2020-01-28 22:47:49 +08:00
xu
c0fa7d8ddb 为优化速度,2D和3D地图不同时显示位置 2020-01-28 18:12:17 +08:00
xu
7ac2f48500 V2.0 修改
1重设将飞机回到起飞点
2默认悬停时间改为1秒
3解锁起飞模拟真飞机改变颜色
4自动计算所有任务飞行时间
5增加从指定任务开始模拟
6连接窗口改为设置并优化布局
7不创建所有航点,只创建要显示的,优化导入速度
8更改背景
9模拟检测碰撞的间隔改为10hz,之前是100hz,对于大量飞机拖慢速度[FlightTask_FlyTo.cs]
2020-01-28 16:06:27 +08:00
xu
f49cd3c722 修改1080p显示不全灯光设计bug 2020-01-20 10:44:30 +08:00
zxd
59672e4f5e 支持先手动设置部分虚拟ID后再自动编号 2019-12-30 10:36:40 +08:00
zxd
9133800b62 自动按照位置排序虚拟ID 2019-12-11 20:41:29 +08:00
406 changed files with 394963 additions and 13853 deletions

View File

@ -1,108 +1,131 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.FormationCreator", "Plane.FormationCreator\Plane.FormationCreator.csproj", "{61E2F31E-220A-4E3F-A64D-F7CDC2135008}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Windows", "..\Plane.Libraries\Plane.Windows\Plane.Windows.csproj", "{06848293-9B17-4068-9B35-44D0ED713CD4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Reflection", "..\Plane.Libraries\Plane.Reflection\Plane.Reflection.csproj", "{98755514-C2E9-4ABE-8A25-007804577558}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Windows.Messages", "..\Plane.Libraries\Plane.Windows.Messages\Plane.Windows.Messages.csproj", "{413C18E2-235F-4E15-B5C1-633657DE5D7A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Logging", "..\Plane.Libraries\Plane.Logging\Plane.Logging.csproj", "{9C2CAFDA-CF1D-4565-B797-398376FCD346}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane", "..\Plane.Libraries\Plane\Plane.csproj", "{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlaneGcsSdk_Private_NET46", "..\Plane.Sdk3\PlaneGcsSdk_Private_NET46\PlaneGcsSdk_Private_NET46.csproj", "{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlaneGcsSdk.Contract_Private", "..\Plane.Sdk3\PlaneGcsSdk.Contract_Private\PlaneGcsSdk.Contract_Private.csproj", "{47141894-ECE3-48CA-8DCF-CA751BDA231E}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk_Shared", "..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.shproj", "{2BE393DC-21A4-48B3-83FD-F21CBE8B038B}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk.Contract_Shared", "..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.shproj", "{695733D7-99FF-4707-8C89-474E949CADCB}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.projitems*{0111eb6e-72e3-499c-a3ba-022f5bbc4caf}*SharedItemsImports = 4
..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.projitems*{2be393dc-21a4-48b3-83fd-f21cbe8b038b}*SharedItemsImports = 13
..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.projitems*{47141894-ece3-48ca-8dcf-ca751bda231e}*SharedItemsImports = 4
..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.projitems*{695733d7-99ff-4707-8c89-474e949cadcb}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
v4.0-Debug|Any CPU = v4.0-Debug|Any CPU
v4.0-Release|Any CPU = v4.0-Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Release|Any CPU.Build.0 = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Release|Any CPU.Build.0 = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Release|Any CPU.Build.0 = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Release|Any CPU.Build.0 = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Release|Any CPU.Build.0 = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Release|Any CPU.Build.0 = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Release|Any CPU.Build.0 = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Release|Any CPU.Build.0 = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34202.233
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.FormationCreator", "Plane.FormationCreator\Plane.FormationCreator.csproj", "{61E2F31E-220A-4E3F-A64D-F7CDC2135008}"
ProjectSection(ProjectDependencies) = postProject
{9BFB2123-2239-4A85-B5BC-0328CE7640D7} = {9BFB2123-2239-4A85-B5BC-0328CE7640D7}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Windows", "..\Plane.Libraries\Plane.Windows\Plane.Windows.csproj", "{06848293-9B17-4068-9B35-44D0ED713CD4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Reflection", "..\Plane.Libraries\Plane.Reflection\Plane.Reflection.csproj", "{98755514-C2E9-4ABE-8A25-007804577558}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Windows.Messages", "..\Plane.Libraries\Plane.Windows.Messages\Plane.Windows.Messages.csproj", "{413C18E2-235F-4E15-B5C1-633657DE5D7A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane.Logging", "..\Plane.Libraries\Plane.Logging\Plane.Logging.csproj", "{9C2CAFDA-CF1D-4565-B797-398376FCD346}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plane", "..\Plane.Libraries\Plane\Plane.csproj", "{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlaneGcsSdk_Private_NET46", "..\Plane.Sdk3\PlaneGcsSdk_Private_NET46\PlaneGcsSdk_Private_NET46.csproj", "{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlaneGcsSdk.Contract_Private", "..\Plane.Sdk3\PlaneGcsSdk.Contract_Private\PlaneGcsSdk.Contract_Private.csproj", "{47141894-ECE3-48CA-8DCF-CA751BDA231E}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk_Shared", "..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.shproj", "{2BE393DC-21A4-48B3-83FD-F21CBE8B038B}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlaneGcsSdk.Contract_Shared", "..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.shproj", "{695733D7-99FF-4707-8C89-474E949CADCB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlightRoute", "..\FlyTest\FlightRoute\FlightRoute.csproj", "{9BFB2123-2239-4A85-B5BC-0328CE7640D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlightRouteV2", "..\FlyCube\FlightRouteV2\FlightRouteV2.csproj", "{626A9BFA-07DE-4063-A178-360EB7057ED6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
v4.0-Debug|Any CPU = v4.0-Debug|Any CPU
v4.0-Release|Any CPU = v4.0-Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Release|Any CPU.ActiveCfg = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.Release|Any CPU.Build.0 = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{61E2F31E-220A-4E3F-A64D-F7CDC2135008}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.Release|Any CPU.Build.0 = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{06848293-9B17-4068-9B35-44D0ED713CD4}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.Release|Any CPU.Build.0 = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{98755514-C2E9-4ABE-8A25-007804577558}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.Release|Any CPU.Build.0 = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{413C18E2-235F-4E15-B5C1-633657DE5D7A}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.Release|Any CPU.Build.0 = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{9C2CAFDA-CF1D-4565-B797-398376FCD346}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.Release|Any CPU.Build.0 = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{6CCE2AEB-3B38-4C00-B32D-433A990AE2AD}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.Release|Any CPU.Build.0 = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{0111EB6E-72E3-499C-A3BA-022F5BBC4CAF}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.Release|Any CPU.Build.0 = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{47141894-ECE3-48CA-8DCF-CA751BDA231E}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.Release|Any CPU.Build.0 = Release|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{9BFB2123-2239-4A85-B5BC-0328CE7640D7}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.Release|Any CPU.Build.0 = Release|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.v4.0-Debug|Any CPU.ActiveCfg = Debug|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.v4.0-Debug|Any CPU.Build.0 = Debug|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.v4.0-Release|Any CPU.ActiveCfg = Release|Any CPU
{626A9BFA-07DE-4063-A178-360EB7057ED6}.v4.0-Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.projitems*{0111eb6e-72e3-499c-a3ba-022f5bbc4caf}*SharedItemsImports = 4
..\Plane.Sdk3\PlaneGcsSdk_Shared\PlaneGcsSdk_Shared.projitems*{2be393dc-21a4-48b3-83fd-f21cbe8b038b}*SharedItemsImports = 13
..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.projitems*{47141894-ece3-48ca-8dcf-ca751bda231e}*SharedItemsImports = 4
..\Plane.Sdk3\PlaneGcsSdk.Contract_Shared\PlaneGcsSdk.Contract_Shared.projitems*{695733d7-99ff-4707-8c89-474e949cadcb}*SharedItemsImports = 13
EndGlobalSection
EndGlobal

View File

@ -1,53 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Plane.FormationCreator.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Windows.Interactivity" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.109.0" newVersion="1.0.109.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<userSettings>
<Plane.FormationCreator.Properties.Settings>
<setting name="IPs" serializeAs="String">
<value>192.168.1.50</value>
</setting>
</Plane.FormationCreator.Properties.Settings>
</userSettings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
<remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
</system.data>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Plane.FormationCreator.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Windows.Interactivity" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.0.109.0" newVersion="1.0.109.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<userSettings>
<Plane.FormationCreator.Properties.Settings>
<setting name="IPs" serializeAs="String">
<value>192.168.1.50</value>
</setting>
</Plane.FormationCreator.Properties.Settings>
</userSettings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6"/>
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6"/>
<remove invariant="System.Data.SQLite"/><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite"/></DbProviderFactories>
</system.data>
</configuration>

View File

@ -1,55 +1,99 @@
<Application x:Class="Plane.FormationCreator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Plane.FormationCreator"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d1p1:Ignorable="d"
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cnv="clr-namespace:Plane.Windows.Converters;assembly=Plane.Windows"
xmlns:lcnv="clr-namespace:Plane.FormationCreator.Converters"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
ShutdownMode="OnMainWindowClose">
<Application.Resources>
<materialDesign:PackIcon x:Key="CheckIcon"
x:Shared="False"
Kind="Check"
Foreground="#2196F3" />
<materialDesign:PackIcon x:Key="CloseIcon"
x:Shared="False"
Kind="Close"
Foreground="White" />
<cnv:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<cnv:BooleanToVisibilityConverter x:Key="InversiveBooleanToVisibilityConverter"
False="Visible"
True="Collapsed" />
<cnv:NullableBooleanToVisibilityConverter x:Key="IsPausedToRunButtonVisibilityConverter"
False="Collapsed"
Null="Visible"
True="Visible" />
<cnv:NullableBooleanToVisibilityConverter x:Key="IsPausedToPauseButtonVisibilityConverter"
False="Visible"
Null="Collapsed"
True="Collapsed" />
<cnv:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<cnv:BooleanToStringConverter x:Key="ShowModifyTaskViewButtonContentConverter"
False="【飞行模式】"
True="【编辑模式】" />
<cnv:BooleanToResourceConverter x:Key="CheckSignConverter"
FalseKey="CloseIcon"
TrueKey="CheckIcon" />
<cnv:BooleanToResourceConverter x:Key="CheckSignConverter2"
FalseKey="CloseIcon"
TrueKey="CheckIcon" />
<cnv:BooleanToStringConverter x:Key="ColorConverter"
False="Red"
True="Green" />
<cnv:BooleanToStringConverter x:Key="SendConverter"
False="发送"
True="关闭" />
<lcnv:HeartbeatCountToBrushConverter x:Key="HeartbeatCountToBrushConverter" />
<lcnv:AppModeToVisibilityConverter x:Key="AppModeToVisibilityConverter" />
<lcnv:FlightTaskStatusToFillConverter x:Key="FlightTaskStatusToFillConverter" />
<lcnv:FlightTaskIsSelectedToEffectConverter x:Key="FlightTaskIsSelectedToEffectConverter" />
</Application.Resources>
<Application x:Class="Plane.FormationCreator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Plane.FormationCreator"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d1p1:Ignorable="d"
xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cnv="clr-namespace:Plane.Windows.Converters;assembly=Plane.Windows"
xmlns:lcnv="clr-namespace:Plane.FormationCreator.Converters"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
ShutdownMode="OnMainWindowClose">
<Application.Resources>
<materialDesign:PackIcon x:Key="ConnectIcon"
x:Shared="False"
Kind="LanConnect"
Foreground="#2196F3" />
<materialDesign:PackIcon x:Key="DisconnectIcon"
x:Shared="False"
Kind="LanDisconnect"
Foreground="White" />
<materialDesign:PackIcon x:Key="CheckIcon"
x:Shared="False"
Kind="Check"
Foreground="#2196F3" />
<materialDesign:PackIcon x:Key="CloseIcon"
x:Shared="False"
Kind="Close"
Foreground="White" />
<cnv:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<cnv:BooleanToVisibilityConverter x:Key="InversiveBooleanToVisibilityConverter"
False="Visible"
True="Collapsed" />
<cnv:NullableBooleanToVisibilityConverter x:Key="IsPausedToRunButtonVisibilityConverter"
False="Collapsed"
Null="Visible"
True="Visible" />
<cnv:NullableBooleanToVisibilityConverter x:Key="IsPausedToPauseButtonVisibilityConverter"
False="Visible"
Null="Collapsed"
True="Collapsed" />
<cnv:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<cnv:BooleanToStringConverter x:Key="ShowModifyTaskViewButtonContentConverter"
False="【飞行模式】"
True="【设计模式】" />
<cnv:BooleanToStringConverter x:Key="MainColorConverterDes"
False="White"
True="DeepSkyBlue" />
<cnv:BooleanToStringConverter x:Key="MainFontSizeConverterDes"
False="12"
True="14" />
<cnv:BooleanToStringConverter x:Key="MainColorConverterFly"
False="DeepSkyBlue"
True="White" />
<cnv:BooleanToStringConverter x:Key="MainFontSizeConverterFly"
False="14"
True="12" />
<cnv:BooleanToStringConverter x:Key="Show2d3dButtonContentConverter"
False="平面视图"
True="立体视图" />
<cnv:BooleanToResourceConverter x:Key="CheckSignConverter"
FalseKey="CloseIcon"
TrueKey="CheckIcon" />
<cnv:BooleanToResourceConverter x:Key="CheckSignConverter2"
FalseKey="DisconnectIcon"
TrueKey="ConnectIcon" />
<cnv:BooleanToStringConverter x:Key="ColorConverter"
False="Red"
True="Green" />
<cnv:BooleanToStringConverter x:Key="SendConverter"
False="发送"
True="关闭" />
<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,280 +1,313 @@
using Plane.Communication;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Logging;
using Plane.Windows;
using Plane.Windows.Messages;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Plane.CommunicationManagement;
using Plane.FormationCreator.Util;
namespace Plane.FormationCreator
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
ServiceLocatorConfigurer.Instance.Configure();
_logger = ServiceLocator.Current.GetInstance<ILogger>();
_copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
_formationController = ServiceLocator.Current.GetInstance<FormationController>();
_mapManager = ServiceLocator.Current.GetInstance<MapManager>();
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
{
var simpleName = new AssemblyName(e.Name).Name;
if (simpleName.EndsWith(".resources"))
{
return null;
}
return LoadAssembly(simpleName);
};
this.DispatcherUnhandledException += (s, e) =>
{
_logger.Log(e.Exception);
// await _formationController.AllStop();
TcpServerConnectionManager.Instance.StopListening();
UdpServerConnectionManager.Instance.StopReceiving();
};
this.Exit += (s, e) =>
{
try
{
// TcpServerConnectionManager.Instance.StopListening();
UdpServerConnectionManager.Instance.StopReceiving();
}
catch (Exception ex)
{
// RaiseExceptionThrown(ex);
}
};
//new Test().Prepare().Run();
VersionControl.GetVersionFromIni();
}
private ILogger _logger;
private CopterManager _copterManager;
private FormationController _formationController;
private MapManager _mapManager;
private Assembly LoadAssembly(string simpleName)
{
String resourceName = this.GetType().Namespace + ".AssemblyLoadingAndReflection." + simpleName + ".dll";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var md = Resources.MergedDictionaries;
// md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/VS/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Plane.Windows.Messages;component/Styles.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Styles/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Styles.xaml") });
/*
new UpdateChecker("http://dl.Plane.com/tools/ver.php?app=FormationCreator", _logger)
.CheckAsync(ver =>
{
var currentVersion = this.GetType().Assembly.GetName().Version;
if (currentVersion < ver
&& Alert.Show("检测到新版本,请下载。", "更新提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Process.Start("http://dl.Plane.com/tools/FormationCreatorSetup.exe");
this.Shutdown();
}
});
*/
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
MainWindow = new MainWindow();
MainWindow.Show();
try
{
/* by panxu tcp 使 --使TCP监听在自动获取IP的情况下
TcpServerConnectionManager.Instance.ConnectionEstablished += ConnectionManager_ConnectionEstablished;
if (!TcpServerConnectionManager.Instance.StartListening())
{
Alert.Show("网络连接不正常,无法连接飞机。");
return;
}
*/
/*
UdpServerConnectionManager.Instance.ExceptionThrown += (sender, e1) =>
{
_logger.Log(e1.Exception);
};
UdpServerConnectionManager.Instance.ConnectionEstablished += ConnectionManager_ConnectionEstablished;
UdpServerConnectionManager.Instance.StartReceiving();
*/
//初始化地面站连接
CommModuleManager.Instance.CommunicationReceived += CommtionReceivedCopterInfo;
CommModuleManager.Instance.CommunicationCopterDisconnect += CommCopterDisconnect;
CommModuleManager.Instance.CommunicationConnected += CommCopterconnected;
CommModuleManager.Instance.Connect();
}
catch (Exception ex)
{
Alert.Show("网络连接不正常,无法连接飞机。");
return;
}
}
protected override void OnExit(ExitEventArgs e)
{
CommModuleManager.Instance.CloseConnection();
base.OnExit(e);
}
private void Copter_TextReceived(object sender, MessageCreatedEventArgs e)
{
_logger.Log(e.Message );
}
private async Task AddOrUpdateCopter(string ip, IConnection Connection)
{
var copters = _copterManager.Copters;
var copterStatus = _copterManager.CopterStatus;
var copter = copters.FirstOrDefault(c => c.Id == ip);
if (copter == null)
{
await Dispatcher.BeginInvoke(new Action(() =>
{
copter = new Copter(Connection, SynchronizationContext.Current, _mapManager.Center.Lat, _mapManager.Center.Lng)
{
Id = ip,
Name = ip.Substring(ip.LastIndexOf('.') + 1)
};
int _index;
_index=copters.AddCopter(copter);
copterStatus.Insert(_index,false);
copter.TextReceived += Copter_TextReceived;
}));
}
else
{
copter.Connection = Connection;
}
await copter.ConnectAsync().ConfigureAwait(false);
}
private async void ConnectionManager_ConnectionEstablished(object sender, ConnectionEstablishedEventArgs e)
{
await AddOrUpdateCopter(e.RemoteAddress, e.Connection);
}
private async void CommtionReceivedCopterInfo(object sender, CommunicationReceiveCopterInfoEventArgs e)
{
await UpdateCommCopterInfo(e.Id, e.Package, e.CommModuleVersion);
//await TaskUtils.CompletedTask;
}
private async void CommCopterDisconnect(object sender, CommunicationCopterDisconnectEventArgs e)
{
await DisconnectCopter(e.Id);
}
private async void CommCopterconnected(object sender, CommunicationConnectEventArgs e)
{
await AddCommCopter(e.Id);
}
private async Task DisconnectCopter(int id)
{
var copters = _copterManager.Copters;
var copter = copters.FirstOrDefault(c => c.Id == id.ToString());
if (copter != null)
{
if (copter is PLCopter)
{
PLCopter plcopter = (PLCopter)copter;
plcopter.CommModuleConnected = false;
}
}
await TaskUtils.CompletedTask;
}
private static readonly object locker = new object();
private async Task AddCommCopter(int id)
{
await Dispatcher.BeginInvoke(new Action(() =>
{
lock(locker)
{
var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == id.ToString());
if (copter == null)
{
var copterStatus = _copterManager.CopterStatus;
var connection = new CommConnection();
copter = new Copter(connection, SynchronizationContext.Current, _mapManager.Center.Lat, _mapManager.Center.Lng)
{
Id = id.ToString(),
Name = id.ToString(),
};
int _index;
_index = _copterManager.Copters.AddCopter(copter);
copterStatus.Insert(_index, false);
copter.TextReceived += Copter_TextReceived;
}
}
}));
}
private async Task UpdateCommCopterInfo(int id, byte[] package, byte CommModuleVersion)
{
await AddCommCopter(id);
lock (locker)
{
var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == id.ToString());
if (copter!= null && copter is PLCopter)
{
PLCopter plcopter = (PLCopter)copter;
if (!plcopter.CommModuleConnected) plcopter.CommModuleConnected = true;
plcopter.InternalCopter.AnalyzeCommMouldePositionIntPacket(package, CommModuleVersion);
plcopter.CommModuleConnected = true;
}
}
}
}
}
using Plane.Communication;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Logging;
using Plane.Windows;
using Plane.Windows.Messages;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Plane.FormationCreator.Util;
using Plane.CommunicationManagement;
namespace Plane.FormationCreator
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
VersionControl.GetSettingFromIni();
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
ServiceLocatorConfigurer.Instance.Configure();
_logger = ServiceLocator.Current.GetInstance<ILogger>();
_copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
_formationController = ServiceLocator.Current.GetInstance<FormationController>();
_mapManager = ServiceLocator.Current.GetInstance<MapManager>();
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
{
var simpleName = new AssemblyName(e.Name).Name;
if (simpleName.EndsWith(".resources"))
{
return null;
}
return LoadAssembly(simpleName);
};
this.DispatcherUnhandledException += (s, e) =>
{
_logger.Log(e.Exception);
// await _formationController.AllStop();
TcpServerConnectionManager.Instance.StopListening();
UdpServerConnectionManager.Instance.StopReceiving();
};
this.Exit += (s, e) =>
{
try
{
// TcpServerConnectionManager.Instance.StopListening();
UdpServerConnectionManager.Instance.StopReceiving();
}
catch (Exception ex)
{
// RaiseExceptionThrown(ex);
}
};
//new Test().Prepare().Run();
}
private ILogger _logger;
private CopterManager _copterManager;
private FormationController _formationController;
private MapManager _mapManager;
private Assembly LoadAssembly(string simpleName)
{
String resourceName = this.GetType().Namespace + ".AssemblyLoadingAndReflection." + simpleName + ".dll";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
Byte[] assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var md = Resources.MergedDictionaries;
// md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/VS/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Plane.Windows.Messages;component/Styles.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Styles/Colors.xaml") });
md.Add(new ResourceDictionary { Source = new Uri("pack://application:,,,/Styles.xaml") });
/*
new UpdateChecker("http://dl.Plane.com/tools/ver.php?app=FormationCreator", _logger)
.CheckAsync(ver =>
{
var currentVersion = this.GetType().Assembly.GetName().Version;
if (currentVersion < ver
&& Alert.Show("检测到新版本,请下载。", "更新提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Process.Start("http://dl.Plane.com/tools/FormationCreatorSetup.exe");
this.Shutdown();
}
});
*/
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
MainWindow = new MainWindow();
MainWindow.Show();
try
{
/* by panxu tcp 使 --使TCP监听在自动获取IP的情况下
TcpServerConnectionManager.Instance.ConnectionEstablished += ConnectionManager_ConnectionEstablished;
if (!TcpServerConnectionManager.Instance.StartListening())
{
Alert.Show("网络连接不正常,无法连接飞机。");
return;
}
*/
if (VersionControl.ConType == 1)
{
CommModuleManager.Instance.UseTransModule = false;
UdpServerConnectionManager.Instance.ExceptionThrown += (sender, e1) =>
{
_logger.Log(e1.Exception);
};
UdpServerConnectionManager.Instance.ConnectionEstablished += ConnectionManager_ConnectionEstablished;
UdpServerConnectionManager.Instance.StartReceiving();
}
else
{
CommModuleManager.Instance.UseTransModule = true;
//初始化地面站连接
CommModuleManager.Instance.CommunicationReceived += CommtionReceivedCopterInfo;
CommModuleManager.Instance.CommunicationCopterDisconnect += CommCopterDisconnect;
CommModuleManager.Instance.CommunicationConnected += CommCopterconnected;
CommModuleManager.Instance.Connect();
}
}
catch (Exception ex)
{
Alert.Show("网络连接不正常,无法连接飞机。");
return;
}
}
protected override void OnExit(ExitEventArgs e)
{
CommModuleManager.Instance.CloseConnection();
base.OnExit(e);
}
private void Copter_TextReceived(object sender, MessageCreatedEventArgs e)
{
_logger.Log(e.Message );
}
//wifi模式添加飞机
private async Task AddOrUpdateCopter(string ip, IConnection Connection)
{
var copters = _copterManager.Copters;
var copterStatus = _copterManager.CopterStatus;
string[] iparr = ip.Split('.');
string vIPID = String.Format("{0:D3}", int.Parse(iparr[2])) + String.Format("{0:D3}", int.Parse(iparr[3]));
var copter = copters.FirstOrDefault(c => c.Id == vIPID);
if (copter == null)
{
if (!_copterManager.EnAddCopter_Real())
{
UdpServerConnectionManager.Instance.DeleteConnections(ip);
}
else
{
await Dispatcher.BeginInvoke(new Action(() =>
{
copter = new Copter(Connection, SynchronizationContext.Current, _mapManager.Center.Lat, _mapManager.Center.Lng)
{
Id = vIPID,
Name = vIPID // ip.Substring(ip.LastIndexOf('.') + 1)
};
int _index;
_index = copters.AddCopter(copter, _copterManager.SortType);
copterStatus.Insert(_index, false);
copter.TextReceived += Copter_TextReceived;
}));
}
}
else
{
copter.Connection = Connection;
}
if (copter!=null)
await copter.ConnectAsync().ConfigureAwait(false);
}
private async void ConnectionManager_ConnectionEstablished(object sender, ConnectionEstablishedEventArgs e)
{
await AddOrUpdateCopter(e.RemoteAddress, e.Connection);
}
private async void CommtionReceivedCopterInfo(object sender, CommunicationReceiveCopterInfoEventArgs e)
{
await UpdateCommCopterInfo(e.Id, e.Package, e.CommModuleVersion);
//await TaskUtils.CompletedTask;
}
private async void CommCopterDisconnect(object sender, CommunicationCopterDisconnectEventArgs e)
{
await DisconnectCopter(e.Id);
}
private async void CommCopterconnected(object sender, CommunicationConnectEventArgs e)
{
await AddCommCopter(e.Id);
}
private async Task DisconnectCopter(int id)
{
var copters = _copterManager.Copters;
var copter = copters.FirstOrDefault(c => c.Id == id.ToString());
if (copter != null)
{
if (copter is PLCopter)
{
PLCopter plcopter = (PLCopter)copter;
plcopter.CommModuleConnected = false;
}
}
await TaskUtils.CompletedTask;
}
private static readonly object locker = new object();
private async Task AddCommCopter(int id)
{
await Dispatcher.BeginInvoke(new Action(() =>
{
lock(locker)
{
var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == id.ToString());
if ((copter != null)&&(copter is FakeCopter))
{
_copterManager.Copters.Remove(copter);
copter = null;
}
if (copter == null)
{
if (_copterManager.EnAddCopter_Real())
{
var copterStatus = _copterManager.CopterStatus;
var connection = new CommConnection();
copter = new Copter(connection, SynchronizationContext.Current, _mapManager.Center.Lat, _mapManager.Center.Lng)
{
Id = id.ToString(),
Name = id.ToString(),
};
copter.VirtualId = 0;
int _index;
_index = _copterManager.Copters.AddCopter(copter, _copterManager.SortType);
copterStatus.Insert(_index, false);
copter.TextReceived += Copter_TextReceived;
}
}
}
}));
}
private async Task UpdateCommCopterInfo(int id, byte[] package, byte CommModuleVersion)
{
await AddCommCopter(id);
lock (locker)
{
var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == id.ToString());
if (copter!= null && copter is PLCopter)
{
PLCopter plcopter = (PLCopter)copter;
if (!plcopter.CommModuleConnected) plcopter.CommModuleConnected = true;
plcopter.InternalCopter.AnalyzeCommMouldePositionIntPacket(package, CommModuleVersion);
plcopter.CommModuleConnected = true;
}
}
}
}
}

View File

@ -41,7 +41,7 @@ namespace Plane.FormationCreator
}
}
private bool _ShowModifyTaskView = true;
private bool _ShowModifyTaskView = false;
public bool ShowModifyTaskView
{
get { return _ShowModifyTaskView; }

View File

@ -17,7 +17,8 @@ namespace Plane.FormationCreator.Converters
{
static DropShadowEffect _effect = new DropShadowEffect
{
Color = Colors.LightGray,
//任务选中颜色
Color = Colors.Firebrick, // Colors.LightGray,
// Color = Colors.White,
Direction = 90,
BlurRadius = 10

View File

@ -26,6 +26,9 @@ namespace Plane.FormationCreator.Converters
if (status == FlightTaskStatus.Paused)
return _PausedFill;
if (status == FlightTaskStatus.Selected)
return _PausedFill;
return _normalFill;
}

View File

@ -1,34 +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;
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;
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,55 +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();
}
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; } = new SolidColorBrush(Color.FromRgb(28, 151, 234));
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); }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -53,6 +53,7 @@ namespace Plane.FormationCreator.Formation
public static double DistanceTo(this ICopter copter, ICopter copter2)
{
return GeographyUtils.CalcDistance(copter.Latitude, copter.Longitude, copter.Altitude, copter2.Latitude, copter2.Longitude, copter2.Altitude);
//return GeographyUtils.CalcDistance_simple(copter.Latitude, copter.Longitude, copter.Altitude, copter2.Latitude, copter2.Longitude, copter2.Altitude);
}
public static double InPlaneDistanceTo(this ICopter copter, double targetLat, double targetLng)
@ -81,8 +82,10 @@ namespace Plane.FormationCreator.Formation
public static bool IsTooCloseTo(this ICopter copter, ICopter copter2, out double distance)
{
// distance = 0;
// return false; //效果图用 不检测碰撞
distance = Math.Round(copter.DistanceTo(copter2), 2) ;
//return false; //效果图用 不检测碰撞
if (copter.Altitude < 3 || copter2.Altitude < 3)
return false;

View File

@ -1,198 +1,196 @@
using Plane.Copters;
using Plane.Logging;
using GalaSoft.MvvmLight;
using Microsoft.Practices.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask : ObservableObject
{
public FlightTask(FlightTaskType type)
{
TaskType = type;
}
private FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
private ILogger _logger = ServiceLocator.Current.GetInstance<ILogger>();
private FlightTaskStatus _Status = FlightTaskStatus.Stop;
public FlightTaskStatus Status
{
get { return _Status; }
set { Set(nameof(Status), ref _Status, value); }
}
private FlightTaskType _TaskType;
public FlightTaskType TaskType
{
get { return _TaskType; }
set
{
Set(nameof(TaskType), ref _TaskType, value);
//if (_TaskType != value)
{
RaisePropertyChanged(nameof(TaskTypeIndex));
RaisePropertyChanged(nameof(TaskCnName));
}
}
}
/*
public int TaskTypeIndex
{
get { return (int)TaskType; }
set
{
TaskType = (FlightTaskType)value;
VerticalLift = false;
if ( (value == (int)FlightTaskType.Loiter) || (value == (int)FlightTaskType.Circle) )
{
VerticalLift = true;
}
}
}
*/
private string _TaskName = "";
public string TaskCnName
{
get
{
string name = "";
switch (TaskType)
{
case FlightTaskType.TakeOff: name = "起飞"; break;
case FlightTaskType.FlyTo: name = _TaskName == "" ? "航点" : _TaskName; break;
case FlightTaskType.Land: name = "降落"; break;
}
//name = (TaskIndex + 1).ToString() + "." + name;
return name;
}
set { Set(nameof(TaskCnName), ref _TaskName, value); }
}
public int TaskTypeIndex
{
get {
int index = 1;
switch (TaskType)
{
case FlightTaskType.TakeOff:index = 0; break;
case FlightTaskType.FlyTo: index = 1; break;
case FlightTaskType.Land: index = 2; break;
}
return index;
}
set
{
switch (value)
{
case 0: TaskType = FlightTaskType.TakeOff; break;
case 1: TaskType = FlightTaskType.FlyTo; break;
case 2: TaskType = FlightTaskType.Land; break;
}
}
}
//task在所以任务中的index
public int TaskIndex
{
get
{
return _flightTaskManager.Tasks.IndexOf(this);
}
}
public int TaskNum
{
get
{
return TaskIndex + 1;
}
}
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set { Set(nameof(IsSelected), ref _IsSelected, value); }
}
// 右键单击任务,用于隐藏任务图标, added by ZJF
private bool _IsRightSelected;
public bool IsRightSelected
{
get { return _IsRightSelected; }
set { Set(nameof(IsRightSelected), ref _IsRightSelected, value); }
}
public List<FlightTaskSingleCopterInfo> SingleCopterInfos { get; set; } = new List<FlightTaskSingleCopterInfo>();
private FlightTaskSingleCopterInfo _ModifyingSingleCopterInfo;
public FlightTaskSingleCopterInfo ModifyingSingleCopterInfo
{
get { return _ModifyingSingleCopterInfo; }
set { Set(nameof(ModifyingSingleCopterInfo), ref _ModifyingSingleCopterInfo, value); }
}
public async Task RunAsync()
{
switch (TaskType)
{
case FlightTaskType.FlyTo:
await RunFlyToTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.Turn:
await RunTurnTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.Circle:
await RunCircleTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.SimpleCircle:
await RunSimpleCircleTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.Loiter:
await RunLoiterTimeTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.TakeOff:
//多架同时起飞
//await MutilRunTakeOffTaskAsync().ConfigureAwait(false);
await NewMutilRunTakeOffTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.ReturnToLand: // Added by ZJF
//多架同时返航
await MutilRunReturnToLandTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.Land:
await MutilLandTaskAsync().ConfigureAwait(false);
break;
default:
throw new InvalidOperationException();
}
}
}
public enum FlightTaskType
{
FlyTo = 0,
Turn = 1,
Circle = 2,
Loiter = 3, // 加入悬停时间选项
// LEDAction = 4,
ReturnToLand = 4, // added by ZJF. 20160315
SimpleCircle = 5,
Land = 6,
TakeOff = 100
}
}
using Plane.Copters;
using Plane.Logging;
using GalaSoft.MvvmLight;
using Microsoft.Practices.ServiceLocation;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask : ObservableObject
{
public FlightTask(FlightTaskType type)
{
TaskType = type;
}
private FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
private ILogger _logger = ServiceLocator.Current.GetInstance<ILogger>();
private FlightTaskStatus _Status = FlightTaskStatus.Stop;
public FlightTaskStatus Status
{
get { return _Status; }
set { Set(nameof(Status), ref _Status, value); }
}
private FlightTaskType _TaskType;
public FlightTaskType TaskType
{
get { return _TaskType; }
set
{
Set(nameof(TaskType), ref _TaskType, value);
RaisePropertyChanged(nameof(TaskTypeIndex));
RaisePropertyChanged(nameof(TaskCnName));
}
}
/*
public int TaskTypeIndex
{
get { return (int)TaskType; }
set
{
TaskType = (FlightTaskType)value;
VerticalLift = false;
if ( (value == (int)FlightTaskType.Loiter) || (value == (int)FlightTaskType.Circle) )
{
VerticalLift = true;
}
}
}
*/
private string _TaskName = "";
public string TaskCnName
{
get
{
string name = "";
switch (TaskType)
{
case FlightTaskType.TakeOff: name = "起飞"; break;
case FlightTaskType.FlyTo: name = _TaskName == "" ? "航点" : _TaskName; break;
case FlightTaskType.Land: name = "降落"; break;
}
//name = (TaskIndex + 1).ToString() + "." + name;
return name;
}
set {
Set(nameof(TaskCnName), ref _TaskName, value);
RaisePropertyChanged(nameof(TaskCnName));
}
}
public int TaskTypeIndex
{
get {
int index = 1;
switch (TaskType)
{
case FlightTaskType.TakeOff:index = 0; break;
case FlightTaskType.FlyTo: index = 1; break;
case FlightTaskType.Land: index = 2; break;
}
return index;
}
set
{
switch (value)
{
case 0: TaskType = FlightTaskType.TakeOff; break;
case 1: TaskType = FlightTaskType.FlyTo; break;
case 2: TaskType = FlightTaskType.Land; break;
}
}
}
//task在所以任务中的index
public int TaskIndex
{
get
{
return _flightTaskManager.Tasks.IndexOf(this);
}
}
public int TaskNum
{
get
{
return TaskIndex + 1;
}
}
private bool _IsTransition=false;
public bool IsTransition
{
get { return _IsTransition; }
set {
Set(nameof(IsTransition), ref _IsTransition, value);
if ((value)&& (TaskCnName == "航点"))
TaskCnName = "过度";
}
}
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set { Set(nameof(IsSelected), ref _IsSelected, value); }
}
// 右键单击任务,用于隐藏任务图标, added by ZJF
private bool _IsRightSelected;
public bool IsRightSelected
{
get { return _IsRightSelected; }
set { Set(nameof(IsRightSelected), ref _IsRightSelected, value); }
}
public List<FlightTaskSingleCopterInfo> SingleCopterInfos { get; set; } = new List<FlightTaskSingleCopterInfo>();
private FlightTaskSingleCopterInfo _ModifyingSingleCopterInfo;
public FlightTaskSingleCopterInfo ModifyingSingleCopterInfo
{
get { return _ModifyingSingleCopterInfo; }
set { Set(nameof(ModifyingSingleCopterInfo), ref _ModifyingSingleCopterInfo, value); }
}
/// <summary>
/// 实际执行某一个任务--包含等待
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task RunAsync()
{
switch (TaskType)
{
case FlightTaskType.FlyTo:
await RunFlyToTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.TakeOff:
await NewMutilRunTakeOffTaskAsync().ConfigureAwait(false);
break;
case FlightTaskType.Land:
await MutilLandTaskAsync().ConfigureAwait(false);
break;
default:
throw new InvalidOperationException();
}
}
}
public enum FlightTaskType
{
FlyTo = 0,
Land = 6,
TakeOff = 100
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Copters;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
public static FlightTaskSingleCopterInfo CreateForCircleTask(ICopter copter, LatLng latLngOffset, float targetAlt, short centerDirectionDeg, int radius, int rate, int turns, ushort channel3)
{
var info = new FlightTaskSingleCopterInfo(copter)
{
LatLngOffset = latLngOffset,
TargetAlt = targetAlt,
CenterDirectionDeg = centerDirectionDeg,
Radius = radius,
Rate = rate,
Turns = turns,
Channel3 = channel3
};
return info;
}
private short _CenterDirectionDeg;
public short CenterDirectionDeg
{
get { return _CenterDirectionDeg; }
set { Set(nameof(CenterDirectionDeg), ref _CenterDirectionDeg, value); }
}
private int _Radius = 1000;
/// <summary>
/// 圆的半径,单位为厘米。
/// </summary>
public int Radius
{
get { return _Radius; }
set { Set(nameof(Radius), ref _Radius, value); }
}
private int _Rate = 20;
/// <summary>
/// 转圈的角速度,单位为 deg/s范围为 -90 到 90。
/// </summary>
public int Rate
{
get { return _Rate; }
set { Set(nameof(Rate), ref _Rate, value); }
}
private int _Turns = 1;
public int Turns
{
get { return _Turns; }
set { Set(nameof(Turns), ref _Turns, value); }
}
private ushort _Channel3 = 1500;
public ushort Channel3
{
get { return _Channel3; }
set { Set(nameof(Channel3), ref _Channel3, value); }
}
}
}

View File

@ -61,7 +61,16 @@ namespace Plane.FormationCreator.Formation
public bool IsLandWaypoint
{
get { return _IsLandWaypoint; }
set { Set(nameof(IsLandWaypoint), ref _IsLandWaypoint, value); }
set {
Set(nameof(IsLandWaypoint), ref _IsLandWaypoint, value);
if (_flightTaskManager.SelectedTask == null) return;
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
info._IsLandWaypoint = _IsLandWaypoint;
}
}
}
private bool _IsChangeSpeed = false;
@ -72,7 +81,15 @@ namespace Plane.FormationCreator.Formation
public bool IsChangeSpeed
{
get {return _IsChangeSpeed; }
set { Set(nameof(IsChangeSpeed), ref _IsChangeSpeed, value); }
set {
Set(nameof(IsChangeSpeed), ref _IsChangeSpeed, value);
if (_flightTaskManager.SelectedTask == null) return;
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
info._IsChangeSpeed = _IsChangeSpeed;
}
}
}
@ -83,7 +100,14 @@ namespace Plane.FormationCreator.Formation
public float LevelSpeed
{
get { return _LevelSpeed; }
set { Set(nameof(LevelSpeed), ref _LevelSpeed, value); }
set {
Set(nameof(LevelSpeed), ref _LevelSpeed, value);
if (_flightTaskManager.SelectedTask == null) return;
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
info._LevelSpeed = _LevelSpeed;
}
}
}
@ -94,7 +118,14 @@ namespace Plane.FormationCreator.Formation
public float UpSpeed
{
get { return _UpSpeed; }
set { Set(nameof(UpSpeed), ref _UpSpeed, value); }
set {
Set(nameof(UpSpeed), ref _UpSpeed, value);
if (_flightTaskManager.SelectedTask == null) return;
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
info._UpSpeed = _UpSpeed;
}
}
}
private float _DownSpeed = 1.5f;
@ -104,7 +135,14 @@ namespace Plane.FormationCreator.Formation
public float DownSpeed
{
get { return _DownSpeed; }
set { Set(nameof(DownSpeed), ref _DownSpeed, value); }
set {
Set(nameof(DownSpeed), ref _DownSpeed, value);
if (_flightTaskManager.SelectedTask == null) return;
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.SelectedTask.SingleCopterInfos)
{
info._DownSpeed = _DownSpeed;
}
}
}
/*

View File

@ -1,18 +1,24 @@
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Plane.CommunicationManagement;
using Plane.Copters;
using Plane.Windows.Messages;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
public static FlightTaskSingleCopterInfo CreateForFlyToTask(ICopter copter)
{
var info = new FlightTaskSingleCopterInfo(copter)
@ -26,19 +32,24 @@ namespace Plane.FormationCreator.Formation
{
LEDInfo LedInfo = new LEDInfo();
LEDInfos.Add(LedInfo);
LedInfo.RemoveEvent += new LEDInfo.RemoveEventHandler(LEDRemove);
LedInfo.RemoveEvent += new LEDInfo.RemoveEventHandler(LEDRemove);
LedInfo.PropertyChanged += (sender, e) =>{RefLEDSumTime();};
RefLEDSumTime();
}
public void AddLEDInfo(LEDInfo LedInfo)
{
LEDInfos.Add(LedInfo);
LedInfo.RemoveEvent += new LEDInfo.RemoveEventHandler(LEDRemove);
LedInfo.PropertyChanged += (sender, e) => { RefLEDSumTime(); };
RefLEDSumTime();
}
public void LEDRemove(object sender)
{
LEDInfo LedInfo = sender as LEDInfo;
LEDInfos.Remove(LedInfo);
RefLEDSumTime();
}
@ -54,9 +65,11 @@ namespace Plane.FormationCreator.Formation
return _AddLEDCommand ?? (_AddLEDCommand = new RelayCommand<double>(async =>
{
AddLEDInfo();
}));
}
}
private CommModuleManager _commModuleManager = CommModuleManager.Instance;
private ICommand _SetAllCopterLEDCommand;
public ICommand SetAllCopterLEDCommand
@ -82,8 +95,84 @@ namespace Plane.FormationCreator.Formation
}
}
public void RefLEDSumTime()
{
float _ledSumTime = 0;
foreach (LEDInfo led in LEDInfos)
{
_ledSumTime += (float)led.Delay;
}
LEDSumTime =(float) Math.Round(_ledSumTime, 1);
}
//灯光总时长
private float _LEDSumTime = 0;
public float LEDSumTime
{
get { return _LEDSumTime; }
set { Set(nameof(LEDSumTime), ref _LEDSumTime, value); }
}
bool LEDTestRun = false;
/*
private string _TestLEDtxt = "测试";
public string TestLEDtxt
{
get { return _TestLEDtxt; }
set { Set(nameof(TestLEDtxt), ref _TestLEDtxt, value); }
}
*/
/*
LEDMode 0 = "常亮"
1="同步闪烁(单色)" />
2 = "异步闪烁(随机)" />
3="渐亮" />
4 = "渐暗" />
5="呼吸灯" />
6 = "同步闪烁(随机)" />
7="异步闪烁(单色)" />
8 = "拉烟" />(50 ? )
*/
//测试灯光
private ICommand _TestCopterLEDCommand;
public ICommand TestCopterLEDCommand
{
get
{
return _TestCopterLEDCommand ?? (_TestCopterLEDCommand = new RelayCommand<double>(async =>
{
if (!LEDTestRun)
{
Task.Run(() =>
{
LEDTestRun = true;
foreach (LEDInfo vLEDInfo in LEDInfos)
{
Thread.Sleep((int)(vLEDInfo.Delay * 1000));
if (!LEDTestRun) break;
_commModuleManager.LED_TaskAsync(vLEDInfo.LEDMode, vLEDInfo.LEDInterval, vLEDInfo.LEDTimes, vLEDInfo.LEDRGB, this.Copter);
}
//LEDTestRun = false;
});
}else
{
LEDTestRun = false;
_commModuleManager.LED_TaskAsync(255, 0, 0, "000000", this.Copter);
_commModuleManager.LED_TaskAsync(255, 0, 0, "000000", this.Copter);
_commModuleManager.LED_TaskAsync(255, 0, 0, "000000", this.Copter);
}
}));
}
}
private ICommand _SetSelectedCopterLEDCommand;
public ICommand SetSelectedCopterLEDCommand
{
@ -112,13 +201,23 @@ namespace Plane.FormationCreator.Formation
}
}
public class LEDInfo
public class LEDInfo :INotifyPropertyChanged
{
private double delay = 1; //灯光延时 单位100ms 从当前任务开为0延时几秒后设置LED
private int ledmode = 0; //灯光模式 0常亮 1闪烁 2随机闪烁(RGB无意义)
private int ledrate = 0; //闪烁延时 单位100ms
private float ledInterval = 0; //闪烁延时 单位:秒
private int ledrate = 0; //为了和以前文件兼容自动转为ledInterval
private int ledtimes = 0; //次数 (预留、暂取消其意义)
private string ledRGB = "FFFFFF"; //灯光颜色
private SolidColorBrush _DrawRGB = new SolidColorBrush(Color.FromRgb(0xFF, 0xFF, 0xFF));
protected internal virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
public LEDInfo()
{
@ -129,13 +228,16 @@ namespace Plane.FormationCreator.Formation
{
delay = led.delay;
ledmode = led.ledmode;
ledrate = led.ledrate;
ledRGB = led.ledRGB;
ledInterval = led.ledInterval;
LEDRGB = led.ledRGB;
}
public double Delay
{
get { return delay; }
set { delay = value; }
set {
delay = Math.Round(value, 1);
OnPropertyChanged("delay");
}
}
public int LEDMode
@ -143,11 +245,25 @@ namespace Plane.FormationCreator.Formation
get { return ledmode; }
set { ledmode = value; }
}
public float LEDInterval
{
get { return ledInterval; }
set { ledInterval = value;
if (ledInterval != 0)
ledrate = (int)Math.Round(1 / ledInterval); //用于兼容老版本
}
}
public int LEDRate
{
get { return ledrate; }
set { ledrate = value; }
set { ledrate = value;
if ((ledrate!=0)&&(ledInterval==0))
ledInterval = 1 / ledrate;
}
}
public int LEDTimes
{
get { return ledtimes; }
@ -157,9 +273,29 @@ namespace Plane.FormationCreator.Formation
public string LEDRGB
{
get { return ledRGB; }
set { ledRGB = value; }
set {
ledRGB = value;
DrawRGB.Color= (Color)ColorConverter.ConvertFromString("#" + ledRGB);
}
}
[Newtonsoft.Json.JsonIgnore]
public SolidColorBrush DrawRGB
{
get
{
return _DrawRGB;
}
set
{
_DrawRGB = value;
}
}
public delegate void RemoveEventHandler(object sender);
public event RemoveEventHandler RemoveEvent;
private ICommand _RemoveLEDCommand;

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Copters;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
public static FlightTaskSingleCopterInfo CreateForLoiterTimeTask(ICopter copter, LatLng latLngOffset, float targetAlt)
{
var info = new FlightTaskSingleCopterInfo(copter)
{
LatLngOffset = latLngOffset,
TargetAlt = targetAlt
};
return info;
}
}
}

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Copters;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
// This file is added by ZJF
public static FlightTaskSingleCopterInfo CreateForReturnToLandTask(ICopter copter, float targetAlt)
{
var info = new FlightTaskSingleCopterInfo(copter)
{
TargetAlt = targetAlt
};
return info;
}
}
}

View File

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Copters;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
public static FlightTaskSingleCopterInfo CreateForSimpleCircleTask(ICopter copter, LatLng latLngOffset, float targetAlt, int rate, int turns, ushort channel3)
{
var info = new FlightTaskSingleCopterInfo(copter)
{
LatLngOffset = latLngOffset,
TargetAlt = targetAlt,
Rate = rate,
Turns = turns,
Channel3 = channel3
};
return info;
}
}
}

View File

@ -13,7 +13,9 @@ namespace Plane.FormationCreator.Formation
{
var info = new FlightTaskSingleCopterInfo(copter)
{
TargetAlt = targetAlt
TargetAlt = targetAlt,
TargetLat = copter.Latitude,
TargetLng=copter.Longitude
};
return info;
}

View File

@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plane.Copters;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTaskSingleCopterInfo
{
public static FlightTaskSingleCopterInfo CreateForTurnTask(ICopter copter, LatLng latLngOffset, float targetAlt, short targetHeading)
{
var info = new FlightTaskSingleCopterInfo(copter)
{
LatLngOffset = latLngOffset,
TargetAlt = targetAlt,
TargetHeading = targetHeading
};
return info;
}
private short _TargetHeading;
public short TargetHeading
{
get { return _TargetHeading; }
set { Set(nameof(TargetHeading), ref _TargetHeading, value); }
}
}
}

View File

@ -1,12 +1,13 @@
public enum FlightTaskStatus
{
Stop,
Running,
Paused
}
public enum TasksStatus
{
Stop,
Running,
Paused
public enum FlightTaskStatus
{
Stop,
Running,
Paused,
Selected
}
public enum TasksStatus
{
Stop,
Running,
Paused
}

View File

@ -1,137 +0,0 @@
using Plane.Copters;
using Plane.Geography;
using Plane.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask
{
public async Task RunCircleTaskAsync()
{
// 林俊清, 20150922, 首先一起调好方向。
await Task.WhenAll(
SingleCopterInfos.Select(info =>
{
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
return Task.Run(()=> { });
info.TargetHeading = info.CenterDirectionDeg;
return TurnTaskFlySingleCopterAsync(info);
})
).ConfigureAwait(false);
await Task.WhenAll(
SingleCopterInfos.Select(info => CircleTaskFlySingleCopterAsync(info))
).ConfigureAwait(false);
}
private async Task CircleTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info)
{
// 林俊清, 20150907, 目前不对 Circle 进行仿真。
if (info.Copter is FakeCopter)
{
await Task.Delay(1000);
return;
}
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
return;
await info.Copter.SetParamAsync("CIRCLE_RADIUS", info.Radius);
await info.Copter.SetParamAsync("CIRCLE_RATE", info.Rate);
var center = GeographyUtils.CalcLatLngSomeMetersAway2D(info.Copter.Latitude, info.Copter.Longitude, info.CenterDirectionDeg, 10);
await info.Copter.CircleAsync();
while (info.Copter.State != Copters.CopterState.Circling)
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
}
await info.Copter.SetChannelsAsync(ch3: info.Channel3);
for (int i = info.Turns; i > 0; i--)
{
//// 等待一段时间,让飞行器飞出一段距离。
//for (int i = 0; i < 3000 / 25; i++)
//{
// if (_flightTaskManager.IsPaused == true)
// {
// info.Copter.Hover();
// return;
// }
// await Task.Delay(25).ConfigureAwait(false);
//}
//var log = new StringBuilder(1024);
//var lastLogTime = DateTime.Now;
bool step1 = false;
while (true)
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
var angle = info.Radius == 0 ? NormalizeAngleDeg(info.Copter.Heading - info.CenterDirectionDeg) : GetNormalizedAngleDeg(info, center);
//log.AppendLine($"{angle} {step1}");
if (!step1)
{
if (angle > 100 && angle < 330)
{
step1 = true;
//log.AppendLine($"step1 is true now.");
}
}
else if (angle > 340 || angle < 5)
{
//log.AppendLine("break");
break;
}
//if (lastLogTime.AddSeconds(10) < DateTime.Now)
//{
// Logger.Instance.Log(log.ToString());
// log.Clear();
// lastLogTime = DateTime.Now;
//}
await Task.Delay(25).ConfigureAwait(false);
}
//Logger.Instance.Log(log.ToString());
}
await info.Copter.HoverAsync();
}
private static double GetNormalizedAngleDeg(FlightTaskSingleCopterInfo info, Tuple<double, double> center)
{
var angle = info.Copter.InPlaneDirectionToDeg(center.Item1, center.Item2) - info.CenterDirectionDeg;
return NormalizeAngleDeg(angle);
}
private static double NormalizeAngleDeg(double angle)
{
while (true)
{
if (angle < 0) angle += 360;
else if (angle >= 360) angle -= 360;
else break;
}
return angle;
}
}
}

View File

@ -1,280 +1,216 @@
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 = 10;
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();
/*
for (int i = 0; i < 5; i++)
{
await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, info.TargetAlt);
await Task.Delay(10).ConfigureAwait(false);
}
*/
double targetLat = info.TargetLat;
double targetLng = info.TargetLng;
if (info.IsLandWaypoint)
{
targetLat = info.Copter.TakeOffPoint.Latitude;
targetLng = info.Copter.TakeOffPoint.Longitude;
}
//发送目标航点1次
await info.Copter.FlyToAsync(targetLat, targetLng, info.TargetAlt);
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(10).ConfigureAwait(false); //判断是否到达位置10hz
// if (info.LEDInfos.Count > 0)
// {
// string LEDRGB = "";
// List<LEDInfo> 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<LEDInfo> 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 (ts.TotalMilliseconds / 10 > sendFlyToTimes) // 每500ms发送一遍指点坐标
{
sendFlyToTimes++;
for (int i = 0; i < 2; i++)
{
await info.Copter.FlyToAsync(targetLat, targetLng, info.TargetAlt);
await Task.Delay(10).ConfigureAwait(false);
}
//dtLastTime = dtNow;
}
// 当该飞机被标记时,悬停并跳过飞行任务
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<FlightTaskSingleCopterInfo> 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;
/// <summary>
/// 单独飞机执行飞行任务
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
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<LEDInfo> 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;
}
if (_flightTaskManager.IsEmergencyRet == true)
{
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<FlightTaskSingleCopterInfo> 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;
}
}
}

View File

@ -36,8 +36,34 @@ namespace Plane.FormationCreator.Formation
DateTime dtLastTime = DateTime.Now;
TimeSpan ts = dtNow - dtLastTime;
int waittime = (int)info.LandWaitTime * 1000;
await Task.Delay(waittime).ConfigureAwait(false);
while (ts.TotalMilliseconds < waittime)
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(100).ConfigureAwait(true);
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
}
await info.Copter.LandAsync();
while ((info.Copter.Altitude>0.0f))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(100).ConfigureAwait(true);
}
}
}
}

View File

@ -1,723 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask
{
private float _LoiterTimeAttr = 0.0f;
public float LoiterTimeAttr
{
get { return _LoiterTimeAttr; }
set
{
Set(nameof(LoiterTimeAttr), ref _LoiterTimeAttr, value);
}
}
// 改变机头
private bool _ChangeYaw = false;
public bool ChangeYaw
{
get { return _ChangeYaw; }
set
{
Set(nameof(ChangeYaw), ref _ChangeYaw, value);
}
}
// 机头方向0为北顺时针360
private float _HeadYaw = 1.0f;
public float HeadYaw
{
get { return _HeadYaw; }
set
{
Set(nameof(HeadYaw), ref _HeadYaw, value);
}
}
// LED灯闪烁
private bool _flashAttr = false;
public bool flashAttr
{
get { return _flashAttr; }
set
{
Set(nameof(flashAttr), ref _flashAttr, value);
}
}
// LED闪烁次数
private float _flashPeriodAttr = 1.0f;
public float flashPeriodAttr
{
get { return _flashPeriodAttr; }
set
{
Set(nameof(flashPeriodAttr), ref _flashPeriodAttr, value);
}
}
private string Name2Index(string name) // 获取指定copter名字对应的序号
{
int index = -1;
for (int i = 0; i < SingleCopterInfos.Count; i++)
{
if (name.Equals(SingleCopterInfos[i].Copter.Name))
{
return i.ToString();
}
}
return index.ToString();
}
// 闪烁的飞机名字编号
private string _flashCopterNameArray = "";
public string flashCopterNameArray
{
get { return _flashCopterNameArray; }
set
{
Set(nameof(flashCopterNameArray), ref _flashCopterNameArray, value);
flashCopterIndexArray = "";
string[] copterArray = flashCopterNameArray.Split(',');
for (int i = 0; i < copterArray.Length; i++)
{
flashCopterIndexArray += Name2Index(copterArray[i])+',';
}
}
}
// 闪烁的飞机序号编号
private string _flashCopterIndexArray = "";
public string flashCopterIndexArray
{
get { return _flashCopterIndexArray; }
set
{
Set(nameof(flashCopterIndexArray), ref _flashCopterIndexArray, value);
}
}
// LED走马灯
private bool _oneByOneAttr = false;
public bool oneByOneAttr
{
get { return _oneByOneAttr; }
set
{
Set(nameof(oneByOneAttr), ref _oneByOneAttr, value);
}
}
// LED走马灯次数
private float _oneByOnePeriodAttr = 1.0f;
public float oneByOnePeriodAttr
{
get { return _oneByOnePeriodAttr; }
set
{
Set(nameof(oneByOnePeriodAttr), ref _oneByOnePeriodAttr, value);
}
}
private int[] columnFirst = {0, 1, 2, 3, 4 };
private int[] columnSecond = { 5, 6, 7, 8, 9 };
private int[] columnThird = { 10, 11, 12, 13, 14 };
private int[] columnFourth = { 15, 16, 17, 18, 19 };
private int[] columnFive = { 20, 21, 22, 23, 24 };
private int[] columnSix = { 25, 26, 27, 28, 29 };
private int[] rowFirst = { 0, 5, 10, 15, 20, 25 };
private int[] rowSecond = { 1, 6, 11, 16, 21, 26 };
private int[] rowThird = { 2, 7, 12, 17, 22, 27 };
private int[] rowFourth = { 3, 8, 13, 18, 23, 28 };
private int[] rowFive = { 4, 9, 14, 19, 24, 29 };
private int[] rowFirstForEight = { 0, 1, 2, 3 };
private int[] rowSecondForEight = { 4, 5, 6, 7 };
private int[] doubleColumnFirst = { 0, 1, 2, 3, 4, 25, 26, 27, 28, 29 };
private int[] doubleColumnSecond = { 5, 6, 7, 8, 9, 20, 21, 22, 23, 24 };
private int[] doubleColumnThird = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
private int[] circleFirst = { 0, 1, 2, 3, 4, 9, 14, 19, 24, 29, 28, 27, 26, 25, 20, 15, 10, 5 };
private int[] circleSecond = { 6, 7, 8, 13, 18, 23, 22, 21, 16, 11 };
private int[] circleThird = { 12, 17 };
private int[] lineFirst = { 4 };
private int[] lineSecond = { 3, 9 };
private int[] lineThird = { 2, 8, 14 };
private int[] lineFourth = { 1, 7, 13, 19 };
private int[] lineFive = { 0, 6, 12, 18, 24 };
private int[] lineSix = { 5, 11, 17, 23, 29 };
private int[] lineSeven = { 10, 16, 22, 28 };
private int[] lineEight = { 15, 21, 27 };
private int[] lineNine = { 20, 26 };
private int[] lineTen = { 25 };
public async Task RunLoiterTimeTaskAsync()
{
if (ChangeYaw)
{
await Task.WhenAll(SingleCopterInfos.Select(info => SetCopterYawAsync(info,HeadYaw)));
}
// 判断flashPeriodAttr, oneByOnePeriodAttr的值执行不同的闪烁模式
// 当flashPeriodAttr小于10正常闪烁即没有预制闪烁模式
// 当flashPeriodAttr大于等于10小于20执行预制闪烁模式
// 当flashPeriodAttr大于等于20 改变飞控闪烁模式以oneByOnePeriodAttr作为周期值
//LEDFlashPlanAsync需要30架飞机
if ((flashPeriodAttr >= 10.0f) && (flashPeriodAttr < 20.0f))
{
await LEDFlashPlanAsync();
return;
}
//需要固件支持
if (flashPeriodAttr >= 20.0f)
{
await LEDFlashParaModifyPlanAsync();
return;
}
var infos = SingleCopterInfos;
if (flashAttr) // LED闪烁显示效果
{
if (flashCopterIndexArray.Equals(""))
return;
string[] copterArray = flashCopterIndexArray.Split(',');
var tasks_selected = new Task[copterArray.Length];
// LED灯全灭
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(1000).ConfigureAwait(false);
// 选中的飞机LED灯全亮
for (int i = 0; i < copterArray.Length; i++)
{
int index = int.Parse(copterArray[i]);
var info = infos[index];
tasks_selected[i] = await Task.Factory.StartNew(async () =>
{
var internalInfo = info;
await LEDFlashTaskFlySingleCopterAsync(internalInfo, true);
});
}
await Task.WhenAll(tasks_selected).ConfigureAwait(false);
await Task.Delay(3000).ConfigureAwait(false);
// LED灯全亮
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
//延时等待
//判断是否下一步
DateTime start = DateTime.Now;
while (true)
{
if (_flightTaskManager.IsPaused == true)
{
await Task.WhenAll(SingleCopterInfos.Select(info => (info.Copter.HoverAsync())));
return;
}
DateTime end = DateTime.Now;
TimeSpan ts = end - start;
//等待指定时间
if (ts.TotalMilliseconds > LoiterTimeAttr * 1000)
break;
await Task.Delay(20).ConfigureAwait(false);
}
}
else if (oneByOneAttr) // LED走马灯显示效果
{
if (flashCopterNameArray.Equals(""))
return;
string[] copterArray = flashCopterIndexArray.Split(',');
//LED全灭
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(1000).ConfigureAwait(false);
// LED灯一个接一个全亮
for (int i = 0; i < copterArray.Length; i++)
{
if (copterArray[i] == "") break;
int index = int.Parse(copterArray[i]);
var info = infos[index];
await LEDFlashTaskFlySingleCopterAsync(info, true);
await Task.Delay(200).ConfigureAwait(false);
}
await Task.Delay(1000).ConfigureAwait(false);
//////////////////全部闪烁一次
// LED灯全亮
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
await Task.Delay(200).ConfigureAwait(false);
// LED灯全灭
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(200).ConfigureAwait(false);
/////////////////////////////////////
//////////////////全部闪烁一次
// LED灯全亮
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
await Task.Delay(200).ConfigureAwait(false);
// LED灯全灭
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(200).ConfigureAwait(false);
/////////////////////////////////////
//////////////////全部闪烁一次
// LED灯全亮
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
await Task.Delay(200).ConfigureAwait(false);
// LED灯全灭
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(200).ConfigureAwait(false);
/////////////////////////////////////
// LED灯全亮
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
//延时等待
//判断是否下一步
DateTime start = DateTime.Now;
while (true)
{
if (_flightTaskManager.IsPaused == true)
{
await Task.WhenAll(SingleCopterInfos.Select(info => (info.Copter.HoverAsync())));
return;
}
DateTime end = DateTime.Now;
TimeSpan ts = end - start;
//等待指定时间
if (ts.TotalMilliseconds > LoiterTimeAttr * 1000)
break;
await Task.Delay(20).ConfigureAwait(false);
}
}
else // 没有LED显示效果只等待
{
//判断是否下一步
DateTime start = DateTime.Now;
while (true)
{
if (_flightTaskManager.IsPaused == true)
{
await Task.WhenAll(SingleCopterInfos.Select(info => (info.Copter.HoverAsync())));
return;
}
DateTime end = DateTime.Now;
TimeSpan ts = end - start;
//等待指定时间
if (ts.TotalMilliseconds > LoiterTimeAttr * 1000)
break;
await Task.Delay(20).ConfigureAwait(false);
}
}
}
private async Task LEDFlashParaModifyPlanAsync()
{
/*
await LEDFlashParaModifyAsync(rowFirstForEight);
await Task.Delay(500).ConfigureAwait(false);
await LEDFlashParaModifyAsync(rowSecondForEight);
await Task.Delay(500).ConfigureAwait(false);
*/
int copterCount = SingleCopterInfos.Count();
int[] intArray = new int[copterCount];
for (int ii=0; ii<copterCount; ii++)
{
intArray[ii] = ii;
}
await LEDFlashParaModifyAsync(intArray);
/*
await LEDFlashParaModifyAsync(rowFirst);
await Task.Delay(500).ConfigureAwait(false);
await LEDFlashParaModifyAsync(rowSecond);
await Task.Delay(500).ConfigureAwait(false);
await LEDFlashParaModifyAsync(rowThird);
await Task.Delay(500).ConfigureAwait(false);
await LEDFlashParaModifyAsync(rowFourth);
await Task.Delay(500).ConfigureAwait(false);
await LEDFlashParaModifyAsync(rowFive);
await Task.Delay(500).ConfigureAwait(false);
*/
}
private async Task LEDFlashParaModifyAsync(int[] LEDArray)
{
var infos = SingleCopterInfos;
var tasks_selected = new Task[LEDArray.Length];
for (int i = 0; i < LEDArray.Length; i++)
{
var info = infos[LEDArray[i]];
tasks_selected[i] = await Task.Factory.StartNew(async () =>
{
var internalInfo = info;
await LEDParaModifySingleCopterAsync(internalInfo, oneByOnePeriodAttr);
});
}
await Task.WhenAll(tasks_selected).ConfigureAwait(false);
}
private async Task SetCopterYawAsync(FlightTaskSingleCopterInfo info, float headyaw)
{
var copter = info.Copter;
// await Task.Delay(200).ConfigureAwait(false);
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
var tasks = new Task[1];
tasks[0] = Task.Run(async () =>
{
try
{
await copter.SetMobileControlAsync(yaw: headyaw);
while (!copter.ArrivedHeading((short)headyaw))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
}
}
catch (TimeoutException ex)
{
_logger.Log($"SetYAWtimeout, {ex.Message}, CopterId: {copter.Id}。");
}
});
await Task.WhenAll(tasks).ConfigureAwait(false);
}
private async Task LEDParaModifySingleCopterAsync(FlightTaskSingleCopterInfo info, float count)
{
var copter = info.Copter;
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
var tasks = new Task[1];
tasks[0] = Task.Run(async () =>
{
try
{
if (count == 1.0)
await copter.SetShowLEDAsync(true);
else
await copter.SetShowLEDAsync(false);
//await copter.SetParamAsync("NTF_SHOWLED", count, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"SetShowLEDAsync 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
/*
var tasks = new Task[2];
tasks[0] = Task.Run(async () =>
{
try
{
await copter.SetParamAsync("NOTI_GPSLED", count, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"NOTI_GPSLED 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
tasks[1] = Task.Run(async () =>
{
try
{
await copter.SetParamAsync("NOTI_ARMLED", count, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"NOTI_ARMLED 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
*/
await Task.WhenAll(tasks).ConfigureAwait(false);
}
/**
* isOn为trueisOn为false
*/
private async Task LEDFlashTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info, bool isOn)
{
var copter = info.Copter;
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
// float gpsLed = await c.GetParamAsync("NOTI_GPSLED");
/*
float ledControl = 0.0f; //关灯
if (isOn)
{
ledControl = 1.0f; //长亮
}
*/
var tasks = new Task[1];
tasks[0] = Task.Run(async () =>
{
try
{
await copter.SetShowLEDAsync(isOn);
// await copter.SetParamAsync("NTF_SHOWLED", ledControl, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"SetShowLED 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
/*
var tasks = new Task[2];
tasks[0] = Task.Run(async () =>
{
try
{
await copter.SetParamAsync("NOTI_GPSLED", ledControl, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"NOTI_GPSLED 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
tasks[1] = Task.Run(async () =>
{
try
{
await copter.SetParamAsync("NOTI_ARMLED", ledControl, 5000);
}
catch (TimeoutException ex)
{
_logger.Log($"NOTI_ARMLED 超时, {ex.Message}, CopterId: {copter.Id}。");
}
});
*/
await Task.WhenAll(tasks).ConfigureAwait(false);
}
private async Task LEDFlashPlanAsync()
{
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(500).ConfigureAwait(false);
await LEDColumnFlashAsync();
await Task.Delay(500).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(500).ConfigureAwait(false);
await LEDDoubleColumnFlashAsync();
await Task.Delay(500).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(500).ConfigureAwait(false);
await LEDLineFlashAsync();
await Task.Delay(500).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(500).ConfigureAwait(false);
await LEDCircleFlashAsync();
await Task.Delay(500).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(200).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
await Task.Delay(200).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, false)));
await Task.Delay(200).ConfigureAwait(false);
await Task.WhenAll(SingleCopterInfos.Select(info => LEDFlashTaskFlySingleCopterAsync(info, true)));
await Task.Delay(200).ConfigureAwait(false);
}
// 一排一排闪烁 需要30架飞机6排一排5架一排排闪灯
private async Task LEDColumnFlashAsync()
{
await LEDArrayFlashAsync(columnFirst);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(columnSecond);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(columnThird);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(columnFourth);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(columnFive);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(columnSix);
await Task.Delay(200).ConfigureAwait(false);
}
// 以圆圈收缩形式显示
private async Task LEDCircleFlashAsync()
{
await LEDArrayFlashAsync(circleFirst);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(circleSecond);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(circleThird);
await Task.Delay(200).ConfigureAwait(false);
}
// 两列同时闪烁
private async Task LEDDoubleColumnFlashAsync()
{
await LEDArrayFlashAsync(doubleColumnFirst);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(doubleColumnSecond);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(doubleColumnThird);
await Task.Delay(200).ConfigureAwait(false);
}
// 斜线方式闪烁
private async Task LEDLineFlashAsync()
{
await LEDArrayFlashAsync(lineFirst);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineSecond);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineThird);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineFourth);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineFive);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineSix);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineSeven);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineEight);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineNine);
await Task.Delay(200).ConfigureAwait(false);
await LEDArrayFlashAsync(lineTen);
await Task.Delay(200).ConfigureAwait(false);
}
private async Task LEDArrayFlashAsync(int[] LEDArray)
{
var infos = SingleCopterInfos;
var tasks_selected = new Task[LEDArray.Length];
for (int i = 0; i < LEDArray.Length; i++)
{
var info = infos[LEDArray[i]];
tasks_selected[i] = await Task.Factory.StartNew(async () =>
{
var internalInfo = info;
await LEDFlashTaskFlySingleCopterAsync(internalInfo, true);
});
}
await Task.WhenAll(tasks_selected).ConfigureAwait(false);
}
}
}

View File

@ -1,489 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask
{
private float _RTLAlt = 20.0f;
public float RTLAlt
{
get { return _RTLAlt; }
set { Set(nameof(RTLAlt), ref _RTLAlt, value); }
}
private int _RetNumAttr = 1;
public int RetNumAttr
{
get { return _RetNumAttr; }
set
{
Set(nameof(RetNumAttr), ref _RetNumAttr, value);
}
}
public async Task RunReturnToLandTaskAsync()
{
int TaskCount = _flightTaskManager.Tasks.Count();
if (TaskCount > 1)
{
var infos = SingleCopterInfos;
// var infos = SingleCopterInfos.OrderByDescending(i => i.TargetAlt).ToList();
var tasks = new Task[infos.Count];
var tasksTmp = new Task[infos.Count];
for (int i = 0; i < infos.Count; i++)
{
var info = infos[i];
// var copter = info.Copter;
if (info.RTLStage <= 1) // 当前阶段小于等于1时进入
{
await ReturnToLandTaskFlySingleCopterAsync(info);
}
tasksTmp[i] = ReturnToLandSecondTaskAsync(info);
}
await Task.WhenAll(tasksTmp).ConfigureAwait(false);
if (_flightTaskManager.IsPaused == false)
{
for (int i = 0; i < infos.Count; i++)
{
var info = infos[i];
info.RTLStage = 0;
}
}
}
}
public async Task MutilRunReturnToLandTaskAsync()
{
int TaskCount = _flightTaskManager.Tasks.Count();
if (TaskCount > 1)
{
var infos = SingleCopterInfos;
int copterCount = infos.Count;
int integerPart = copterCount / RetNumAttr;
int residualPart = copterCount % RetNumAttr;
var tasksTmp = new Task[infos.Count];
//整数部分执行返航降落
for (int i = 0; i < integerPart; i++)
{
var tasksRetutn = new Task[RetNumAttr*2];
//设置返航任务
for (int j = RetNumAttr * i; j < RetNumAttr * (i + 1); j++)
{
var info = infos[j];
int indexTmp = j - RetNumAttr * i;
// var copter = info.Copter;
if (info.RTLStage <= 1) // 当前阶段小于等于1时进入
{
tasksRetutn[indexTmp] = ReturnToLandTaskFlySingleCopterAsync(info);
}
else
{
tasksRetutn[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
//设置降落任务
if (i > 0)
{
for (int j = RetNumAttr * (i - 1); j < RetNumAttr * (i); j++)
{
var info = infos[j];
int indexTmp = RetNumAttr+ j - RetNumAttr * (i-1);
// var copter = info.Copter;
if (info.RTLStage == 2) // 当前阶段小于等于1时进入
{
tasksRetutn[indexTmp] = ReturnToLandSecondTaskAsync(info);
}
else
{
tasksRetutn[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
}
else {
//第一波返航,降落任务为空
for (int j = RetNumAttr * (i +1); j < RetNumAttr * (i+2); j++)
{
int indexTmp = j - RetNumAttr * i;
tasksRetutn[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
//开始执行这波返航和上波降落
await Task.WhenAll(tasksRetutn).ConfigureAwait(false);
//上波降落后设置为0
if (_flightTaskManager.IsPaused == false)
{
if (i > 0)
{
for (int j = RetNumAttr * (i - 1); j < RetNumAttr * (i); j++)
{
var info = infos[j];
info.RTLStage = 0;
}
}
}
}
if (residualPart > 0)
{
var tasksreturn = new Task[residualPart+ RetNumAttr];
//余数部分开始返航
for (int j = integerPart * RetNumAttr; j < RetNumAttr * integerPart + residualPart; j++)
{
var info = infos[j];
int indexTmp = j - RetNumAttr * integerPart;
// var copter = info.Copter;
if (info.RTLStage <= 1) // 当前阶段小于等于1时进入
{
tasksreturn[indexTmp] = ReturnToLandTaskFlySingleCopterAsync(info);
}
else
{
tasksreturn[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
//无余数的整数部分最后一波开始降落
// var tasksLastland = new Task[RetNumAttr];
for (int j = RetNumAttr * (integerPart - 1); j < RetNumAttr * (integerPart); j++)
{
var info = infos[j];
int indexTmp = RetNumAttr + j - RetNumAttr * integerPart;
// var copter = info.Copter;
if (info.RTLStage == 2) // 当前阶段小于等于1时进入
{
tasksreturn[residualPart + indexTmp] = ReturnToLandSecondTaskAsync(info);
}
else
{
tasksreturn[residualPart+indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
//开始执行降落和返航
await Task.WhenAll(tasksreturn).ConfigureAwait(false);
//降落后设置为0
if (_flightTaskManager.IsPaused == false)
{
for (int j = RetNumAttr * (integerPart - 1); j < RetNumAttr * (integerPart); j++)
{
var info = infos[j];
info.RTLStage = 0;
}
}
//最后余数部分降落
var tasksRetutn1 = new Task[residualPart];
for (int j = integerPart * RetNumAttr; j < RetNumAttr * integerPart + residualPart; j++)
{
var info = infos[j];
int indexTmp = j - RetNumAttr * integerPart;
// var copter = info.Copter;
if (info.RTLStage == 2) // 当前阶段小于等于1时进入
{
tasksRetutn1[indexTmp] = ReturnToLandSecondTaskAsync(info);
}
else
{
tasksRetutn1[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
await Task.WhenAll(tasksRetutn1).ConfigureAwait(false);
if (_flightTaskManager.IsPaused == false)
{
for (int j = integerPart * RetNumAttr; j < RetNumAttr * integerPart + residualPart; j++)
{
var info = infos[j];
info.RTLStage = 0;
}
}
}
else
{
//无余数的整数部分最后一波开始降落
var tasksLastland = new Task[RetNumAttr];
for (int j = RetNumAttr * (integerPart - 1); j < RetNumAttr * (integerPart); j++)
{
var info = infos[j];
int indexTmp = RetNumAttr + j - RetNumAttr * integerPart;
// var copter = info.Copter;
if (info.RTLStage == 2) // 当前阶段小于等于1时进入
{
tasksLastland[indexTmp] = ReturnToLandSecondTaskAsync(info);
}
else
{
tasksLastland[indexTmp] = Task.Run(async () => { await Task.Delay(1).ConfigureAwait(false); });
}
}
await Task.WhenAll(tasksLastland).ConfigureAwait(false);
//降落后设置为0
if (_flightTaskManager.IsPaused == false)
{
for (int j = RetNumAttr * (integerPart - 1); j < RetNumAttr * (integerPart); j++)
{
var info = infos[j];
info.RTLStage = 0;
}
}
}
}
}
//原地下降高度到15米然后返回起飞点
private async Task ReturnToLandTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info)
{
float takeOffAlt = RTLAlt;
int TaskCount = _flightTaskManager.Tasks.Count();
int copterIndex = SingleCopterInfos.IndexOf(info);
var copter = info.Copter;
var copterPreviousTask = _flightTaskManager.Tasks[TaskCount-2].SingleCopterInfos[copterIndex]; // 倒数第二步的目标位置
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
DateTime dtNow = DateTime.Now;
DateTime dtLastTime = DateTime.Now;
TimeSpan ts = dtNow - dtLastTime;
// 第一阶段:垂直飞行
if (info.RTLStage == 0)
{
for (int j = 0; j < 3; j++)
{
await info.Copter.FlyToAsync(copterPreviousTask.TargetLat, copterPreviousTask.TargetLng, takeOffAlt);
}
while (!info.Copter.ArrivedTarget(copterPreviousTask.TargetLat, copterPreviousTask.TargetLng, takeOffAlt))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
if (ts.TotalMilliseconds > 1000)
{
for (int j = 0; j < 2; j++)
{
await info.Copter.FlyToAsync(copterPreviousTask.TargetLat, copterPreviousTask.TargetLng, takeOffAlt);
}
dtLastTime = dtNow;
}
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
}
info.RTLStage++;
}
dtNow = DateTime.Now;
dtLastTime = DateTime.Now;
ts = dtNow - dtLastTime;
var copterFirstTask = _flightTaskManager.Tasks[0].SingleCopterInfos[copterIndex]; // 第一步记录的家位置
// 第二阶段:水平飞行
if (info.RTLStage == 1)
{
for (int j = 0; j < 3; j++)
{
await info.Copter.FlyToAsync(copterFirstTask.TargetLat, copterFirstTask.TargetLng, takeOffAlt);
}
while (!info.Copter.ArrivedTarget(copterFirstTask.TargetLat, copterFirstTask.TargetLng, takeOffAlt))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
if (ts.TotalMilliseconds > 1000)
{
for (int j = 0; j < 2; j++)
{
await info.Copter.FlyToAsync(copterFirstTask.TargetLat, copterFirstTask.TargetLng, takeOffAlt);
}
dtLastTime = dtNow;
}
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
}
info.RTLStage++;
}
}
//在起飞点上空从15米降落到4米然后切land模式
private async Task ReturnToLandSecondTaskAsync(FlightTaskSingleCopterInfo info)
{
// await Task.Run(async () =>
// {
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
DateTime dtNow = DateTime.Now;
DateTime dtLastTime = DateTime.Now;
TimeSpan ts = dtNow - dtLastTime;
float landAlt = 4.0f; // 飞机降落到4m再切land模式
var copterFirstTask = _flightTaskManager.Tasks[0].SingleCopterInfos[copterIndex]; // 第一步记录的家位置
// 第三阶段
if (info.RTLStage == 2)
{
for (int j = 0; j < 3; j++)
{
await info.Copter.FlyToAsync(copterFirstTask.TargetLat, copterFirstTask.TargetLng, landAlt);
}
while (!info.Copter.ArrivedTarget(copterFirstTask.TargetLat, copterFirstTask.TargetLng, landAlt))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
if (ts.TotalMilliseconds > 1000)
{
for (int j = 0; j < 2; j++)
{
await info.Copter.FlyToAsync(copterFirstTask.TargetLat, copterFirstTask.TargetLng, landAlt);
}
dtLastTime = dtNow;
}
// 当该飞机被标记时,悬停并跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
{
await info.Copter.HoverAsync();
return;
}
}
info.RTLStage++;
}
// 切到land模式
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
var copter = info.Copter;
if (info.RTLStage == 3) // 下降过程
{
for (int j = 0; j < 5; j++) // added by ZJF
{
// await copter.ReturnToLaunchAsync();
await copter.LandAsync(); // 修改为降落模式
await Task.Delay(10);
}
}
// });
}
}
}

View File

@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask
{
public async Task RunSimpleCircleTaskAsync()
{
var center = SingleCopterInfos.Select(info => info.Copter).GetCenter().Value;
// 林俊清, 20150921, 自动计算圆心方向和半径,然后直接调用普通画圈的方法。
foreach (var info in SingleCopterInfos)
{
info.CenterDirectionDeg = (short)info.Copter.InPlaneDirectionToDeg(center.Lat, center.Lng);
info.Radius = (int)(info.Copter.InPlaneDistanceTo(center.Lat, center.Lng) * 100);
}
await RunCircleTaskAsync().ConfigureAwait(false);
}
}
}

View File

@ -1,481 +1,488 @@
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 int _TakeOffNumAttr = 1;
public int TakeOffNumAttr
{
get { return _TakeOffNumAttr; }
set
{
Set(nameof(TakeOffNumAttr), ref _TakeOffNumAttr, value);
}
}
//起飞到第一个航点高度的飞行时间
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();
for (int i = 0; i < 5; i++) // added by ZJF
{
await copter.TakeOffAsync();
await Task.Delay(50).ConfigureAwait(false);
}
var copterNextTask = _flightTaskManager.Tasks[TaskIndex + 1].SingleCopterInfos[copterIndex];
float takeOffAlt = copterNextTask.TargetAlt;
info.TargetLat = info.Copter.Latitude;
info.TargetLng = info.Copter.Longitude;
for (int j = 0; j < 3; j++)
{
await info.Copter.FlyToAsync(info.TargetLat, info.TargetLng, takeOffAlt);
await Task.Delay(10).ConfigureAwait(false);
}
dtNow = DateTime.Now;
ts = dtNow - dtLastTime;
FlightTask task = _flightTaskManager.CurrentRunningTask;
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;
}
}
//老方案 ----- 按起飞数量起飞
// 几架飞机同时起飞参数为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<CopterManager>();
//执行第一阶段解锁起飞任务---使用中
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);
}
/// <summary>
/// 单独飞机 执行起飞任务
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
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;
if (task==null)
return;
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<LEDInfo> 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<CopterManager>();
//执行第一阶段解锁起飞任务---使用中
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;
}
}
}
// });
}
}
}

View File

@ -1,41 +0,0 @@
using Plane.Copters;
using Plane.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Plane.FormationCreator.Formation
{
public partial class FlightTask
{
public async Task RunTurnTaskAsync()
{
await Task.WhenAll(
SingleCopterInfos.Select(info => TurnTaskFlySingleCopterAsync(info))
).ConfigureAwait(false);
}
private async Task TurnTaskFlySingleCopterAsync(FlightTaskSingleCopterInfo info)
{
int copterIndex = SingleCopterInfos.IndexOf(info);
// 当该飞机被标记时,跳过飞行任务
if ((bool)_copterManager.CopterStatus[copterIndex])
return;
await info.Copter.SetMobileControlAsync(yaw: info.TargetHeading);
while (!info.Copter.ArrivedHeading(info.TargetHeading))
{
if (_flightTaskManager.IsPaused == true)
{
await info.Copter.HoverAsync();
return;
}
await Task.Delay(25).ConfigureAwait(false);
}
await info.Copter.HoverAsync();
}
}
}

View File

@ -133,15 +133,16 @@ namespace Plane.FormationCreator.Formation
// {
//_copterManager.Select(_copterManager.Copters[copterIndex]);
ICopter copter = null;
// try
// {
// copter = _copterManager.Copters.First(o => o.Name == (copterIndex + 1).ToString());
// }
// catch (Exception)
// {
// continue;
// }
copter = _copterManager.Copters.FirstOrDefault(o => o.Name == (copterIndex + 1).ToString());
// try
// {
// copter = _copterManager.Copters.First(o => o.Name == (copterIndex + 1).ToString());
// }
// catch (Exception)
// {
// continue;
// }
string strcoptername = _copterManager.Copters[copterIndex].Name;
copter = _copterManager.Copters.FirstOrDefault(o => o.Name == strcoptername);
if (copter != null)
{
_copterManager.Select(copter);

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,15 @@
WindowTransitionsEnabled="False"
FontFamily="Microsoft YaHei"
WindowState="Maximized"
Title="无人机编队控制中心"
Title="飞行魔方无人机编队控制系统 V2.0"
PreviewKeyDown="MetroWindow_PreviewKeyDown"
PreviewKeyUp="MetroWindow_PreviewKeyUp"
Style="{StaticResource VSWindowStyleKey}"
Width="800"
Height="600">
Width="1920"
Height="1080"
Closing="Window_Closing"
Loaded="Window_Loaded"
>
<c:MetroWindow.Resources>
<Style TargetType="Separator"
@ -42,18 +45,49 @@
<c:MetroWindow.RightWindowCommands>
<c:WindowCommands>
<Button Content="{Binding LoginDisp}"
Command="{Binding LoginCommand}" />
<Button Content="飞行面板"
Foreground="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainColorConverterFly}}"
FontSize="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainFontSizeConverterFly}}"
Command="{Binding HideModifyTaskViewCommand}" />
<Button Content="设计面板"
Foreground="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainColorConverterDes}}"
FontSize="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource MainFontSizeConverterDes}}"
Command="{Binding ShowModifyTaskViewCommand}" />
<Button Content="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource ShowModifyTaskViewButtonContentConverter}}"
Command="{Binding ShowOrHideModifyTaskViewCommand}" />
<Button Content="切换地图"
Command="{Binding ChangeMapModeCommand}"/>
Command="{Binding ShowOrHideModifyTaskViewCommand}" Visibility="Collapsed" />
<Button Content="平面编辑"
Foreground="{Binding b2DMapMode, Converter={StaticResource MainColorConverterDes}}"
FontSize="{Binding b2DMapMode, Converter={StaticResource MainFontSizeConverterDes}}"
Command="{Binding Map2DCommand}"/>
<Button Content="实景效果"
Foreground="{Binding b2DMapMode, Converter={StaticResource MainColorConverterFly}}"
FontSize="{Binding b2DMapMode, Converter={StaticResource MainFontSizeConverterFly}}"
Command="{Binding Map3DCommand}"/>
<Button Content="{Binding b2DMapMode, Converter={StaticResource Show2d3dButtonContentConverter}}"
Command="{Binding ChangeMapModeCommand}" Visibility="Collapsed"/>
<Button Content="重启监听"
Visibility="Collapsed"
Command="{Binding RestartListeningCommand}" />
<Button Content="{Binding SwitchVelocityModeButtonContent}"
Command="{Binding SwitchVelocityModeCommand}"
Visibility="Collapsed"/>
<!--// 林俊清, 20150930, 不分这些模式了。
<!--// 王海, 20150930, 不分这些模式了。
<Button Content="进入任务模式"
Command="{Binding SwitchAppModeCommand}"
CommandParameter="{x:Static m:AppMode.PreparedForRunningTasks}"
@ -71,7 +105,7 @@
Visibility="Collapsed"
Click="btnRefreshMap_Click" />
<Button Name="btnConnect"
Content="连接"
Content="设置"
Click="btnConnect_Click" />
<Menu Name="menuTask" Background="Transparent" VerticalAlignment="Center" >
@ -98,11 +132,17 @@
Command="{Binding ImportTasksCommand}"/>
<StackPanel VerticalAlignment="Center" Margin="0,8,0,8" Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
<TextBlock Foreground="#969696" VerticalAlignment="Center" Text="起始步骤:"/>
<TextBox VerticalAlignment="Bottom" Width="40"
<TextBox VerticalAlignment="Center" Width="40" Margin="0,0,5,0"
Text="{Binding txtStarindex, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Foreground="#969696" VerticalAlignment="Center" Text="截止:"/>
<TextBox VerticalAlignment="Bottom" Width="40"
<TextBox VerticalAlignment="Center" Width="40" Margin="0,0,5,0"
Text="{Binding txtendindex, UpdateSourceTrigger=PropertyChanged}"/>
<CheckBox Content="飞机位置" Grid.Column="1" Margin="0,8,0,8" Foreground="#969696"
IsChecked="{Binding isimpCopterLoc}" />
</StackPanel>
<Button BorderThickness="1" BorderBrush="#FFFFFF" Content="导入分组信息" Margin="25,8,0,8" Grid.Row="2"
Command="{Binding ImportGroupCommand}"/>
@ -122,7 +162,7 @@
</c:WindowCommands>
</c:MetroWindow.RightWindowCommands>
<Grid>
<Grid>
<Grid.Background>
<ImageBrush ImageSource=".\bg.jpg" />
</Grid.Background>
@ -131,7 +171,7 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Margin="1">
<Grid Margin="1" d:IsHidden="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="73*" />
<ColumnDefinition Width="27*" MinWidth="360" />
@ -139,20 +179,19 @@
<Grid Margin="0,0,10,0"
Width="Auto" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1371*"/>
<ColumnDefinition Width="13*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TabControl SelectedIndex="{Binding MapMode,UpdateSourceTrigger=PropertyChanged}" Grid.RowSpan="3">
<TabItem Visibility="Collapsed">
<v:MapView x:Name="map"/>
</TabItem >
<TabItem Visibility="Collapsed">
<v:View3D/>
</TabItem>
</TabControl>
<v:MapView x:Name="map" Grid.RowSpan="3" Margin="0,0,0,0" />
<v:View3D x:Name="map3D" Visibility="Collapsed" Grid.RowSpan="3" Margin="0,0,0,0"/>
<Grid Grid.Row="1" HorizontalAlignment="Right">
<WrapPanel Orientation="Vertical">
@ -183,12 +222,12 @@
x:Name="TaskbarControl"
VerticalAlignment="Bottom"
Visibility="{Binding Source={x:Static local:AppEx.Current}, Path=AppMode, Converter={StaticResource AppModeToVisibilityConverter}, ConverterParameter=TaskBarView}" />
</Grid>
</Grid>
<Grid Margin="0,0,0,0"
Grid.Column="1">
<Viewbox Stretch="Fill" Grid.Column="1" Margin="0,0,0,0">
<DockPanel>
<Grid Margin="0,0,0,0"
>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
@ -200,7 +239,7 @@
<StackPanel Grid.Row="1">
<StackPanel Grid.Row="2"
Visibility="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource InversiveBooleanToVisibilityConverter}}">
<Separator Grid.ColumnSpan="2" />
<Separator Grid.ColumnSpan="2" Margin="0,5,5,5"/>
<v:ControlPanelView />
</StackPanel>
@ -212,41 +251,74 @@
<StackPanel Grid.Row="2"
Visibility="{Binding AppEx.ShowModifyTaskView, Converter={StaticResource InversiveBooleanToVisibilityConverter}}">
<Separator Grid.ColumnSpan="2" />
<Separator Grid.ColumnSpan="2" Margin="0,0,5,5" />
<v:CopterInfoView DataContext="{Binding Path=CopterListViewModel.SelectedCopter}" />
</StackPanel>
</Grid>
</DockPanel>
</Viewbox>
</Grid>
<Border Grid.Row="1"
Background="{StaticResource WhiteBrush}">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Margin="4"
Text="{Binding Message}" MouseUp="LogShowHide"/>
<TextBlock Margin="4"
Text="{Binding CopterListViewModel.SelectedCopter.StatusText}" />
<TextBlock Margin="10,4"
Text="{Binding Message}" Width="480" MouseUp="LogShowHide"/>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="0,8" BorderBrush="LightGray" BorderThickness="1"/>
<TextBlock Margin="10,4" Width="280" Text="{Binding SysStatusText}" />
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="0,8" BorderBrush="LightGray" BorderThickness="1"/>
<TextBlock Margin="10,4" Width="210"
Text="{Binding ControlPanelViewModelData.RTKState}" />
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" Margin="0,8" BorderBrush="LightGray" BorderThickness="1"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="{Binding Loginstate}" Margin="0,4,14,0"/>
<TextBlock Text="广播端口:" Margin="4"/>
<ContentPresenter Margin="0,4,4,0" Content="{Binding BoardcastPortOpened, Converter={StaticResource CheckSignConverter2}, Mode=OneWay}" />
<TextBlock Text="通信连接:" Margin="4"/>
<ContentPresenter Content="{Binding CommunicationModuleConnected, Converter={StaticResource CheckSignConverter}, Mode=OneWay}" />
<ContentPresenter Margin="0,4,14,0" Content="{Binding CommunicationModuleConnected, Converter={StaticResource CheckSignConverter2}, Mode=OneWay}" />
</StackPanel>
</Grid>
</Border>
<TextBox Name="logTextBox" Height="700" Width="600" Background="#FF2D2D2D"
<Grid x:Name="logGrid" Height="900" VerticalAlignment="Top" HorizontalAlignment="Left" Visibility="Hidden" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="20" MaxWidth="800" Width="500"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<DockPanel Grid.Row="0" Grid.Column="0">
<TextBox x:Name="logTextBox" Height="900" Width="800" Background="#FF2D2D2D"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Visibility="Hidden"
VerticalAlignment="Top"
Text="{Binding Logs}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
TextChanged="LogTextChange"
IsReadOnly="True"
TextWrapping="Wrap"
FontSize="14"
ContextMenu="{StaticResource LogMenu}"/>
</DockPanel>
<GridSplitter Grid.Row="0" Grid.Column="1" Width="3" Margin="0,0,0,0" Background="MidnightBlue"
VerticalAlignment="Stretch" HorizontalAlignment="Center" />
</Grid>
</Grid>
</c:MetroWindow>

View File

@ -21,6 +21,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Plane.CommunicationManagement;
using System.Reflection;
namespace Plane.FormationCreator
{
@ -34,7 +35,11 @@ namespace Plane.FormationCreator
InitializeComponent();
this.DataContext = ServiceLocator.Current.GetInstance<MainViewModel>();
// this.OnClosing += Window_Closing;
//改到设置窗口显示版本信息
// var version = Assembly.GetExecutingAssembly().GetName().Version;
// Title = "飞行魔方无人机编队控制系统 V" + version.ToString() + "编译时间[" + System.IO.File.GetLastWriteTime(this.GetType().Assembly.Location).ToString() + "]";
//ShowConnectDialog();
//if (_copterManager.CoptersForControlling.Count <= 0)
@ -53,8 +58,32 @@ namespace Plane.FormationCreator
{
loginWindow = new ConnectWindow();
}
loginWindow.Show();
loginWindow.ShowDialog ();
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
bool waitnet = _copterManager.Logined;
_copterManager.NetLogout();
//等待网络退出
if (waitnet)
System.Threading.Thread.Sleep(1000);
/*
MessageBoxResult result = MessageBox.Show("Do you really want to exit?", "", MessageBoxButton.YesNo);
if (result == MessageBoxResult.No)
{
e.Cancel = true;
}
*/
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ServiceLocator.Current.GetInstance<MainViewModel>().LoginCommand.Execute(this);
}
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
@ -81,7 +110,7 @@ namespace Plane.FormationCreator
};
var point = PointToScreen(Mouse.GetPosition(this));
point.X = Math.Min(point.X, SystemParameters.WorkArea.Width - connectWindow.Width - 30);
point.Y = Math.Min(point.Y, SystemParameters.WorkArea.Height - connectWindow.Height - 30);
point.Y = Math.Min(point.Y+10, SystemParameters.WorkArea.Height - connectWindow.Height - 30);
connectWindow.Left = point.X;
connectWindow.Top = point.Y;
@ -109,7 +138,9 @@ namespace Plane.FormationCreator
{
case Key.LeftCtrl:
{
case Key.RightCtrl:
case Key.LeftAlt:
{
var copters = _copterManager.AcceptingControlCopters;
Shiftkeydown = true;
_copterManager.shiftkeydown = true;
@ -393,6 +424,8 @@ namespace Plane.FormationCreator
switch (e.Key)
{
case Key.LeftCtrl:
case Key.RightCtrl:
case Key.LeftAlt:
{
Shiftkeydown = false;
_copterManager.shiftkeydown = false;
@ -481,15 +514,20 @@ namespace Plane.FormationCreator
{
MainViewModel vm = DataContext as MainViewModel;
LogWindow logWindows = new LogWindow(vm.Messages);
logWindows.Show();
logWindows.ShowDialog();
}
private void LogShowHide(object sender, MouseButtonEventArgs e)
{
if (logTextBox.Visibility == Visibility.Visible)
logTextBox.Visibility = Visibility.Hidden;
if (logGrid.Visibility == Visibility.Visible)
logGrid.Visibility = Visibility.Hidden;
else
logTextBox.Visibility = Visibility.Visible;
{
logGrid.Height = Math.Max(map.ActualHeight, map3D.ActualHeight) - ((TaskBarView)TaskbarControl).TasksControl.ActualHeight;
logTextBox.Height = logGrid.Height;
logGrid.Visibility = Visibility.Visible;
}
}
private void LogTextChange(object sender, TextChangedEventArgs e)

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;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,9 @@ using System.Windows;
[assembly: AssemblyTitle("GroupGCSMain")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("GroupGCS")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyCompany("北京飞行魔方科技有限公司")]
[assembly: AssemblyProduct("无人机编队地面控制系统")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -51,5 +51,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyVersion("2.2.0.*")]
[assembly: AssemblyFileVersion("2.2.0.0")]

View File

@ -1,5 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Plane.FormationCreator.Properties">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/FGCS;component/Styles/Window.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@ -1,63 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plane.FormationCreator.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Plane.FormationCreator.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plane.FormationCreator.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Plane.FormationCreator.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找 System.Drawing.Bitmap 类型的本地化资源。
/// </summary>
internal static System.Drawing.Bitmap Logo_small {
get {
object obj = ResourceManager.GetObject("Logo_small", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@ -46,7 +46,7 @@
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
@ -60,6 +60,7 @@
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
@ -68,9 +69,10 @@
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
@ -85,9 +87,10 @@
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
@ -109,9 +112,13 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Logo_small" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Logo_small.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@ -1,38 +1,38 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plane.FormationCreator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("192.168.1.50")]
public string IPs {
get {
return ((string)(this["IPs"]));
}
set {
this["IPs"] = value;
}
}
}
}
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace Plane.FormationCreator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("192.168.1.50")]
public string IPs {
get {
return ((string)(this["IPs"]));
}
set {
this["IPs"] = value;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -34,6 +34,8 @@ namespace Plane.FormationCreator
_container.Register<View3DViewModel>();
_container.Register<ModifyTaskViewModel>();
_container.Register<CalibrationViewModel>();
_container.Register<LoginViewModel>();
_container.Register<ChangePasswordViewModel>();
_container.Register<GroupsViewModel>();
_container.Register<RtcmInfoViewModel>();
_container.Register<ConfigVirtualIdViewModel>();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 238 KiB

View File

@ -0,0 +1,72 @@
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Plane.Util
{
public class AsynDataUtils
{
public delegate void DataResultCallBack(string data,bool haveerror);
DataResultCallBack _callback;
bool haveerror;
string errorstr;
public bool AsynGetData(string tagUrl, DataResultCallBack callback, out string verrorstr)
{
haveerror = false;
errorstr = "";
try
{
_callback = callback;
AsyncGetWithWebRequest(tagUrl, new AsyncCallback(ReadCallback));
}
catch (Exception ex)
{
errorstr += ex.Message;
haveerror = true;
Console.WriteLine(ex.Message);
}
verrorstr = errorstr;
return !haveerror;
}
private void ReadCallback(IAsyncResult asynchronousResult)
{
try
{
string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
var request = (HttpWebRequest)asynchronousResult.AsyncState;
request.Timeout = 5000;
request.Method = "GET";
request.UserAgent = DefaultUserAgent;
var response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
using (var streamReader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default ))
{
var resultString = streamReader.ReadToEnd();
Console.WriteLine(resultString);
if (_callback != null)
{
_callback(resultString,false);
}
}
}
catch (Exception ex)
{
if (_callback != null)
{
_callback(ex.Message, true);
}
Console.WriteLine(ex.Message);
}
}
private void AsyncGetWithWebRequest(string url, AsyncCallback callback)
{
var request = (HttpWebRequest)System.Net.WebRequest.Create(new Uri(url));
request.BeginGetResponse(callback, request);
}
}
}

View File

@ -1,431 +1,430 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Net; // dns, ip address
using System.Net.Sockets; // tcplistner
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace Plane.Util
{
public class CommsNTRIP : ICommsSerial, IDisposable
{
public TcpClient client = new TcpClient();
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
private Uri remoteUri;
public double lat = 0;
public double lng = 0;
public double alt = 0;
int retrys = 3;
private string host;
public int WriteBufferSize { get; set; }
public int WriteTimeout { get; set; }
public bool RtsEnable { get; set; }
private string url;
public Stream BaseStream
{
get { return client.GetStream(); }
}
public CommsNTRIP(string url, double lat, double lng)
{
this.url = url;
this.lat = lat;
this.lng = lng;
ReadTimeout = 500;
}
public void toggleDTR()
{
}
public string Port { get; set; }
public int ReadTimeout
{
get; // { return client.ReceiveTimeout; }
set; // { client.ReceiveTimeout = value; }
}
public int ReadBufferSize { get; set; }
public int BaudRate { get; set; }
public StopBits StopBits { get; set; }
public Parity Parity { get; set; }
public int DataBits { get; set; }
public string PortName { get; set; }
public int BytesToRead
{
get
{
/*Console.WriteLine(DateTime.Now.Millisecond + " tcp btr " + (client.Available + rbuffer.Length - rbufferread));*/
SendNMEA();
return (int)client.Available;
}
}
public int BytesToWrite
{
get { return 0; }
}
public bool IsOpen
{
get
{
try
{
return client.Client.Connected;
}
catch
{
return false;
}
}
}
public bool DtrEnable { get; set; }
public void Open()
{
if (client.Client.Connected)
{
return;
}
/*string url = "";*/
int count = url.Split('@').Length - 1;
if (count > 1)
{
var regex = new Regex("@");
url = regex.Replace(url, "%40", 1);
}
url = url.Replace("ntrip://", "http://");
remoteUri = new Uri(url);
doConnect();
}
private byte[] TcpKeepAlive(bool On_Off, uint KeepaLiveTime, uint KeepaLiveInterval)
{
byte[] InValue = new byte[12];
Array.ConstrainedCopy(BitConverter.GetBytes(Convert.ToUInt32(On_Off)), 0, InValue, 0, 4);
Array.ConstrainedCopy(BitConverter.GetBytes(KeepaLiveTime), 0, InValue, 4, 4);
Array.ConstrainedCopy(BitConverter.GetBytes(KeepaLiveInterval), 0, InValue, 8, 4);
return InValue;
}
private void doConnect()
{
string usernamePassword = remoteUri.UserInfo;
string userpass2 = Uri.UnescapeDataString(usernamePassword);
string auth = "Authorization: Basic " +
Convert.ToBase64String(new ASCIIEncoding().GetBytes(userpass2)) + "\r\n";
if (usernamePassword == "")
auth = "";
host = remoteUri.Host;
Port = remoteUri.Port.ToString();
client = new TcpClient(host, int.Parse(Port));
client.Client.IOControl(IOControlCode.KeepAliveValues, TcpKeepAlive(true, 36000000, 3000), null);
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns);
string line = "GET " + remoteUri.PathAndQuery + " HTTP/1.0\r\n"
+ "User-Agent: NTRIP MissionPlanner/1.0\r\n"
+ auth
+ "Connection: close\r\n\r\n";
sw.Write(line);
sw.Flush();
line = sr.ReadLine();
if (!line.Contains("200"))
{
client.Dispose();
client = new TcpClient();
throw new Exception("Bad ntrip Responce\n\n" + line);
}
// vrs may take up to 60+ seconds to respond
SendNMEA();
VerifyConnected();
}
DateTime _lastnmea = DateTime.MinValue;
private void SendNMEA()
{
if (lat != 0 || lng != 0)
{
if (_lastnmea.AddSeconds(30) < DateTime.Now)
{
double latdms = (int)lat + ((lat - (int)lat) * .6f);
double lngdms = (int)lng + ((lng - (int)lng) * .6f);
var line = string.Format(System.Globalization.CultureInfo.InvariantCulture,
"$GP{0},{1:HHmmss.ff},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14}", "GGA",
DateTime.Now.ToUniversalTime(), Math.Abs(latdms * 100).ToString("0000.00"), lat < 0 ? "S" : "N",
Math.Abs(lngdms * 100).ToString("00000.00"), lng < 0 ? "W" : "E", 1, 10,
1, alt.ToString("0.00"), "M", 0, "M", "0.0", "0");
string checksum = GetChecksum(line);
WriteLine(line + "*" + checksum);
_lastnmea = DateTime.Now;
}
}
}
// Calculates the checksum for a sentence
string GetChecksum(string sentence)
{
// Loop through all chars to get a checksum
int Checksum = 0;
foreach (char Character in sentence.ToCharArray())
{
switch (Character)
{
case '$':
// Ignore the dollar sign
break;
case '*':
// Stop processing before the asterisk
continue;
default:
// Is this the first value for the checksum?
if (Checksum == 0)
{
// Yes. Set the checksum to the value
Checksum = Convert.ToByte(Character);
}
else
{
// No. XOR the checksum with this character's value
Checksum = Checksum ^ Convert.ToByte(Character);
}
break;
}
}
// Return the checksum formatted as a two-character hexadecimal
return Checksum.ToString("X2");
}
void VerifyConnected()
{
if (!IsOpen)
{
try
{
client.Dispose();
client = new TcpClient();
}
catch { }
// this should only happen if we have established a connection in the first place
if (client != null && retrys > 0)
{
doConnect();
retrys--;
}
throw new Exception("The ntrip is closed");
}
}
public int Read(byte[] readto, int offset, int length)
{
VerifyConnected();
SendNMEA();
try
{
if (length < 1) { return 0; }
return client.Client.Receive(readto, offset, length, SocketFlags.Partial);
/*
byte[] temp = new byte[length];
clientbuf.Read(temp, 0, length);
temp.CopyTo(readto, offset);
return length;*/
}
catch { throw new Exception("ntrip Socket Closed"); }
}
public int ReadByte()
{
VerifyConnected();
int count = 0;
while (this.BytesToRead == 0)
{
System.Threading.Thread.Sleep(1);
if (count > ReadTimeout)
throw new Exception("ntrip Timeout on read");
count++;
}
byte[] buffer = new byte[1];
Read(buffer, 0, 1);
return buffer[0];
}
public int ReadChar()
{
return ReadByte();
}
public string ReadExisting()
{
VerifyConnected();
byte[] data = new byte[client.Available];
if (data.Length > 0)
Read(data, 0, data.Length);
string line = Encoding.ASCII.GetString(data, 0, data.Length);
return line;
}
public void WriteLine(string line)
{
VerifyConnected();
line = line + "\r\n";
Write(line);
}
public void Write(string line)
{
VerifyConnected();
byte[] data = new System.Text.ASCIIEncoding().GetBytes(line);
Write(data, 0, data.Length);
}
public void Write(byte[] write, int offset, int length)
{
VerifyConnected();
try
{
client.Client.Send(write, length, SocketFlags.None);
}
catch { }//throw new Exception("Comport / Socket Closed"); }
}
public void DiscardInBuffer()
{
VerifyConnected();
int size = (int)client.Available;
byte[] crap = new byte[size];
Read(crap, 0, size);
}
public string ReadLine()
{
byte[] temp = new byte[4000];
int count = 0;
int timeout = 0;
while (timeout <= 100)
{
if (!this.IsOpen) { break; }
if (this.BytesToRead > 0)
{
byte letter = (byte)this.ReadByte();
temp[count] = letter;
if (letter == '\n') // normal line
{
break;
}
count++;
if (count == temp.Length)
break;
timeout = 0;
}
else
{
timeout++;
System.Threading.Thread.Sleep(5);
}
}
Array.Resize<byte>(ref temp, count + 1);
return Encoding.ASCII.GetString(temp, 0, temp.Length);
}
public void Close()
{
try
{
if (client.Client != null && client.Client.Connected)
{
client.Client.Dispose();
client.Dispose();
}
}
catch { }
try
{
client.Dispose();
}
catch { }
client = new TcpClient();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
this.Close();
client = null;
}
// free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Net; // dns, ip address
using System.Net.Sockets; // tcplistner
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace Plane.Util
{
public class CommsNTRIP : ICommsSerial, IDisposable
{
public TcpClient client = new TcpClient();
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
private Uri remoteUri;
public double lat = 0;
public double lng = 0;
public double alt = 0;
int retrys = 3;
private string host;
public int WriteBufferSize { get; set; }
public int WriteTimeout { get; set; }
public bool RtsEnable { get; set; }
private string url;
public Stream BaseStream
{
get { return client.GetStream(); }
}
public CommsNTRIP(string url, double lat, double lng)
{
this.url = url;
this.lat = lat;
this.lng = lng;
ReadTimeout = 500;
}
public void toggleDTR()
{
}
public string Port { get; set; }
public int ReadTimeout
{
get; // { return client.ReceiveTimeout; }
set; // { client.ReceiveTimeout = value; }
}
public int ReadBufferSize { get; set; }
public int BaudRate { get; set; }
public StopBits StopBits { get; set; }
public Parity Parity { get; set; }
public int DataBits { get; set; }
public string PortName { get; set; }
public int BytesToRead
{
get
{
/*Console.WriteLine(DateTime.Now.Millisecond + " tcp btr " + (client.Available + rbuffer.Length - rbufferread));*/
SendNMEA();
return (int)client.Available;
}
}
public int BytesToWrite
{
get { return 0; }
}
public bool IsOpen
{
get
{
try
{
return client.Client.Connected;
}
catch
{
return false;
}
}
}
public bool DtrEnable { get; set; }
public void Open()
{
if (client.Client.Connected)
{
return;
}
/*string url = "";*/
int count = url.Split('@').Length - 1;
if (count > 1)
{
var regex = new Regex("@");
url = regex.Replace(url, "%40", 1);
}
url = url.Replace("ntrip://", "http://");
remoteUri = new Uri(url);
doConnect();
}
private byte[] TcpKeepAlive(bool On_Off, uint KeepaLiveTime, uint KeepaLiveInterval)
{
byte[] InValue = new byte[12];
Array.ConstrainedCopy(BitConverter.GetBytes(Convert.ToUInt32(On_Off)), 0, InValue, 0, 4);
Array.ConstrainedCopy(BitConverter.GetBytes(KeepaLiveTime), 0, InValue, 4, 4);
Array.ConstrainedCopy(BitConverter.GetBytes(KeepaLiveInterval), 0, InValue, 8, 4);
return InValue;
}
private void doConnect()
{
string usernamePassword = remoteUri.UserInfo;
string userpass2 = Uri.UnescapeDataString(usernamePassword);
string auth = "Authorization: Basic " +
Convert.ToBase64String(new ASCIIEncoding().GetBytes(userpass2)) + "\r\n";
if (usernamePassword == "")
auth = "";
host = remoteUri.Host;
Port = remoteUri.Port.ToString();
client = new TcpClient(host, int.Parse(Port));
client.Client.IOControl(IOControlCode.KeepAliveValues, TcpKeepAlive(true, 36000000, 3000), null);
NetworkStream ns = client.GetStream();
StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns);
string line = "GET " + remoteUri.PathAndQuery + " HTTP/1.0\r\n"
+ "User-Agent: NTRIP MissionPlanner/1.0\r\n"
+ auth
+ "Connection: close\r\n\r\n";
sw.Write(line);
sw.Flush();
line = sr.ReadLine();
if (!line.Contains("200"))
{
client.Dispose();
client = new TcpClient();
throw new Exception("Bad ntrip Responce\n\n" + line);
}
// vrs may take up to 60+ seconds to respond
SendNMEA();
VerifyConnected();
}
DateTime _lastnmea = DateTime.MinValue;
private void SendNMEA()
{
if (lat != 0 || lng != 0)
{
DateTime currentUtcTime = DateTime.UtcNow;
if (_lastnmea.AddSeconds(30) < currentUtcTime)
{
double latdms = (int)lat + ((lat - (int)lat) * .6f);
double lngdms = (int)lng + ((lng - (int)lng) * .6f);
var line = string.Format(System.Globalization.CultureInfo.InvariantCulture,
"$GP{0},{1:HHmmss.ff},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14}", "GGA",
currentUtcTime, Math.Abs(latdms * 100).ToString("0000.00"), lat < 0 ? "S" : "N",
Math.Abs(lngdms * 100).ToString("00000.00"), lng < 0 ? "W" : "E", 1, 10,
1, alt.ToString("0.00"), "M", 0, "M", "0.0", "0");
string checksum = GetChecksum(line);
WriteLine(line + "*" + checksum);
_lastnmea = currentUtcTime;
}
}
}
// Calculates the checksum for a sentence
string GetChecksum(string sentence)
{
// Loop through all chars to get a checksum
int Checksum = 0;
foreach (char Character in sentence.ToCharArray())
{
switch (Character)
{
case '$':
// Ignore the dollar sign
break;
case '*':
// Stop processing before the asterisk
continue;
default:
// Is this the first value for the checksum?
if (Checksum == 0)
{
// Yes. Set the checksum to the value
Checksum = Convert.ToByte(Character);
}
else
{
// No. XOR the checksum with this character's value
Checksum = Checksum ^ Convert.ToByte(Character);
}
break;
}
}
// Return the checksum formatted as a two-character hexadecimal
return Checksum.ToString("X2");
}
void VerifyConnected()
{
if (!IsOpen)
{
try
{
client.Dispose();
client = new TcpClient();
}
catch { }
// this should only happen if we have established a connection in the first place
if (client != null && retrys > 0)
{
doConnect();
retrys--;
}
throw new Exception("网络RTK基站通讯已关闭!");
}
}
public int Read(byte[] readto, int offset, int length)
{
VerifyConnected();
SendNMEA();
try
{
if (length < 1) { return 0; }
return client.Client.Receive(readto, offset, length, SocketFlags.Partial);
/*
byte[] temp = new byte[length];
clientbuf.Read(temp, 0, length);
temp.CopyTo(readto, offset);
return length;*/
}
catch { throw new Exception("ntrip Socket Closed"); }
}
public int ReadByte()
{
VerifyConnected();
int count = 0;
while (this.BytesToRead == 0)
{
System.Threading.Thread.Sleep(1);
if (count > ReadTimeout)
throw new Exception("ntrip Timeout on read");
count++;
}
byte[] buffer = new byte[1];
Read(buffer, 0, 1);
return buffer[0];
}
public int ReadChar()
{
return ReadByte();
}
public string ReadExisting()
{
VerifyConnected();
byte[] data = new byte[client.Available];
if (data.Length > 0)
Read(data, 0, data.Length);
string line = Encoding.ASCII.GetString(data, 0, data.Length);
return line;
}
public void WriteLine(string line)
{
VerifyConnected();
line = line + "\r\n";
Write(line);
}
public void Write(string line)
{
VerifyConnected();
byte[] data = new System.Text.ASCIIEncoding().GetBytes(line);
Write(data, 0, data.Length);
}
public void Write(byte[] write, int offset, int length)
{
VerifyConnected();
try
{
client.Client.Send(write, length, SocketFlags.None);
}
catch { }//throw new Exception("Comport / Socket Closed"); }
}
public void DiscardInBuffer()
{
VerifyConnected();
int size = (int)client.Available;
byte[] crap = new byte[size];
Read(crap, 0, size);
}
public string ReadLine()
{
byte[] temp = new byte[4000];
int count = 0;
int timeout = 0;
while (timeout <= 100)
{
if (!this.IsOpen) { break; }
if (this.BytesToRead > 0)
{
byte letter = (byte)this.ReadByte();
temp[count] = letter;
if (letter == '\n') // normal line
{
break;
}
count++;
if (count == temp.Length)
break;
timeout = 0;
}
else
{
timeout++;
System.Threading.Thread.Sleep(5);
}
}
Array.Resize<byte>(ref temp, count + 1);
return Encoding.ASCII.GetString(temp, 0, temp.Length);
}
public void Close()
{
try
{
if (client.Client != null && client.Client.Connected)
{
client.Client.Dispose();
client.Dispose();
}
}
catch { }
try
{
client.Dispose();
}
catch { }
client = new TcpClient();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources
this.Close();
client = null;
}
// free native resources
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -0,0 +1,512 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Threading;
namespace Plane.Util
{
public class SerialPort : System.IO.Ports.SerialPort, ICommsSerial
{
static object locker = new object();
public new bool DtrEnable { get { return base.DtrEnable; } set { if (base.DtrEnable == value) return; if (ispx4(base.PortName)) return; base.DtrEnable = value; } }
public new bool RtsEnable { get { return base.RtsEnable; } set { if (base.RtsEnable == value) return; if (ispx4(base.PortName)) return; base.RtsEnable = value; } }
/*
protected override void Dispose(bool disposing)
{
try
{
try
{
Type mytype = typeof(System.IO.Ports.SerialPort);
FieldInfo field = mytype.GetField("internalSerialStream", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Stream stream = (Stream)field.GetValue(this);
if (stream != null)
{
try
{
stream.Dispose();
}
catch (Exception ex) { Console.WriteLine("1 " + ex.ToString()); }
stream = null;
}
}
}
catch (Exception ex) { Console.WriteLine("2 " + ex.ToString()); }
base.Dispose(disposing);
}
catch (Exception ex) { Console.WriteLine("3 " + ex.ToString()); }
}
*/
public new void Open()
{
// 500ms write timeout - win32 api default
this.WriteTimeout = 500;
if (base.IsOpen)
return;
try
{
// this causes element not found with bluetooth devices.
if (BaudRate > 115200)
{
Console.WriteLine("Doing SerialPortFixer");
SerialPortFixer.Execute(this.PortName);
Console.WriteLine("Done SerialPortFixer");
}
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
if (PortName.StartsWith("/"))
if (!File.Exists(PortName))
throw new Exception("No such device");
try
{
base.Open();
}
catch {
try { Close(); }
catch { }
throw;
}
}
public new void Close()
{
base.Close();
}
public void toggleDTR()
{
if (ispx4(this.PortName))
{
Console.WriteLine("PX4 - no DTR");
return;
}
bool open = this.IsOpen;
Console.WriteLine("toggleDTR " + this.IsOpen);
try
{
if (!open)
this.Open();
}
catch { }
base.DtrEnable = false;
base.RtsEnable = false;
System.Threading.Thread.Sleep(50);
base.DtrEnable = true;
base.RtsEnable = true;
System.Threading.Thread.Sleep(50);
try
{
if (!open)
this.Close();
}
catch { }
Console.WriteLine("toggleDTR done " + this.IsOpen);
}
public new static string[] GetPortNames()
{
// prevent hammering
lock (locker)
{
List<string> allPorts = new List<string>();
if (Directory.Exists("/dev/"))
{
// cleanup now
GC.Collect();
// mono is failing in here on linux "too many open files"
try
{
if (Directory.Exists("/dev/serial/by-id/"))
allPorts.AddRange(Directory.GetFiles("/dev/serial/by-id/", "*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyACM*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyUSB*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "rfcomm*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "*usb*"));
}
catch { }
}
string[] ports = null;
try
{
ports = System.IO.Ports.SerialPort.GetPortNames()
.Select(p => p.TrimEnd())
.Select(FixBlueToothPortNameBug)
.ToArray();
}
catch { }
if (ports != null)
allPorts.AddRange(ports);
return allPorts.ToArray();
}
}
static Dictionary<string, string> comportnamecache = new Dictionary<string, string>();
public static string GetNiceName(string port)
{
// make sure we are exclusive
lock (locker)
{
portnamenice = "";
if (comportnamecache.ContainsKey(port))
{
return comportnamecache[port];
}
try
{
CallWithTimeout(new Action<string>(GetName), 1000, port);
}
catch
{
}
comportnamecache[port] = portnamenice;
return (string)portnamenice.Clone();
}
}
static string portnamenice = "";
static void GetName(string port)
{
try
{
/*
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_SerialPort"); // Win32_USBControllerDevice
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
foreach (ManagementObject obj2 in searcher.Get())
{
//DeviceID
if (obj2.Properties["DeviceID"].Value.ToString().ToUpper() == port.ToUpper())
{
portnamenice = obj2.Properties["Name"].Value.ToString();
return;
}
}
}
*/
}
catch { }
portnamenice = "";
}
static void CallWithTimeout(Action<string> action, int timeoutMilliseconds, string data)
{
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action(data);
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
wrappedAction.EndInvoke(result);
}
else
{
threadToKill.Abort();
throw new TimeoutException();
}
}
internal bool ispx4(string port)
{
return false;
}
// .NET bug: sometimes bluetooth ports are enumerated with bogus characters
// eg 'COM10' becomes 'COM10c' - one workaround is to remove the non numeric
// char. Annoyingly, sometimes a numeric char is added, which means this
// does not work in all cases.
// See http://connect.microsoft.com/VisualStudio/feedback/details/236183/system-io-ports-serialport-getportnames-error-with-bluetooth
private static string FixBlueToothPortNameBug(string portName)
{
if (!portName.StartsWith("COM"))
return portName;
var newPortName = "COM"; // Start over with "COM"
foreach (var portChar in portName.Substring(3).ToCharArray()) // Remove "COM", put the rest in a character array
{
if (char.IsDigit(portChar))
newPortName += portChar.ToString(); // Good character, append to portName
// else
//log.WarnFormat("Bad (Non Numeric) character in port name '{0}' - removing", portName);
}
return newPortName;
}
}
public sealed class SerialPortFixer : IDisposable
{
public static void Execute(string portName)
{
using (new SerialPortFixer(portName))
{
}
}
#region IDisposable Members
public void Dispose()
{
if (m_Handle != null)
{
m_Handle.Dispose();
m_Handle = null;
}
GC.SuppressFinalize(this);
}
#endregion
#region Implementation
private const int DcbFlagAbortOnError = 14;
private const int CommStateRetries = 10;
private SafeFileHandle m_Handle;
private SerialPortFixer(string portName)
{
const int dwFlagsAndAttributes = 0x40000000;
const int dwAccess = unchecked((int)0xC0000000); if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
SafeFileHandle hFile = NativeMethods.CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
IntPtr.Zero);
if (hFile.IsInvalid)
{
WinIoError();
}
try
{
int fileType = NativeMethods.GetFileType(hFile);
if ((fileType != 2) && (fileType != 0))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
m_Handle = hFile;
InitializeDcb();
}
catch
{
hFile.Dispose();
m_Handle = null;
throw;
}
}
private static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, IntPtr arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr securityAttrs, int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int GetFileType(SafeFileHandle hFile);
}
private void InitializeDcb()
{
Dcb dcb = new Dcb();
GetCommStateNative(ref dcb);
dcb.Flags &= ~(1u << DcbFlagAbortOnError);
SetCommStateNative(ref dcb);
}
private static string GetMessage(int errorCode)
{
StringBuilder lpBuffer = new StringBuilder(0x200);
if (
NativeMethods.FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
IntPtr.Zero) != 0)
{
return lpBuffer.ToString();
}
return "Unknown Error";
}
private static int MakeHrFromErrorCode(int errorCode)
{
return (int)(0x80070000 | (uint)errorCode);
}
private static void WinIoError()
{
int errorCode = Marshal.GetLastWin32Error();
throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
}
private void GetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!NativeMethods.ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (NativeMethods.GetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
private void SetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat(); for (int i = 0; i < CommStateRetries; i++)
{
if (!NativeMethods.ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (NativeMethods.SetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
#region Nested type: COMSTAT
[StructLayout(LayoutKind.Sequential)]
private struct Comstat
{
public readonly uint Flags;
public readonly uint cbInQue;
public readonly uint cbOutQue;
}
#endregion
#region Nested type: DCB
/*
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx
DWORD fBinary :1;
DWORD fParity :1;
DWORD fOutxCtsFlow :1;
DWORD fOutxDsrFlow :1;
DWORD fDtrControl :2;
DWORD fDsrSensitivity :1;
DWORD fTXContinueOnXoff :1;
DWORD fOutX :1;
DWORD fInX :1;
DWORD fErrorChar :1;
DWORD fNull :1;
DWORD fRtsControl :2;
DWORD fAbortOnError :1;
DWORD fDummy2 :17;
*/
[StructLayout(LayoutKind.Sequential)]
public struct Dcb
{
public readonly uint DCBlength;
public readonly uint BaudRate;
public uint Flags;
public readonly ushort wReserved;
public readonly ushort XonLim;
public readonly ushort XoffLim;
public readonly byte ByteSize;
public readonly byte Parity;
public readonly byte StopBits;
public readonly byte XonChar;
public readonly byte XoffChar;
public readonly byte ErrorChar;
public readonly byte EofChar;
public readonly byte EvtChar;
public readonly ushort wReserved1;
}
#endregion
#endregion
}
}

View File

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace Plane.Util
{
/// <summary>
/// 为PasswordBox控件的Password增加绑定功能
/// </summary>
public static class PasswordBoxHelper
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordBoxHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordBoxHelper));
public static void SetAttach(DependencyObject dp, bool value)
{
dp.SetValue(AttachProperty, value);
}
public static bool GetAttach(DependencyObject dp)
{
return (bool)dp.GetValue(AttachProperty);
}
public static string GetPassword(DependencyObject dp)
{
return (string)dp.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject dp, string value)
{
dp.SetValue(PasswordProperty, value);
}
private static bool GetIsUpdating(DependencyObject dp)
{
return (bool)dp.GetValue(IsUpdatingProperty);
}
private static void SetIsUpdating(DependencyObject dp, bool value)
{
dp.SetValue(IsUpdatingProperty, value);
}
private static void OnPasswordPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
passwordBox.PasswordChanged -= PasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
}

View File

@ -1,7 +1,9 @@
using Plane.Windows.IniHelper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
@ -9,6 +11,7 @@ namespace Plane.FormationCreator.Util
{
public static class VersionControl
{
private static string DefaultServrURL= "http://111.229.174.37:81/login/";
public static int Version = 0;
/// <summary>
/// 是否是完整版本 仅在Version = 255时为完整版本
@ -20,13 +23,34 @@ namespace Plane.FormationCreator.Util
/// </summary>
public static int CopterUpperLimit = 50;
public static void GetVersionFromIni()
public static string Username = "";
public static string Password = "";
public static bool IssavePassword = false;
public static string ServerURL = "";
public static int ConType = 0; //通讯模块
public static void SetUserLever(int vuserlever)
{
if (vuserlever==0)
//管理员
IsFullVersion = true;
else
IsFullVersion = false;
}
public static void GetSettingFromIni()
{
IniFiles iniFiles = new IniFiles();
int intTemp;
bool boolTemp;
string readvalue;
//完整版本和更多飞机数量通过网络授权或者超级用户得到
/*
readvalue = iniFiles.IniReadvalue("Version", "Version");
if (readvalue != "" && int.TryParse(readvalue, out intTemp))
Version = int.Parse(readvalue);
@ -35,6 +59,108 @@ namespace Plane.FormationCreator.Util
readvalue = iniFiles.IniReadvalue("Version", "CopterUpperLimit");
if (readvalue != "" && int.TryParse(readvalue, out intTemp))
CopterUpperLimit = int.Parse(readvalue);
*/
readvalue = iniFiles.IniReadvalue("Login", "Username");
if (readvalue != "")
Username = readvalue;
readvalue = Decrypt(iniFiles.IniReadvalue("Login", "Password"));
if (readvalue != "")
Password = readvalue;
readvalue = iniFiles.IniReadvalue("Login", "issavePassword");
if (readvalue != "" && bool.TryParse(readvalue, out boolTemp))
IssavePassword = bool.Parse(readvalue);
readvalue = iniFiles.IniReadvalue("Default", "Server");
if (readvalue != "")
ServerURL = readvalue;
else
ServerURL = DefaultServrURL;
readvalue = iniFiles.IniReadvalue("Default", "ConType");
if (readvalue != "")
ConType = int.Parse(readvalue);
else
ConType = 0;
}
public static void SaveLogininfoToIni(string username,string password,bool issavepassword)
{
Username = username;
Password = password;
IssavePassword = issavepassword;
IniFiles iniFiles = new IniFiles();
iniFiles.IniWritevalue("Login", "Username", username);
if (issavepassword)
iniFiles.IniWritevalue("Login", "Password", Encrypt(password));
else
iniFiles.IniWritevalue("Login", "Password", "");
iniFiles.IniWritevalue("Login", "issavepassword", issavepassword.ToString());
}
static string encryptKey = "fxmf";//字符串加密密钥(注意密钥只能是4位)
private static string Encrypt(string str)
{//加密字符串
try
{
byte[] key = Encoding.Unicode.GetBytes(encryptKey);//密钥
byte[] data = Encoding.Unicode.GetBytes(str);//待加密字符串
DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();//加密、解密对象
MemoryStream MStream = new MemoryStream();//内存流对象
//用内存流实例化加密流对象
CryptoStream CStream = new CryptoStream(MStream, descsp.CreateEncryptor(key, key), CryptoStreamMode.Write);
CStream.Write(data, 0, data.Length);//向加密流中写入数据
CStream.FlushFinalBlock();//将数据压入基础流
byte[] temp = MStream.ToArray();//从内存流中获取字节序列
CStream.Close();//关闭加密流
MStream.Close();//关闭内存流
return Convert.ToBase64String(temp);//返回加密后的字符串
}
catch
{
return str;
}
}
private static string Decrypt(string str)
{//解密字符串
try
{
byte[] key = Encoding.Unicode.GetBytes(encryptKey);//密钥
byte[] data = Convert.FromBase64String(str);//待解密字符串
DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();//加密、解密对象
MemoryStream MStream = new MemoryStream();//内存流对象
//用内存流实例化解密流对象
CryptoStream CStream = new CryptoStream(MStream, descsp.CreateDecryptor(key, key), CryptoStreamMode.Write);
CStream.Write(data, 0, data.Length);//向加密流中写入数据
CStream.FlushFinalBlock();//将数据压入基础流
byte[] temp = MStream.ToArray();//从内存流中获取字节序列
CStream.Close();//关闭加密流
MStream.Close();//关闭内存流
return Encoding.Unicode.GetString(temp);//返回解密后的字符串
}
catch
{
return str;
}
}
}
}

View File

@ -0,0 +1,123 @@
using System;
using uint8_t = System.Byte;
using uint16_t = System.UInt16;
using int32_t = System.Int32;
using uint32_t = System.UInt32;
using int8_t = System.SByte;
using System.Runtime.InteropServices;
namespace Plane.Util
{
public class nmea : ICorrections
{
int step = 0;
public byte[] buffer = new byte[1024 * 1];
int payloadlen = 0;
int msglencount = 0;
public int length
{
get
{
return 2 + 2 + 2 + 2 + payloadlen; // header2, class,subclass,length2,data,crc2
}
}
public byte[] packet
{
get
{
return buffer;
}
}
public bool resetParser()
{
step = 0;
return true;
}
public int Read(byte data)
{
switch (step)
{
default:
case 0:
if (data == '$')
{
step = 1;
msglencount = 0;
buffer[0] = data;
}
break;
case 1:
if (data == 'G')
{
buffer[1] = data;
step++;
}
else
step = 0;
break;
case 2:
if (msglencount > 1000)
{
step = 0;
}
buffer[msglencount + 2] = data;
msglencount++;
if(data == '\n')
{
var line = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, msglencount + 2);
string[] items = line.Trim().Split(',', '*');
if (items[items.Length-1] == GetChecksum(line))
{
return 1;
}
step = 0;
}
break;
}
return -1;
}
// Calculates the checksum for a sentence
string GetChecksum(string sentence)
{
// Loop through all chars to get a checksum
int Checksum = 0;
foreach (char Character in sentence.ToCharArray())
{
switch (Character)
{
case '$':
// Ignore the dollar sign
break;
case '*':
// Stop processing before the asterisk
return Checksum.ToString("X2");
default:
// Is this the first value for the checksum?
if (Checksum == 0)
{
// Yes. Set the checksum to the value
Checksum = Convert.ToByte(Character);
}
else
{
// No. XOR the checksum with this character's value
Checksum = Checksum ^ Convert.ToByte(Character);
}
break;
}
}
// Return the checksum formatted as a two-character hexadecimal
return Checksum.ToString("X2");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,573 @@
using System;
using uint8_t = System.Byte;
using uint16_t = System.UInt16;
using int32_t = System.Int32;
using uint32_t = System.UInt32;
using int8_t = System.SByte;
using System.Runtime.InteropServices;
using System.Threading;
namespace Plane.Util
{
public class Ubx : ICorrections
{
int step = 0;
public byte[] buffer = new byte[1024 * 8];
int payloadlen = 0;
int msglencount = 0;
public byte @class
{
get { return buffer[2]; }
}
public byte subclass
{
get { return buffer[3]; }
}
public int length
{
get
{
return 2 + 2 + 2 + 2 + payloadlen; // header2, class,subclass,length2,data,crc2
}
}
public byte[] packet
{
get { return buffer; }
}
public bool resetParser()
{
step = 0;
return true;
}
public int Read(byte data)
{
switch (step)
{
default:
case 0:
if (data == 0xb5)
{
step = 1;
buffer[0] = data;
}
break;
case 1:
if (data == 0x62)
{
buffer[1] = data;
step++;
}
else
step = 0;
break;
case 2:
buffer[2] = data;
step++;
break;
case 3:
buffer[3] = data;
step++;
break;
case 4:
buffer[4] = data;
payloadlen = data;
step++;
break;
case 5:
buffer[5] = data;
step++;
payloadlen += (data << 8);
msglencount = 0;
// reset on oversize packet
if (payloadlen > buffer.Length)
step = 0;
break;
case 6:
if (msglencount < (payloadlen))
{
buffer[msglencount + 6] = data;
msglencount++;
if (msglencount == payloadlen)
step++;
}
break;
case 7:
buffer[msglencount + 6] = data;
step++;
break;
case 8:
buffer[msglencount + 6 + 1] = data;
var crc = ubx_checksum(buffer, payloadlen + 6);
var crcpacket = new byte[] { buffer[msglencount + 6], data };
if (crc[0] == crcpacket[0] && crc[1] == crcpacket[1])
{
step = 0;
return (@class << 8) + subclass;
}
step = 0;
break;
}
return -1;
}
private static byte[] ubx_checksum(byte[] packet, int size, int offset = 2)
{
uint a = 0x00;
uint b = 0x00;
var i = offset;
while (i < size)
{
a += packet[i++];
b += a;
}
var ans = new byte[2];
ans[0] = (byte)(a & 0xFF);
ans[1] = (byte)(b & 0xFF);
return ans;
}
public static byte[] generate(byte cl, byte subclass, byte[] payload)
{
var data = new byte[2 + 2 + 2 + 2 + payload.Length];
data[0] = 0xb5;
data[1] = 0x62;
data[2] = cl;
data[3] = subclass;
data[4] = (byte)(payload.Length & 0xff);
data[5] = (byte)((payload.Length >> 8) & 0xff);
Array.ConstrainedCopy(payload, 0, data, 6, payload.Length);
var checksum = ubx_checksum(data, data.Length - 2);
data[data.Length - 2] = checksum[0];
data[data.Length - 1] = checksum[1];
return data;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_mon_ver
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] swVersion;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public Byte[] hwVersion;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public byte[] extension;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_mon_hw
{
public int pinSel;
public int pinBank;
public int pinDir;
public int pinVal;
public ushort noisePerMS;
public ushort agcCnt;
public byte aStatus;
public byte aPower;
public byte flags;
public byte reserved1;
public int usedMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public byte[] VP;
public byte jamInd;
public ushort reserved3;
public int pinIrq;
public int pullH;
public int pullL;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_nav_pvt
{
public uint32_t itow;
public uint16_t year;
public uint8_t month, day, hour, min, sec;
public uint8_t valid;
public uint32_t t_acc;
public int32_t nano;
public uint8_t fix_type;
public uint8_t flags;
public uint8_t flags2;
public uint8_t num_sv;
public int32_t lon, lat;
public int32_t height, h_msl;
public uint32_t h_acc, v_acc;
public int32_t velN, velE, velD, gspeed;
public int32_t head_mot;
public uint32_t s_acc;
public uint32_t head_acc;
public uint16_t p_dop;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public uint8_t[] reserved1;
public uint32_t headVeh;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public uint8_t[] reserved2;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_nav_svin
{
public uint8_t version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public uint8_t[] reserved1;
public uint32_t iTOW;
public uint32_t dur;
public int32_t meanX;
public int32_t meanY;
public int32_t meanZ;
public int8_t meanXHP;
public int8_t meanYHP;
public int8_t meanZHP;
public uint8_t reserved2;
public uint32_t meanAcc;
public uint32_t obs;
public uint8_t valid;
public uint8_t active;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint8_t[] reserved3;
public double[] getECEF()
{
var X = meanX / 100.0 + meanXHP * 0.0001;
var Y = meanY / 100.0 + meanYHP * 0.0001;
var Z = meanZ / 100.0 + meanZHP * 0.0001;
return new double[] { X, Y, Z };
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_nav_velned
{
public uint iTOW;
public int velN;
public int velE;
public int velD;
public uint speed;
public uint gSpeed;
public int heading;
public uint sAcc;
public uint cAcc;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ubx_cfg_nav5_getset_s
{
public uint16_t mask;
public uint8_t dynModel;
public uint8_t fixMode;
public int32_t fixedAlt;
public uint32_t fixedAltVar;
public int8_t minElev;
public uint8_t drLimit;
public uint16_t pDop;
public uint16_t tDop;
public uint16_t pAcc;
public uint16_t tAcc;
public uint8_t staticHoldThresh;
public uint8_t dgnssTimeout;
public uint8_t cnoThreshNumSVs;
public uint8_t cnoThresh;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint8_t[] reserved1;
public uint16_t staticHoldMaxDist;
public uint8_t utcStandard;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public uint8_t[] reserved2;
}
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 40)]
public struct ubx_cfg_tmode3
{
public ubx_cfg_tmode3(double lat, double lng, double alt, double acc = 0.001)
{
version = 0;
reserved1 = 0;
if (Math.Abs(lat) > 90)
{
flags = 2; // fixed mode ecef
ecefXorLat = (int)(lat * 100);
ecefYorLon = (int)(lng * 100);
ecefZorAlt = (int)(alt * 100);
ecefXOrLatHP = (sbyte)((lat * 100 - ecefXorLat) * 100.0);
ecefYOrLonHP = (sbyte)((lng * 100 - ecefYorLon) * 100.0);
ecefZOrAltHP = (sbyte)((alt * 100 - ecefZorAlt) * 100.0);
}
else
{
flags = 256 + 2; // lla + fixed mode
ecefXorLat = (int)(lat * 1e7);
ecefYorLon = (int)(lng * 1e7);
ecefZorAlt = (int)(alt * 100.0);
ecefXOrLatHP = (sbyte)((lat * 1e7 - ecefXorLat) * 100.0);
ecefYOrLonHP = (sbyte)((lng * 1e7 - ecefYorLon) * 100.0);
ecefZOrAltHP = (sbyte)((alt * 100.0 - ecefZorAlt) * 100.0);
}
reserved2 = 0;
fixedPosAcc = (uint)(acc * 1000.0);
svinMinDur = 60;
svinAccLimit = 2000;
reserved3 = new byte[8];
}
public ubx_cfg_tmode3(uint DurationS, double AccLimit)
{
version = 0;
reserved1 = 0;
flags = 1; // surveyin mode
ecefXorLat = 0;
ecefYorLon = 0;
ecefZorAlt = 0;
ecefXOrLatHP = (sbyte)0;
ecefYOrLonHP = (sbyte)0;
ecefZOrAltHP = (sbyte)0;
reserved2 = 0;
fixedPosAcc = 0;
svinMinDur = DurationS;
svinAccLimit = (uint)(AccLimit * 10000);
reserved3 = new byte[8];
}
public static ubx_cfg_tmode3 Disable
{
get
{
return new ubx_cfg_tmode3()
{
flags = 0, // disable
reserved3 = new byte[8]
};
}
}
public static implicit operator byte[] (ubx_cfg_tmode3 input)
{
return null;// MavlinkUtil.StructureToByteArray(input);
}
public enum modeflags
{
Disabled = 0,
SurveyIn = 1,
FixedECEF = 2,
LLA = 256,
FixedLLA = 258
}
public byte version;
public byte reserved1;
public ushort flags;
public int ecefXorLat; // 1e7
public int ecefYorLon;
public int ecefZorAlt;
public sbyte ecefXOrLatHP;
public sbyte ecefYOrLonHP;
public sbyte ecefZOrAltHP;
public byte reserved2;
public uint fixedPosAcc;
public uint svinMinDur;
public uint svinAccLimit;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] reserved3;
public void SetupM8P(ICommsSerial port, bool m8p_130plus = false, bool movingbase = false)
{
port.BaseStream.Flush();
var bauds = new[] { port.BaudRate, 9600, 38400, 57600, 115200, 230400, 460800 };
// change the baudrate
foreach (var baud in bauds)
{
port.BaudRate = baud;
System.Threading.Thread.Sleep(50);
// U = bit 01010101 - often used for autobaud
port.Write("UU");
// port config - 460800 - uart1
var packet = generate(0x6, 0x00, new byte[]
{
0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x08,
0x07, 0x00, 0x23, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00
});
port.Write(packet, 0, packet.Length);
port.BaseStream.Flush();
System.Threading.Thread.Sleep(100);
}
{
// port config - usb
var packet = generate(0x6, 0x00, new byte[]
{
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x23, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00
});
port.Write(packet, 0, packet.Length);
System.Threading.Thread.Sleep(300);
port.BaseStream.Flush();
port.BaudRate = 460800;
}
{
// set rate to 1hz
var packet = generate(0x6, 0x8, new byte[] { 0xE8, 0x03, 0x01, 0x00, 0x01, 0x00 });
port.Write(packet, 0, packet.Length);
System.Threading.Thread.Sleep(200);
// set navmode to stationary
{
packet = generate(0x6, 0x24,
new byte[]
{
0xFF, 0xFF, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x0F, 0x00, 0xFA,
0x00,
0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x23, 0x10, 0x27, 0x00, 0x00, 0x00,
0x00,
0x00, 0x00, 0x00, 0x00
});
port.Write(packet, 0, packet.Length);
System.Threading.Thread.Sleep(200);
}
}
// turn off all nmea
for (int a = 0; a <= 0xf; a++)
{
if (a == 0xb || a == 0xc || a == 0xe)
continue;
turnon_off(port, 0xf0, (byte)a, 0);
}
// mon-ver
poll_msg(port, 0xa, 0x4);
// surveyin msg - for feedback
turnon_off(port, 0x01, 0x3b, 1);
// pvt msg - for feedback
turnon_off(port, 0x01, 0x07, 1);
// 1005 - 5s
turnon_off(port, 0xf5, 0x05, 5);
byte rate1 = 1;
byte rate2 = 0;
if (m8p_130plus)
{
rate1 = 0;
rate2 = 1;
}
// 1074 - 1s
turnon_off(port, 0xf5, 0x4a, rate2);
// 1077 - 1s
turnon_off(port, 0xf5, 0x4d, rate1);
// 1084 - 1s
turnon_off(port, 0xf5, 0x54, rate2);
// 1087 - 1s
turnon_off(port, 0xf5, 0x57, rate1);
// 1094 - 1s
turnon_off(port, 0xf5, 0x5e, rate2);
// 1097 - 1s
turnon_off(port, 0xf5, 0x61, rate1);
// 1124 - 1s
turnon_off(port, 0xf5, 0x7c, rate2);
// 1127 - 1s
turnon_off(port, 0xf5, 0x7f, rate1);
// 4072
turnon_off(port, 0xf5, 0xFE, 0);
// 1230 - 5s
turnon_off(port, 0xf5, 0xE6, 5);
// NAV-VELNED - 1s
turnon_off(port, 0x01, 0x12, 1);
// rxm-raw/rawx - 1s
turnon_off(port, 0x02, 0x15, 1);
turnon_off(port, 0x02, 0x10, 1);
// rxm-sfrb/sfrb - 2s
turnon_off(port, 0x02, 0x13, 2);
turnon_off(port, 0x02, 0x11, 2);
// mon-hw - 2s
turnon_off(port, 0x0a, 0x09, 2);
System.Threading.Thread.Sleep(100);
}
public void turnon_off(ICommsSerial port, byte clas, byte subclass, byte every_xsamples)
{
byte[] datastruct1 = { clas, subclass, 0, every_xsamples, 0, every_xsamples, 0, 0 };
var packet = generate(0x6, 0x1, datastruct1);
port.Write(packet, 0, packet.Length);
System.Threading.Thread.Sleep(10);
}
public void poll_msg(ICommsSerial port, byte clas, byte subclass)
{
byte[] datastruct1 = { };
var packet = generate(clas, subclass, datastruct1);
port.Write(packet, 0, packet.Length);
System.Threading.Thread.Sleep(10);
}
}
}
}

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

@ -0,0 +1,150 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.Formation;
using Plane.FormationCreator.Util;
using Plane.FormationCreator.Views;
using Plane.Util;
using Plane.Windows.Messages;
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace Plane.FormationCreator.ViewModels
{
/// <summary>
/// This class contains properties that a View can data bind to.
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class ChangePasswordViewModel : ViewModelBase
{
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private MainViewModel _MainViewModel=ServiceLocator.Current.GetInstance<MainViewModel>();
/// <summary>
/// Initializes a new instance of the LoginViewModel class.
/// </summary>
public ChangePasswordViewModel()
{
NewPassword = "";
OldPassword = "";
NewPassword1 = "";
Username = "";
}
private string _Username="";
public string Username
{
get { return _Username; }
set
{
Set(nameof(Username), ref _Username, value);
}
}
private string _OldPassword = "";
public string OldPassword
{
get { return _OldPassword; }
set
{
Set(nameof(OldPassword), ref _OldPassword, value);
}
}
private string _NewPassword = "";
public string NewPassword
{
get { return _NewPassword; }
set
{
Set(nameof(NewPassword), ref _NewPassword, value);
}
}
private string _NewPassword1 = "";
public string NewPassword1
{
get { return _NewPassword1; }
set
{
Set(nameof(NewPassword1), ref _NewPassword1, value);
}
}
private ICommand _ExitCommand;
public ICommand ExitCommand
{
get
{
return _ExitCommand ?? (_ExitCommand = new RelayCommand<ChangePasswordView>(wd =>
{
if (wd != null)
{
NewPassword = "";
OldPassword = "";
NewPassword1 = "";
Username = "";
wd.Close();
}
}));
}
}
private ICommand _ChangePasswordCommand;
public ICommand ChangePasswordCommand
{
get
{
return _ChangePasswordCommand ?? (_ChangePasswordCommand = new RelayCommand<ChangePasswordView>(wd =>
{
if (Username.Trim() == "")
{
Alert.Show("请输入账号!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (OldPassword=="")
{
Alert.Show("请输入原密码!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (NewPassword.Length<6)
{
Alert.Show("新密码长度不能低于6位", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (NewPassword != NewPassword1)
{
Alert.Show("两次新密码不相同!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
_copterManager.NetChangePassword(Username.Trim(), OldPassword, NewPassword);
//wd.Close();
}));
}
}
}
}

View File

@ -0,0 +1,336 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Plane.Copters;
using Plane.FormationCreator.Formation;
using Plane.Geography;
using Plane.Windows.Messages;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.Practices.ServiceLocation;
using System.IO;
namespace Plane.FormationCreator.ViewModels
{
public class ConfigVirtualIdViewModel : ViewModelBase
{
CopterManager _copterManager;
public ConfigVirtualIdViewModel(CopterManager copterManager)
{
_copterManager = copterManager;
}
private int _SingleVirtualId = 0;
public int SingleVirtualId
{
get { return _SingleVirtualId; }
set { Set(nameof(SingleVirtualId), ref _SingleVirtualId, value); }
}
/// <summary>
/// 清除所有编号
/// </summary>
private ICommand _ClearVirtualIdCommand;
public ICommand ClearVirtualIdCommand
{
get
{
return _ClearVirtualIdCommand ?? (_ClearVirtualIdCommand = new RelayCommand(() =>
{
foreach (var c in _copterManager.Copters)
{
c.VirtualId = 0;
}
Message.Show($"已清除所有飞机编号");
}));
}
}
/// <summary>
/// 清除所有编号
/// </summary>
private ICommand _SaveVirtualIdCommand;
public ICommand SaveVirtualIdCommand
{
get
{
return _SaveVirtualIdCommand ?? (_SaveVirtualIdCommand = new RelayCommand(() =>
{
string Savestr = "";
foreach (var c in _copterManager.Copters)
{
Savestr += c.Id + "=" + c.VirtualId + ';';
}
StreamWriter writer = new StreamWriter("vid.dat");
writer.Write(Savestr);
writer.Close();
Message.Show($"保存成功");
}));
}
}
/// <summary>
/// 清除所有编号
/// </summary>
private ICommand _LoadVirtualIdCommand;
public ICommand LoadVirtualIdCommand
{
get
{
return _LoadVirtualIdCommand ?? (_LoadVirtualIdCommand = new RelayCommand(() =>
{
if (!File.Exists("vid.dat"))
return;
// string str = System.IO.File.ReadAllText(@"vid.dat");
string str = File.ReadAllText("vid.dat");
string[] arr = str.Split(';');
foreach (string s in arr)
{
string[] arrs = s.Split('=');
var copter = _copterManager.Copters.FirstOrDefault(c => c.Id == arrs[0]);
if (copter != null)
{
copter.VirtualId = int.Parse(arrs[1]);
}
}
_copterManager.SortType = CopterManager.CopterSortType.ByVID;// .sortbyvid();
Message.Show($"读入成功");
}));
}
}
/// <summary>
/// 设置单个虚拟ID
/// </summary>
private ICommand _SetSingleVirtualIdCommand;
public ICommand SetSingleVirtualIdCommand
{
get
{
return _SetSingleVirtualIdCommand ?? (_SetSingleVirtualIdCommand = new RelayCommand(() =>
{
if (SingleVirtualId <= 0)
{
System.Windows.MessageBox.Show("编号必须大于0");
return;
}
if (_copterManager.AcceptingControlCopters.Count() == 1)
{
var copter = _copterManager.AcceptingControlCopters.FirstOrDefault();
copter.VirtualId = SingleVirtualId;
Message.Show($"飞机{copter.Name} 设置编号={SingleVirtualId}");
}
_copterManager.ReSort();
}));
}
}
private ICommand _AutoLocationNumsCommand;
public ICommand AutoLocationNumsCommand
{
get
{
//目前方案是
//1.保证所有没有正确定位的飞机都人工编号,
//2.然后选中3架飞机1号飞机第一排任意飞机第一列任意飞机尽量远离1号机
//3.开始计算
return _AutoLocationNumsCommand ?? (_AutoLocationNumsCommand = new RelayCommand( () =>
{
//飞机摆放最小间距
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
float StepDis_Row = _flightTaskManager.ColumnDistance; //行内间距-列间距
float StepDis_Col = _flightTaskManager.RowDistance ; //列间距-行间距
float FindDis =Math.Min(StepDis_Row, StepDis_Col)*0.8f; //查找半径
//如果选中的飞机总数大于2--需要2-3架用来确认行列方向只有一行飞机就选2架多行需要3架
if (_copterManager.AcceptingControlCopters.Count() >= 2)
{
var copters = _copterManager.AcceptingControlCopters.ToList();
var firstCopter = copters[0];
var secondCopter = copters[1];
ICopter thirdCopter=null;
if (_copterManager.AcceptingControlCopters.Count() > 2)
{
thirdCopter = copters[2];
Message.Show($"选中了3架飞机将自动查找所有行列的飞机");
}
else
Message.Show($"选中了2架飞机将查找一行飞机");
//行角度(1,2) 用于查找每行的飞机位置
float RowDirect = (float)GeographyUtils.RadToDeg(firstCopter.CalcDirection2D(secondCopter));
//列角度(1,3) 用于查找每行第一架飞机
float ColDirect = 0;
if (thirdCopter!=null)
ColDirect = (float)GeographyUtils.RadToDeg(firstCopter.CalcDirection2D(thirdCopter));
ICopter FindedCopter = firstCopter;
ICopter LastCopter = firstCopter;
ILocation2D LastRowHewadCopter = firstCopter;
Message.Show($"开始查找飞机:行角度{RowDirect},列角度{ColDirect},列间距{StepDis_Row},行间距{StepDis_Col},查找半径{FindDis}米...");
firstCopter.VirtualId = 1;
int rowindex = 1;
while (FindedCopter!=null)
{
//按一行找飞机
FindedCopter = FindNextCopter(LastCopter, RowDirect, StepDis_Row, FindDis);
//一行找不到了 找下一行的前3架飞机
if ((FindedCopter == null) && (thirdCopter != null))
{
rowindex++;
FindedCopter = FindNextColHeadCopter(out LastRowHewadCopter, LastRowHewadCopter, ColDirect, StepDis_Col, RowDirect, StepDis_Row, 3, FindDis);
if (FindedCopter != null)
Message.Show($"开始第{rowindex}行--找到飞机");
else
Message.Show($"开始第{rowindex}行--无飞机");
}
//如果找到了分配ID
if (FindedCopter != null)
{
FindedCopter.VirtualId = GetVID(LastCopter.VirtualId);
// Message.Show($"分配ID={FindedCopter.Id}飞机VID:={FindedCopter.VirtualId}");
LastCopter = FindedCopter;
}else
{
Message.Show($"未找到飞机,自动分配结束");
}
}
}
_copterManager.ReSort();
}));
}
}
//根据位置和查找范围查找飞机
private ICopter FindCopteratLoc(ILocation2D startLoc, float findDis)
{
ICopter retCopter = null;
ICopter foundCopter = null;
double mindis = 1000;
//所有没有虚拟ID的飞机
List<ICopter> NoVIDCopters = _copterManager.Copters.Where(o => o.VirtualId == 0).ToList();
//找距离startLoc最近的飞机
foreach (var copter in NoVIDCopters)
{
//计算这些飞机和startLoc的距离
double temp = startLoc.CalcDistance2D(copter);
//找最近的飞机
if (temp < mindis)
{
mindis = temp;
foundCopter = copter;
}
}
//如果找到的最近的飞机小于查找半径就认为找到了
if (mindis < findDis)
retCopter = foundCopter;
return retCopter;
}
//根据VID查找飞机
private ICopter FindCopteratVID(int VID)
{
List<ICopter> HaveVIDCopters = _copterManager.Copters.Where(o => o.VirtualId == VID).ToList();
if (HaveVIDCopters.Count==1)
return HaveVIDCopters[0];
return null;
}
//计算VID,找下一个没有提前分配的VID
private int GetVID(int VirtualId)
{
int retvid = VirtualId+1;
ICopter Copter = FindCopteratVID(retvid);
while (Copter!=null)
Copter = FindCopteratVID(++retvid);
return retvid;
}
/// <summary>
/// 按方向步长等找下一架飞机
/// </summary>
/// <param name="Copter">起始飞机</param>
/// <param name="Direct">方向</param>
/// <param name="findstep">步长</param>
/// <param name="finddis">查找半径</param>
/// <returns>找到的飞机</returns>
private ICopter FindNextCopter(ILocation2D Copter, float Direct,float findstep,float finddis,int findstepnum=5)
{
ICopter FindedCopter = null;
ILocation2D FindLoc = null;
int step = 1;
while ((FindedCopter == null) && (step <= findstepnum))
{
//查找下一个飞机应在摆放的位置
FindLoc = Copter.CalcLatLngSomeMetersAway2D(Direct, findstep * step++);
//该位置是否有飞机
FindedCopter = FindCopteratLoc(FindLoc, finddis);
}
return FindedCopter;
}
/// <summary>
///按方向步长等找下一行的第一架飞机同时输出该行第一个应该摆放飞机的位置
/// </summary>
/// <param name="HeadLoc">输出第一架飞机应该在的位置</param>
/// <param name="Copter">起始飞机</param>
/// <param name="ColDirect">列角度</param>
/// <param name="Colstep">列步长</param>
/// <param name="RowDirect">行角度</param>
/// <param name="Rowstep">行步长</param>
/// <param name="Rowstepnum">行查找深度</param>
/// <param name="finddis">位置查找范围</param>
/// <returns>找到的飞机</returns>
private ICopter FindNextColHeadCopter(out ILocation2D HeadLoc, ILocation2D Copter, float ColDirect, float Colstep,
float RowDirect, float Rowstep, int Rowstepnum,float finddis, int Colfindstepnum = 5)
{
ICopter FindedCopter = null;
HeadLoc = null;
int step = 1;
while ((FindedCopter == null) && (step <= Colfindstepnum))
{
//查找下一行第一架飞机应在摆放的位置
HeadLoc = Copter.CalcLatLngSomeMetersAway2D(ColDirect, Colstep * step++);
//该位置是否有飞机
FindedCopter = FindCopteratLoc(HeadLoc, finddis);
//如果没有飞机,横着找找行有没飞机
if (FindedCopter==null)
FindedCopter=FindNextCopter(HeadLoc, RowDirect, Rowstep, finddis, Rowstepnum);
}
return FindedCopter;
}
}
}

View File

@ -24,16 +24,32 @@ using Plane.CommunicationManagement;
using Plane.Protocols;
using Microsoft.Practices.ServiceLocation;
using System.Windows.Media;
using Plane.FormationCreator.Views;
using System.Collections.ObjectModel;
using Plane.Util;
using System.IO.Ports;
using SerialPort = Plane.Util.SerialPort;
namespace Plane.FormationCreator.ViewModels
{
public class ConnectViewModel : ViewModelBase
{
public ConnectViewModel(CopterManager copterManager)
{
_copterManager = copterManager;
RefreshPorts();
}
public void RefreshPorts()
{
serialRePorts.Clear();
string[] commports = SerialPort.GetPortNames();
foreach (var item in commports)
{
serialRePorts.Add(item);
}
}
private CommModuleManager _commModuleManager = CommModuleManager.Instance;
private CopterManager _copterManager;
private const int PORT = 5250;
@ -66,6 +82,16 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(IsProcessing), ref _IsProcessing, value); }
}
public ObservableCollection<string> serialRePorts { get; } = new ObservableCollection<string>();
private string _serialPortResend;
public string SerialPortResend
{
get { return _serialPortResend; }
set { Set(nameof(SerialPortResend), ref _serialPortResend, value); }
}
private ICommand _ConnectCommand;
public ICommand ConnectCommand
{
@ -78,7 +104,67 @@ namespace Plane.FormationCreator.ViewModels
));
}
}
RtcmInfoViewModel _rtcmInfoViewModel = ServiceLocator.Current.GetInstance<RtcmInfoViewModel>();
private ICommand _Openboardport;
public ICommand Openboardport
{
get
{
return _Openboardport ?? (_Openboardport = new RelayCommand<string>(async connectionType =>
{
if (btnBoardPortStr== "关闭广播端口")
{
//关闭广播端口
//正在发送rtcm数据并且使用了广播端口
if (_rtcmInfoViewModel.RtcmManager.Rtcmthreadrun&& _rtcmInfoViewModel.ResendToComMK)
{
if (Alert.Show("正在使用广播端口发送RTCM数据关闭后广播端口将停止发送,继续吗?", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
== MessageBoxResult.OK)
{
// _rtcmInfoViewModel.ResendToComMK = false;
}
else
{
return;
}
}
//关闭同时清除广播端口,这样就不会重试打开
_commModuleManager.CloseResendRtcmserial(true);
btnBoardPortStr = "打开广播端口";
BoardPortStatusStr = _commModuleManager.BoardPortStatusStr;
Message.BoardOpen(false);
}
else
{ //打开广播端口
if ((SerialPortResend != null))
{
if (!_commModuleManager.OpenResendRtcmserial(SerialPortResend))
{
Alert.Show($"打开串口失败", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
btnBoardPortStr = "关闭广播端口";
Message.BoardOpen(true);
}
BoardPortStatusStr = _commModuleManager.BoardPortStatusStr;
}
else
{
Alert.Show($"请选择需要广播的端口", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
}
_rtcmInfoViewModel.SetRTKStatestr();
}
));
}
}
private ICommand _SendCommand;
public ICommand SendCommand
{
@ -86,7 +172,7 @@ namespace Plane.FormationCreator.ViewModels
{
return _SendCommand ?? (_SendCommand = new RelayCommand(async () =>
{
await SendCommandAsync(CopterNum);
await SendCommandAsync(CopterSum);
}
));
}
@ -125,13 +211,43 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(CopterNum), ref _CopterNum, value); }
}
private string _CopterColor = "";
public float scale3d
{
get { return _copterManager.scale3d ; }
set { _copterManager.scale3d = value;}
}
private int _CopterSum=100;
public int CopterSum
{
get { return _CopterSum; }
set { Set(nameof(CopterSum), ref _CopterSum, value); }
}
private string _CopterColor = "330033";
public string CopterColor
{
get { return _CopterColor; }
set { Set(nameof(CopterColor), ref _CopterColor, value); }
}
private string _BoardPortStatusStr = "广播端口未打开";
public string BoardPortStatusStr
{
get { return _BoardPortStatusStr; }
set { Set(nameof(BoardPortStatusStr), ref _BoardPortStatusStr, value); }
}
private string _btnBoardPortStr = "打开广播端口";
public string btnBoardPortStr
{
get { return _btnBoardPortStr; }
set { Set(nameof(btnBoardPortStr), ref _btnBoardPortStr, value); }
}
private ICommand _WriteIdCommand;
public ICommand WriteIdCommand
{
@ -213,6 +329,46 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private ICommand _ChangepasswordCommand;
public ICommand ChangepasswordCommand
{
get
{
return _ChangepasswordCommand ?? (_ChangepasswordCommand = new RelayCommand( () =>
{
ChangePasswordView changePasswordView = new ChangePasswordView();
changePasswordView.ShowDialog();
}));
}
}
private ICommand _TestModuleCommand;
public ICommand TestModuleCommand
{
get
{
return _TestModuleCommand ?? (_TestModuleCommand = new RelayCommand(async () =>
{
await commModule.TestModule((short)scale3d);
}));
}
}
private ICommand _SetModulePowerCommand;
public ICommand SetModulePowerCommand
{
get
{
return _SetModulePowerCommand ?? (_SetModulePowerCommand = new RelayCommand(async () =>
{
int mPower = int.Parse(CopterColor);
await commModule.SetModulePower((short)CopterNum, (short)mPower);
}));
}
}
private ICommand _CommDataAsync;
public ICommand CommDataAsync
@ -227,6 +383,27 @@ namespace Plane.FormationCreator.ViewModels
}
}
private ICommand _TestPWMCommandAsync;
public ICommand TestPWMCommandAsync
{
get
{
return _TestPWMCommandAsync ?? (_TestPWMCommandAsync = new RelayCommand(async () =>
{
try
{
int channel = 10; //固定10是控制PWM舵机
await commModule.TestFire((short)CopterNum, channel);
}
catch
{ }
}
));
}
}
private ICommand _TestFireCommandAsync;
public ICommand TestFireCommandAsync
{
@ -234,9 +411,15 @@ namespace Plane.FormationCreator.ViewModels
{
return _TestFireCommandAsync ?? (_TestFireCommandAsync = new RelayCommand(async () =>
{
int channel = int.Parse(CopterColor);
if (channel >= 0 && channel <= 4)
await commModule.TestFire((short)CopterNum, channel);
try
{
int channel = int.Parse(CopterColor);
if (channel >= 0 && channel <= 4)
await commModule.TestFire((short)CopterNum, channel);
}
catch
{ }
}
));
}
@ -251,7 +434,7 @@ namespace Plane.FormationCreator.ViewModels
IMission LEDMission = Mission.CreateLEDControlMission(
(int)(ledInfo.Delay * 10),
ledInfo.LEDMode,
ledInfo.LEDRate,
ledInfo.LEDInterval,
0, //ledInfo.LEDTimes,
color.R,
color.G,

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@ using Newtonsoft.Json;
using System.IO;
using Newtonsoft.Json.Linq;
using Plane.Windows.Messages;
using Plane.Collections;
namespace Plane.FormationCreator.ViewModels
{
@ -92,6 +93,12 @@ namespace Plane.FormationCreator.ViewModels
get { return _IntervalNum; }
set { Set(nameof(IntervalNum), ref _IntervalNum, value); }
}
private int _RowNum;
public int RowNum
{
get { return _RowNum; }
set { Set(nameof(RowNum), ref _RowNum, value); }
}
private int _ContinuousNum;
public int ContinuousNum
@ -110,6 +117,19 @@ namespace Plane.FormationCreator.ViewModels
public ObservableCollection<string[]> CopterGroups { get; } = new ObservableCollection<string[]>();
private int getNextcopterindex( int currindex)
{
//每行数量
int colcount = _flightTaskManager.ColumnCount;
int newind = currindex;
for (int i = 0;i< IntervalNum;i++)
{
newind +=1;
if ((newind % colcount) == 0)
newind += RowNum * colcount;
}
return newind;
}
private ICommand _IntervalSelectCoptersCommand;
public ICommand IntervalSelectCoptersCommand
@ -125,6 +145,21 @@ namespace Plane.FormationCreator.ViewModels
_copterManager.Select(null);
int index = _copterManager.Copters.IndexOf(copter);
_copterManager.shiftkeydown = true;
int colcount = _flightTaskManager.ColumnCount;
for (; index < _copterManager.Copters.Count; index= getNextcopterindex( index) )
{
for (int i = 0; i < ContinuousNum; i++)
{
if (index >= _copterManager.Copters.Count) break;
_copterManager.Select(_copterManager.Copters[index]);
index += 1;
if ((index % colcount) == 0)
index += RowNum * colcount;
getNextcopterindex(index);
}
}
/*
for (; index < _copterManager.Copters.Count; index += IntervalNum)
{
for (int i = 0; i < ContinuousNum; i++)
@ -134,6 +169,7 @@ namespace Plane.FormationCreator.ViewModels
index++;
}
}
*/
_copterManager.shiftkeydown = false;
}));
@ -158,6 +194,44 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private ICommand _SortbyVIdCommand;
public ICommand SortbyVIdCommand
{
get
{
return _SortbyVIdCommand ?? (_SortbyVIdCommand = new RelayCommand( () =>
{
_copterManager.SortType = CopterManager.CopterSortType.ByVID;
//强制刷新飞机显示
// _copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
private ICommand _SortbyIdCommand;
public ICommand SortbyIdCommand
{
get
{
return _SortbyIdCommand ?? (_SortbyVIdCommand = new RelayCommand(() =>
{
_copterManager.SortType = CopterManager.CopterSortType.ByID;
//强制刷新飞机显示
// _copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
private ICommand _ShowAllCoptersCommand;
public ICommand ShowAllCoptersCommand
@ -173,25 +247,31 @@ namespace Plane.FormationCreator.ViewModels
}
}
bool showVirtualId = false;
private ICommand _SwitchIdVirtualIdCommand;
public ICommand SwitchIdVirtualIdCommand
private ICommand _ShowAllIDCommand;
public ICommand ShowAllIDCommand
{
get
{
return _SwitchIdVirtualIdCommand ?? (_SwitchIdVirtualIdCommand = new RelayCommand(async () =>
return _ShowAllIDCommand ?? (_ShowAllIDCommand = new RelayCommand(() =>
{
showVirtualId = !showVirtualId;
foreach (var copter in _copterManager.Copters)
{
copter.DisplayVirtualId = showVirtualId;
}
await Task.Delay(10);
_copterManager.SortType = CopterManager.CopterSortType.ByVIDShowAll;
//强制刷新飞机显示
// _copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
private ICommand _AddVirtualCopterCommand;
public ICommand AddVirtualCopterCommand
{
@ -200,10 +280,10 @@ namespace Plane.FormationCreator.ViewModels
return _AddVirtualCopterCommand ?? (_AddVirtualCopterCommand = new RelayCommand<int>(async addcount =>
{
//给第三方时候限制数量用
if (_copterManager.Copters.Count() >= VersionControl.CopterUpperLimit)
{
return;
}
// if (_copterManager.Copters.Count() >= VersionControl.CopterUpperLimit)
/// {
// return;
// }
var center = _mapManager.Center;
string id;
@ -223,13 +303,14 @@ namespace Plane.FormationCreator.ViewModels
//内蒙地区
// if (center.Lat < 37.4307185218 || center.Lat > 45.6754821756
// || center.Lng < 97.3493089056 || center.Lng > 115.8006783856)
// return ;
// if (center.Lat < 37.4307185218 || center.Lat > 45.6754821756
// || center.Lng < 97.3493089056 || center.Lng > 115.8006783856)
// return ;
LatLng? colLatLng = new LatLng(center.Lat, center.Lng); ;
LatLng? colLatLng = new LatLng(center.Lat, center.Lng);
for (int i = 0; i < addcount; ++i, ++_virtualCopterId)
{
@ -247,7 +328,7 @@ namespace Plane.FormationCreator.ViewModels
else
{
if (currcol < colnum)
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Value.Lat, colLatLng.Value.Lng , orientation + 90, currcol * coldis);
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(colLatLng.Value.Lat, colLatLng.Value.Lng , orientation + 90, (currcol * coldis));
else
{
currrow++;
@ -257,7 +338,17 @@ namespace Plane.FormationCreator.ViewModels
colheadLatLng = targetLatLng;
}
_lastVirtualCopterLocation= new LatLng(targetLatLng.Item1, targetLatLng.Item2);
/*
//随机位置偏差40cm
Random r1 = new Random();
float rdrad= ((float)r1.Next(0, 360));
float rddis = ((float)r1.Next(-40, 40) / 100.0f);
targetLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(targetLatLng.Item1, targetLatLng.Item2, rdrad, rddis);
*/
_lastVirtualCopterLocation = new LatLng(targetLatLng.Item1, targetLatLng.Item2);
}
currcol++;
@ -271,19 +362,28 @@ namespace Plane.FormationCreator.ViewModels
*/
var copter = new FakeCopter(SynchronizationContext.Current);
copter.SetProperties(
latitude: _lastVirtualCopterLocation.Value.Lat,
longitude: _lastVirtualCopterLocation.Value.Lng,
id: id,
name: id
);
await copter.ConnectAsync();
await copter.GetCopterDataAsync();
_copterManager.Copters.AddCopter(copter);
_copterManager.CopterStatus.Add(false);
if (_copterManager.EnAddCopter_Fake())
{
var copter = new FakeCopter(SynchronizationContext.Current);
copter.SetProperties(
latitude: _lastVirtualCopterLocation.Value.Lat,
longitude: _lastVirtualCopterLocation.Value.Lng,
id: id,
name: id
);
if (_copterManager.FC_VER_NO >= 3)
copter.FlightControlMode = 1;
else copter.FlightControlMode = 0;
//不再预先分配VID
// copter.VirtualId = _virtualCopterId;
await copter.ConnectAsync();
await copter.GetCopterDataAsync();
_copterManager.CopterStatus.Add(false);
_copterManager.Copters.AddCopter(copter, _copterManager.SortType);
}
}
if (_flightTaskManager.OriginLat == 0 && _flightTaskManager.OriginLng == 0)
_flightTaskManager.SetOriginal();
}));
}
}
@ -356,6 +456,8 @@ namespace Plane.FormationCreator.ViewModels
return _ClearCoptersCommand ?? (_ClearCoptersCommand = new RelayCommand(async () =>
{
_flightTaskManager.Pause();
await _copterManager.ClearCopters();
/*
foreach (var copter in _copterManager.Copters)
{
await copter.DisconnectAsync();
@ -363,12 +465,19 @@ namespace Plane.FormationCreator.ViewModels
await Task.Delay(100); // 如果不等待一段时间,很可能会再触发 DataStreamReceived 事件导致飞行器重新出现在地图上。
_copterManager.Copters.Clear();
_copterManager.CopterStatus.Clear();
*/
_mapManager.ClearCopters();
_view3DManager.ClearCopters();
_flightTaskManager.ClearTasks();
//UdpServerConnectionManager.Instance.ClearConnections();
// UdpServerConnectionManager.Instance.ClearConnections();
_virtualCopterId = 1;
_lastVirtualCopterLocation = null;
_flightTaskManager.OriginLat = 0;
_flightTaskManager.OriginLng = 0;
_flightTaskManager.ObserverLat = 0;
_flightTaskManager.ObserverLng = 0;
}));
}
}

View File

@ -0,0 +1,123 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.Formation;
using Plane.FormationCreator.Util;
using Plane.FormationCreator.Views;
using Plane.Util;
using Plane.Windows.Messages;
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace Plane.FormationCreator.ViewModels
{
/// <summary>
/// This class contains properties that a View can data bind to.
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class LoginViewModel : ViewModelBase
{
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private MainViewModel _MainViewModel=ServiceLocator.Current.GetInstance<MainViewModel>();
/// <summary>
/// Initializes a new instance of the LoginViewModel class.
/// </summary>
public LoginViewModel()
{
Username = VersionControl.Username;
SavePassword = VersionControl.IssavePassword;
if (SavePassword)
Password = VersionControl.Password;
}
private string _Username="";
public string Username
{
get { return _Username; }
set
{
Set(nameof(Username), ref _Username, value);
}
}
private string _Password = "";
public string Password
{
get { return _Password; }
set
{
Set(nameof(Password), ref _Password, value);
}
}
private bool _SavePassword = false;
public bool SavePassword
{
get { return _SavePassword; }
set
{
Set(nameof(SavePassword), ref _SavePassword, value);
}
}
private ICommand _ExitCommand;
public ICommand ExitCommand
{
get
{
return _ExitCommand ?? (_ExitCommand = new RelayCommand<LoginView>(wd =>
{
if (wd != null)
{
wd.Close();
}
}));
}
}
private ICommand _LoginCommand;
public ICommand LoginCommand
{
get
{
return _LoginCommand ?? (_LoginCommand = new RelayCommand<LoginView>(wd =>
{
if (Username.Trim() == "")
{
Alert.Show("请输入账号!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (Password == "")
{
Alert.Show("请输入密码!", "登录提示", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
_copterManager.NetLogoin(Username.Trim(), Password, SavePassword);
if (!SavePassword) Password = "";
wd.Close();
}));
}
}
}
}

View File

@ -14,6 +14,11 @@ using Microsoft.Practices.ServiceLocation;
using System.IO;
using Newtonsoft.Json;
using Plane.Geography;
using Plane.FormationCreator.Views;
using System.Windows;
using Plane.Collections;
using Plane.Copters;
using Newtonsoft.Json.Linq;
namespace Plane.FormationCreator.ViewModels
{
@ -23,12 +28,22 @@ namespace Plane.FormationCreator.ViewModels
{
_copterListViewModel = copterListViewModel;
//状态信息
Plane.Windows.Messages.Message.ConfigureStatus(showAction: msg => this.SysStatusText = msg);
//日志信息
Plane.Windows.Messages.Message.Configure(showAction: msg => this.Message = msg);
//连接信息
Plane.Windows.Messages.Message.Configure(connectAction: connected => this.CommunicationModuleConnected = connected);
//广播是否打开
Plane.Windows.Messages.Message.Configureboard(boardportAction: opened => this.BoardcastPortOpened = opened);
this.SwitchVelocityModeButtonContent = GetSwitchVelocityModeButtonContent();
AppEx.Current.PropertyChanged += AppEx_PropertyChanged;
_copterManager.netStatusChanged += CopterManagernetStatusChanged;
ControlPanelViewModelData = ServiceLocator.Current.GetInstance<ControlPanelViewModel>();
}
private CopterListViewModel _copterListViewModel;
@ -39,6 +54,8 @@ namespace Plane.FormationCreator.ViewModels
public AppEx AppEx { get; } = AppEx.Current;
private void AppEx_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
switch (e.PropertyName)
@ -51,6 +68,14 @@ namespace Plane.FormationCreator.ViewModels
}
}
private void CopterManagernetStatusChanged(bool Logined, string status)
{
Loginstate = status;
if (Logined)
LoginDisp = "注销";
else LoginDisp = "登录";
}
private string _SwitchVelocityModeButtonContent;
public string SwitchVelocityModeButtonContent
{
@ -68,6 +93,18 @@ namespace Plane.FormationCreator.ViewModels
Logs += (Environment.NewLine + value);
}
}
private ControlPanelViewModel _controlPanelViewModelData;
public ControlPanelViewModel ControlPanelViewModelData
{
get { return _controlPanelViewModelData; }
set
{
Set(nameof(ControlPanelViewModelData), ref _controlPanelViewModelData, value);
}
}
// public ControlPanelViewModel ControlPanelViewModelData = ServiceLocator.Current.GetInstance<ControlPanelViewModel>();
private bool _CommunicationModuleConnected;
public bool CommunicationModuleConnected
@ -79,6 +116,29 @@ namespace Plane.FormationCreator.ViewModels
}
}
private bool _BoardcastPortOpened=false;
public bool BoardcastPortOpened
{
get { return _BoardcastPortOpened; }
set
{
Set(nameof(BoardcastPortOpened), ref _BoardcastPortOpened, value);
}
}
private string _SysStatusText="系统信息";
public string SysStatusText
{
get { return _SysStatusText; }
set
{
Set(nameof(SysStatusText), ref _SysStatusText, value);
}
}
private List<string> _MessageList = new List<string>();
public string Messages
@ -140,6 +200,75 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private string _Loginstate = "未登录";
public string Loginstate
{
get { return _copterManager.Loginstate ; }
set
{
Set(nameof(Loginstate), ref _Loginstate, value);
}
}
private ICommand _LoginCommand;
public ICommand LoginCommand
{
get
{
return _LoginCommand ?? (_LoginCommand = new RelayCommand(() =>
{
if (!_copterManager.Logined)
{
LoginView loginview = new LoginView();
loginview.ShowDialog();
}
else
{
if (_copterManager.Copters.Count() > 0)
{
if (Alert.Show("注销将导致飞机全部清除,您确定要继续吗?", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Warning)
== MessageBoxResult.Cancel)
return;
}
_copterListViewModel.ClearCoptersCommand.Execute(null);
_copterManager.NetLogout();
}
}));
}
}
private ICommand _ShowModifyTaskViewCommand;
public ICommand ShowModifyTaskViewCommand
{
get
{
return _ShowModifyTaskViewCommand ?? (_ShowModifyTaskViewCommand = new RelayCommand(() =>
{
AppEx.Current.ShowModifyTaskView = true;
}));
}
}
private ICommand _HideModifyTaskViewCommand;
public ICommand HideModifyTaskViewCommand
{
get
{
return _HideModifyTaskViewCommand ?? (_HideModifyTaskViewCommand = new RelayCommand(() =>
{
AppEx.Current.ShowModifyTaskView =false;
}));
}
}
private ICommand _ShowOrHideModifyTaskViewCommand;
public ICommand ShowOrHideModifyTaskViewCommand
@ -160,6 +289,72 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(MapMode), ref _MapMode, value); }
}
private bool _b2DMapMode = true;
public bool b2DMapMode
{
get { return _b2DMapMode; }
set { Set(nameof(b2DMapMode), ref _b2DMapMode, value); }
}
private string _LoginDisp = "登录";
public string LoginDisp
{
get { return _LoginDisp; }
set { Set(nameof(LoginDisp), ref _LoginDisp, value); }
}
private ICommand _Map2DCommand;
public ICommand Map2DCommand
{
get
{
return _Map2DCommand ?? (_Map2DCommand = new RelayCommand(() =>
{
MainWindow mainw = (MainWindow)App.Current.MainWindow;
mainw.map.Visibility = System.Windows.Visibility.Visible;
mainw.map3D.Visibility = System.Windows.Visibility.Collapsed;
MapMode = 0;
b2DMapMode = true;
_flightTaskManager.TaskRun_2D = b2DMapMode; //2D模式模拟显示
//强制刷新飞机位置
_copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
private ICommand _Map3DCommand;
public ICommand Map3DCommand
{
get
{
return _Map3DCommand ?? (_Map3DCommand = new RelayCommand(() =>
{
MainWindow mainw = (MainWindow)App.Current.MainWindow;
mainw.map.Visibility = System.Windows.Visibility.Collapsed;
mainw.map3D.Visibility = System.Windows.Visibility.Visible;
MapMode = 1;
b2DMapMode = false;
_flightTaskManager.TaskRun_2D = b2DMapMode; //3D模式模拟显示
mainw.map3D.ResetCamera();
}));
}
}
private ICommand _ChangeMapModeCommand;
public ICommand ChangeMapModeCommand
{
@ -167,10 +362,29 @@ namespace Plane.FormationCreator.ViewModels
{
return _ChangeMapModeCommand ?? (_ChangeMapModeCommand = new RelayCommand(() =>
{
MainWindow mainw =(MainWindow) App.Current.MainWindow;
if (MapMode == 0)
{
mainw.map.Visibility = System.Windows.Visibility.Collapsed;
mainw.map3D.Visibility = System.Windows.Visibility.Visible;
MapMode = 1;
b2DMapMode = false;
_flightTaskManager.TaskRun_2D = b2DMapMode; //3D模式模拟显示
}
else
{
mainw.map.Visibility = System.Windows.Visibility.Visible;
mainw.map3D.Visibility = System.Windows.Visibility.Collapsed;
MapMode = 0;
b2DMapMode = true;
_flightTaskManager.TaskRun_2D = b2DMapMode; //2D模式模拟显示
}
//强制刷新飞机位置
_copterManager.Copters.ForEach(copter => copter.RefreashLoc());
}));
}
}
@ -183,6 +397,22 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(OnlyImpotWaypointS), ref _OnlyImpotWaypointS, value); }
}
//导入飞机的位置
private bool _isimpCopterLoc =true;
public bool isimpCopterLoc
{
get { return _isimpCopterLoc; }
set { Set(nameof(isimpCopterLoc), ref _isimpCopterLoc, value); }
}
//导出飞机和航点等
private ICommand _ExportTasksCommand;
public ICommand ExportTasksCommand
{
@ -195,7 +425,7 @@ namespace Plane.FormationCreator.ViewModels
Alert.Show("作为参照的原点未设置,无法导出相对位置!", "提示");
return;
}
bool isToMeter = false;
var dialog = new SaveFileDialog
{
DefaultExt = "fcgm",
@ -205,11 +435,16 @@ namespace Plane.FormationCreator.ViewModels
{
IEnumerable<object> taskObject;
string extension = Path.GetExtension(dialog.FileName);
if (extension == ".fcgm")
isToMeter = (extension == ".fcgm");
if (isToMeter)
taskObject = _flightTaskManager.ExportTasksToMeter();
else
taskObject = _flightTaskManager.ExportTasks();
string exportedText;
if (OnlyImpotWaypointS)
@ -219,11 +454,15 @@ namespace Plane.FormationCreator.ViewModels
else
{
var groupObject = _groupManager.ExportGroups();
var locateObject = ExportLocate();
var locateObject = ExportLocate(isToMeter);
object obj = new
{
ID="flycube.com",
ver = "2.0",
coptercount = _copterManager.Copters.Count,
taskcount = _flightTaskManager.Tasks.Count,
groups = groupObject,
locate = locateObject,
tasks = taskObject
@ -240,21 +479,41 @@ namespace Plane.FormationCreator.ViewModels
}
}
private List<object> ExportLocate()
private List<object> ExportLocate(bool isToMeter)
{
List<object> locateList = new List<object>();
foreach (var copter in _copterManager.Copters)
{
double[] locate = new double[3];
locate[0] = copter.Latitude - _flightTaskManager.OriginLat;
locate[1] = copter.Longitude - _flightTaskManager.OriginLng;
if (isToMeter)
{
double x = GeographyUtils.CalcDistance(_flightTaskManager.OriginLat, _flightTaskManager.OriginLng, 0,
_flightTaskManager.OriginLat, copter.Longitude, 0);
if (copter.Longitude < _flightTaskManager.OriginLng) x = -x;
double y = GeographyUtils.CalcDistance(_flightTaskManager.OriginLat, _flightTaskManager.OriginLng, 0,
copter.Latitude, _flightTaskManager.OriginLng, 0);
if (copter.Latitude < _flightTaskManager.OriginLat) y = -y;
locate[0] = x;
locate[1] = y;
}
else
{
//为了和老版本兼容
locate[1] = copter.Longitude - _flightTaskManager.OriginLng;
locate[0] = copter.Latitude - _flightTaskManager.OriginLat;
}
locate[2] = copter.GroundAlt;
locateList.Add(locate);
}
return locateList;
}
private int _txtStarindex = 0;
public int txtStarindex
{
@ -269,6 +528,7 @@ namespace Plane.FormationCreator.ViewModels
set { Set(nameof(txtendindex), ref _txtendindex, value); }
}
//导入航点
private ICommand _ImportTasksCommand;
public ICommand ImportTasksCommand
{
@ -290,7 +550,8 @@ namespace Plane.FormationCreator.ViewModels
{
string extension = Path.GetExtension(dialog.FileName);
bool isMeter = extension == ".fcgm";
int _startindex = txtStarindex;
int _endindex = txtendindex;
@ -300,10 +561,31 @@ namespace Plane.FormationCreator.ViewModels
dynamic taskinfo = null;
if (importInfo is Newtonsoft.Json.Linq.JObject)
{
int ? filecoptercount = importInfo.coptercount;
string ver = importInfo.ver;
string ID = importInfo.ID;
if ((ID!=null)&&(ID!="flycube.com"))
{
Alert.Show($"文件格式不正确", "提示");
return;
}
if ((filecoptercount != null)&&(filecoptercount != _copterManager.Copters.Count ))
{
Alert.Show($"导入的飞机数量不符!导入飞机{filecoptercount},实际飞机{ _copterManager.Copters.Count}", "提示");
return;
}
taskinfo = importInfo.tasks;
if (importInfo.locate != null)
{
ImportCoptersLocate(importInfo.locate);
//老版本无论是fcgm还是fcg格式这个地方都存的经纬差新版fcgm才用米为单位保存
if ((ver != null) && (ver == "2.0"))
ImportCoptersLocate(importInfo.locate, isMeter);
else
ImportCoptersLocate(importInfo.locate, false);
}
if (importInfo.groups != null)
{
@ -317,9 +599,22 @@ namespace Plane.FormationCreator.ViewModels
//int task Newtonsoft.Json.Linq.JArray
string extension = Path.GetExtension(dialog.FileName);
bool isMeter = extension == ".fcgm";
if (taskinfo.Count == 0)
{
Alert.Show($"导入的文件没有飞行任务!", "提示");
return;
}
if ((taskinfo[0].singleCopterInfos.Count != _copterManager.Copters.Count))
{
Alert.Show($"导入的飞机数量不符!导入飞机{taskinfo[0].singleCopterInfos.Count},实际飞机{ _copterManager.Copters.Count}", "提示");
return;
}
if ((txtStarindex == 0) && (txtendindex == 0))
{
@ -337,6 +632,7 @@ namespace Plane.FormationCreator.ViewModels
}
// Alert.Show("导入完成!", "提示");
}));
}
}
@ -410,16 +706,54 @@ namespace Plane.FormationCreator.ViewModels
}));
}
}
private void ImportCoptersLocate(dynamic coptersLocate)
private void ImportCoptersLocate(dynamic coptersLocate,bool isMeter)
{
//if (Newtonsoft.Json.Linq.JArray)
try
{
int index = 0;
bool loadxyLocate = isimpCopterLoc;
foreach (var locate in coptersLocate)
{
_copterManager.Copters[index].GroundAlt = Convert.ToSingle(locate[2]);
//虚拟飞机将读入保存时的位置
if (loadxyLocate&&(_copterManager.Copters[index] is FakeCopter))
{
var fc = _copterManager.Copters[index] as FakeCopter;
if (isMeter)
{
Tuple<double, double> observationLatLng = null;
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat,
_flightTaskManager.OriginLng,
90,
Convert.ToSingle(locate[0]));
double TargetLng = observationLatLng.Item2;
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat,
_flightTaskManager.OriginLng,
0,
Convert.ToSingle(locate[1]));
double TargetLat = observationLatLng.Item1;
fc.SetProperties(
latitude: TargetLat,
longitude: TargetLng
);
}else
{
double TargetLng = _flightTaskManager.OriginLng + Convert.ToSingle(locate[1]);
double TargetLat = _flightTaskManager.OriginLat + Convert.ToSingle(locate[0]);
fc.SetProperties(
latitude:TargetLat,
longitude: TargetLng
);
}
}
index++;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Practices.ServiceLocation;
using Plane.CommunicationManagement;
using Plane.FormationCreator.Formation;
using Plane.Windows.Messages;
using System;
@ -8,6 +10,7 @@ using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
namespace Plane.FormationCreator.ViewModels
@ -17,9 +20,41 @@ namespace Plane.FormationCreator.ViewModels
private RtcmManager _rtcmManager;
public RtcmManager RtcmManager { get { return _rtcmManager; } }
//方式
public ObservableCollection<string> serialPorts { get; } = new ObservableCollection<string>();
private CommModuleManager _commModuleManager = CommModuleManager.Instance;
public string BoardPortsStatus
{
get
{
return _commModuleManager.BoardPortStatusStr;
}
}
private ControlPanelViewModel ControlPanelVM = ServiceLocator.Current.GetInstance<ControlPanelViewModel>();
public void SetRTKStatestr()
{
string rtksstr = "";
// ResendToCom
if (_rtcmManager.Rtcmthreadrun)
{
rtksstr = "RTK发送中 ";
if (_rtcmManager.SmallRtcmData)
rtksstr += ",低带宽模式 ";
if (_rtcmManager.ResendToCom && _commModuleManager.Recomisopen)
rtksstr += ",双通道模式 ";
rtksstr += "...";
}
else
rtksstr = "RTK未发送";
ControlPanelVM.RTKState = rtksstr;
}
private string _serialPortsSelectdValue;
public string SerialPortsSelectdValue
{
@ -29,15 +64,57 @@ namespace Plane.FormationCreator.ViewModels
}
private bool _smalldatamk;
public bool SmalldataMK
{
get { return _smalldatamk; }
set
{
Set(nameof(SmalldataMK), ref _smalldatamk, value);
_rtcmManager.SmallRtcmData= value;
}
}
private bool _resendtocommk=true;
public bool ResendToComMK
{
get { return _resendtocommk; }
set
{
if (value)
{
//发送
if (_commModuleManager.last_reserialport == "")
{
Alert.Show($"先在设置里打开广播端口", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}else
if (!_commModuleManager.Recomisopen)
{
Alert.Show($"广播端口未打开,无法发送", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
Set(nameof(ResendToComMK), ref _resendtocommk, value);
_rtcmManager.ResendToCom = value;
}
}
public RtcmInfoViewModel(RtcmManager rtcmManager)
{
_rtcmManager = rtcmManager;
serialPorts.Add("魔方基站");
serialPorts.Add("千寻");
string[] commports = _rtcmManager.GetPortNames();
foreach (var item in commports)
{
serialPorts.Add(item);
}
serialPorts.Add("千寻");
SerialPortsSelectdValue = serialPorts[0];
}
@ -47,12 +124,13 @@ namespace Plane.FormationCreator.ViewModels
{
string lastSelectValue = SerialPortsSelectdValue;
serialPorts.Clear();
serialPorts.Add("魔方基站");
serialPorts.Add("千寻");
string[] commports = _rtcmManager.GetPortNames();
foreach (var item in commports)
{
serialPorts.Add(item);
}
serialPorts.Add("千寻");
if (serialPorts.Contains(lastSelectValue))
SerialPortsSelectdValue = lastSelectValue;
}
@ -64,10 +142,13 @@ namespace Plane.FormationCreator.ViewModels
{
return _ConnectRtcmCommand ?? (_ConnectRtcmCommand = new RelayCommand(async() =>
{
//是否转发到特定端口
string resendserial = "";
_rtcmManager.ResendToCom = ResendToComMK;
if (!_rtcmManager.Rtcmthreadrun)
await _rtcmManager.Open(SerialPortsSelectdValue);
else
await _rtcmManager.Close();
await _rtcmManager.Close(SerialPortsSelectdValue);
}));
}
}

View File

@ -42,8 +42,9 @@ namespace Plane.FormationCreator.ViewModels
{
get
{
return _ClearTasksCommand ?? (_ClearTasksCommand = new RelayCommand(() =>
return _ClearTasksCommand ?? (_ClearTasksCommand = new RelayCommand(async () =>
{
await _flightTaskManager.ResetTasks();
_flightTaskManager.ClearTasks();
}));
}
@ -65,6 +66,54 @@ namespace Plane.FormationCreator.ViewModels
}
}
private ICommand _renametaskCommand;
public ICommand renametaskCommand
{
get
{
return _renametaskCommand ?? (_renametaskCommand = new RelayCommand( () =>
{
FlightTask task = _flightTaskManager.SelectedTask;
if ((task==null) ||(task.TaskType != FlightTaskType.FlyTo)) return;
string newName = task.TaskCnName;
if (PlaneMessageBox.OnShow("请输入新的名称", "重命名", ref newName))
{
task.TaskCnName = newName;
}
}));
}
}
private ICommand _DelTaskCommand;
public ICommand DelTaskCommand
{
get
{
return _DelTaskCommand ?? (_DelTaskCommand = new RelayCommand(() =>
{
// _flightTaskManager
// FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
_flightTaskManager.DelSelectedTask();
}));
}
}
private ICommand _SetOriginCommand;
public ICommand SetOriginCommand
{

View File

@ -24,7 +24,7 @@ namespace Plane.FormationCreator.ViewModels
{
private FlightTaskManager _flightTaskManager;
private CopterManager _copterManager;
private View3DManager _view3DManager = ServiceLocator.Current.GetInstance<View3DManager>();
public View3DViewModel(FlightTaskManager flightTaskManager, CopterManager copterManager)
@ -51,6 +51,16 @@ namespace Plane.FormationCreator.ViewModels
case nameof(FlightTaskManager.SelectedTaskIndex):
SelectTask();
break;
case nameof(FlightTaskManager.RightSelectedTaskIndex): // 单击右键触发清除航点
int taskIndexTmp = Math.Abs(_flightTaskManager.RightSelectedTaskIndex);
if (_flightTaskManager.Tasks[taskIndexTmp].IsRightSelected)
{
if (waypointGroup == null) waypointGroup = new Model3DGroup();
waypointGroup.Children.Clear();
}
else SelectTask();
break;
default:
break;
}
@ -83,6 +93,7 @@ namespace Plane.FormationCreator.ViewModels
planeModel3Ds.Clear();
planeGroup.Children.Clear();
observationLatLng = null;
SelectTask();
}
private void Copter_LocationChanged(object sender, EventArgs e)
@ -99,64 +110,88 @@ namespace Plane.FormationCreator.ViewModels
}
private Dictionary<ICopter, GeometryModel3D> planeModel3Ds = new Dictionary<ICopter, GeometryModel3D>();
Tuple<double, double> observationLatLng = null;
private Tuple<double, double> observationLatLng = null;
private void AddOrMove3DCopter(ICopter copter)
//得到观测位置
//observationLatLng 观察点坐标,第一列的中间再往前2个中间距离)
//观测点的位置放到最后排飞机的中间位置
private void getobservationpos()
{
//var copternum1 = _copterManager.Copters.FirstOrDefault();
if (_flightTaskManager.OriginLat == 0 || _flightTaskManager.OriginLng == 0)
return;
observationLatLng = new Tuple<double, double>(_flightTaskManager.ObserverLat, _flightTaskManager.ObserverLng);
/*
//第一列到中间的距离
float midColDistance = (_flightTaskManager.ColumnCount - 1) * _flightTaskManager.ColumnDistance / 2;
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat,
_flightTaskManager.OriginLng,
_flightTaskManager.Orientation + 90,
midColDistance);
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
observationLatLng.Item1,
observationLatLng.Item2,
_flightTaskManager.Orientation + 180,
midColDistance * 4);
*/
}
private void AddOrMove3DCopter(ICopter copter)
{
if (_flightTaskManager.TaskRun_2D) return; //不在3D模式运行直接退出
//var copternum1 = _copterManager.Copters.FirstOrDefault();
if (_flightTaskManager.OriginLat == 0 || _flightTaskManager.OriginLng == 0)
return;
//得到观测位置
if (observationLatLng == null)
{
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat,
_flightTaskManager.OriginLng,
_flightTaskManager.Orientation + 90,
midColDistance);
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
observationLatLng.Item1,
observationLatLng.Item2,
_flightTaskManager.Orientation + 180,
midColDistance * 2);
getobservationpos();
}
//没有这架飞机就加入
if (!planeModel3Ds.ContainsKey(copter))
{
//观测点的位置放到最后排飞机的中间位置
var meshBuilderwaypoint = new MeshBuilder(false, false);
//meshBuilderwaypoint.AddTriangle(new Point3D(-0.1, -0.1, 0), new Point3D(0.1, -0.1, 0), new Point3D(0, 0.2, 0));
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.2);
//飞机点的大小形状
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.3* _copterManager.scale3d);
var meshwaypoint = meshBuilderwaypoint.ToMesh(true);
//离观测点距离y
double y = GeographyUtils.CalcDistance(0, observationLatLng.Item1, 0, 0, copter.Latitude, 0) / 2;
if (observationLatLng.Item1 > copter.Latitude) y = -y;
//离观测点距离x
double x = GeographyUtils.CalcDistance(observationLatLng.Item2, 0, 0, copter.Longitude, 0, 0) / 2;
if (observationLatLng.Item2 > copter.Longitude) x = -x;
//离观测点距离z
double z = copter.Altitude + 0.1;
x *= _copterManager.scale3d;
y *= _copterManager.scale3d;
z *= _copterManager.scale3d;
Color color ;
if (copter.LEDColor != null && copter.LEDColor != "")
color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
else
color = (Color)ColorConverter.ConvertFromString("#" + CopterManager.CopterDefaultColor);
var model3D = new GeometryModel3D
{
Geometry = meshwaypoint,
Transform = new TranslateTransform3D(x, y, copter.Altitude + 0.1),
Material = MaterialHelper.CreateMaterial(Color.FromRgb(238, 210, 238)),
BackMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(238, 210, 238))
Transform = new TranslateTransform3D(x, y, z),
Material = new DiffuseMaterial(new SolidColorBrush(color)),
//Material = MaterialHelper.CreateMaterial(color),
// BackMaterial = MaterialHelper.CreateMaterial(color)
};
planeModel3Ds.Add(copter, model3D);
planeGroup.Children.Add(model3D);
}
//有飞机在视图里就移动位置
else
{
//计算和观测点的相对位置
double y = GeographyUtils.CalcDistance(0, observationLatLng.Item1, 0, 0, copter.Latitude, 0) / 2;
if (observationLatLng.Item1 > copter.Latitude) y = -y;
@ -167,51 +202,69 @@ namespace Plane.FormationCreator.ViewModels
x = Math.Round(x, 2);//按照四舍五入的国际标准
y = Math.Round(y, 2);
double z = Math.Round(copter.Altitude / 2, 2);
x *= _copterManager.scale3d;
y *= _copterManager.scale3d;
z *= _copterManager.scale3d;
//移动飞机到新位置
GeometryModel3D panle3D = planeModel3Ds[copter];
if (x != panle3D.Transform.Value.OffsetX || y != panle3D.Transform.Value.OffsetY || z != panle3D.Transform.Value.OffsetZ)
{
panle3D.Transform = new TranslateTransform3D(x, y, z);
var trans = panle3D.Transform as TranslateTransform3D;
trans.OffsetX = x;
trans.OffsetY = y;
trans.OffsetZ = z;
}
//设置灯光
Color color;
if (copter.LEDColor != null && copter.LEDColor != "")
{
Color color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
color = (Color)ColorConverter.ConvertFromString("#" + copter.LEDColor);
panle3D.Material = MaterialHelper.CreateMaterial(color);
panle3D.BackMaterial = MaterialHelper.CreateMaterial(color);
// panle3D.BackMaterial = MaterialHelper.CreateMaterial(color);
}
/*
// Color color;
if (copter.LEDShowColor != null)
{
Color currcolor = System.Windows.Media.Color.FromArgb(
copter.LEDShowColor.A, copter.LEDShowColor.R, copter.LEDShowColor.G, copter.LEDShowColor.B);
{
((panle3D.Material as DiffuseMaterial).Brush as SolidColorBrush).Color = currcolor;
}
}
*/
}
//Message.Show("添加3D飞机" + copter.Name);
}
private void SelectTask()
{
{
if (waypointGroup == null) waypointGroup = new Model3DGroup();
waypointGroup.Children.Clear();
if (_flightTaskManager.SelectedTaskIndex > 0)
{
//观测点的位置放到最后排飞机的中间位置
Tuple<double, double> observationLatLng;
//列的中间位置
float midDistance = (_flightTaskManager.ColumnCount - 1) * _flightTaskManager.ColumnDistance / 2;
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat, _flightTaskManager.OriginLng, _flightTaskManager.Orientation + 90, midDistance);
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
observationLatLng.Item1, observationLatLng.Item2, _flightTaskManager.Orientation + 180, midDistance * 2);
//得到观测位置
if (observationLatLng == null)
{
getobservationpos();
}
//modelGroup.Children.Clear();
var meshBuilderwaypoint = new MeshBuilder(false, false);
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.2);
//航点的大小形状
meshBuilderwaypoint.AddSphere(new Point3D(0, 0, 0), 0.2* _copterManager.scale3d);
var meshwaypoint = meshBuilderwaypoint.ToMesh(true);
var greenMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(0,255,0));
var greenMaterial = MaterialHelper.CreateMaterial(Color.FromRgb(50,50,255));
foreach (FlightTaskSingleCopterInfo info in _flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].SingleCopterInfos)
{
@ -221,12 +274,16 @@ namespace Plane.FormationCreator.ViewModels
double x = GeographyUtils.CalcDistance(observationLatLng.Item2, 0, 0, info.TargetLng, 0, 0)/2;
if (observationLatLng.Item2 > info.TargetLng) x = -x;
double z = info.TargetAlt / 2;
x *= _copterManager.scale3d;
y *= _copterManager.scale3d;
z *= _copterManager.scale3d;
waypointGroup.Children.Add(new GeometryModel3D
{
Geometry = meshwaypoint,
Transform = new TranslateTransform3D(x, y, info.TargetAlt/2),
Transform = new TranslateTransform3D(x, y, z),
Material = greenMaterial,
BackMaterial = greenMaterial
});

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}"/>
</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

@ -0,0 +1,77 @@
<Window x:Class="Plane.FormationCreator.Views.ChangePasswordView"
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:ignore="http://www.galasoft.ch/ignore"
xmlns:Helper="clr-namespace:Plane.Util"
mc:Ignorable="d ignore" Height="316.504" Width="490.433" Title="更改登录密码" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Content="账号:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Right" />
<TextBox
Margin="10"
Width="120" VerticalContentAlignment="Center"
Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left"
Grid.Row="0" Grid.Column="1"/>
<Label Content="原密码:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" />
<PasswordBox
x:Name="passwordBox"
Margin="10"
Width="120"
HorizontalAlignment="Left" VerticalContentAlignment="Center" Grid.Row="1" Grid.Column="1"
PasswordChar="*"
MaxLength="20"
Helper:PasswordBoxHelper.Attach="True"
Helper:PasswordBoxHelper.Password="{Binding Path=OldPassword ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="新密码:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right" />
<PasswordBox
x:Name="newpasswordBox"
Margin="10"
Width="120"
HorizontalAlignment="Left" VerticalContentAlignment="Center" Grid.Row="2" Grid.Column="1"
PasswordChar="*"
MaxLength="20"
Helper:PasswordBoxHelper.Attach="True"
Helper:PasswordBoxHelper.Password="{Binding Path=NewPassword ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="再次输入新密码:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right" />
<PasswordBox
x:Name="newpasswordBox1"
Margin="10"
Width="120"
HorizontalAlignment="Left" VerticalContentAlignment="Center" Grid.Row="3" Grid.Column="1"
PasswordChar="*"
MaxLength="20"
Helper:PasswordBoxHelper.Attach="True"
Helper:PasswordBoxHelper.Password="{Binding Path=NewPassword1 ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="取消" Grid.Row="4" Grid.Column="0" Margin="10,5,10,5" Height="40" Width="80" IsCancel="True"
Command="{Binding ExitCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" />
<Button Content="更改" Grid.Row="4" Grid.Column="1" Margin="50,5,10,5" Height="40" Width="80" IsDefault="True"
Command="{Binding ChangePasswordCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" />
</Grid>
</Window>

View File

@ -0,0 +1,24 @@
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.ViewModels;
using System.Windows;
using System.Windows.Controls;
namespace Plane.FormationCreator.Views
{
/// <summary>
/// Description for ChangePasswordView.
/// </summary>
public partial class ChangePasswordView : Window
{
/// <summary>
/// Initializes a new instance of the ChangePasswordView class.
/// </summary>
public ChangePasswordView()
{
InitializeComponent();
ChangePasswordViewModel loginViewModel = ServiceLocator.Current.GetInstance<ChangePasswordViewModel>();
this.DataContext = loginViewModel;
}
}
}

View File

@ -0,0 +1,42 @@
<UserControl x:Class="Plane.FormationCreator.Views.ConfigVirtualIdView"
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"
mc:Ignorable="d"
BorderThickness="1"
Background="#FF2D2D2D" Width="340" Height="260" BorderBrush="#FF006595">
<Grid>
<StackPanel>
<StackPanel>
<TextBlock Margin="10,5" Text="手动编号"/>
<TextBlock Margin="10,5" Text="选中单架无人机输入虚拟ID后点击设置"/>
<StackPanel Margin="10,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBox Margin="0,5" Width="80" VerticalAlignment="Center"
Text="{Binding SingleVirtualId}"/>
<Button Margin="10,5" Width="100" Content = "设置编号" VerticalAlignment="Center"
Command="{Binding SetSingleVirtualIdCommand}"/>
</StackPanel>
</StackPanel>
<StackPanel>
<TextBlock Margin="10,5" Text="自动编号"/>
<StackPanel Margin="10,0" >
<TextBlock Margin="0,5" TextWrapping = "Wrap" Height="auto" Text="请按顺序选择2-3架飞机分别是1号机第一行任意飞机第一列任意飞机(如只有一行不用选),自动配置前必须:1.设置行间距和列间距2.把不在正确位置的飞机手动编号"/>
<Button Margin="0,0,0,0" Width="100" Content = "自动编号" VerticalAlignment="Center"
Command="{Binding AutoLocationNumsCommand}"/>
</StackPanel>
</StackPanel>
<StackPanel Margin="5" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Margin="5" Width="95" Content = "清除编号" Command="{Binding ClearVirtualIdCommand}"/>
<Button Margin="5" Width="95" Content = "保存编号" Command="{Binding SaveVirtualIdCommand}"/>
<Button Margin="5" Width="95" Content = "读入编号" Command="{Binding LoadVirtualIdCommand}"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,31 @@
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.ViewModels;
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.Navigation;
using System.Windows.Shapes;
namespace Plane.FormationCreator.Views
{
/// <summary>
/// ConfigVirtualIdView.xaml 的交互逻辑
/// </summary>
public partial class ConfigVirtualIdView : UserControl
{
public ConfigVirtualIdView()
{
InitializeComponent();
this.DataContext = ServiceLocator.Current.GetInstance<ConfigVirtualIdViewModel>();
}
}
}

View File

@ -7,157 +7,102 @@
xmlns:c="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:ec="clr-namespace:Plane.Windows.Controls;assembly=Plane.Windows"
mc:Ignorable="d"
Title="连接"
Width="432.175"
Height="300.371"
Title=""
Width="565.58"
Height="325.107"
WindowStartupLocation="CenterScreen"
FontFamily="Microsoft YaHei"
ResizeMode="NoResize">
ResizeMode="NoResize" >
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="Auto" Width="Auto" >
<Grid HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid.Resources>
<Style TargetType="Label"
BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="HorizontalAlignment"
Value="Right" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>
<Style TargetType="ComboBox"
BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="HorizontalAlignment"
Value="Left" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Width"
Value="150" />
</Style>
<Style TargetType="TextBox"
BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="HorizontalAlignment"
Value="Left" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Width"
Value="150" />
</Style>
<Style TargetType="PasswordBox"
BasedOn="{StaticResource {x:Type PasswordBox}}">
<Setter Property="HorizontalAlignment"
Value="Left" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="MinWidth"
Value="150" />
</Style>
<Style TargetType="Button"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="VerticalAlignment"
Value="Center" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="40" />
<RowDefinition Height="30" />
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="10" />
<ColumnDefinition />
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Target="{Binding ElementName=txtIPs}" Visibility="Collapsed"
Content="IP" />
<TextBox Name="txtIPs"
Grid.Column="2"
AcceptsReturn="True"
MinHeight="200"
ScrollViewer.VerticalScrollBarVisibility="Auto"
Visibility="Collapsed"
Text="{Binding IPs, UpdateSourceTrigger=PropertyChanged}" />
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Grid.Row="1"
Grid.ColumnSpan="3"
Name="panel1">
<ec:ProgressButton HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10"
Content="连接 _TCP"
IsDefault="True"
IsProcessing="{Binding IsProcessing}"
Command="{Binding Path=ConnectCommand}" />
<ec:ProgressButton HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10"
Content="连接 _UDP"
IsDefault="True"
IsProcessing="{Binding IsProcessing}"
Command="{Binding Path=ConnectCommand}"
CommandParameter="UDP"/>
<ec:ProgressButton HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10"
Content="连接串口"
IsProcessing="{Binding IsProcessing}"
Command="{Binding Path=ConnectCommand}"
CommandParameter="SerialPort" />
<!--<ec:ProgressButton Name="btnConnectUdp"
Grid.Row="1"
Grid.ColumnSpan="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10"
Content="连接 _UDP"
IsDefault="True"
IsProcessing="{Binding IsProcessing}"
Command="{Binding Path=ConnectCommand}"
CommandParameter="UDP" />-->
<Button Content="关闭TCP" Margin="5" Command="{Binding CloseCommand}"/>
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Grid.Row="2"
Grid.ColumnSpan="3"
Name="panel2">
<Button Content="通信模块状态" Margin="5" Command="{Binding Path=StateInquireCommand}"/>
<Button Content="设置总数" Margin="5" Command="{Binding Path=SendCommand}" />
<Button Content="切换写航点" Margin="5" Command="{Binding Path=ChangeWriteMissionCommand}" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Grid.Row="3"
Grid.ColumnSpan="3">
<TextBox Margin="2,5,5,5" Width="30" Text="{Binding CopterNum}"></TextBox>
<Button Content=" 对频 " Margin="5,5,0,5" Command="{Binding Path=WriteIdCommand}" />
<Button Content="闪灯" Margin="5" Command="{Binding CommDataAsync}"/>
<Button Content="拉烟" Margin="5" Command="{Binding TestFireCommandAsync}"/>
<TextBox Width="80" Text="{Binding CopterColor}"/>
HorizontalAlignment="Left"
Grid.Row="0" >
<TextBlock Margin="5" VerticalAlignment="Center" Text="ID:" />
<TextBox Width="30" VerticalContentAlignment="Center" Text="{Binding CopterNum}" Margin="5,5,5,5" />
<TextBlock Margin="5" VerticalAlignment="Center" Text="参数:" />
<TextBox Width="56" VerticalContentAlignment="Center" Text="{Binding CopterColor}" Margin="5,5,5,5"/>
<Button Content="对频" Width="67" Margin="5,5,5,5" Command="{Binding Path=WriteIdCommand}" ToolTip="ID框输入新编号" />
<Button Content="闪灯 " Width="67" Margin="5,5,5,5" Command="{Binding CommDataAsync}" ToolTip="参数为十六进制颜色"/>
<Button Content="拉烟" Width="67" Margin="5,5,5,5" Command="{Binding TestFireCommandAsync}" ToolTip="参数为通道号1-4"/>
<Button Content="抛物" Width="67" Margin="5,5,5,5" Command="{Binding TestPWMCommandAsync}" ToolTip="接入舵机控制"/>
<Button Content="功率" Width="67" Margin="5,5,5,5" Command="{Binding SetModulePowerCommand}" ToolTip="设置模块回传功率"/>
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
Grid.Row="4"
Grid.ColumnSpan="3"
Name="panel3">
<Button Content="空中升级" Margin="5" Command="{Binding UpdateAllCopterCommand}"></Button>
<Button Content="搜索飞机" Margin="5" Command="{Binding QueryAllCopterCommand}"/>
HorizontalAlignment="Left"
Grid.Row="1"
Name="panel4" >
<Button Content="立体缩放" Width="90" Margin="5,5,5,5" Command="{Binding UpdateAllCopterCommand}"></Button>
<TextBlock Margin="5" VerticalAlignment="Center" Text="比例/模块号:" />
<TextBox Width="30" VerticalContentAlignment="Center" Text="{Binding scale3d}" Margin="5,5,5,5" />
<Button Content="更改密码" Width="90" Margin="5,5,5,5" Command="{Binding ChangepasswordCommand}"></Button>
<Button Content="测试模块" Width="90" Margin="5,5,5,5" Command="{Binding TestModuleCommand}" ToolTip="测试地面站通讯模块1-8"></Button>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Grid.Row="2" Name="panel7" >
<Button Content="{Binding btnBoardPortStr}" Width="115" Margin="5,5,5,5" Command="{Binding Openboardport}"/>
<ComboBox Width="90" Height="25" Foreground="White" SelectedIndex="0"
ItemsSource="{Binding serialRePorts, Mode=OneWay}"
SelectedValue="{Binding SerialPortResend}"
DropDownOpened="ComboBox_DropDownOpened"/>
<TextBlock Margin="10,5,5,5" VerticalAlignment="Center" Text="{Binding BoardPortStatusStr}" />
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
Grid.Row="3"
Name="panel2" >
<TextBlock Margin="5" VerticalAlignment="Center" Text="总数:" />
<TextBox Width="45" VerticalContentAlignment="Center" Text="{Binding CopterSum}" Margin="5,5,5,5" />
<Button Content="设置总数" Width="90" Margin="5,5,5,5" Command="{Binding Path=SendCommand}" />
<Button Content="切换写航点" Width="90" Margin="5,5,5,5" Command="{Binding Path=ChangeWriteMissionCommand}" />
<Button Content="通信状态" Width="90" Margin="5,5,5,5" Command="{Binding StateInquireCommand}"/>
</StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
Grid.Row="4"
Name="panel3" >
<Button Content="空中升级" Width="90" Margin="5,5,5,5" Command="{Binding UpdateAllCopterCommand}"></Button>
<Button Content="搜索飞机" Width="90" Margin="5,5,5,5" Command="{Binding QueryAllCopterCommand}"/>
</StackPanel>
<Image Margin="0,0,0,0" x:Name="image1" Grid.RowSpan="2" Grid.Row="5" Source="/Resources/Logo_small.png" HorizontalAlignment="Left" />
<TextBlock Margin="5" Grid.Row="6" x:Name="about_ver" HorizontalAlignment="Right" VerticalAlignment="Bottom" Text="版本V2.0.1213" />
<TextBlock Margin="5" Grid.Row="7" HorizontalAlignment="Right" x:Name="about_buildtm" VerticalAlignment="Bottom" Text="编译日期2020.12.12" />
</Grid>
</c:MetroWindow>

View File

@ -16,6 +16,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Plane.FormationCreator.Util;
using System.Reflection;
namespace Plane.FormationCreator.Views
{
@ -41,12 +42,24 @@ namespace Plane.FormationCreator.Views
if (!VersionControl.IsFullVersion)
{
panel1.Visibility = Visibility.Collapsed;
//panel1.Visibility = Visibility.Collapsed;
panel2.Visibility = Visibility.Collapsed;
panel3.Visibility = Visibility.Collapsed;
}
CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
var version = Assembly.GetExecutingAssembly().GetName().Version;
about_ver.Text = "版本:" + version.ToString() + "(飞控兼容:" + _copterManager.FC_VER_STRING + ")";
about_buildtm .Text= "编译时间:" + System.IO.File.GetLastWriteTime(this.GetType().Assembly.Location).ToString();
//txtIPs.Focus();
}
ConnectViewModel _ConnectViewModel = ServiceLocator.Current.GetInstance<ConnectViewModel>();
private void ComboBox_DropDownOpened(object sender, EventArgs e)
{
_ConnectViewModel.RefreshPorts();
txtIPs.Focus();
}
}
}

View File

@ -1,191 +1,235 @@
<UserControl x:Class="Plane.FormationCreator.Views.ControlPanelView"
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:fc="clr-namespace:Plane.FormationCreator"
xmlns:ec="clr-namespace:Plane.Copters;assembly=PlaneGcsSdk_Private_NET46"
xmlns:vm="clr-namespace:Plane.FormationCreator.ViewModels"
xmlns:m="clr-namespace:Plane.FormationCreator.Formation"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Button"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin"
Value="0,0,3,5" />
</Style>
</StackPanel.Resources>
<!--<TextBlock Text="连接" />
<WrapPanel>
<Button Content="连接"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Command="{Binding DisconnectCommand}" />
</WrapPanel>-->
<TextBlock Text="飞行控制"
Margin="5,0,0,8"/>
<WrapPanel>
<Button Content="解锁"
Command="{Binding UnlockCommand}" />
<Button Content="起飞" Visibility="Collapsed"
Command="{Binding TakeOffCommand}" />
<Button Content="起飞"
Command="{Binding GuidAsyncCommand}" />
<Button Content="悬停"
Command="{Binding HoverCommand}" />
<Button Content="手动"
Command="{Binding FloatCommand}" />
<Button Content="参数"
Command="{Binding ParamModify}" />
<Button Content="参数文件" Visibility="Collapsed"
Command="{Binding LoadParamfile}" />
<Button Content="版本"
Command="{Binding GetVersionsCommand}" />
<Button Content="校准"
Command="{Binding CalibrationSingleCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="返航"
Command="{Binding ReturnToLaunchCommand}" />
<Button Content="降落"
Command="{Binding LandCommand}" />
<Button Content="上锁"
Command="{Binding LockCommand}" />
<Button Content="跳过" Visibility="Collapsed"
Command="{Binding FlagCommand}" />
<Button Content="闪灯"
Command="{Binding LEDFlickerCommand}" />
<Button Content="测试" Visibility="Collapsed"
Command="{Binding TestCommand}" />
<Button Content="开灯"
Command="{Binding LEDOnOffCommand}"
CommandParameter="0"/>
<Button Content="关灯"
Command="{Binding LEDOnOffCommand}"
CommandParameter="1"/>
<Button Content="电机"
Command="{Binding MotorTestCommand}" />
<TextBox Width="50"
Visibility="Collapsed"
Text="{Binding AltP, UpdateSourceTrigger=PropertyChanged}" />
</WrapPanel>
<WrapPanel>
<Button Content="选写航点"
Command="{Binding WriteMissionSingleCommand}" />
<Button Content="定位统计"
Command="{Binding ReportGPSTypeCommand}"/>
<Button Content="统计模块"
Command="{Binding DetectionCommModuleVersion}" />
<Button Content="正式参数"
Command="{Binding TurnOffTestLightsCommand}"
/>
<TextBlock Margin="5,0,3,0" Text="起飞高度" VerticalAlignment="Center"></TextBlock>
<TextBox Width="30" Height="26" Text="{Binding TaskOffAlt}"
/>
<Label Visibility="Collapsed">Lat</Label>
<TextBox Visibility="Collapsed" Text="{Binding LatOffset}" Width="50"/>
<Label Visibility="Collapsed">Lng</Label>
<TextBox Visibility="Collapsed" Text="{Binding LngOffset}" Width="50"/>
<Button Visibility="Collapsed" Content="设置返航点"
Command="{Binding RLTOffsetCommand}" />
</WrapPanel>
<Separator/>
<WrapPanel>
<Button Content="全部降落"
Command="{Binding AllLandCommand}" />
<Button Content="全部加锁"
Command="{Binding LockAllCommand}" />
<Button Content="检测电压"
Command="{Binding DetectionVoltage}" />
<Button Content="统计返回"
Command="{Binding DetectionReturnData}" />
<Button Content="统计航点"
Command="{Binding DetectionMissionData}" />
</WrapPanel>
<WrapPanel>
<Button Content="写入航点"
Command="{Binding WriteMissionCommand}" />
<Button Content="全部解锁"
Command="{Binding UnlockAllCommand}"
IsEnabled="{Binding AllowMissionStart, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="开始任务"
Command="{Binding MissionStartCommand}"
IsEnabled="{Binding AllowMissionStart, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="暂停任务"
Command="{Binding MissionPauseCommand}" />
<Button Content="继续任务"
Command="{Binding MissionResumeCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="航点续写"
Command="{Binding WriteMissionFailedCommand}" />
<TextBox
Grid.Column="1"
Width="55"
Margin="5, 5, 5, 5"
HorizontalContentAlignment="Right"
Text="{Binding RTKcomvalue, UpdateSourceTrigger=PropertyChanged}"
/>
<Button Content="{Binding Path=RTKbtntxt}"
Command="{Binding SendRTKCommand}" />
<Button Content="{Binding Path=NTRIPbtntxt}"
Command="{Binding SendRTCMCommand}"/>
<Button Content="RTK" Command="{Binding OpenRtcmManageCommand}" />
<TextBlock
Margin="5,5,5,5"
Text="{Binding Path=RTKState}"
/>
</WrapPanel>
<!--// 林俊清, 20150920, 目前不再使用 FormationController删除相关按钮。
<StackPanel Visibility="{Binding Source={x:Static fc:AppEx.Current}, Path=AppMode, Converter={StaticResource AppModeToVisibilityConverter}, ConverterParameter=ControlPanelView_Formation}">
<TextBlock Text="任务" />
<WrapPanel>
<Button Content="飞到50米高"
Command="{Binding FlyToAltitudeCommand}"
CommandParameter="50" />
<Button Content="飞到15米高"
Command="{Binding FlyToAltitudeCommand}"
CommandParameter="15" />
<Button Content="Test"
Command="{Binding TestCommand}" />
</WrapPanel>
-->
<!--<WrapPanel>
<Button Content="画圈"
Command="{Binding FlyInCircleCommand}" />
<Button Content="绕队列中心画圈"
Command="{Binding FlyAroundCenterOfCoptersCommand}" />
<Button Content="Test"
Command="{Binding TestCommand}" />
<Button Content="画矩形"
Command="{Binding FlyInRectangleCommand}"
Visibility="Collapsed" />
</WrapPanel>
<WrapPanel>
<Button Content="飞到一条竖线画圈"
Command="{Binding FlyToVerticalLineAndMakeCircleCommand}" />
</WrapPanel>-->
<!--
<WrapPanel>
<Button Content="停止"
Command="{Binding StopTaskCommand}" />
</WrapPanel>
</StackPanel>-->
</StackPanel>
</UserControl>
<UserControl x:Class="Plane.FormationCreator.Views.ControlPanelView"
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:fc="clr-namespace:Plane.FormationCreator"
xmlns:ec="clr-namespace:Plane.Copters;assembly=PlaneGcsSdk_Private_NET46"
xmlns:vm="clr-namespace:Plane.FormationCreator.ViewModels"
xmlns:m="clr-namespace:Plane.FormationCreator.Formation"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<StackPanel Margin="0,0,-8,0">
<StackPanel.Resources>
<Style TargetType="Button"
BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin"
Value="0,0,3,5" />
</Style>
</StackPanel.Resources>
<!--<TextBlock Text="连接" />
<WrapPanel>
<Button Content="连接"
Command="{Binding ConnectCommand}" />
<Button Content="断开"
Command="{Binding DisconnectCommand}" />
</WrapPanel>-->
<TabControl Margin="0,0,13,0">
<TabItem Header="飞行前准备">
<StackPanel Orientation="Vertical" Margin="0,5,0,0">
<WrapPanel>
<Button Content="电压检测"
Command="{Binding DetectionVoltage}" />
<Button Content="版本检测"
Command="{Binding GetVersionsCommand}" />
<Button Content="通讯版本" Command="{Binding DetectionCommModuleVersion}" />
<Button Content="统计返回"
Command="{Binding DetectionReturnData}" />
<Button Content="通讯统计"
Command="{Binding GetCommsumCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="参数设置"
Command="{Binding ParamModify}" />
<Button Content="读入参数"
Command="{Binding LoadParamfile}" />
<Button Content="状态统计" Command="{Binding ReportGPSTypeCommand}"/>
<Button Content="飞机校准"
Command="{Binding CalibrationSingleCommand}" />
<Button Content="正式参数" Command="{Binding TurnOffTestLightsCommand}" Visibility="Collapsed" />
<Button Content="电机" Visibility="Collapsed"
Command="{Binding MotorTestCommand}" />
<Button Content="删除飞机"
Command="{Binding DelCommand}" />
<Label Visibility="Collapsed" Content="Lat"/>
<TextBox Visibility="Collapsed" Text="{Binding LatOffset}" Width="50"/>
<Label Visibility="Collapsed" Content="Lng"/>
<TextBox Visibility="Collapsed" Text="{Binding LngOffset}" Width="50"/>
<Button Visibility="Collapsed" Content="设置返航点" Command="{Binding RLTOffsetCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="写入航点"
Command="{Binding WriteMissionCommand}" />
<Button Content="航点续写"
Command="{Binding WriteMissionFailedCommand}" />
<Button Content="选写航点" Command="{Binding WriteMissionSingleCommand}" />
<Button Content="统计航点"
Command="{Binding DetectionMissionData}" />
<TextBox
Grid.Column="1"
Width="55"
Margin="5, 5, 5, 5"
HorizontalContentAlignment="Right"
Text="{Binding RTKcomvalue, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed"
/>
<Button Content="{Binding RTKbtntxt}"
Command="{Binding SendRTKCommand}" Visibility="Collapsed" />
<Button Content="{Binding NTRIPbtntxt}"
Command="{Binding SendRTCMCommand}" Visibility="Collapsed"/>
<Button Content="RTK 控制" Command="{Binding OpenRtcmManageCommand}" />
</WrapPanel>
</StackPanel>
</TabItem>
<TabItem Header="飞行控制">
<StackPanel Orientation="Vertical" Margin="0,5,0,0">
<WrapPanel >
<Button Content="解锁"
Command="{Binding UnlockCommand}" />
<Button Content="加锁"
Command="{Binding LockCommand}" />
<Button Content="单独任务"
Command="{Binding TakeOffCommand}" />
<Button Content="抛物"
Command="{Binding ThrowoutCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="起飞"
Command="{Binding GuidAsyncCommand}" />
<Button Content="悬停"
Command="{Binding HoverCommand}" />
<Button Content="手动"
Command="{Binding FloatCommand}" />
<Button Content="返航"
Command="{Binding ReturnToLaunchCommand}" />
<Button Content="降落"
Command="{Binding LandCommand}" />
<Button Content="跳过" Visibility="Collapsed"
Command="{Binding FlagCommand}" />
<TextBox Width="50"
Visibility="Collapsed"
Text="{Binding AltP, UpdateSourceTrigger=PropertyChanged}" />
</WrapPanel>
<WrapPanel>
<Button Content="闪灯"
Command="{Binding LEDFlickerCommand}" />
<Button Content="测试" Visibility="Collapsed"
Command="{Binding TestCommand}" />
<Button Content="开灯"
Command="{Binding LEDOnOffCommand}"
CommandParameter="0"/>
<Button Content="关灯"
Command="{Binding LEDOnOffCommand}"
CommandParameter="1"/>
<TextBlock Margin="8,-3,5,0" Text="起飞高度" VerticalAlignment="Center"/>
<TextBox VerticalContentAlignment="Center" Margin="0,0,0,5" Width="30" Height="25" Text="{Binding TaskOffAlt}" />
<TextBlock Margin="5,-3,5,0" Text="米" VerticalAlignment="Center"/>
</WrapPanel>
</StackPanel>
</TabItem>
<TabItem Header="任务控制">
<StackPanel Orientation="Vertical" Margin="0,5,0,0">
<WrapPanel>
<Button Content="全部解锁"
Command="{Binding UnlockAllCommand}"
IsEnabled="{Binding AllowMissionStart, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="全部加锁"
Command="{Binding LockAllCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="开始任务"
Command="{Binding MissionStartCommand}"
IsEnabled="{Binding AllowMissionStart, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="暂停任务"
Command="{Binding MissionPauseCommand}" />
<Button Content="继续任务"
Command="{Binding MissionResumeCommand}" />
</WrapPanel>
<WrapPanel>
<Button Content="全部降落"
Command="{Binding AllLandCommand}" />
<Button Content="紧急返航"
Command="{Binding EmergencyRetCommand}" />
<Button Content="重设任务"
Command="{Binding ResetRealMissionCommand}" />
</WrapPanel>
</StackPanel>
</TabItem>
<TabItem Header="飞行报告" Visibility="Collapsed">
<StackPanel Orientation="Vertical" Margin="0,5,0,0">
<WrapPanel>
<Button Content="添加报告"
Command="{Binding UnlockAllCommand}"
IsEnabled="{Binding AllowMissionStart, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="查看报告"
Command="{Binding LockAllCommand}" />
</WrapPanel>
</StackPanel>
</TabItem>
</TabControl>
</StackPanel>
</UserControl>

View File

@ -7,7 +7,7 @@
mc:Ignorable="d"
d:DesignHeight="300"
BorderThickness="1"
Background="#FF2D2D2D" Width="464">
Background="#FF2D2D2D" Width="340">
<UserControl.BorderBrush>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}"/>
</UserControl.BorderBrush>
@ -17,7 +17,7 @@
<Label Margin="5,0,0,0" Content="属性设置" VerticalAlignment="Center"/>
<Separator></Separator>
<StackPanel Margin="5,0,0,5" Orientation="Horizontal" HorizontalAlignment="Left">
<Label Margin="0" Content="摆放高度" ></Label>
<Label Margin="0" Content="摆放高度(米)" ></Label>
<TextBox
Margin="30,0"
Width="80"

View File

@ -6,7 +6,7 @@
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
mc:Ignorable="d"
BorderThickness="1"
Background="#FF2D2D2D" Width="464" Height="300">
Background="#FF2D2D2D" Width="340" Height="300">
<UserControl.BorderBrush>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.ActiveBorderColorKey}}"/>
</UserControl.BorderBrush>
@ -14,14 +14,14 @@
<StackPanel Orientation="Vertical">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="70"/>
<ColumnDefinition />
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<Label Margin="5,0" Content="分组设置" HorizontalAlignment="Left" />
<Label Margin="15,0" Grid.Column="1" Content="最后选中:" HorizontalAlignment="Left"/>
<Label Grid.Column="1" Content="{Binding GroupManager.LastSelectedGroup}" HorizontalAlignment="Right"/>
<Button Margin="5,0" Grid.Column="2" Content="添加分组" HorizontalAlignment="Right"
<Label Margin="0,0" Grid.Column="1" Content="最后选中:" HorizontalAlignment="Left"/>
<Label Margin="0,0" Grid.Column="1" Content="{Binding GroupManager.LastSelectedGroup}" HorizontalAlignment="Right"/>
<Button Margin="0,0" Grid.Column="2" Content="添加" HorizontalAlignment="Right"
Command="{Binding Path=GroupManager.AddGroupsCommand}"/>
</Grid>
<Separator></Separator>
@ -48,9 +48,9 @@
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Width="95" Text="{Binding groupName,UpdateSourceTrigger=PropertyChanged}"/>
<Button Margin="20,0,0,0" Width="90" Content="删除" Command="{Binding RemoveGroupCommand}"/>
<Button Margin="20,0,0,0" Width="90" Content="设置" Command="{Binding SetGroupCoptersCommand}"/>
<Button Margin="20,0,0,0" Width="90" Content="选中" Command="{Binding SelectCoptersCommand}"/>
<Button Margin="5,0,0,0" Width="65" Content="删除" Command="{Binding RemoveGroupCommand}"/>
<Button Margin="5,0,0,0" Width="65" Content="设置" Command="{Binding SetGroupCoptersCommand}"/>
<Button Margin="5,0,0,0" Width="65" Content="选中" Command="{Binding SelectCoptersCommand}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>

View File

@ -1,187 +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}">
<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 Text="{Binding Path=Id}" />
</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>
<Slider x:Name="sldChannel3"
Width="100"
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>

View File

@ -38,10 +38,10 @@ namespace Plane.FormationCreator.Views
var copter = sldChannel3.DataContext as ICopter;
var selectedCopter = _copterManager.SelectedCopters.FirstOrDefault();
if (copter == null || copter != selectedCopter) return; // copter != selectedCopter 说明正在切换 copter。
var newCh3 = (ushort)e.NewValue;
if (Math.Abs(copter.Channel3 - newCh3) > 5)
var vol = (ushort)e.NewValue;
if (vol<15)
{
await copter.SetChannelsAsync(ch3: newCh3);
// sldChannel3.co
}
}
catch { }

View File

@ -10,21 +10,30 @@
d:DesignHeight="600"
d:DesignWidth="300">
<UserControl.Resources>
<ContextMenu x:Key="CoptersMenu" >
<MenuItem Header="只显示当前选中"
<MenuItem Header="显示当前选中"
Foreground="White"
Command="{Binding OnlyShowSelectedCoptersCommand}"/>
<MenuItem Header="显示所有飞机"
Foreground="White"
Command="{Binding ShowAllCoptersCommand}"/>
<MenuItem Header="显示自动编号"
<MenuItem Header="所有编号(虚拟排序)"
Foreground="White"
Command="{Binding SwitchIdVirtualIdCommand}"/>
Command="{Binding ShowAllIDCommand}"/>
<MenuItem Header="虚拟编号(虚拟排序)"
Foreground="White"
Command="{Binding SortbyVIdCommand}"/>
<MenuItem Header="真实编号(真实排序)"
Foreground="White"
Command="{Binding SortbyIdCommand}"/>
</ContextMenu>
</UserControl.Resources>
<Grid>
<Grid Width="550">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="540"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
@ -60,24 +69,31 @@
</MultiBinding>
</Rectangle.Fill>
</Rectangle>
<TextBlock MaxWidth="100"
<TextBlock MaxWidth="50" Visibility="{Binding DisplayID, Converter={StaticResource BooleanToVisibilityConverter}}"
Text="{Binding Name}" />
<TextBlock MaxWidth="100"
Margin="2,0,0,0"
Foreground="Red"
<TextBlock Margin="2,0,0,0" MaxWidth="5" Visibility="{Binding DisplayVirtualId, Converter={StaticResource BooleanToVisibilityConverter}}"
Text="[" />
<TextBlock MaxWidth="50" Visibility="{Binding DisplayVirtualId, Converter={StaticResource BooleanToVisibilityConverter}}"
Margin="0,0,0,0"
Foreground="Yellow"
Text="{Binding VirtualId}" />
<TextBlock Margin="0,0,0,0" MaxWidth="5" Visibility="{Binding DisplayVirtualId, Converter={StaticResource BooleanToVisibilityConverter}}"
Text="]" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Margin="0,0,0,5"
<StackPanel Grid.Row="1" Margin="0,5,0,5"
Orientation="Horizontal">
<Button Content="间隔选" Command="{Binding IntervalSelectCoptersCommand}"/>
<Button Content="间隔选" Command="{Binding IntervalSelectCoptersCommand}"/>
<TextBlock Text="连选数量" Margin="5,5,0,0"/>
<TextBox Width="30" Margin="5,0,0,0" Text="{Binding ContinuousNum}"/>
<TextBox Width="30" Margin="5,0" VerticalContentAlignment="Center" Text="{Binding ContinuousNum}"/>
<TextBlock Text="间隔数量" Margin="5,5,0,0"/>
<TextBox Width="30" Margin="5,0,0,0" Text="{Binding IntervalNum}"/>
<TextBox Width="30" Margin="5,0" VerticalContentAlignment="Center" Text="{Binding IntervalNum}"/>
<TextBlock Text="间隔排数" Margin="5,5,0,0"/>
<TextBox Width="30" Margin="5,0" VerticalContentAlignment="Center" Text="{Binding RowNum}"/>
<TextBlock Text="选中个数" Margin="5,5,0,0"/>
<TextBlock Width="30" Margin="5,5,0,0" Text="{Binding CopterManager.SeletedCopterCount, UpdateSourceTrigger=PropertyChanged}"/>
@ -104,7 +120,7 @@
Margin="5,0,0,0"
Command="{Binding ShowLackCopterNumsCommand}"/>
<Button Content="自动编号"
Margin="5,0,0,0"
Margin="5,0,0,0" Visibility="Collapsed"
Command="{Binding AutoLocationNumsCommand}"/>
<Button Content="设置"
Margin="5,0,5,0"

View File

@ -16,6 +16,8 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;
namespace Plane.FormationCreator.Views
{
@ -44,22 +46,47 @@ namespace Plane.FormationCreator.Views
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private void SelectitemMessage(ICopter copter)
{
if (copter == null)
////需要访问UI线程可能在其他线程里面
Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
if (dispatcher != null)
{
lvwDrones.SelectedItems.Clear();
}
else
{
if (!_copterManager.shiftkeydown)
if (copter == null)
{
lvwDrones.SelectedItems.Clear();
lvwDrones.SelectedItem = copter;
}
else
lvwDrones.SelectedItems.Add(copter);
}
{
if (!_copterManager.shiftkeydown)
{
lvwDrones.SelectedItems.Clear();
lvwDrones.SelectedItem = copter;
}
else
lvwDrones.SelectedItems.Add(copter);
}
}else
lvwDrones.Dispatcher.BeginInvoke(new Action(() =>
{
if (copter == null)
{
lvwDrones.SelectedItems.Clear();
}
else
{
if (!_copterManager.shiftkeydown)
{
lvwDrones.SelectedItems.Clear();
lvwDrones.SelectedItem = copter;
}
else
lvwDrones.SelectedItems.Add(copter);
}
}));
}
private void SelectitemClearMessage(ICopter copter)

View File

@ -0,0 +1,30 @@
<Window x:Class="Plane.FormationCreator.Views.InputDialog"
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:ignore="http://www.galasoft.ch/ignore"
Title="输入窗口" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered" ResizeMode="NoResize">
<Grid Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="/FGCS;component/Resources/logo_big.png" Width="40" Height="40" Grid.RowSpan="2" Margin="20,0" />
<Label Name="lblQuestion" Grid.Column="1">最低更换电压:</Label>
<TextBox Name="txtAnswer" Grid.Column="1" Grid.Row="1" MinWidth="250">15.6</TextBox>
<WrapPanel Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="0,15,0,0">
<Button IsDefault="True" Name="btnDialogOk" Click="btnDialogOk_Click" MinWidth="60" Margin="0,0,10,0">确定</Button>
<Button IsCancel="True" MinWidth="60">取消</Button>
</WrapPanel>
</Grid>
</Window>

View File

@ -0,0 +1,31 @@
using System;
using System.Windows;
namespace Plane.FormationCreator.Views
{
public partial class InputDialog : Window
{
public InputDialog(string question, string defaultAnswer = "")
{
InitializeComponent();
lblQuestion.Content = question;
txtAnswer.Text = defaultAnswer;
}
private void btnDialogOk_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void Window_ContentRendered(object sender, EventArgs e)
{
txtAnswer.SelectAll();
txtAnswer.Focus();
}
public string Answer
{
get { return txtAnswer.Text; }
}
}
}

View File

@ -0,0 +1,58 @@
<Window x:Class="Plane.FormationCreator.Views.LoginView"
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:ignore="http://www.galasoft.ch/ignore"
xmlns:Helper="clr-namespace:Plane.Util"
mc:Ignorable="d ignore" Height="253.421" Width="463.894" Title="飞行魔方地面控制中心" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Content="账号:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="0" Grid.Column="0" />
<TextBox
Margin="10"
Width="120" VerticalContentAlignment="Center"
Text="{Binding Username, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left"
Grid.Row="0" Grid.Column="1"/>
<Label Content="密码:" Margin="10" FontWeight="Bold" FontSize="14" Grid.Row="1" Grid.Column="0" />
<PasswordBox
x:Name="passwordBox"
Margin="10"
Width="120"
HorizontalAlignment="Left" VerticalContentAlignment="Center" Grid.Row="1" Grid.Column="1"
PasswordChar="*"
MaxLength="20"
Helper:PasswordBoxHelper.Attach="True"
Helper:PasswordBoxHelper.Password="{Binding Path=Password ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="取消" Grid.Row="2" Grid.Column="0" Margin="10,5,10,5" Height="40" Width="80" IsCancel="True"
Command="{Binding ExitCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" />
<Button Content="登录" Grid.Row="2" Grid.Column="1" Margin="50,5,10,5" Height="40" Width="80" IsDefault="True"
Command="{Binding LoginCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}" />
<CheckBox x:Name="checkBox" Content="保存密码" Grid.Column="1" HorizontalAlignment="Right" Margin="0,18.033,-85.353,12.168" Grid.Row="1" Width="75.353"
IsChecked="{Binding SavePassword}"/>
<Label x:Name="about_ver" Content="版本:" HorizontalContentAlignment="Right" Margin="0,10,-85,0" Grid.Row="3" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
</Grid>
</Window>

View File

@ -0,0 +1,30 @@
using Microsoft.Practices.ServiceLocation;
using Plane.FormationCreator.Formation;
using Plane.FormationCreator.ViewModels;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
namespace Plane.FormationCreator.Views
{
/// <summary>
/// Description for LoginView.
/// </summary>
public partial class LoginView : Window
{
/// <summary>
/// Initializes a new instance of the LoginView class.
/// </summary>
public LoginView()
{
InitializeComponent();
LoginViewModel loginViewModel = ServiceLocator.Current.GetInstance<LoginViewModel>();
this.DataContext = loginViewModel;
var version = Assembly.GetExecutingAssembly().GetName().Version;
CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
about_ver.Content = "版本:" + version.ToString() + "(飞控兼容:"+ _copterManager.FC_VER_STRING + ")";
}
}
}

View File

@ -41,16 +41,16 @@
>
<CheckBox Grid.Row="0" Content="所有航点" Margin="5,5,0,0"
Click="showallpoint_Checked"
Foreground="White" IsChecked="True"
Foreground="White" IsChecked="True" Visibility="Collapsed"
/>
<CheckBox Grid.Row="0" Content="计划航线" Margin="5,5,0,0"
<CheckBox Grid.Row="0" Content="飞行航线" Margin="5,5,0,0"
Click="showpanline_Checked"
Foreground="White"
Foreground="White" IsChecked="True"
/>
<CheckBox Grid.Row="0" Content="实时航线" Margin="5,5,0,0"
Foreground="White"
Click="showrealtimeline_Checked" />
Click="showrealtimeline_Checked" Visibility="Collapsed" />
<ComboBox x:Name="MapSelectionComboBox"
HorizontalAlignment="Right"

View File

@ -41,25 +41,33 @@ namespace Plane.FormationCreator.Views
/// </summary>
public partial class MapView : UserControl
{
public void initmap()
{
gmap.MinZoom = 2; //最小缩放
gmap.MaxZoom = 30; //最大缩放
gmap.Zoom = 19; //当前缩放
gmap.ShowCenter = true; //不显示中心十字点
gmap.DragButton = MouseButton.Middle; //中键拖拽地图
}
public MapView()
{
InitializeComponent();
this.DataContext = ServiceLocator.Current.GetInstance<MapViewModel>();
gmap.MapProvider = GMapProviders.BingHybridMap; //google china 地图
gmap.MinZoom = 2; //最小缩放
gmap.MaxZoom = 30; //最大缩放
gmap.Zoom = 19; //当前缩放
gmap.ShowCenter = false; //不显示中心十字点
gmap.DragButton = MouseButton.Middle; //左键拖拽地图
initmap();
gmap.Position = new LatLng(40.07734857737275, 116.34323845862502).ToGCJ02();
_mapManager.MapView = this;
_mapManager.SetCenterGetter(() => new LatLng { Lat = gmap.Position.ToWGS84().Lat, Lng = gmap.Position.ToWGS84().Lng });
_flightTaskManager.TaskAdded += FlightTaskManager_TaskAdded;
_flightTaskManager.TaskDeled += FlightTaskManager_TaskDeled;
_flightTaskManager.OnOriginalSet += FlightTaskManager_SetOriginal;
/*
Task.Factory.StartNew(async () =>
{
int delay = 500;
@ -73,7 +81,7 @@ namespace Plane.FormationCreator.Views
await Task.Delay(delay);
}
});
*/
_copterManager.SelectedCoptersChanged += (sender, e) =>
{
//if (AppEx.Instance.CurrentMode.IsForTasks())
@ -87,11 +95,18 @@ namespace Plane.FormationCreator.Views
{
switch (e.PropertyName)
{
//选中任务时触发
case nameof(FlightTaskManager.SelectedTaskIndex):
//_copterDrawings有多少架飞机航点
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
//设置选中的航点白边和下面任务块的白影
copterDrawing.ShowWaypoint(_flightTaskManager.SelectedTaskIndex);
copterDrawing.SetTaskEffect(_flightTaskManager.SelectedTaskIndex);
//画计划航线
copterDrawing.ResetRoute(_flightTaskManager.SelectedTaskIndex);
}
break;
@ -125,30 +140,7 @@ namespace Plane.FormationCreator.Views
gmap.MouseDoubleClick += async (sender, e) =>
{
e.Handled = true;
//// Test
//var pos = map.ViewportPointToLocation(e.GetPosition(map));
//AddOrMoveCopter(new FakeCopter(pos.Latitude, pos.Longitude));
// 林俊清, 20150930, AppMode 存在意义已不大;只有正在运行任务的时候才不允许指点。
//if (AppEx.Current.AppMode != AppMode.ControllingCopters) return;
if (_flightTaskManager.IsPaused == false) return;
var copters = _copterManager.AcceptingControlCopters;
if (!copters.Any()) return;
Point clickPoint = e.GetPosition(gmap);
var pos = gmap.FromLocalToLatLng((int)clickPoint.X, (int)clickPoint.Y);
var centerLat = copters.Average(c => c.Latitude);
var centerLng = copters.Average(c => c.Longitude);
var latDelta = pos.Lat - centerLat;
var lngDelta = pos.Lng - centerLng;
await Task.WhenAll(copters.Select(copter => copter.FlyToAsync(copter.Latitude + latDelta, copter.Longitude + lngDelta, copter.Altitude)));
};
};
var center = _appConfig.Center;
gmap.Position = new LatLng(center.Lat, center.Lng).ToGCJ02();
@ -170,6 +162,19 @@ namespace Plane.FormationCreator.Views
originalMarker.Position = gmap.FromLocalToLatLng((int)wpPos.X, (int)wpPos.Y);
//MapLayer.SetPosition(original, gmap.ViewportPointToLocation(wpPos));
}
if (observerMarker != null && gmap.Markers.Contains(observerMarker))
{
PointLatLng location = new LatLng(_flightTaskManager.ObserverLat, _flightTaskManager.ObserverLng).ToGCJ02();
GPoint wpPos = gmap.FromLatLngToLocal(location);
//Point wpPos = gmap.LocationToViewportPoint(location);
wpPos.X -= (long)ORIGIN_RADIUS;
wpPos.Y -= (long)ORIGIN_RADIUS;
observerMarker.Position = gmap.FromLocalToLatLng((int)wpPos.X, (int)wpPos.Y);
//MapLayer.SetPosition(original, gmap.ViewportPointToLocation(wpPos));
}
};
GMapMarker rectangleMarker = null;
@ -263,6 +268,9 @@ namespace Plane.FormationCreator.Views
gmap.MouseMove += new MouseEventHandler(OriginalMove);
gmap.MouseLeftButtonUp += new MouseButtonEventHandler(OriginalMouseUp);
gmap.MouseMove += new MouseEventHandler(observerMove);
gmap.MouseLeftButtonUp += new MouseButtonEventHandler(observerMouseUp);
}
private CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
@ -273,6 +281,7 @@ namespace Plane.FormationCreator.Views
const string COPTER_TAG = "Copter";
const string WAYPOINT_TAG = "Waypoint";
const string ORIGINALPOINT_TAG = "Originalpoint";
const string OBSERVER_TAG = "Observerpoint";
public void Refresh()
{
@ -322,6 +331,8 @@ namespace Plane.FormationCreator.Views
private void Copter_LocationChanged(object sender, EventArgs e)
{
if (!_flightTaskManager.TaskRun_2D) return; //不在3D模式运行直接退出
var copter = sender as ICopter;
if (App.Current.CheckAccess())
{
@ -352,6 +363,19 @@ namespace Plane.FormationCreator.Views
}
}
public void ShowAllWaypoint()
{
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.ShowAllWaypoint();
}
}
public void ClearCopters()
{
/*
@ -369,6 +393,11 @@ namespace Plane.FormationCreator.Views
*/
gmap.Markers.Clear();
//_copterManager.Copters.ForEach(copter => _copterDrawings[copter]=null );
_copterDrawings.Clear();
}
@ -390,14 +419,29 @@ namespace Plane.FormationCreator.Views
private void FlightTaskManager_TaskAdded(object sender, FlightTaskAddedEventArgs e)
{
//给每个任务在地图上添加航点
foreach (var info in e.AddedTask.SingleCopterInfos)
{
var drawingInfo = _copterDrawings[info.Copter];
//计算位置
var location = new Microsoft.Maps.MapControl.WPF.Location(info.TargetLat, info.TargetLng, info.TargetAlt);
drawingInfo.AddWaypoint(location, e.AddedTask.TaskType);
//添加航点
drawingInfo.AddWaypoint(location, e.AddedTask.TaskType,e.AddedTask);
}
}
private void FlightTaskManager_TaskDeled(object sender, FlightTaskDeledEventArgs e)
{
//清除每架飞机的这个任务的航点
// foreach (var info in e.DeledTask.SingleCopterInfos)
// {
// _copterDrawings[info.Copter].Waypoints.RemoveAt(e.TaskIndex);
// }
}
GMapMarker observerMarker = null;
Microsoft.Expression.Shapes.RegularPolygon observer = null;
GMapMarker originalMarker = null;
Microsoft.Expression.Shapes.RegularPolygon original = null;
const double ORIGIN_RADIUS = 12;
@ -436,8 +480,131 @@ namespace Plane.FormationCreator.Views
_flightTaskManager.OriginLng = location.Lng;
original.MouseLeftButtonDown += new MouseButtonEventHandler(OriginalMouseDown);
///加入或者改变观测点用于3D模拟
if (gmap.Markers.Contains(observerMarker))
gmap.Markers.Remove(observerMarker);
observer = new Microsoft.Expression.Shapes.RegularPolygon
{
Tag = OBSERVER_TAG,
Fill = new SolidColorBrush(Color.FromArgb(200, 3, 155, 3)),
Stroke = new SolidColorBrush(Color.FromArgb(200, 3, 80, 238)),
StrokeThickness = 1,
Width = ORIGIN_RADIUS *2,
Height = ORIGIN_RADIUS * 2,
InnerRadius = 1,
PointCount = 6,
};
if (_flightTaskManager.ObserverLat == 0)
{
Tuple<double, double> observationLatLng = null;
//第一列到中间的距离
float midColDistance = (_flightTaskManager.ColumnCount - 1) * _flightTaskManager.ColumnDistance / 2;
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
_flightTaskManager.OriginLat,
_flightTaskManager.OriginLng,
_flightTaskManager.Orientation + 90,
midColDistance);
observationLatLng = GeographyUtils.CalcLatLngSomeMetersAway2D(
observationLatLng.Item1,
observationLatLng.Item2,
_flightTaskManager.Orientation + 180,
midColDistance * 4);
_flightTaskManager.ObserverLat = observationLatLng.Item1;
_flightTaskManager.ObserverLng = observationLatLng.Item2;
}
//_flightTaskManager.ObserverLat = _flightTaskManager.OriginLat;
//_flightTaskManager.ObserverLng = _flightTaskManager.OriginLng;
PointLatLng Observerlocation = new LatLng(_flightTaskManager.ObserverLat, _flightTaskManager.ObserverLng).ToGCJ02();
GPoint opoint = gmap.FromLatLngToLocal(Observerlocation);
opoint.X -= (long)ORIGIN_RADIUS;
opoint.Y -= (long)ORIGIN_RADIUS;
mapLocation = gmap.FromLocalToLatLng((int)opoint.X, (int)opoint.Y);
observerMarker = new GMapMarker(mapLocation);
observerMarker.ZIndex = 200;
observerMarker.Shape = observer;
observerDrag = false;
observer.MouseLeftButtonDown += new MouseButtonEventHandler(observerMouseDown);
gmap.Markers.Add(observerMarker);
}
private bool observerDrag = false;
double observerX = 0;
double observerY = 0;
private void observerMouseDown(object sender, MouseButtonEventArgs e)
{
observerDrag = true;
gmap.CanDragMap = false;
var originPoint = e.GetPosition(gmap);
observerX = originPoint.X;
observerX = originPoint.Y;
var posInObject = e.GetPosition(observer);
wpOffsetX = posInObject.X;
wpOffsetY = posInObject.Y;
}
private void observerMove(object sender, MouseEventArgs e)
{
if (observerDrag)
{
Point eventPos = e.GetPosition(gmap);
var leftTopPos = new Point(eventPos.X - wpOffsetX, eventPos.Y - wpOffsetY);
observerMarker.Position = gmap.FromLocalToLatLng((int)leftTopPos.X, (int)leftTopPos.Y);
//MapLayer.SetPosition(original, map.ViewportPointToLocation(leftTopPos));
}
}
private void observerMouseUp(object sender, MouseButtonEventArgs e)
{
if (observerDrag)
{
Point eventPos = e.GetPosition(gmap);
var centrePos = new Point(eventPos.X - wpOffsetX + ORIGIN_RADIUS, eventPos.Y - wpOffsetY + ORIGIN_RADIUS);
PointLatLng location = gmap.FromLocalToLatLng((int)centrePos.X, (int)centrePos.Y);
_flightTaskManager.ObserverLat = location.Lat;
_flightTaskManager.ObserverLng = location.Lng;
// original.ToolTip = location.ToString();
//Clipboard.SetDataObject(string.Format("{0},{1}", location.Lat, location.Lng), true);
observerDrag = false;
gmap.CanDragMap = true;
}
}
private bool originaDrag = false;
double originX = 0;
double originY = 0;
@ -501,11 +668,7 @@ namespace Plane.FormationCreator.Views
break;
}
gmap.MinZoom = 2; //最小缩放
gmap.MaxZoom = 30; //最大缩放
gmap.Zoom = 19; //当前缩放
gmap.ShowCenter = false; //不显示中心十字点
gmap.DragButton = MouseButton.Left; //左键拖拽地图
initmap();
/*
switch ((e.AddedItems[0] as FrameworkElement).Tag.ToString())
@ -559,7 +722,8 @@ namespace Plane.FormationCreator.Views
foreach (var item in _copterDrawings)
{
var copterDrawing = item.Value;
copterDrawing.SetShowroute(chk.IsChecked);
_flightTaskManager.showroute = chk.IsChecked??false;
copterDrawing.UpdateShowroute();
}
}
@ -573,9 +737,6 @@ namespace Plane.FormationCreator.Views
}
}
private void RemoveTileLayers()
{
/*
@ -617,9 +778,7 @@ namespace Plane.FormationCreator.Views
grid_bg.Background = ib;
gmap.Opacity = 0.5;
}
}
}
}
static class LocationExtensions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,20 +17,48 @@ using System.Windows.Navigation;
using System.Windows.Shapes;
using Plane.Geography;
using Plane.FormationCreator.Util;
using System.Drawing;
namespace Plane.FormationCreator.Views
{
/// <summary>
/// Interaction logic for ModifyTaskView.xaml
/// </summary>
public partial class ModifyTaskView : UserControl
{
private int[] defcolor= { 255, 65280, 16711680, 65535 , 16711935, 16776960,0 };
ModifyTaskViewModel _modifyTaskViewModel = ServiceLocator.Current.GetInstance<ModifyTaskViewModel>();
CopterManager _copterManager = ServiceLocator.Current.GetInstance<CopterManager>();
private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
{
return (childItem)child;
}
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
public ModifyTaskView()
{
InitializeComponent();
this.DataContext = _modifyTaskViewModel;
if (!VersionControl.IsFullVersion)
{
//lightDesign.Visibility = Visibility.Collapsed;
@ -39,28 +67,113 @@ namespace Plane.FormationCreator.Views
private void Button_Click(object sender, RoutedEventArgs e)
{
// distanceCopters.Text;
/*
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
int firstIndex = int.Parse( firstCopter.Text );
int secondIndex = int.Parse( secondCopter.Text );
if (_flightTaskManager.SelectedTask != null)
{
var firstCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos[firstIndex-1];
var secondCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos[secondIndex-1];
double distance = GeographyUtils.CalcDistance(firstCopterInfo.TargetLat, firstCopterInfo.TargetLng, firstCopterInfo.TargetAlt,
secondCopterInfo.TargetLat, secondCopterInfo.TargetLng, secondCopterInfo.TargetAlt);
distanceCopters.Text = ((double)Math.Round(distance*100)/100).ToString();
}
/*
DependencyObject myListItem = LEDItems.ItemContainerGenerator.ContainerFromItem(LEDItems.Items.CurrentItem);
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListItem);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
ComboBox ledcomb = (ComboBox)myDataTemplate.FindName("cmbTemplateLEDMode", myContentPresenter);
// ledcomb.SelectedIndex = 2;
*/
// distanceCopters.Text;
/*
FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
int firstIndex = int.Parse( firstCopter.Text );
int secondIndex = int.Parse( secondCopter.Text );
if (_flightTaskManager.SelectedTask != null)
{
var firstCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos[firstIndex-1];
var secondCopterInfo = _flightTaskManager.SelectedTask.SingleCopterInfos[secondIndex-1];
double distance = GeographyUtils.CalcDistance(firstCopterInfo.TargetLat, firstCopterInfo.TargetLng, firstCopterInfo.TargetAlt,
secondCopterInfo.TargetLat, secondCopterInfo.TargetLng, secondCopterInfo.TargetAlt);
distanceCopters.Text = ((double)Math.Round(distance*100)/100).ToString();
}
*/
}
void OnCBLoaded(object sender, EventArgs e)
{
}
private void TextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
System.Windows.Forms.ColorDialog colorDialog = new System.Windows.Forms.ColorDialog();
colorDialog.CustomColors = defcolor;
try
{
colorDialog.Color = ColorTranslator.FromHtml("#" + (sender as TextBox).Text);
}
catch (Exception)
{
colorDialog.Color = System.Drawing.Color.White;
}
if (colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
defcolor = colorDialog.CustomColors;
(sender as TextBox).Text = String.Format("{0:X2}", colorDialog.Color.R) +
String.Format("{0:X2}", colorDialog.Color.G) +
String.Format("{0:X2}", colorDialog.Color.B);
}
}
private void cmbTemplateLEDMode_Initialized(object sender, EventArgs e)
{
int selind = 0;
ComboBox cb = (ComboBox)sender;
selind = cb.SelectedIndex;
cb.Items.Clear();
if (_copterManager.FC_VER_NO == 1)
{
cb.Items.Add("常亮"); //0
cb.Items.Add("同步闪烁(单色)"); //1
cb.Items.Add("异步闪烁(随机)"); //2
cb.Items.Add("渐亮"); //3
cb.Items.Add("渐暗"); //4
cb.Items.Add("呼吸灯(单色)"); //5
cb.Items.Add("同步闪烁(随机)"); //6
cb.Items.Add("异步闪烁(单色)"); //7
cb.Items.Add("拉烟"); //8
}
else
{
cb.Items.Add("常亮"); //0
cb.Items.Add("同步闪烁(单色)"); //1
cb.Items.Add("异步闪烁(随机)"); //2
cb.Items.Add("同步闪烁(随机)"); //3
cb.Items.Add("异步闪烁(单色)"); //4
cb.Items.Add("渐亮"); //5
cb.Items.Add("渐暗"); //6
cb.Items.Add("同步呼吸灯(单色)"); //7
cb.Items.Add("同步呼吸灯(随机色)"); //8
cb.Items.Add("异步呼吸(单色)"); //9
cb.Items.Add("异步呼吸(随机色)"); //10
cb.Items.Add("变色(单色)"); //11
cb.Items.Add("变色(随机)"); //12
cb.Items.Add("异步变色(单色)"); //13
cb.Items.Add("异步变色(随机)"); //14
cb.Items.Add("拉烟"); //15
cb.Items.Add("抛物"); //16
}
cb.SelectedIndex = selind;
}
}
}

View File

@ -5,78 +5,114 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
xmlns:c="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="800"
Height="350" Width="1500" WindowStartupLocation="CenterScreen" Background="#FF2D2D2D" BorderBrush="#FF039AF0">
mc:Ignorable="d" d:DesignWidth="800"
Height="426" Width="1500" WindowStartupLocation="CenterScreen" Background="#FF2D2D2D" BorderBrush="#FF039AF0" Title="RTK控制" ResizeMode="NoResize">
<Grid Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Margin="5" Orientation="Horizontal" VerticalAlignment="Center">
<ComboBox Width="120" Height="25" Foreground="White" SelectedIndex="0"
ItemsSource="{Binding serialPorts, Mode=OneWay}"
<Border Margin="10,5" BorderBrush="#FFB9B8B8" BorderThickness="1">
<StackPanel Margin="0" Orientation="Vertical">
<StackPanel Margin="0" Orientation="Horizontal">
<ComboBox Width="120" Height="25" Foreground="White" SelectedIndex="0"
Margin="10" ItemsSource="{Binding serialPorts, Mode=OneWay}"
SelectedValue="{Binding SerialPortsSelectdValue}"
DropDownOpened="ComboBox_DropDownOpened"/>
<Button Margin="6" Width="80" Height="28"
<Button Margin="6" Width="90" Height="28"
Content="{Binding RtcmManager.Rtcmthreadrun,Converter={StaticResource SendConverter}}"
Command="{Binding ConnectRtcmCommand}"/>
<Label Margin="6,6,0,6" Height="28" Content="总数:"/>
<Label Margin="0,6,6,6" Height="28" Content="{Binding RtcmManager.rtcmInfoList.Count,UpdateSourceTrigger=PropertyChanged}"></Label>
<Label Margin="6,6,0,6" Height="28" Content="卫星数:"/>
<Label Margin="0,6,6,6" Height="28" Content="{Binding RtcmManager.rtcmInfoList.Count,UpdateSourceTrigger=PropertyChanged}"></Label>
</StackPanel>
<StackPanel Margin="6,0,0,2" Orientation="Horizontal">
<CheckBox x:Name="checkBox" Content="双通道模式 (同时发到广播端口)"
Margin="4,5,5,0" Width="190"
IsChecked="{Binding ResendToComMK}"/>
<CheckBox x:Name="cBsmalldata" Content="低带宽模式"
Margin="20,5,5,0" Width="95"
IsChecked="{Binding SmalldataMK}"/>
</StackPanel>
<StackPanel Margin="6,0,0,2" Orientation="Horizontal">
<TextBlock Margin="23,1,0,0" Text="{Binding BoardPortsStatus}"/>
</StackPanel>
</StackPanel>
</Border>
<Border Margin="10,5" BorderBrush="#FFB9B8B8" BorderThickness="1">
<StackPanel Margin="5" Orientation="Vertical">
<StackPanel Margin="5" Orientation="Horizontal">
<TextBlock Text="Input data rate "/>
<TextBlock Text="接收速率: "/>
<TextBlock TextAlignment="Right" Width="30"
Text="{Binding RtcmManager.Bps}"/>
<TextBlock Text=" bps: put data rate "/>
<TextBlock Text=" 字节/秒;发送速率:"/>
<TextBlock TextAlignment="Right" Width="30"
Text="{Binding RtcmManager.Bpsusefull}"/>
<TextBlock Text=" bps sent"/>
<TextBlock Text=" 字节/秒"/>
</StackPanel>
<StackPanel Margin="5" Orientation="Horizontal">
<TextBlock Text="Messages seen "/>
<TextBlock Text="{Binding RtcmManager.Messages_seen}"
/>
<TextBlock Text="消息: "/>
<TextBlock Text="{Binding RtcmManager.Messages_seen}"/>
</StackPanel>
<StackPanel Margin="0" Orientation="Horizontal">
<TextBlock Margin="5" Text="L1信号强度"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20" Fill="#3EBE55"/>
<TextBlock Margin="5" Text="L2信号强度"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20" Fill="#ACACEC"/>
<TextBlock Margin="5" Text="L1/L2重合"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20" Fill="#04845C"/>
</StackPanel>
</StackPanel>
</Border>
<Border Margin="10,5" BorderBrush="#FFB9B8B8" BorderThickness="1">
<StackPanel Margin="5" Width="488">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="Base"/>
<TextBlock Margin="5" Text="基站位置"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20"
Fill="{Binding RtcmManager.BaseState,Converter={StaticResource ColorConverter}}"/>
<TextBlock Margin="5" Text="Gps"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20"
Fill="{Binding RtcmManager.GlonassState,Converter={StaticResource ColorConverter}}"/>
Fill="{Binding RtcmManager.GpsState ,Converter={StaticResource ColorConverter}}"/>
<TextBlock Margin="5" Text="Glonass"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20"
Fill="{Binding RtcmManager.GpsState,Converter={StaticResource ColorConverter}}"/>
<TextBlock Margin="5" Text="Beidou"/>
Fill="{Binding RtcmManager.GlonassState,Converter={StaticResource ColorConverter}}"/>
<TextBlock Margin="5" Text="北斗"/>
<Rectangle Margin="0,0,15,0" Width="20" Height="20"
Fill="{Binding RtcmManager.BeidouState,Converter={StaticResource ColorConverter}}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" >
<TextBlock Margin="5" Text="RTCM Base"/>
<TextBlock Margin="5" Text="RTCM 位置"/>
<TextBlock Margin="2,5" Text="{Binding RtcmManager.StationLat}"/>
<TextBlock Margin="2,5" Text="{Binding RtcmManager.StationLng}"/>
<TextBlock Margin="2,5" Text="{Binding RtcmManager.StationAlt}"/>
<TextBlock Margin="2,5" Text="-"/>
<TextBlock Margin="2,5" Text="{Binding RtcmManager.StationTime}"/>
</StackPanel>
</StackPanel>
</Border>
</StackPanel>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding Path = RtcmManager.rtcmInfoList}"
ItemsSource="{Binding Path = RtcmManager.rtcmInfoList}" Margin="0,0.333,-0.333,-80" Height="303" VerticalAlignment="Top"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
@ -95,19 +131,34 @@
Minimum="25"
Maximum="55"
Grid.RowSpan="2"
Value="{Binding Snr, UpdateSourceTrigger=PropertyChanged}"/>
<StackPanel Orientation ="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
Value="{Binding Snr, UpdateSourceTrigger=PropertyChanged}"
/>
<ProgressBar x:Name="BarSnr2"
Margin="0.5"
Orientation="Vertical"
Minimum="25"
Maximum="55"
Grid.RowSpan="2"
Foreground="Blue"
Value="{Binding Snr2, UpdateSourceTrigger=PropertyChanged}"
Opacity="0.25"
/>
<StackPanel Orientation ="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center">
<StackPanel Orientation ="Horizontal">
<TextBlock Text="{Binding Sys,UpdateSourceTrigger=PropertyChanged}" Foreground="Black"></TextBlock>
<TextBlock Text="{Binding Prn,UpdateSourceTrigger=PropertyChanged}" Foreground="Black"></TextBlock>
</StackPanel>
<TextBlock Margin="0,20,0,0" Text="{Binding Snr,UpdateSourceTrigger=PropertyChanged}" Foreground="Black"></TextBlock>
<TextBlock Margin="0,5,0,0" Text="{Binding Snr,UpdateSourceTrigger=PropertyChanged}" Foreground="Black"></TextBlock>
<TextBlock Margin="0,5,0,0" Text="{Binding Snr2,UpdateSourceTrigger=PropertyChanged}" Foreground="Blue" ></TextBlock>
</StackPanel>
<StackPanel Grid.Row="1" Orientation ="Vertical" HorizontalAlignment="Center">
<Line Stroke="Red" X2="1000" StrokeThickness="3" />
<TextBlock Text="40" Foreground="Black"/>
</StackPanel>
</Grid>

View File

@ -5,20 +5,20 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Plane.FormationCreator.Views"
mc:Ignorable="d"
Title="设置摆放" Height="301.595" Width="364.628" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="NoResize">
<Grid Margin="90,45">
Title="设置摆放" Height="290.592" Width="364.628" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="NoResize">
<Grid Margin="90,35,90,20">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="28"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="每数量" Margin="5,2"></Label>
<Label Content="每数量" Margin="5,2"></Label>
<TextBox Name="textboxColNum" Grid.Column="1" Margin="5" Width="80" ></TextBox>
<Label Content="列间距" Margin="5,2" Grid.Row="1"></Label>

View File

@ -1,209 +1,234 @@
<UserControl 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:m="clr-namespace:Plane.FormationCreator.Formation"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
x:Class="Plane.FormationCreator.Views.TaskBarView"
mc:Ignorable="d"
d:DesignHeight="156.968"
d:DesignWidth="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Left" Grid.Column="1"
Visibility="{Binding FlightTaskManager.IsPaused, Converter={StaticResource IsPausedToRunButtonVisibilityConverter}}"
Command="{Binding RunTasksCommand}">
<Button.Template>
<ControlTemplate>
<Grid Width="30"
Height="30"
Background="#00FFFFFF"
VerticalAlignment="Bottom">
<ed:RegularPolygon Fill="Black"
InnerRadius="1"
PointCount="3"
Width="30"
Height="30"
Stretch="Fill"
Stroke="Gray">
<ed:RegularPolygon.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="90" />
<TranslateTransform X="30" />
</TransformGroup>
</ed:RegularPolygon.RenderTransform>
</ed:RegularPolygon>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<Button HorizontalAlignment="Left" Grid.Column="1"
Background="#00FFFFFF"
Visibility="{Binding FlightTaskManager.IsPaused, Converter={StaticResource IsPausedToPauseButtonVisibilityConverter}}"
Command="{Binding PauseTasksCommand}">
<Button.Template>
<ControlTemplate>
<Grid Width="30"
Height="30"
VerticalAlignment="Bottom"
Background="#00FFFFFF">
<Rectangle Fill="Black"
HorizontalAlignment="Left"
Width="10"
Height="30"
Stroke="Gray" />
<Rectangle Fill="Black"
Margin="0,0,3,0"
HorizontalAlignment="Right"
Width="10"
Height="30"
Stroke="Gray" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<ItemsControl Grid.Column="0"
VerticalAlignment="Bottom"
ItemsSource="{Binding Tasks}"
Name="TasksControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="itemgrid">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Background="{Binding Status, Converter={StaticResource FlightTaskStatusToFillConverter}}"
Width="85"
Height="19"
BorderThickness="1"
BorderBrush="Black"
Effect="{Binding IsSelected, Converter={StaticResource FlightTaskIsSelectedToEffectConverter}}"
MouseLeftButtonDown="TaskLeftButtonDown"
MouseLeftButtonUp="SelectTask"
MouseRightButtonUp="HideTask">
<WrapPanel VerticalAlignment="Center"
HorizontalAlignment="Center" >
<TextBlock Width="auto"
FontSize="12"
Margin="0,0,2,0"
Foreground="White"
Text="{Binding TaskNum}"/>
<TextBlock Width="auto"
FontSize="12"
Foreground="White"
Text="{Binding TaskCnName}"/>
</WrapPanel>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<StackPanel Height="100" Background="#FF2D2D2D" VerticalAlignment="Bottom">
<TabControl
DataContext="{Binding FlightTaskManager.SelectedTask}"
SelectedIndex="{Binding TaskTypeIndex,UpdateSourceTrigger=PropertyChanged}">
<TabItem Header="起飞">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="起飞时间"/>
<TextBox Grid.Column="1" Margin="2"
Text="{Binding TakeOffTime, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</TabItem>
<TabItem Header="航点">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text="飞行时间: " />
<TextBox Grid.Column="1" Margin="2"
MaxLength="4"
Text="{Binding FlytoTime, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Text="悬停时间: " />
<TextBox Grid.Row="1" Grid.Column="1" Margin="2"
MaxLength="4"
Text="{Binding LoiterTime, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</TabItem>
<TabItem Header="降落">
<Grid Margin="10" >
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</TabItem>
</TabControl>
</StackPanel>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
VerticalAlignment="Bottom">
<Button Content="添加任务"
Background="#232323"
Command="{Binding AddTaskCommand}" />
<Button Content="清除任务"
Background="#232323"
Command="{Binding ClearTasksCommand}" />
<Button Content="重置任务"
Background="#232323"
Command="{Binding ResetTasksCommand}" />
<Button Content="强制下一步"
Background="#232323"
Command="{Binding NextTasksCommand}" />
<Button Content="重设原点"
Background="#232323"
Command="{Binding SetOriginCommand}" />
<!--<Button Content="保存" />
<Button Content="取消" />-->
</StackPanel>
</Grid>
</Grid>
</UserControl>
<UserControl 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:m="clr-namespace:Plane.FormationCreator.Formation"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
x:Class="Plane.FormationCreator.Views.TaskBarView"
mc:Ignorable="d"
d:DesignHeight="156.968"
d:DesignWidth="500">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Left" Grid.Column="1"
Visibility="{Binding FlightTaskManager.IsPaused, Converter={StaticResource IsPausedToRunButtonVisibilityConverter}}"
Command="{Binding RunTasksCommand}">
<Button.Template>
<ControlTemplate>
<Grid Width="40"
Height="40"
Background="#00FFFFFF"
VerticalAlignment="Bottom">
<ed:RegularPolygon Fill="MidnightBlue"
InnerRadius="1"
PointCount="3"
Width="40"
Height="40"
Stretch="Fill"
Stroke="Gray">
<ed:RegularPolygon.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="90" />
<TranslateTransform X="40" />
</TransformGroup>
</ed:RegularPolygon.RenderTransform>
</ed:RegularPolygon>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<Button HorizontalAlignment="Left" Grid.Column="1"
Background="#00FFFFFF"
Visibility="{Binding FlightTaskManager.IsPaused, Converter={StaticResource IsPausedToPauseButtonVisibilityConverter}}"
Command="{Binding PauseTasksCommand}">
<Button.Template>
<ControlTemplate>
<Grid Width="40"
Height="40"
VerticalAlignment="Bottom"
Background="#00FFFFFF">
<Rectangle Fill="Red"
HorizontalAlignment="Left"
Width="15"
Height="40"
Stroke="Gray" />
<Rectangle Fill="Red"
Margin="0,0,3,0"
HorizontalAlignment="Right"
Width="15"
Height="40"
Stroke="Gray" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
<ItemsControl Grid.Column="0"
VerticalAlignment="Bottom"
ItemsSource="{Binding Tasks}"
Name="TasksControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="itemgrid">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border
Width="88"
Height="19"
BorderThickness="1"
BorderBrush="Black"
Effect="{Binding IsSelected, Converter={StaticResource FlightTaskIsSelectedToEffectConverter}}"
MouseLeftButtonDown="TaskLeftButtonDown"
MouseLeftButtonUp="SelectTask"
MouseRightButtonUp="HideTask">
<Border.Background>
<MultiBinding Converter="{StaticResource FlightTaskStatusAndTransitionToFillConverter}">
<Binding Path="Status" />
<Binding Path="IsTransition" />
</MultiBinding>
</Border.Background>
<WrapPanel VerticalAlignment="Center"
HorizontalAlignment="Center" >
<TextBlock Width="auto"
FontSize="12"
Margin="0,0,2,0"
Foreground="White"
Text="{Binding TaskNum}"/>
<TextBlock Width="auto"
FontSize="12"
Foreground="White"
Text="{Binding TaskCnName}"/>
</WrapPanel>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Column="2" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="28"/>
</Grid.RowDefinitions>
<StackPanel Height="120" Background="#FF2D2D2D" VerticalAlignment="Bottom">
<TextBlock x:Name="hintaddtask" Margin="0,25,0,0" Text="请添加或选择飞行任务" Visibility="Collapsed" FontSize="18" TextAlignment="Center"/>
<TabControl x:Name="tasktabcont"
DataContext="{Binding FlightTaskManager.SelectedTask}"
SelectedIndex="{Binding TaskTypeIndex,UpdateSourceTrigger=PropertyChanged}">
<TabItem Header="1 起飞" x:Name="takeoffpage">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="起飞时间:" Margin="2" VerticalAlignment="Center"/>
<TextBox Grid.Column="1" Margin="2" VerticalAlignment="Center"
Text="{Binding TakeOffTime, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</TabItem>
<TabItem x:Name="flytopage" >
<TabItem.Header>
<Label x:Name="flytoLabel" Content="航点" HorizontalAlignment="Stretch" MouseLeftButtonDown="TaskLabelLeftButtonDown"
ToolTip="双击修改名称" />
</TabItem.Header>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Margin="2" Text="飞行时间: " VerticalAlignment="Center" />
<TextBox Grid.Column="1" Margin="2" VerticalAlignment="Center"
MaxLength="4"
Text="{Binding FlytoTime, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Grid.Row="1" Margin="2" Text="悬停时间: " VerticalAlignment="Center" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="2" VerticalAlignment="Center"
MaxLength="4"
Text="{Binding LoiterTime, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox Grid.Row="2" Grid.Column="2" x:Name="tranBox" Content="过度航点" HorizontalAlignment="Left" Width="75.353"
IsChecked="{Binding IsTransition}"/>
</Grid>
</TabItem>
<TabItem Header="降落" x:Name="landpage">
<Grid Margin="10" >
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
</Grid>
</TabItem>
</TabControl>
</StackPanel>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
VerticalAlignment="Bottom">
<Button Content="添加" x:Name="addtaskbtn"
Background="#232323"
Command="{Binding AddTaskCommand}" />
<Button Content="删除"
Background="#232323"
Command="{Binding DelTaskCommand}" />
<Button Content="清除"
Background="#232323"
Command="{Binding ClearTasksCommand}" />
<Button Content="重置"
Background="#232323"
Command="{Binding ResetTasksCommand}" />
<Button Content="更名" Visibility="Collapsed"
Background="#232323"
Command="{Binding renametaskCommand}" />
<Button Content="原点"
Background="#232323"
Command="{Binding SetOriginCommand}" />
<!--<Button Content="保存" />
<Button Content="取消" />-->
</StackPanel>
</Grid>
</Grid>
</UserControl>

View File

@ -28,103 +28,165 @@ namespace Plane.FormationCreator.Views
InitializeComponent();
this.DataContext = ServiceLocator.Current.GetInstance<TaskBarViewModel>();
hintaddtask.Visibility = Visibility.Visible;
tasktabcont.Visibility = Visibility.Collapsed;
_flightTaskManager.TaskTypeChanged += (sender, e) =>
{
if (e.ChangedFlightTask.TaskType == FlightTaskType.Land)
addtaskbtn.IsEnabled = false;
else addtaskbtn.IsEnabled = true;
};
_flightTaskManager.TaskcnNameChanged += (sender, e) =>
{
if (e.ChangedFlightTask.TaskType == FlightTaskType.Land)
flytoLabel.Content = (_flightTaskManager.SelectedTaskIndex + 1) + " 航点";
else
flytoLabel.Content = (_flightTaskManager.SelectedTaskIndex + 1) + " " + _flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].TaskCnName;
};
_flightTaskManager.PropertyChanged += (sender, e) =>
{
if (_flightTaskManager.SelectedTaskIndex == -1) return;
switch (e.PropertyName)
{
//选中任务时触发--控制任务类型选项卡的显示和是否允许加入新任务
case nameof(FlightTaskManager.SelectedTaskIndex):
if (_flightTaskManager.Tasks.Count == 0)
{
tasktabcont.Visibility = Visibility.Collapsed;
hintaddtask.Visibility = Visibility.Visible;
addtaskbtn.IsEnabled = true;
}
else
{
hintaddtask.Visibility = Visibility.Collapsed;
tasktabcont.Visibility = Visibility.Visible;
//刷新任务编号--可能删除了任务
TasksControl.Items.Refresh();
//起飞任务
if (_flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].TaskType == FlightTaskType.TakeOff)
{
takeoffpage.Visibility = Visibility.Visible;
landpage.Visibility = Visibility.Collapsed;
flytopage.Visibility = Visibility.Collapsed;
}else
//选中中间的任务
if (_flightTaskManager.SelectedTaskIndex < (_flightTaskManager.Tasks.Count - 1))
{
takeoffpage.Visibility = Visibility.Collapsed;
landpage.Visibility = Visibility.Collapsed;
flytopage.Visibility = Visibility.Visible;
flytoLabel.Content = (_flightTaskManager.SelectedTaskIndex+1)+" "+ _flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].TaskCnName;
//允许添加中途任务
addtaskbtn.IsEnabled = true;
}
else
//最后一个任务--只有最后一个任务能设置成降落-防止中途降落
{
takeoffpage.Visibility = Visibility.Collapsed;
landpage.Visibility = Visibility.Visible;
flytopage.Visibility = Visibility.Visible;
//如果不是降落任务
if (_flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].TaskType != FlightTaskType.Land)
{
addtaskbtn.IsEnabled = true;
flytoLabel.Content = (_flightTaskManager.SelectedTaskIndex + 1) + " " + _flightTaskManager.Tasks[_flightTaskManager.SelectedTaskIndex].TaskCnName;
}
else
{
flytoLabel.Content = (_flightTaskManager.SelectedTaskIndex + 1) + " 航点";
addtaskbtn.IsEnabled = false;
}
}
}
break;
// case nameof(FlightTaskManager.SelectedTask .TaskTypeIndex):
default:
break;
}
};
}
private FlightTaskManager _flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
//用于直接飞到航点
public void TaskLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount > 1)
{
var elem = sender as FrameworkElement;
var task = elem.DataContext as FlightTask;
if (task.TaskType != FlightTaskType.FlyTo) return;
TasksControl.Focus();
_flightTaskManager.FlyToTasks();
}
}
//用于更名
public void TaskLabelLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount > 1)
{
FlightTask task = _flightTaskManager.SelectedTask;
if ((task == null) || (task.TaskType != FlightTaskType.FlyTo)) return;
string newName = task.TaskCnName;
if (PlaneMessageBox.OnShow("请输入新的名称", "重命名", ref newName))
{
task.TaskCnName = newName;
}
}
}
//选择任务
private void SelectTask(object sender, MouseButtonEventArgs e)
{
var elem = sender as FrameworkElement;
var task = elem.DataContext as FlightTask;
//if (task.TaskType != FlightTaskType.TakeOff) // 不让选起飞任务。 现在可以选择起飞任务
{
_flightTaskManager.Select(task);
}
}
_flightTaskManager.Select(task);
}
//以前的右键隐藏航点,已不用
public void setRightSelect(FlightTask task, bool vRightSelect)
{
// var borderBrush = new SolidColorBrush(vRightSelect ? Colors.Gray : Colors.OrangeRed);
var borderBrush = new SolidColorBrush( Colors.OrangeRed);
if (task.TaskType == FlightTaskType.TakeOff) return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(TasksControl); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(TasksControl, i);
if (child != null && child is FrameworkElement)
{
var taskdata = (child as FrameworkElement).DataContext as FlightTask;
if (taskdata == task)
{
if (child is Rectangle)
{
(child as Rectangle).Stroke = borderBrush;
}
else if (child is Border)
{
(child as Border).BorderBrush = borderBrush;
}
}
}
}
/*
if (elem is Rectangle)
{
(elem as Rectangle).Stroke = borderBrush;
}
else if (elem is Border)
{
(elem as Border).BorderBrush = borderBrush;
}
*/
}
}
//右键功能 ---隐藏航点
private void HideTask(object sender, MouseButtonEventArgs e)
{
var elem = sender as FrameworkElement;
var task = elem.DataContext as FlightTask;
// int a = _flightTaskManager.RightSelectedTaskIndex;
if (task.TaskType != FlightTaskType.TakeOff) // 不让选起飞任务。
{
var borderBrush = new SolidColorBrush(task.IsRightSelected ? Colors.Gray : Colors.OrangeRed);
if (elem is Rectangle)
{
(elem as Rectangle).Stroke = borderBrush;
}
else if (elem is Border)
{
(elem as Border).BorderBrush = borderBrush;
}
_flightTaskManager.RightSelect(task);
setRightSelect(task, true);
_flightTaskManager.RightSelect(task);
}
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)

View File

@ -31,20 +31,15 @@ namespace Plane.FormationCreator.Views
{
InitializeComponent();
var camera = view3d.Camera as PerspectiveCamera;
camera.Position = new Point3D(0, 0, 0);
camera.LookDirection = new Vector3D(0, 1, 0);
camera.UpDirection = new Vector3D(0, 0, 1);
camera.FieldOfView = 120;
ResetCamera();
_flightTaskManager = ServiceLocator.Current.GetInstance<FlightTaskManager>();
_view3DManager = ServiceLocator.Current.GetInstance<View3DViewModel>();
this.DataContext = _view3DManager;
//view3d.ShowCameraInfo = true;
//view3d.ShowFieldOfView = true;
}
private void ResetCamera_Click(object sender, RoutedEventArgs e)
public void ResetCamera()
{
// view3d.CameraController.CameraPosition = new Point3D(0, 40, 1);
// view3d.CameraController.CameraUpDirection = new Vector3D(0, -1, 10);
@ -53,12 +48,29 @@ namespace Plane.FormationCreator.Views
// view3d.CameraController.CameraRotationMode = CameraRotationMode.Turntable;
var camera = view3d.Camera as PerspectiveCamera;
camera.Position = new Point3D(0, 0, 0);
camera.LookDirection = new Vector3D(0, 1, 0);
camera.UpDirection = new Vector3D(0, 0, 1);
camera.FieldOfView = 120;
camera.Position = new Point3D(0, 0, 1);
//用于朝向180度
// camera.LookDirection = new Vector3D(-0.025, -0.911, 0.411);
//用于朝向9度
camera.LookDirection = new Vector3D(0, 1, 0.8);
camera.UpDirection = new Vector3D(0.011, 0.411, 0.912);
//用于0度
//camera.LookDirection = new Vector3D(0, 1, 0);
//camera.UpDirection = new Vector3D(0,0, 1);
camera.FieldOfView = 120;
_view3DManager.Clear3DCopters();
//for test 用来确定上面的参数
//view3d.ShowCameraInfo = true;
//view3d.ShowFieldOfView = true;
}
private void ResetCamera_Click(object sender, RoutedEventArgs e)
{
ResetCamera();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Some files were not shown because too many files have changed in this diff Show More