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() |