航迹点导入大疆无人机

学习到了如何通过经纬度和海拔设置大疆无人机航迹飞行,记录如下:

1. 使用的软件是:DJI Pilot
2.通过航迹点(经纬度以及海拔)csv文件转为kml文件。(KML文件主要用于描述地球上的地理特征,如点、线、多边形、图层、图标等,以及与这些特征相关的属性信息。KML文件可以包含地理坐标、颜色、高度、图标等元素,使其能够用于在地图上呈现丰富的地理信息。)步骤如下:

参考链接(参考代码)

 准备一些航迹点,保存为csv文件,格式如下:
pointnamelonlatheightheadinggimbalspeedturnmodeactions_sequence
point1114.355730.527968180-13AUTOH1000*SHOOT
point2114.355730.527968160-13AUTOH1000*SHOOT
point3114.355730.527958140-13AUTOH1000*SHOOT
point4114.355830.527948120-13AUTOH1000*SHOOT
point5114.355830.527938100-13AUTOH1000*SHOOT
point6114.355830.52791880-13AUTOH1000*SHOOT
point7114.355830.5279860-13AUTOH1000*SHOOT
point8114.355730.52788840-13AUTOH1000*SHOOT

其中列分别是:点名经度维度海拔高度偏航角(注意所使用的大疆软件偏航角是否可以为小数,DJI Pilot软件不支持偏航角为小数,如果偏航角是小数在DJI Pilot中为0!),云台俯仰角无人机飞行的速度转弯模式(可能的值包括"MANUAL"、"AUTO"),在航迹点执行的动作序列(可以没有任何动作,也可以有一个或多个动作。例如表格中动作为悬停1s并拍照)

  • H1000 => 悬停 1000ms = 1s
  • 拍摄 => 拍照
  • G40 =>万向架 a -40°
  • REC => 开始视频录制
  • STOPREC => 停止录像
  • A-170 => 将飞机转向 -170 。航向的范围为 [-180, 180] 度,其中 0 代表正北。
3. 利用Python脚本将csv转化为kml文件
from string import Template
import csv
import sys
import argparse
import xml.etree.ElementTree as ET
import simplekml
from pyproj import CRS, Transformer
import pandas as pd

# csv to kml
def generate_kml(csv_file, output_file, on_finish='hover'):
    CSV_HEADER = False
    ON_FINISH = "Hover" if on_finish == 'hover' else "GoHome"

    XML_string = """<?xml version="1.0" encoding="UTF-8"?>
    <kml xmlns="http://www.opengis.net/kml/2.2">
      <Document xmlns="">
        <name>chambon_small</name>
        <open>1</open>
        <ExtendedData xmlns:mis="www.dji.com">
          <mis:type>Waypoint</mis:type>
          <mis:stationType>0</mis:stationType>
        </ExtendedData>
        <Style id="waylineGreenPoly">
          <LineStyle>
            <color>FF0AEE8B</color>
            <width>6</width>
          </LineStyle>
        </Style>
        <Style id="waypointStyle">
          <IconStyle>
            <Icon>
              <href>https://cdnen.dji-flighthub.com/static/app/images/point.png</href>
            </Icon>
          </IconStyle>
        </Style>
        <Folder>
          <name>Waypoints</name>
          <description>Waypoints in the Mission.</description>\n"""

    all_coordinates = ""
    waypoint_number = 1

    waypoint_start = Template("""      <Placemark>
            <name>Waypoint$waypoint_number</name>
            <visibility>1</visibility>
            <description>Waypoint</description>
            <styleUrl>#waypointStyle</styleUrl>
            <ExtendedData xmlns:mis="www.dji.com">
              <mis:useWaylineAltitude>false</mis:useWaylineAltitude>
              <mis:heading>$heading</mis:heading>
              <mis:turnMode>$turnmode</mis:turnMode>
              <mis:gimbalPitch>$gimbal</mis:gimbalPitch>
              <mis:useWaylineSpeed>false</mis:useWaylineSpeed>
              <mis:speed>$speed</mis:speed>
              <mis:useWaylineHeadingMode>true</mis:useWaylineHeadingMode>
              <mis:useWaylinePointType>true</mis:useWaylinePointType>
              <mis:pointType>LineStop</mis:pointType>
              <mis:cornerRadius>0.2</mis:cornerRadius>""")

    waypoint_end = Template("""
            </ExtendedData>
            <Point>
              <altitudeMode>relativeToGround</altitudeMode>
              <coordinates>$lon,$lat,$height</coordinates>
            </Point>
          </Placemark>""")
    hover_template = Template("""
              <mis:actions param="$length" accuracy="0" cameraIndex="0" payloadType="0" payloadIndex="0">Hovering</mis:actions>""")
    shoot_template = Template("""
              <mis:actions param="0" accuracy="0" cameraIndex="0" payloadType="0" payloadIndex="0">ShootPhoto</mis:actions>""")
    gimbal_template = Template("""
              <mis:actions param="$gimbal_angle" accuracy="1" cameraIndex="0" payloadType="0" payloadIndex="0">GimbalPitch</mis:actions>""")
    aircraftyaw_template = Template("""
              <mis:actions param="$aircraftyaw" accuracy="0" cameraIndex="0" payloadType="0" payloadIndex="0">AircraftYaw</mis:actions>""")
    record_template = Template("""
              <mis:actions param="0" accuracy="0" cameraIndex="0" payloadType="0" payloadIndex="0">StartRecording</mis:actions>""")
    stoprecord_template = Template("""
              <mis:actions param="0" accuracy="0" cameraIndex="0" payloadType="0" payloadIndex="0">StopRecording</mis:actions>""")

    all_coordinates_template = Template("$lon,$lat,$height")
    xml_end = Template("""    </Folder>
        <Placemark>
          <name>Wayline</name>
          <description>Wayline</description>
          <visibility>1</visibility>
          <ExtendedData xmlns:mis="www.dji.com">
            <mis:altitude>50.0</mis:altitude>
            <mis:autoFlightSpeed>5.0</mis:autoFlightSpeed>
            <mis:actionOnFinish>$ON_FINISH</mis:actionOnFinish>
            <mis:headingMode>UsePointSetting</mis:headingMode>
            <mis:gimbalPitchMode>UsePointSetting</mis:gimbalPitchMode>
            <mis:powerSaveMode>false</mis:powerSaveMode>
            <mis:waypointType>LineStop</mis:waypointType>
            <mis:droneInfo>
              <mis:droneType>COMMON</mis:droneType>
              <mis:advanceSettings>false</mis:advanceSettings>
              <mis:droneCameras/>
              <mis:droneHeight>
                <mis:useAbsolute>false</mis:useAbsolute>
                <mis:hasTakeoffHeight>false</mis:hasTakeoffHeight>
                <mis:takeoffHeight>0.0</mis:takeoffHeight>
              </mis:droneHeight>
            </mis:droneInfo>
          </ExtendedData>
          <styleUrl>#waylineGreenPoly</styleUrl>
          <LineString>
            <tessellate>1</tessellate>
            <altitudeMode>relativeToGround</altitudeMode>
            <coordinates>$all_coordinates</coordinates>
          </LineString>
        </Placemark>
      </Document>
    </kml>""")

    with open(csv_file, newline='') as csvfile:
        if csv.Sniffer().has_header(csvfile.read(1024)):
            CSV_HEADER = True
        csvfile.seek(0)
        dialect = csv.Sniffer().sniff(csvfile.read(1024))
        csvfile.seek(0)
        csv_lines = csv.reader(csvfile, dialect)
        if CSV_HEADER:
            next(csv_lines, None)  # skip the headers

        for row in csv_lines:
            if row:
                name, lon, lat, height, heading, gimbal, speed, turnmode, actions_sequence = row

                if lon[0] == '_':
                    lon = lon[1:]
                if lat[0] == '_':
                    lat = lat[1:]

                if (float(speed) > 15) or (float(speed) <= 0):
                    sys.exit('speed should be >0 or <=15 m/s for {}'.format(name))
                if '.' not in speed:
                    speed = speed+'.0'

                if '.' not in gimbal:
                    gimbal = gimbal+'.0'

                if turnmode == 'AUTO':
                    turnmode = 'Auto'
                elif turnmode == 'C':
                    turnmode = 'Clockwise'
                elif turnmode == 'CC':
                    turnmode = 'Counterclockwise'
                else:
                    sys.exit('turnmode should be AUTO, C, or CC for {}'.format(name))

                XML_string += waypoint_start.substitute(
                    turnmode=turnmode, waypoint_number=waypoint_number, speed=speed, heading=heading, gimbal=gimbal)

                # Actions decoding
                if actions_sequence:
                    action_list = actions_sequence.split('*')
                    for action in action_list:
                        if action == 'SHOOT':
                            XML_string += shoot_template.substitute()
                        elif action == 'REC':
                            XML_string += record_template.substitute()
                        elif action == 'STOPREC':
                            XML_string += stoprecord_template.substitute()
                        # Gimbal orientation
                        elif action[0] == 'G':
                            XML_string += gimbal_template.substitute(
                                gimbal_angle=action[1:])
                        # Aircraft orientation
                        elif action[0] == 'A':
                            XML_string += aircraftyaw_template.substitute(
                                aircraftyaw=action[1:])
                        elif action[0] == 'H':
                            if float(action[1:]) < 500:
                                sys.exit(
                                    'Hover length is in ms and should be >500  for {}'.format(name))
                            XML_string += hover_template.substitute(
                                length=action[1:])

                XML_string += "\n" + \
                    waypoint_end.substitute(lon=lon, lat=lat,
                                            height=height,)+"\n"

                all_coordinates += all_coordinates_template.substitute(
                    lon=lon, lat=lat, height=height)+" "
            waypoint_number += 1
    # remove last space from coordinates string
    all_coordinates = all_coordinates[:-1]
    XML_string += xml_end.substitute(
        all_coordinates=all_coordinates, ON_FINISH=ON_FINISH)

    with open(output_file, 'w') as output_file:
        output_file.write(XML_string)

