简介:这是一套集成高德地图的Mission Planner飞控软件完整工程源码包,面向无人机开发者、飞控调参人员以及ArduPilot/Mission Planner进阶用户,解决原版地图服务在国内使用不便、飞行规划和实时监控地图信息不准的问题。压缩包共7344个文件,约56.41MB,以C#源码(cs)、资源文件(resx)、证书与图像文件(crt、png、jpg)为主,同时包含xml、json、config等配置类文件和Python辅助脚本,目录结构接近真实项目,便于二次开发与功能裁剪。已有6100人学习。资源内可见高德地图相关模块与地图API接入逻辑,有助于理解地图插件安装、任务规划、实时飞行监控及数据后处理等完整流程,既适合学习研究,也可作为功能定制的参考基底。 进门先交代,这是个常年折腾飞控地面站的人踩坑记录。MissionPlanner(以下简称MP)对玩APM/PX4的人来说应该是老朋友了,航点规划、调参、日志解析、模拟器样样都有,唯独地图这块,默认那套国外图源在国内用着是真闹心。后来我把高德地图整进去了,规划和干活都舒服不少,这篇文章就聊聊整个思路和实操过程中的那些坑,包括在线瓦片和离线瓦片两种路线、坐标系偏移问题,以及路况道路这类图层值不值得想办法叠。
1. 动手之前:为什么MP的地图源要动手术
1.1 默认地图源的尴尬
MP内置的地图源看起来不少,OpenStreetMap、Bing、Google系列都有,国内用起来问题却一堆:OSM在偏远飞场更新慢,很多田块道路根本没有;Google系列连接不稳定,经常白屏或只有一半瓦片;Bing国内访问同样时好时坏,尤其飞到山区、荒地,底图要么空白要么模糊到没法目视参考。这个状态在作测绘、植保或者找飞场的时候特别难受,航线画得再好,底图不可靠心里就发虚。
高德在国内的地图数据相对完整,村级道路、田块边界、近年新建建筑都比较新,而且服务器在国内,加载速度快。更关键的是,高德底图对国内飞场周边的参照物标识很清楚,外场找地、判断禁飞位置、规划起降点都比洋图源顺手。所以网上搜索热度一直不低,大家就是想给MP换上一双“本地眼睛”,这就涉及直接添加在线地图源,或者把瓦片下载到本地长期使用。
1.2 高德地图瓦片URL规则
要接入高德,首先得明白瓦片是怎么组织的。和OpenStreetMap一样,高德也把地图切成256x256的小方块,按照“z(缩放级别)/x(列号)/y(行号)”的方式排列,在第16级缩放时一个瓦片大约能覆盖地面几百米范围。MP请求哪个瓦片,就往URL模板里填对应的z、x、y值,本质上就是拼一个HTTP地址。
高德开放的几个瓦片地址模板,目前常用的是下面这三类:
| 图层类型 | URL模板(说明) |
|---|---|
| 街道/矢量底图 | https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z} |
| 卫星影像底图 | https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z} |
| 道路路网叠加层 | https://webrd0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z} |
其中,{s}一般取1到4,对应不同服务器子域,比如webrd01、webrd02;scale=1是普通分辨率,高清屏也可以试scale=2,不过瓦片体积会变大。style=6返回卫星影像,style=7是道路、河流标记和地名标注,style=8则是完整街道图,也是大多数人加载之后看到的那种带路网的高德样式。下面这段代码是给MOBAC这类工具用的示例配置思路,方便大家理解URL是怎么拼出来的:
GMapProvider provider = new GMapProvider(); // 伪代码示意,实际语言需要把{x}、{y}、{z}替换成参数 string url = string.Format( "https://webrd0{0}.is.autonavi.com/appmaptile?style=8&x={1}&y={2}&z={3}", (x + y) % 4 + 1, x, y, z); // style改成7就是道路标注层,改成6就是卫星图在浏览器里手动打开一个瓦片URL,能直接看到一张256x256的小图,就说明URL模板可以用。这一步建议在接入前先做,能避免后面一堆排查时间。
2. 按需选用:在线地图源与离线瓦片两条路线
2.1 在线接入高德地图源
想让MP直接在线刷高德瓦片,最正统的办法是修改MP内置的GMap.NET地图源定义,在源码里新增一个“GaodeMapProvider”类,然后把类的实例注册到用户地图源集合里,再重新编译MissionPlanner。整体思路并不复杂,因为GMap.NET里所有地图源都长一个样:重写GetTileImage方法,按瓦片坐标拼接URL并请求图片即可。核心代码参考如下,具体API版本可能有差异,主要是理解原理:
public class GaodeMapProvider : GMapProvider { public static readonly GaodeMapProvider Instance = new GaodeMapProvider(); public override Guid Id => new Guid("A1B2C3D4-1234-4567-89AB-CDEF01234567"); public override string Name => "GaodeMap_Street"; public override PureImage GetTileImage(GPoint pos, int zoom) { string url = string.Format( "https://webrd0{0}.is.autonavi.com/appmaptile?style=8&x={1}&y={2}&z={3}", (pos.X + pos.Y) % 4 + 1, pos.X, pos.Y, zoom); return GetTileImageUsingHttp(url); } } // 注册到用户地图源 GMaps.Instance.UserProviders.Add(GaodeMapProvider.Instance);这套方案适合有编译能力的兄弟,能彻底解决地图源切换问题,想加百度、腾讯、ArcGIS都一个套路。但也要有心理准备:MP的GMap.NET是魔改版,不同版本API可能不一样,编译报错需要逐行对源码;另外高德对高频率瓦片请求有防滥用限制,短时间内大面积拖动地图可能触发HTTP错误。还有一点不太推荐的是下载网上所谓的“高德地图集成版MP”,这类修改版有没有夹带后门谁也无法保证,外场链接飞控调参数,安全第一,能自己编译就自己编译。
2.2 离线瓦片缓存方案
如果你只是为了外场无网规划航线,在线接入并不是最好的路,离线瓦片才是长久之计。离线方案的核心思路是:提前把飞场周边的高德瓦片下载到MP的MapCache缓存目录,外场断开网络后MP从本地缓存读图。我实测下来,离线方案比在线方案稳得多,没有网络抖动、没有防盗链限制,起降场周边地图秒开。
具体操作分三步。第一步,用MOBAC(Mobile Atlas Creator)这类工具下载高德瓦片,注意在MOBAC里新建自定义Tile Source,把高德的URL模板填进去;第二步,设置下载层级和范围,普通旋翼机做航拍或植保规划,14级到17级就够了,再低看不清田地边界,再高则瓦片数量爆炸;第三步,就是输出格式和存放路径。这些年我试过比较省事的做法是让MOBAC按“GMap.NET”格式输出,然后把输出目录直接指向MP的MapCache文件夹,并确保子目录名与MP里地图源名称对应,MP启动后认目录结构认得很死,名字对不上就白干活。
如果不想装MOBAC,还有个土办法:在家把MP切到能用的在线地图源,打开飞行计划界面,用鼠标或键盘方向键慢慢把目标区域整体划一遍,等所有瓦片都加载出来,MP会自动写进缓存,然后把整个MapCache目录拷到外场电脑即可。这个方法没有任何额外学习成本,缺点是手动划图容易漏瓦片,建议每级缩放都来回扫两三遍。
2.3 路况道路图层能不能叠
关于网上高频搜索的“高德路况道路矢量导出”,我的结论是:如果是想要高德实时路况那种红黄绿线段,MP里基本叠不了,也没必要叠,飞控规划根本用不到实时路况,那是导航软件的需求;但如果是想要“卫星底图+道路标注”的静态图层,那是有办法的。高德style=7返回的就是带道路、地名、水系的标注层瓦片,用QGIS或者图像拼接工具把同一范围、同一缩放级别的style=6卫星图和style=7路网图两张瓦片做像素级叠加,导出成新的瓦片集,再放进MP缓存,就能看到类似“高德卫星+道路”的底图效果。
这个叠加过程不难,但工程量不小。你先要下载两套瓦片,再逐个缩放级别做图片合成,出错的概率也不低。我的建议是,普通飞行任务直接用style=8的街道图就行,只有做低空勘测、需要精确判断某个地块旁道路走向时,才值得去做卫星和路网的合成底图。至于把高德道路矢量数据直接导出成SHP或KML,涉及地图数据版权,个人飞着玩研究可以,别拿去做公开项目或商业应用,高德商业授权这块查得越来越严。
3. 坐标系统和偏移问题:用起来之前必须搞懂
3.1 WGS-84与GCJ-02是怎么回事
这是整个方案里最绕不开的问题。GPS设备输出的是WGS-84坐标系,而高德地图上所有坐标都经过了一次加密偏移,加密后我们常叫GCJ-02,俗称“火星坐标系”。偏移量在国内不同地区不一样,有的地方几十米,有的地方上百米,而且不是匀速平移,不同经纬度偏移方向和大小都有变化。MP默认把所有要素都按WGS-84处理,航点、飞行器实时位置、航线都是用GPS原始坐标画的;高德底图本身是GCJ-02标准下的瓦片,两层一叠加,自然对不齐。
动手之前先想清楚,你到底需不需要“绝对对齐”。如果你只是离线在高德底图上框一块作业区域,然后在MP里画航点,这时航点坐标是高德底图上点选出来的经纬度,MP会把它们当作WGS-84发给飞控,飞机实际会落在“你在地图上点的那个位置的东南方或西北方几十米处”。对大面积植保、测绘来说这个误差不可接受;但如果你只是目视范围内飞动作秀、练习,或者用Pixhawk跑固定线路做巡逻,几十米偏移可能还在容忍范围内,这就要你自己权衡了。
3.2 实操中的偏移补偿思路
要真正解决偏移,有几个方向。最彻底的做法是改GMap.NET的投影变换,在获取瓦片URL之前把地图瓦片坐标从GCJ-02反算回WGS-84,等于把高德底图强行纠正到GPS坐标系下,代码上可以引入现有的“GCJ02转WGS84”开源算法,对每个瓦片边界做变换,再调整显示位置。听上去简单,实际很容易把瓦片接缝弄出重影,我试过一轮效果一般,需要花时间调参数。
更实用的办法是错位容忍加基准校准。具体操作是:在飞场用一台已接入高德底图的电脑,把飞机或手持GPS放到某个固定地物旁,记录地图显示位置和真实GPS位置的差,算出偏移向量。规划航线时,在MP里做一个整体平移。MP本身没有一键平移所有航点的按钮,但你可以把航点导出成KML或waypoint文件,用文本方式批量改经纬度后再导回来。这个方法精度谈不上高,胜在快速、可控,适合临时任务。
如果你的项目对绝对位置精度要求很高,比如测绘、打点、贴线飞行,我劝你放弃高德底图做主坐标系,老老实实回到WGS-84的标准地图源,或者上RTK。底图这东西更多是给你一个空间参照,真到了精算环节,坐标系统一和差分定位才是唯一正路。
4. 常见问题与排查技巧实录
4.1 地图白屏或加载不动
遇到白屏,第一件事不是怀疑MP坏了,而是扒出瓦片URL,复制到浏览器里看能不能打开。如果浏览器能打开、MP里打不开,多半是请求头问题,高德部分瓦片服务器对非浏览器的User-Agent和Referer有限制,需要在自定义地图源里把请求头的Referer伪装成高德官网地址;如果浏览器也打不开,说明URL模板参数过期了,高德偶尔会调整参数或子域名,换一个服务器编号挨个试。还有一点,MP某些版本里地图提供商的显示名称和类名不一致,加载时可能调到别的源,注意看右下角地图源名称是不是你选的那一个。
4.2 缓存明明有却读不出来
这类问题多半出在目录结构上。GMap.NET缓存不是简单一堆图片扔进去就能认,它有固定层级:MapCache\地图源名称\Zoom\TileX\TileY.png,如果文件夹名和MP里实际注册的地图源名称对不上,MP扫描缓存时找不到对应provider,就只能干瞪眼。另外,缓存路径要在MP设置里确认过,有人把MOBAC输出目录放到了桌面,却忘了在MP里改缓存位置,自然读不到。可以先用一个小缩放级别下载十几张瓦片,验证路径通了再批量下载,别一上来就下载几百兆。
4.3 航线与地图对齐,但飞机飞行时看着偏了
这正是GCJ-02偏移的典型表现。航点是在高德底图上选的,飞机飞的时候按照GPS坐标走,飞控并不知道高德地图被偏移过,所以飞行器实时位置图标在高德底图上会和实际位置偏差一大截,甚至飞出航线显示。这个情况不要慌,不要试图用“平移地图”来解决,治标不治本。最推荐的做法是提前做基准校准,取得该区域的偏移向量后,对航点批量修正;如果只是目视飞行,就还是回到WGS-84底图或接受视觉偏差。外场出现这种问题时,优先看飞控日志里的GPS坐标和实际位置是否一致,确认飞控本身没毛病,再回头处理地图。
4.4 界面卡死、瓦片线程占用过高
MP卡死大多是因为一次请求的瓦片数量太多,尤其在高缩放级别下拖拽地图,GMap.NET会瞬间发起几十上百个HTTP请求,网络稍微波动就导致线程堆积。解决思路是限制最大请求数,或者把地图操作缩放级别控制在合理范围内,比如规划阶段用15到17级,不要手贱放大到19级左右来回拖。还需要检查电脑的显卡和默认渲染方式,一些老电脑在GDI渲染模式下地图刷新效率很差,可以在MP设置里调整地图刷新选项。如果还是卡,外场就安心用离线缓存,在线请求关闭,整个界面流畅度会好很多。
最后再分享一点我自己的习惯:我一般会在两套电脑上配合用——家里那台专门负责在线刷高德地图并预热缓存,外场那台完全离线,只做航点规划和飞控调参,这样既不担心现场断网,也不用在现场干等地图加载。现在每次出去干活,开着提前预热好的高德底图,在农田、林场、河边找参照物都很快,配合MP的航点规划,效率确实提升明显。如果你也想折腾,建议先按第二节里的离线方案走一遍,熟练之后再研究编译自定义地图源,这条路最稳,踩坑成本也最低。
本文还有配套的精品资源,点击获取