大疆KMZ航线文件解析:template.kml与waylines.wpml的区别与实战
开头先讲个我自己的经历。前几年第一次分析大疆导出的航线文件拿到手是一个KMZ压缩包连解压带看结构用了不到两分钟发现自己面对的是两个文件template.kml和waylines.wpml。当时想都没想直接把template.kml拖进GIS软件里看觉得航线一目了然顺手在这里改了几个坐标重新打包想上传到遥控器结果DJI Pilot一直报“航线文件格式错误”。后来才搞清楚原来template.kml只是一个“给地图软件看的预览文件”真正会被大疆飞控和执行端读取的是waylines.wpml。这篇文章我会把这两个文件的结构、区别、解析方法和排错经验完整讲一遍尤其适合刚开始接触大疆航线文件解析的飞手、GIS开发者和做第三方无人机平台集成的朋友。5分钟读完核心区别后面遇到问题也能少走弯路。1. 大疆KMZ的“双文件”结构template.kml只是图层waylines.wpml才是任务书1.1 先别把它当成普通KMZ大疆航线文件的KMZ格式底层确实和Google Earth的KMZ一样本质上是一个ZIP压缩包。你用解压工具打开后会看到里面通常包含两个核心文件template.kml和waylines.wpml。有些特殊版本还会带上缩略图、图标或者机场信息文件但核心永远是这两个。很多人把KMZ当成普通KML的压缩壳用GIS工具直接打开这是第一个坑。普通KMZ里面一般只有一个doc.kml而大疆航线KMZ里面是两个人文件。如果你的GIS软件不认识WPML后缀它很可能只读取了template.kml告诉你“航线文件打开成功”但实际上执行层面的字段你一个都没看到更别说修改后上传给飞机。我建议拿到任何一份大疆航线KMZ第一步永远是用解压工具把它解开而不是双击或者直接拖进GIS软件。让两个文件都“裸”在桌面上再用文本编辑器打开你才会真正看到大疆航线数据的原始样貌。1.2 为什么大疆偏偏要放两个文件大疆这么设计不是没事找事。template.kml是标准的KML文档遵循OGC KML 2.2规范里面的航点、路径、坐标都是通用地理信息。这意味着你用Google Earth、QGIS、ArcGIS这类通用地图软件就能直接打开快速预览航线走向判断航线是否经过禁飞区、是否跨越障碍物。waylines.wpml则完全不是通用标准。WPML可以理解成大疆在KML基础上扩展出来的私有XML方言里面除了航点坐标还包含大量通用KML根本不支持的字段例如飞往首航点的模式、任务结束后的动作、失控行为、每个航点的速度、转弯模式、云台角度、拍照动作、变焦动作等等。通用地图软件不需要这些信息也读不懂这些信息。所以大疆把文件拆成两个是很有意机的template.kml负责“给人看”waylines.wpml负责“给飞机看”。如果你只做可视化拿着template.kml就够了如果你要让飞机按航线执行任务无论如何都要保证waylines.wpml里的内容是完整、合法的。2. template.kml解析坐标、高度与可视化的套路2.1 KML的底层骨架template.kml说到底就是一个XML文件根节点是kml里面通常有一个Document然后是一堆Placemark。每一个Placemark可以是一个点也可以是一条线。大疆生成的template.kml中航点一般以Point形式存在航点之间的连线以LineString形式存在。下面是一段真实风格的大疆template.kml片段?xml version1.0 encodingUTF-8? kml xmlnshttp://www.opengis.net/kml/2.2 Document nametemplate/name Placemark name1/name Point coordinates113.0548,22.5047,100.0/coordinates /Point /Placemark Placemark name2/name Point coordinates113.0551,22.5052,100.0/coordinates /Point /Placemark Placemark name航线/name LineString tessellate1/tessellate coordinates 113.0548,22.5047,100.0 113.0551,22.5052,100.0 /coordinates /LineString /Placemark /Document /kml注意coordinates里面的三个值顺序永远是“经度,纬度,高度”单位是十进制度数和米。这个顺序和很多国内坐标系里“纬度,经度”的习惯不一样新手特别容易在这上面栽跟头。我在给第三方平台做对接时就见过有人把坐标解析成“维度,精度”导致飞机跑去几十公里外。解析template.kml和waylines.wpml时必须严格记住前两个字段是经度、纬度第三位才是高度。2.2 高度到底是不是海拔template.kml里的高度取决于你使用DJI Pilot 2或者其他规划软件时的设置。如果航线设置的是“相对起飞点高度”那么这里面的数字就是相对高度而不是绝对海拔。如果设置的是“海拔高度”那么这里面的数字就是绝对海拔。这一点非常关键。因为导入到部分第三方系统时系统可能默认把template.kml里的高度当海拔高导致航线比预期高或者低几十米。我在实际项目里就遇到过客户用仿地航线导出template.kml里面高度数值其实已经是相对地面高度结果拿去做地形叠加分析时高度全线飘移。所以你在用template.kml做可视化时一定要先确认高度模式别只看一个数字。2.3 template.kml里没有的东西template.kml里面没有速度没有转弯半径没有拍摄动作没有云台俯仰角没有航点动作列表。它就是一个相对干净的地理信息文件。对大疆航线文件解析来说template.kml最大的价值是让你快速获得航线轨迹用于地图展示、地理围栏碰撞检测、或者作为调试时的参考层。我自己的做法是在开发航线可视化功能时直接解析template.kml生成轨迹图层但是所有任务编辑、任务重放、模拟仿真全部读waylines.wpml。两条腿走路各干各的活既避免了过度解析复杂WPML字段又不会因为缺失执行层数据而出错。3. waylines.wpml解析大疆私有命名空间下的参数与动作3.1 WPML的“KML皮DJI核”waylines.wpml从表面上看也是KML语法根节点同样是kml但是你打开文件头部的属性会发现多了很多命名空间。典型的结构类似?xml version1.0 encodingUTF-8? kml xmlnshttp://www.opengis.net/kml/2.2 xmlns:wpmlhttp://www.dji.com/wpmz/1.0 Document wpml:missionConfig ... /wpml:missionConfig Placemark nameWPT_1/name Point coordinates113.0548,22.5047,100.0/coordinates /Point wpml:waypointSpeed5/wpml:waypointSpeed wpml:waypointTurnModetoPointAndStop/wpml:waypointTurnMode ... /Placemark /Document /kmlxmlns:wpmlhttp://www.dji.com/wpmz/1.0这一段就是它的排他性身份证。通用KML解析器看到这个前缀通常会直接忽略这就是为什么你不能指望QGIS把waylines.wpml完整显示出来的原因。解析这类文件时必须带着命名空间去解析节点否则你拿到手的就是一堆空值。不同机型、不同固件版本导出的WPML字段会有些差别M300 RTK、M350 RTK、Mavic 3E、机场上传的版本在具体字段名和动作类型上都有各自的小脾气。但整体骨架是稳定的都是“一个全局配置段 一组航点Placemark”的结构。刚上手时建议你用官方Pilot 2导出几份不同机型的航线做对比比自己到处找二手资料靠谱得多。3.2 missionConfig全局配置决定整条航线的行为wpml:missionConfig位于Document节点下控制的是整条航线的全局行为。以某些机型的WPML为例常见字段包括flyToWaylineMode飞机从当前位置飞到第一个航点的模式取值可能是safely或straightLine。safely会先爬升到安全高度再水平飞行适合地形复杂场景。finishAction航线执行完后的动作常见有goHome返航、goContinue继续执行后续任务、noAction原地悬停、backFirstWaypoint返回第一个航点。exitOnRCLost遥控器信号丢失后的行为例如goHome、goContinue、hover。takeOffSecurityRecheck起飞前是否需要安全检查。takeOffAltitude起飞后爬升到指定高度。坐标系参数包括coordinateMode和heightMode例如WGS84坐标、EGM96高程模式。这些字段之间是相互配合的。例如finishAction设为goHome同时exitOnRCLost也设为goHome这意味着无论正常结束还是失控飞机都会以返航为最终保底策略。解析时我建议把这些全局参数单独抽出来做成一个配置对象在后续模拟推演、风险评估时直接引用而不要每次都去嵌套翻XML。3.3 航点Placemark航线动作真正发挥作用的地方每个航点都是一个Placemark除了一组坐标之外还挂着大量wpml命名的扩展字段。常见的包括waypointSpeed经过该航点时的飞行速度单位m/s。waypointTurnMode航点转弯模式可以是toPointAndStop、coordinateTurn、spiralMode等决定飞机是减速到零再转还是联动转弯。useStraightLine是否直线飞向下一个航点。航向参数waypointHeadingParam航向模式、航向角、俯仰角等。航点动作wpml:actions里面可以挂多个wpml:action例如拍照takePhoto、开始录像startRecord、停止录像stopRecord、云台转向gimbalRotate、变焦cameraZoom等。举一个动作段的示例wpml:actions wpml:action wpml:actionId1/wpml:actionId wpml:actionTypetakePhoto/wpml:actionType wpml:actionParam wpml:payloadIndex0/wpml:payloadIndex wpml:photoStorageTypenormal/wpml:photoStorageType /wpml:actionParam /wpml:action /wpml:actions这里actionId是动作在航点内的顺序编号actionType是动作类型actionParam里面放该动作的参数。解析时最容易出的问题是有人用标准XML解析库读actionType时忘了前缀结果所有动作都是空字符串。记住在WPML里只要带wpml:前缀的节点解析时必须写全命名空间。4. template.kml与waylines.wpml的关系一张表说清所有差异初次接触大疆航线文件的朋友最关心的问题往往是这两个文件能不能互相替代谁更重要我直接用对照表说明。对比维度template.kmlwaylines.wpml文件本质标准KML文件基于KML语法的XML私有多字段文件标准兼容性通用GIS软件可直接打开通用GIS软件基本无法完整识别主要内容航点坐标、高度、航线LineString航点坐标、高度、速度、转向、动作、全局配置、失控逻辑使用对象地图、浏览器、GIS系统DJI Pilot、飞控系统、行业平台是否能被飞机执行不能能修改后对执行的影响基本不影响直接影响适合做啥可视化预览、轨迹叠加航线仿真、任务执行、动作编排补充一点必须强调的关系这两个文件并不是严格同步的。你在DJI Pilot里规划好航线后导出的KMZ里两个文件都根据同一份任务数据生成因此正常情况下坐标和高度是一致的。但如果你手动改了其中一个另一个不会自动跟着变。更麻烦的是如果你用模板文件的方式去创建新的KMZ比如用Python脚本直接写了一个template.kml和一个waylines.wpml但两者之间的航点数量、坐标顺序不一致Pilot在加载时很可能只认WPML的内容可部分旧版本在显示地图轨迹时会去读template.kml于是就会出现“预览轨迹和实际执行轨迹不一样”的诡异现象。所以我在生成或编辑大疆航线文件时始终坚持一个原则以waylines.wpml为准template.kml作为附属品同步生成。绝不手工单独改其中一个再打包。5. 实操演示解压KMZ、转换KML、读取航线文件的完整流程5.1 解压KMZ5分钟能完成的动作最简单的办法是把.kmz后缀改成.zip然后用系统压缩工具解压。Windows直接改扩展名后右键解压macOS双击解压即可Linux命令行用unzipunzip wayline.kmz -d wayline_files如果你的机器装了7-Zip或WinRAR直接右键用压缩工具打开KMZ也可以不需要改后缀。解压完成后你会看到template.kml和waylines.wpml。我强烈建议你在解压出来的目录里直接右键用文本编辑器打开这两个文件先感受一下它们的原始结构比任何文档都直观。很多人会问能不能把KMZ直接“转换”成KML方便在通用GIS工具里看这里要注意普通KMZ转KML是成立的因为普通KMZ里只有一个KML文件但大疆航线KMZ里有两个文件直接改扩展名会让GIS工具晕头转向。正确做法是先解压出template.kml再导入GIS。如果只想要航线轨迹template.kml就够了。5.2 Python解析示例快速读取两个文件的内容下面是一段我用过的解析示例用的都是Python标准库实测可以快速提取两个文件里的坐标和航点数import zipfile import xml.etree.ElementTree as ET KML_NS {http://www.opengis.net/kml/2.2} WPML_NS {http://www.dji.com/wpmz/1.0} def read_kmz(path): with zipfile.ZipFile(path, r) as z: template z.read(template.kml) waylines z.read(waylines.wpml) return template, waylines def parse_template(xml_bytes): root ET.fromstring(xml_bytes) points [] for placemark in root.iter(KML_NS Placemark): point placemark.find(KML_NS Point) if point is not None: coords point.findtext(KML_NS coordinates) points.append(coords.strip()) return points def parse_waylines(xml_bytes): root ET.fromstring(xml_bytes) waypoints [] for placemark in root.iter(KML_NS Placemark): name placemark.findtext(KML_NS name) coords placemark.findtext(KML_NS Point/ KML_NS coordinates) speed placemark.findtext(WPML_NS waypointSpeed) actions [] action_list placemark.find(WPML_NS actions) if action_list is not None: for action in action_list.findall(WPML_NS action): act_type action.findtext(WPML_NS actionType) actions.append(act_type) waypoints.append({ name: name, coords: coords, speed: speed, actions: actions, }) return waypoints if __name__ __main__: template_xml, waylines_xml read_kmz(wayline.kmz) track_points parse_template(template_xml) waypoints_info parse_waylines(waylines_xml) print(template航点数:, len(track_points)) print(wpml航点数:, len(waypoints_info)) for wp in waypoints_info[:3]: print(wp)这段代码有个小细节我用root.iter遍历所有的Placemark而不是用findall因为大疆某些WPML文件里可能会在missionConfig之外又套一层折叠结构直接用findall可能会漏掉航点。用iter更稳妥。当然正式产品中我会用lxml替代ElementTree处理大文件和复杂命名空间时性能更好。5.3 用JS生成KMZ需要同时写两个文件“js生成kmz”这个需求在浏览器端很常见例如在线航线规划工具导出任务文件。核心思路是用JSZip构造ZIP把两个文件同时放进去然后生成Blob并触发下载。关键并不是生成ZIP本身而是你得先构造一个合法可用的waylines.wpml。我见过有人在浏览器端只生成一个template.kml就打包成KMZ结果上传Pilot直接失败。用JSZip生成KMZ的骨架大致是import JSZip from jszip; function generateKMZ(templateKml, waylinesWpml) { const zip new JSZip(); zip.file(template.kml, templateKml); zip.file(waylines.wpml, waylinesWpml); return zip.generateAsync({ type: blob, mimeType: application/vnd.google-earth.kmz, }); }注意mimeType要设置成KMZ的标准类型同时文件名后缀必须用.kmz。否则一些终端识别不了。更重要的还是waylines.wpml里的字段要齐全、合法尤其missionConfig不能缺否则Pilot会认为这不是航线任务文件。6. 开发与排错经验从航线解析到飞控执行的几道坎6.1 为什么劝你别直接在template.kml里改坐标有人会想我只需要调整航线的一个航点直接在template.kml里把坐标改了然后重新打包是不是更简单这个做法在可视化层面确实“看起来”改了但飞机执行时读的是waylines.wpml你改template.kml等于白改甚至可能因为两个文件不一致导致导入报错。正确做法是同时修改或者重新生成两个文件并且确保坐标序列完全一致。如果是少量航点手工同步改还可行如果是几十个航点我建议写脚本以waylines.wpml为主文件修改同时用脚本根据WPML里的坐标重新生成template.kml。这样能避免很多莫名其妙的同步问题。6.2 高度基准的坑EGM96与WGS84我提到过WPML里的高度模式字段很重要。在部分大疆机型的航线文件中高度模式默认使用EGM96大地水准面模型而不是飞机GPS给出的WGS84椭球高。EGM96更多的是“海拔高度”的概念更贴近真实海平面而GPS接收机算出来的是相对于WGS84椭球的高度。两者差值在不同地区可能达到二三十米甚至更多。所以当你的第三方平台把航线文件里的高度直接当成WGS84高度做地形分析时会差一大截。我的建议是解析到heightMode字段后先把它存起来后续做三维仿真或者与数字高程模型叠加时要么做高程转换要么至少提醒用户当前高度模式。不要想当然。还有一个特别容易踩的坑白天的风、气流会让气压计高度在飞行过程中发生漂移所以如果你把WPML里标称的高度当成绝对物理高度来做精确的避障计算肯定会出问题。航线文件里的高度只是任务计划值实际飞行高度受飞控传感器影响解析工具只能忠实反映计划不能代表实际。6.3 常见导入失败排查链路遇到DJI Pilot导入航线失败我一般按下面的链路排查检查KMZ内部文件名是否完全正确。必须是template.kml和waylines.wpml不能有额外路径大小写也要一致。检查两个文件编码是否为UTF-8开头有没有BOM。某些Windows记事本保存的UTF-8 BOM会导致XML解析器报错。检查waylines.wpml根节点是否带wpml命名空间没有命名空间基本上无法执行。检查wpml:missionConfig是否存在以及关键字段是否合理。比如finishAction、exitOnRCLost都不能缺。检查每个航点是否有Pointcoordinates坐标里是否有非数字字符。检查动作字段里的actionType是否是该机型支持的类型。给M300的航线塞了M3E才支持的相机变焦参数不报错才怪。最后再检查template.kml和waylines.wpml的航点数量、坐标是否一致。如果你是用程序批量生成航线文件建议在这套检查链路上写一个自动化校验脚本每次生成完KMZ先自检一遍再上传。我自己就把这套脚本放到了CI里每次更新航线生成逻辑后自动跑一轮省去了大量现场试飞时间。6.4 嵌入式环境下的解析注意点聊到“大疆A板”或者这类嵌入式主板上的航线文件解析我觉得有必要单独说两句。很多第三方吊舱、机载电脑、甚至自己做的“A板”会对KMZ做离线解析把航线转成飞控可执行的指令。这种场景下你的硬件资源往往没那么宽裕XML解析不能肆无忌惮地展开递归。我实际踩过的几个坑解析XML时内存占用过高。建议用Expat或者libxml2的流式解析不要一次性把整个WPML文档load成DOM树尤其是航线超过几百个航点、动作字段又多的时候。浮点精度问题。坐标值建议用double存储不要用float。一个float在小数点后第7位就开始丢精度换算到地面上可能偏了几米。字符串编码。嵌入式系统经常默认GBK或ASCII遇到带中文名称的航点可能乱码。解析时尽量统一转UTF-8。文件系统大小写。KMZ里文件名大小写不能想当然有的国外SD卡格式是FAT32大小写不敏感但有的Linux文件系统是大小写敏感的上传前先校验文件名完全匹配。7. 延伸讨论JS生成KMZ、硬件笔试常考点与航线文件的边界7.1 一道常见的硬件工程师笔试题很多公司招聘无人机方向硬件工程师时喜欢拿KMZ解析当笔试题因为它能把文件系统、ZIP解压、XML解析、坐标转换、内存管理串在一起。你如果能讲清楚template.kml和waylines.wpml的区别基本就赢了一半。题目往往会这样出“给定一个大疆航线KMZ请设计一个解析程序读取所有航点坐标和动作列表并转换成目标飞控的指令。”这道题表面考编程实际考的是你对“展示层”和“执行层”分离的理解。很多人一上来就只读template.kml认为拿到坐标就够了但真正完整的答案必须读waylines.wpml还要处理动作字段、命名空间、高度模式这些细节。如果应聘者能在答案里主动提出“template.kml无法提供速度与动作信息”说明他真的理解大疆航线文件的设计意图。7.2 航线文件不控制电机也不属于Pocket这类设备这个话题和“大疆电机”有关。有个误解是航线文件里可能藏着电机转速指令修改它就能改变飞行姿态。实际上完全没有。WPML里只有航点、速度、转向、云台、相机等任务级参数不会出现电机的PWM占空比、电机KV值这类东西。飞控收到航线后会自己规划轨迹、计算姿态、输出电机控制量。所以解析航线文件时不要试图去找电机控制参数找不到的。至于“大疆pocket”这类手持云台相机它压根没有飞行平台也没有飞控航线文件对它没有任何意义。航线文件天生是给飞行器或者说执行任务平台用的。你拿它去套其他设备方向就错了。7.3 我的个人建议研究大疆航线文件最靠谱的方法不是到处找现成的解析库而是自己先从官方工具导出一份最简单的航线比如两个航点、只拍一张照然后解压KMZ用文本编辑器把两个文件里的每一个标签都过一遍。你会发现很多字段的含义远没有网上说的那么玄乎字段名就是最好的注释。把这个基础打牢之后你再去看各种第三方解析库、在线KMZ生成器、自动任务生成系统就能很容易判断它们到底是用template.kml糊弄人还是真的把waylines.wpml处理到位了。最后再分享一个小技巧维护一份“字段对照表”特别有用。你可以用一个Excel或Markdown表记录每个机型导出的WPML版本、字段名、示例值、是否必填。我做了这份表之后后续做任何KMZ生成或者解析任务都只需要查表而不是反复翻原始文件。这样的积累比看十篇文档都实在。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →