Skip to content

Flight path analysys

Dongwon Lee edited this page Jul 11, 2018 · 1 revision

PSCS에서 기록한 GPS 데이터를 구글어스의 KML파일로 변환하는 python 을 알아보자

예제 코드는 여기에서 발췌하였다.

PSCS에서 기록한 csv로그 파일은 아래와 같다.

date,time,time_index,mode,longitude,latitude,altitude,numsat,speed,cource,bearing,distance,controlangle
90718,105851,563,1,127.10637,37.301155,81.8,12,0,166.32,251.2,3881.29,84.88
90718,105852,564,1,127.10637,37.301155,81.9,12,0,166.32,251.2,3881.29,84.88
90718,105853,565,1,127.10637,37.301155,81.9,12,0,166.32,251.2,3881.29,84.88
90718,105854,566,1,127.10637,37.301155,81.9,12,0,166.32,251.2,3881.29,84.88
90718,105855,567,1,127.10638,37.301155,82,12,0.01,166.32,251.2,3882.63,84.88
90718,105856,568,1,127.10638,37.301155,82.2,12,0.01,166.32,251.2,3882.63,84.88
90718,105857,569,1,127.10638,37.301151,82.3,12,0.02,166.32,251.21,3882.5,84.89
90718,105858,570,1,127.10638,37.301151,82.4,12,0.01,166.32,251.21,3882.5,84.89

1. KML root만들기

구글 어스의 KML 형태는 여기를 참고 하기 바란다

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
   <Document>
    내용....
    내용....
   </Document>
</kml>

파이선 라이브러중에 xml.dom.minidom 을 import 한다. DOM 형식에 대한 자세한 설명은 여기참고하기 바란다.

import xml.dom.minidom

우선 xml 전체 다큐먼트를 하나 만들고 그안에 하나씩 객체를 추가하는 방식을 사용한다.

kmlDoc = xml.dom.minidom.Document()

이제 kmlDoc 이라는 큰 밑그림이 생겼다.

kmlElement = kmlDoc.createElementNS('http://www.opengis.net/kml/2.2', 'kml')
kmlElement.setAttribute('xmlns','http://www.opengis.net/kml/2.2')
kmlElement = kmlDoc.appendChild(kmlElement)

맨처음 있는 kml 요소를 만들고 kmlDoc에 append 시킨다. 다음은 Document 요소 이다.

documentElement = kmlDoc.createElement('Document')
documentElement = kmlElement.appendChild(documentElement)

같은 방법으로 documentElement을 생성하고 이번에는 kmlElement에 append시킨다.

자 여기 까지 이해가 가는가?

이제는 csv를 읽고 row 마다 placemark를 append해주면 된다.

placemark 에 앞서 약간의 꾸미기 과정을 해보자

name 만들기

<name>Cansat Flight path</name>

kml의 이름이 나오게 한다.

 nameElement = kmlDoc.createElement('name')
 nameElement.appendChild(kmlDoc.createTextNode('Cansat Flight path'))
 documentElement.appendChild(nameElement)

아이콘 스타일 만들기

이 문구를 쓰지 않으면 엄청 큰 노랑 압정핀이 지도에 그려진다. 아이콘을 바꾸고 싶으면 아래 png 파일의 이름을 바꾸면 된다.

음.. 객체가 좀 많쿤... 그래도 찬찬히 하나씩 해보자

<Style id="hiker-icon">
 <IconStyle>
   <Icon>
     <href>http://maps.google.com/mapfiles/kml/pal4/icon49.png</href>
   </Icon>
   <hotSpot x="0" y=".5" xunits="fraction" yunits="fraction"/>
 </IconStyle>
</Style>

웬지 쉬운 에디터가 있을꺼 같다..

styleIdElement = kmlDoc.createElement('Style')
styleIdElement.setAttribute('id','hiker-icon')
documentElement.appendChild(styleIdElement)

iconStyleElement = kmlDoc.createElement('IconStyle')
styleIdElement.appendChild(iconStyleElement)

iconElement = kmlDoc.createElement('Icon')
iconStyleElement.appendChild(iconElement)

hrefElement = kmlDoc.createElement('href')
hrefElement.appendChild(kmlDoc.createTextNode('http://maps.google.com/mapfiles/kml/pal4/icon49.png'))
iconElement.appendChild(hrefElement)

hotSpotElement = kmlDoc.createElement('hotSpot')
hotSpotElement.setAttribute('x','0')
hotSpotElement.setAttribute('y','.5')
hotSpotElement.setAttribute('xunits','fraction')
hotSpotElement.setAttribute('yunits','fraction')
iconStyleElement.appendChild(hotSpotElement)

Placemark

여기가 메인 루프라 하겠다. 아래의 형태로 만들어 보다

<Placemark>
  <styleUrl>#hiker-icon</styleUrl>
  <Point>
    <coordinates>127.10637,37.301155,81.8</coordinates>
  </Point>
</Placemark>

placemark요소, styleUrl 요소, Point요소를 만들고 csv에서 위도,경도,고도를 읽어 보자

def extractCoord(row):
  # This extracts an address from a row and returns it as a string. This requires knowing
  # ahead of time what the columns are that hold the address information.
  return '%s,%s,%s' % (row['longitude'], row['latitude'], row['altitude'])

def createPlacemark(kmlDoc, row, order):
  # This creates a  element for a row of data.
  # A row is a dict.
  placemarkElement = kmlDoc.createElement('Placemark')
  
  #timeStampElement = kmlDoc.createElement('TimeStamp')
  #placemarkElement.appendChild(timeStampElement)
  
  styleUrlElement = kmlDoc.createElement('styleUrl')
  styleUrlElement.appendChild(kmlDoc.createTextNode('#hiker-icon'))
  placemarkElement.appendChild(styleUrlElement)
  
  pointElement = kmlDoc.createElement('Point')
  placemarkElement.appendChild(pointElement)
  
  coordinates = extractCoord(row)
  coorElement = kmlDoc.createElement('coordinates')
  coorElement.appendChild(kmlDoc.createTextNode(coordinates))
  pointElement.appendChild(coorElement)
  return placemarkElement

