A Python script for generating KML with timestamps from Pixhawk logs.
See the script for a few comments.
A Python script for generating KML with timestamps from Pixhawk logs.
See the script for a few comments.
#!/usr/bin/env python | |
# Generate KML from a Pixhawk log. Includes timestamps so that a | |
# Google Earth time slider is available. Also include any data you | |
# want. Using the Elevation Profile, you can plot this data over | |
# time within Google Earth. | |
# Reads 'iris.log' and writes 'iris.kml'. | |
import csv | |
from datetime import datetime | |
gps_epoch_ms = 315964800 | |
def unix_time(week,ms): | |
return gps_epoch_ms + ms/1000.0 + (week * 7 * 24 * 60 * 60) | |
def ms_iso(ms): | |
return datetime.fromtimestamp(ms).isoformat() | |
inFilename = "iris.log" | |
out = open('iris.kml', 'w') | |
out.write("<?xml version='1.0' encoding='UTF-8'?>\n") | |
out.write("<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n") | |
out.write("<Document>\n") | |
out.write(" <Schema id=\"schema\">\n") | |
out.write(" <gx:SimpleArrayField name=\"gps_alt\" type=\"float\">\n") | |
out.write(" <displayName>GPS Alt</displayName>\n") | |
out.write(" </gx:SimpleArrayField>\n") | |
out.write(" <gx:SimpleArrayField name=\"ahr_alt\" type=\"float\">\n") | |
out.write(" <displayName>AHR Alt</displayName>\n") | |
out.write(" </gx:SimpleArrayField>\n") | |
out.write(" </Schema>\n") | |
out.write(" <Folder>\n") | |
out.write(" <name>" + inFilename + "</name>\n") | |
out.write(" <Placemark>\n") | |
out.write(" <gx:Track>\n") | |
out.write(" <altitudeMode>absolute</altitudeMode>\n") | |
# out.write(" <altitudeMode>relativeToGround</altitudeMode>\n") | |
# gx:Track wants its time stamps before is coordinates. Really | |
# strange. Rather than keeping lots of data in memory, we make | |
# multiple passes over the file. We won't run out of memory. Due to | |
# page caching, shouldn't be that slow, either. | |
# Emit timestamps and find min baro. | |
min_baro = -1 | |
with open(inFilename) as input: | |
data = csv.reader(input, delimiter = ',') | |
for row in data: | |
if len(row) == 0: | |
continue | |
if row[0] == 'BARO': | |
baro = float(row[3]) | |
if min_baro < 0 or baro < min_baro: | |
min_baro = baro | |
continue | |
if row[0] == 'GPS': | |
ms = int(row[2]) | |
week = int(row[3]) | |
iso = ms_iso(unix_time(week,ms)) | |
out.write(" <when>" + iso + "</when>\n") | |
# Emit GPS coordinates along with latest baro | |
with open(inFilename) as input: | |
data = csv.reader(input, delimiter = ',') | |
rel_baro = 0 | |
for row in data: | |
if len(row) == 0: | |
continue | |
if row[0] == 'BARO': | |
rel_baro = (float(row[3]) - min_baro)/10.0 | |
continue | |
if row[0] == 'GPS': | |
# Which altitude do we want to report here? | |
# Originally I was debugging a mini-fly-away. | |
baro_alt = rel_baro | |
gps_alt = row[9] | |
# If using gps_alt, use altitudeMode: absolute instead of | |
# relativeToGround. | |
out.write(" <gx:coord>" + str(row[7]) + "," + str(row[6]) + "," + str(gps_alt) + "</gx:coord>\n") | |
# Emit data associated with each point. | |
out.write(" <ExtendedData>\n") | |
with open(inFilename) as input: | |
data = csv.reader(input, delimiter = ',') | |
out.write(" <SchemaData schemaUrl=\"#gps_alt\">\n") | |
out.write(" <gx:SimpleArrayData name=\"GPS Alt\">\n") | |
for row in data: | |
if len(row) == 0: | |
continue | |
if row[0] == 'GPS': | |
gps_alt = row[9] | |
out.write(" <gx:value>" + str(gps_alt) + "</gx:value>\n") | |
out.write(" </gx:SimpleArrayData>\n") | |
out.write(" </SchemaData>\n") | |
with open(inFilename) as input: | |
data = csv.reader(input, delimiter = ',') | |
out.write(" <SchemaData schemaUrl=\"#ahr_alt\">\n") | |
out.write(" <gx:SimpleArrayData name=\"AHR Alt\">\n") | |
ahr_alt = 0 | |
for row in data: | |
if len(row) == 0: | |
continue | |
if row[0] == 'AHR2': | |
ahr_alt = row[5] | |
if row[0] == 'GPS': | |
out.write(" <gx:value>" + str(ahr_alt) + "</gx:value>\n") | |
out.write(" </gx:SimpleArrayData>\n") | |
out.write(" </SchemaData>\n") | |
out.write(" </ExtendedData>\n") | |
out.write(" </gx:Track>\n") | |
out.write(" </Placemark>\n") | |
out.write(" </Folder>\n") | |
out.write("</Document>\n") | |
out.write("</kml>\n") | |
out.close() |