大疆无人机航点飞行KMZ文件提取航点坐标

一、需要插件

复制代码
<!--        解析KMZ航线-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.4</version>
        </dependency>


        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

二、KMZ解压成KML

复制代码
package com.dji.sample.common.util;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;


import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

//将KMZ航线转成KML航线
public class KmzKml {
    public Document unzipKmzToKml() throws Exception, Exception {
        String strkmz="/home/ych/KmzKml/航点飞行测试.kmz";

        System.out.println("**********************     【KMZ转kml开始】kmz路径:       **********************\n"+ strkmz);

        File file = new File(strkmz);

        ZipFile zipFile = new ZipFile(file);

        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(file));
        InputStream inputStream = null;
        ZipEntry entry = null;
        Document doc = null;
        while ((entry = zipInputStream.getNextEntry()) != null) {
            String zipEntryName = entry.getName();
            //获取所需文件的节点
            if (zipEntryName.equals("wpmz/template.kml")) {

                inputStream = zipFile.getInputStream(entry);
                SAXReader reader = new SAXReader();
                doc = (Document) reader.read(inputStream);

                inputStream.close();
            }
        }
        zipFile.close();
        zipInputStream.close();
        return doc;
    }

}

三、KML提取航点坐标

复制代码
package com.dji.sample.common.util;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;


import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

//将KMZ航线转成KML航线
public class KmzKml {
    public Document unzipKmzToKml() throws Exception, Exception {
        String strkmz="/home/ych/KmzKml/航点飞行测试.kmz";

        System.out.println("**********************     【KMZ转kml开始】kmz路径:       **********************\n"+ strkmz);

        File file = new File(strkmz);

        ZipFile zipFile = new ZipFile(file);

        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(file));
        InputStream inputStream = null;
        ZipEntry entry = null;
        Document doc = null;
        while ((entry = zipInputStream.getNextEntry()) != null) {
            String zipEntryName = entry.getName();
            //获取所需文件的节点
            if (zipEntryName.equals("wpmz/template.kml")) {

                inputStream = zipFile.getInputStream(entry);
                SAXReader reader = new SAXReader();
                doc = (Document) reader.read(inputStream);

                inputStream.close();
            }
        }
        zipFile.close();
        zipInputStream.close();
        return doc;
    }

}

四、调用

复制代码
@PostMapping("${url.wayline.prefix}${url.wayline.version}/workspaces/{workspace_id}/waylines/{wayline_id}/kmzKml")
    public HttpResultResponse<?> Kmz() throws Exception {
        KmzKml kmz = new KmzKml();
        Document unzipKmzToKml = kmz.unzipKmzToKml();

        // 将dom4j 的document对象转换成String
        // String asXML = unzipKmzToKml.asXML();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        Date date = new Date();
        String fileName = sdf.format(date);
        String strkml = "/home/ych/KmzKml/航点飞行.kml";

        // 创建kml到本地
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(strkml),format);
        xmlWriter.write(unzipKmzToKml);
        xmlWriter.close();

        System.out.println("\n**********************     【KMZ转kml成功】kml路径:       **********************\n"+ strkml);

        return HttpResultResponse.success();
    }
    @GetMapping("${url.wayline.prefix}${url.wayline.version}/workspaces/{workspace_id}/waylines/{wayline_id}/singlePoint")
    public  HttpResultResponse<?> Kml() throws Exception {
        File file = new File("/home/ych/KmzKml/航点飞行.kml");
        InputStream in  = new FileInputStream(file);
        Kml kml = new Kml();
        Collection<? extends String> coordinatesList = kml.parseXmlWithDom4j(in);
        List<?>  list = (List)coordinatesList;
        System.out.println(list.get(3));

        System.out.println("获取到的坐标值:");
        for (String coordinates : coordinatesList) {
            System.out.println(coordinates);
        }


        return HttpResultResponse.success(list);
    }

五、效果

复制代码
获取到的坐标值:
[121.369754843606, 37.5227177120414]
[121.370733797755, 37.5233089872322]
[121.370402874547, 37.5243355293892]
[121.372488283707, 37.5240973025597]
[121.372337081214, 37.5227352183251]
[121.370980455301, 37.5213158608334]
[121.372248708559, 37.5224800846951]

