大疆无人机航点飞行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>标签检测到并读取值即可获得坐标,可以按照该思路获取其它类型的航线,再将坐标系转换即可将航线展示到前端。

相关推荐
火烧屁屁啦9 分钟前
【JavaEE进阶】初始Spring Web MVC
java·spring·java-ee
w_312345423 分钟前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
岁岁岁平安25 分钟前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA28 分钟前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
北辰浮光30 分钟前
[spring]XML配置文件标签
xml·spring
Q_192849990635 分钟前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
CYBEREXP20081 小时前
MacOS M3源代码编译Qt6.8.1
c++·qt·macos
张国荣家的弟弟1 小时前
【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
java·jar·bi
ZSYP-S1 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos1 小时前
C++----------函数的调用机制
java·c++·算法