#分割csv
def split_csv(input_file, chunk_size=99):
    # 读取原始CSV文件
    df = pd.read_csv(input_file)

    # 获取总行数
    total_rows = len(df)

    # 计算分割后的文件数
    num_files = (total_rows + chunk_size - 1) // chunk_size
    
    filenames = []
    # 分割数据并保存为新的CSV文件
    for i in range(num_files):
        start_idx = i * chunk_size
        end_idx = min((i + 1) * chunk_size, total_rows)

        # 生成新文件名
        output_file = f"{input_file.replace('.csv', '')}_{i + 1}.csv"

        filenames.append(output_file)

        # 写入分割后的数据到新文件
        df.iloc[start_idx:end_idx].to_csv(output_file, index=False)

    return filenames


def main():  
    Split = True
    input_csv_filename = 'kml.csv'  # 替换为输入 CSV 文件名
    output_kml_filename = 'kml.kml'  # 替换为输出 KML 文件名

    #是否分割
    if Split:
            filenames = split_csv(input_csv_filename,99)
            for i, file in enumerate(filenames, start=1):
                generate_kml(file, f"{output_kml_filename.replace('.kml', '')}_{i}.kml")
    else:
        generate_kml(input_csv_filename, output_kml_filename)  #csv转kml


if __name__ == '__main__':
    main()


将输入的csv文件进行修改,以及是否进行分割(DJI Pilot中每次飞行不可多于99个点所以我进行了切割)。 

4. kml文件制作完成后可导入到大疆的无人机软件中或者Google Earth中查看,例如:

 导入到大疆无人机控制软件中后即可进行飞行!注意不同软件可能有不同限制,例如DJI Pilot中每次飞行不可多于99个点且相邻航迹点不可过近,并且偏航角只能是整数。

### 回答1: 雷达航迹迹融合是指将两种或多种不同的雷达信号(如气象雷达和空管雷达)采集的航迹迹信息进行合并、分析和处理,从而获得更完整和准确的目标信息。而 MATLAB是一种非常优秀的科学计算软件,可用于数据分析、图像处理、数学建模等领域。在雷达航迹迹融合方面,MATLAB可以被用于以下几个方面: 1. 数据处理: MATLAB可以用于导入和处理雷达信号数据。可以通过编写程序,实现数据的滤波、分割、格式转换等操作。 2. 融合算法: MATLAB也是一种很好的算法开发和测试平台,可以编写各种融合算法。比如基于Kalman滤波的航迹预测和迹跟踪算法、基于多源信息的航迹迹融合算法等。 3. 可视化呈现:MATLAB可以将分析结果通过绘图、图表等方式呈现出来,可视化显示雷达目标航迹迹的位置、速度等信息。 总之,通过使用MATLAB的数据处理、算法开发和可视化呈现功能,可以有效地对雷达航迹迹融合进行分析和处理,提高数据的准确性和可用性。 ### 回答2: 雷达航迹迹融合是指将多个雷达观测到的目标信息进行整合和融合,得到更为准确、可靠的目标航迹信息。Matlab是一种非常常用的数学计算软件工具,可以用于雷达航迹迹融合的处理和分析。 在雷达航迹迹融合中,可以使用多种算法和模型进行处理。常见的算法包括最小二乘法、卡尔曼滤波、粒子滤波等等。这些算法可以将多个雷达观测得到的目标信息进行整合和修正,降低误判率和漏报率,得到更加准确的目标航迹信息。 Matlab提供了丰富的数学计算和分析工具,可以方便地实现这些算法并进行结果可视化和分析。例如,使用Matlab可以进行雷达观测数据的数据预处理、滤波、目标检测、目标跟踪等步骤,最终得到精确的航迹信息。 总之,雷达航迹迹融合是提高雷达目标探测和跟踪精度的重要技术手段,而Matlab作为一个强大的数学计算软件工具,可以方便地实现航迹迹融合的处理和分析,为实现高精度的雷达目标跟踪和探测打下坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值