六、航线文件解读

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.2">
<Document>

  <!-- Step 1: Implement File Creation Information -->
  <wpml:author>Name</wpml:author>
  <wpml:createTime>1637600807044</wpml:createTime>
  <wpml:updateTime>1637600875837</wpml:updateTime>
 
  <!-- Step 2: Setup Mission Configuration -->
  <wpml:missionConfig>
    <wpml:flyToWaylineMode>safely</wpml:flyToWaylineMode>
    <wpml:finishAction>goHome</wpml:finishAction>
    <wpml:exitOnRCLost>goContinue</wpml:exitOnRCLost>
    <wpml:executeRCLostAction>hover</wpml:executeRCLostAction>
    <wpml:takeOffSecurityHeight>20</wpml:takeOffSecurityHeight>
    <wpml:takeOffRefPoint>23.98057,115.987663,100</wpml:takeOffRefPoint>
    <wpml:takeOffRefPointAGLHeight>35</wpml:takeOffRefPointAGLHeight>
    <wpml:globalTransitionalSpeed>8</wpml:globalTransitionalSpeed>
    <wpml:droneInfo>
      <!-- Declare drone model with M30 -->
      <wpml:droneEnumValue>67</wpml:droneEnumValue>
      <wpml:droneSubEnumValue>0</wpml:droneSubEnumValue>
    </wpml:droneInfo>
    <wpml:payloadInfo>
      <!-- Declare payload model with M30 -->
      <wpml:payloadEnumValue>52</wpml:payloadEnumValue>
      <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
    </wpml:payloadInfo>
  </wpml:missionConfig>
 
  <!-- Step 3: Setup A Folder for Waypoint Template -->
  <Folder>
    <wpml:templateType>waypoint</wpml:templateType>
    <wpml:useGlobalTransitionalSpeed>0</wpml:useGlobalTransitionalSpeed>
    <wpml:templateId>0</wpml:templateId>
    <wpml:waylineCoordinateSysParam>
      <wpml:coordinateMode>WGS84</wpml:coordinateMode>
      <wpml:heightMode>EGM96</wpml:heightMode>
      <wpml:globalShootHeight>50</wpml:globalShootHeight>
      <wpml:positioningType>GPS</wpml:positioningType>
      <wpml:surfaceFollowModeEnable>1</wpml:surfaceFollowModeEnable>
      <wpml:surfaceRelativeHeight>100</wpml:surfaceRelativeHeight>
    </wpml:waylineCoordinateSysParam>
    <wpml:autoFlightSpeed>7</wpml:autoFlightSpeed>
    <wpml:gimbalPitchMode>usePointSetting</wpml:gimbalPitchMode>
    <wpml:globalWaypointHeadingParam>
      <wpml:waypointHeadingMode>followWayline</wpml:waypointHeadingMode>
      <wpml:waypointHeadingAngle>45</wpml:waypointHeadingAngle>
      <wpml:waypointPoiPoint>24.323345,116.324532,31.000000</wpml:waypointPoiPoint>
      <wpml:waypointHeadingPathMode>clockwise</wpml:waypointHeadingPathMode>
    </wpml:globalWaypointHeadingParam>
    <wpml:globalWaypointTurnMode>toPointAndStopWithDiscontinuityCurvature</wpml:globalWaypointTurnMode>
    <wpml:globalUseStraightLine>0</wpml:globalUseStraightLine>
    <Placemark>
      <Point>
        <!-- Fill longitude and latitude here -->
        <coordinates>
          longitude,latitude
        </coordinates>
      </Point>
      <wpml:index>0</wpml:index>
      <wpml:ellipsoidHeight>90.2</wpml:ellipsoidHeight>
      <wpml:height>100</wpml:height>
      <wpml:useGlobalHeight>1</wpml:useGlobalHeight>
      <wpml:useGlobalSpeed>1</wpml:useGlobalSpeed>
      <wpml:useGlobalHeadingParam>1</wpml:useGlobalHeadingParam>
      <wpml:useGlobalTurnParam>1</wpml:useGlobalTurnParam>
      <wpml:gimbalPitchAngle>0</wpml:gimbalPitchAngle>
    </Placemark>
    <Placemark>
      <Point>
        <!-- Fill longitude and latitude here -->
        <coordinates>
          longitude,latitude
        </coordinates>
      </Point>
      <wpml:index>1</wpml:index>
      <wpml:ellipsoidHeight>90.2</wpml:ellipsoidHeight>
      <wpml:height>100</wpml:height>
      <wpml:useGlobalHeight>1</wpml:useGlobalHeight>
      <wpml:useGlobalSpeed>1</wpml:useGlobalSpeed>
      <wpml:useGlobalHeadingParam>1</wpml:useGlobalHeadingParam>
      <wpml:useGlobalTurnParam>1</wpml:useGlobalTurnParam>
      <wpml:gimbalPitchAngle>0</wpml:gimbalPitchAngle>
      <!-- Declare action group for waypoint 1# -->
      <wpml:actionGroup>
        <wpml:actionGroupId>0</wpml:actionGroupId>
        <wpml:actionGroupStartIndex>1</wpml:actionGroupStartIndex>
        <wpml:actionGroupEndIndex>1</wpml:actionGroupEndIndex>
        <wpml:actionGroupMode>sequence</wpml:actionGroupMode>
        <wpml:actionTrigger>
          <wpml:actionTriggerType>reachPoint</wpml:actionTriggerType>
        </wpml:actionTrigger>
        <!-- Declare the 1st action: rotate gimbal -->
        <wpml:action>
          <wpml:actionId>0</wpml:actionId>
          <wpml:actionActuatorFunc>gimbalRotate</wpml:actionActuatorFunc>
          <wpml:actionActuatorFuncParam>
            <wpml:gimbalRotateMode>absoluteAngle</wpml:gimbalRotateMode>
            <wpml:gimbalPitchRotateEnable>0</wpml:gimbalPitchRotateEnable>
            <wpml:gimbalPitchRotateAngle>0</wpml:gimbalPitchRotateAngle>
            <wpml:gimbalRollRotateEnable>0</wpml:gimbalRollRotateEnable>
            <wpml:gimbalRollRotateAngle>0</wpml:gimbalRollRotateAngle>
            <wpml:gimbalYawRotateEnable>1</wpml:gimbalYawRotateEnable>
            <wpml:gimbalYawRotateAngle>30</wpml:gimbalYawRotateAngle>
            <wpml:gimbalRotateTimeEnable>0</wpml:gimbalRotateTimeEnable>
            <wpml:gimbalRotateTime>0</wpml:gimbalRotateTime>
            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
          </wpml:actionActuatorFuncParam>
        </wpml:action>
        <!-- Declare the 2nd action: take photo -->
        <wpml:action>
          <wpml:actionId>1</wpml:actionId>
          <wpml:actionActuatorFunc>takePhoto</wpml:actionActuatorFunc>
          <wpml:actionActuatorFuncParam>
            <wpml:fileSuffix>point1</wpml:fileSuffix>
            <wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
          </wpml:actionActuatorFuncParam>
        </wpml:action>
      </wpml:actionGroup>
    </Placemark>
  </Folder>
</Document>
</kml>

将航线里的<coordinates>标签检测到并读取值即可获得坐标,可以按照该思路获取其它类型的航线,再将坐标系转换即可将航线展示到前端。

相关推荐
面朝大海,春不暖,花不开22 分钟前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
得过且过的勇者y23 分钟前
Java安全点safepoint
java
夜晚回家1 小时前
「Java基本语法」代码格式与注释规范
java·开发语言
斯普信云原生组1 小时前
Docker构建自定义的镜像
java·spring cloud·docker
wangjinjin1801 小时前
使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理
java·spring boot·intellij-idea
wtg44521 小时前
使用 Rest-Assured 和 TestNG 进行购物车功能的 API 自动化测试
java
白宇横流学长2 小时前
基于SpringBoot实现的大创管理系统设计与实现【源码+文档】
java·spring boot·后端
fat house cat_2 小时前
【redis】线程IO模型
java·redis
stein_java3 小时前
springMVC-10验证及国际化
java·spring
weixin_478689763 小时前
C++ 对 C 的兼容性
java·c语言·c++