최종 파일을 여기에 올린다. csv 파일 python 파일

3차원 경로 표시

앞의 예제는 이동 경로를 표시 하는 방법이 이다. PSCS가 비행하는 3차원 경로를 보려면 새로운 kml을 만들어 보자

document 요소 안에 아래 요소를 추가 하자. 노란색 기둥과 녹색 기둥으로 표시된다.

<Style id="yellowLineGreenPoly">
   <LineStyle>
     <color>7f00ffff</color>
     <width>4</width>
   </LineStyle>
 <PolyStyle>
     <color>7f00ff00</color>
 </PolyStyle>
</Style> 
<Placemark>
  <name>Absolute Extruded</name>
  <description>Transparent green wall with yellow outlines</description>
  <styleUrl>#yellowLineGreenPoly</styleUrl>
  <LineString>
    <extrude>1</extrude>
    <tessellate>1</tessellate>
    <altitudeMode>absolute</altitudeMode>
    <coordinates> 127.0653457,37.2894706,162.2
    127.0653686,37.2894783,150.5
    127.0653991,37.2894821,140.4
    127.0654373,37.289505,131.2
    127.0654754,37.2895202,123.7
    127.0654983,37.2895202,118
    127.0655364,37.289505,113.3
    127.0655593,37.289463,111.2
    127.0655899,37.2894172,110.1
    127.065628,37.2893867,108.3
    127.0656661,37.2893524,107
    127.0657043,37.2893257,105.7
    127.0657577,37.2893066,104
    127.0657958,37.289299,102.7
    127.0658187,37.2893142,101
    127.0657958,37.2893142,99.1
    127.0659561,37.289257,72.3 </coordinates>
  </LineString> 
</Placemark>

파이선 코드는 아래와 같다 전체 코드는 여기를 참고하자

def createKML(csvReader, fileName, order):
  # This constructs the KML document from the CSV file.
  kmlDoc = xml.dom.minidom.Document()
  
  kmlElement = kmlDoc.createElementNS('http://www.opengis.net/kml/2.2', 'kml')
  kmlElement.setAttribute('xmlns','http://www.opengis.net/kml/2.2')
  kmlElement = kmlDoc.appendChild(kmlElement)
  documentElement = kmlDoc.createElement('Document')
  documentElement = kmlElement.appendChild(documentElement)
  
  nameElement = kmlDoc.createElement('name')
  nameElement.appendChild(kmlDoc.createTextNode('Cansat Flight 3D path'))
  documentElement.appendChild(nameElement)
  
  styleIdElement = kmlDoc.createElement('Style')
  styleIdElement.setAttribute('id',"yellowLineGreenPoly")
  documentElement.appendChild(styleIdElement)
  
  lineStyleElement = kmlDoc.createElement('LineStyle')
  styleIdElement.appendChild(lineStyleElement)
  
  colorElement = kmlDoc.createElement('color')
  colorElement.appendChild(kmlDoc.createTextNode('7f00ffff'))
  lineStyleElement.appendChild(colorElement)

  widthElement = kmlDoc.createElement('width')
  widthElement.appendChild(kmlDoc.createTextNode('4'))
  lineStyleElement.appendChild(widthElement)
  
  polyStyleElement = kmlDoc.createElement('PolyStyle')
  styleIdElement.appendChild(polyStyleElement)
  
  colorElement = kmlDoc.createElement('color')
  colorElement.appendChild(kmlDoc.createTextNode('7f00ff00'))
  polyStyleElement.appendChild(colorElement)  
 
    
  placemarkElement = kmlDoc.createElement('Placemark')
  documentElement.appendChild(placemarkElement)
  
  styleUrlElement = kmlDoc.createElement('styleUrl')
  styleUrlElement.appendChild(kmlDoc.createTextNode('#yellowLineGreenPoly'))
  placemarkElement.appendChild(styleUrlElement)  
  
  lineStringElement = kmlDoc.createElement('LineString')
  placemarkElement.appendChild(lineStringElement)  
  
  extrudeElement = kmlDoc.createElement('extrude')
  extrudeElement.appendChild(kmlDoc.createTextNode('1'))
  lineStringElement.appendChild(extrudeElement)   
  
  tessellateElement = kmlDoc.createElement('tessellate')
  tessellateElement.appendChild(kmlDoc.createTextNode('1'))
  lineStringElement.appendChild(tessellateElement) 
  
  altitudeModeElement = kmlDoc.createElement('altitudeMode')
  altitudeModeElement.appendChild(kmlDoc.createTextNode('absolute'))
  lineStringElement.appendChild(altitudeModeElement)   

  # Skip the header line.  
  csvReader.next()
  
  coordinatesElement = kmlDoc.createElement('coordinates')
  
  for row in csvReader:
    coordinatesElement.appendChild(kmlDoc.createTextNode(extractCoord(row)))
    
  lineStringElement.appendChild(coordinatesElement)   
  


  kmlFile = open(fileName, 'w')
  kmlFile.write(kmlDoc.toprettyxml('  ', newl = '\n', encoding = 'utf-8'))

아래 로그를 이용하여 구글 어스에서 직접 그려 보자

PSCS log파일

경로 kml

3D경로 kml

구글 어스에서 두개의 kml 파일을 함께 그리면 아래 처럼 3차원 비행 경로를 분석할수 있다.

Clone this wiki locally