Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions kml2g1000.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ def calcSpeed(fm, to, start, end):
dt = (end - start).total_seconds() / 3600.0 # hours
return round(dx / dt) if dt else 0

# Parse date time but do not crash if some entries have fractional seconds and others do not. E.g. ADSBExchange exports with fractional seconds
def parse_datetime(date_str):
# Try the version with fractional seconds first
try:
return datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S.%f")
except ValueError:
# Fall back to the version without fractional seconds
return datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")

# Converts a kml tracklog exported from flightaware.com to G1000 csv format.
def export(kml, folder=None):
if not folder:
Expand All @@ -38,10 +47,11 @@ def export(kml, folder=None):
print("Skipping " + fileName + " (already exists)")
return


# G1000 header, format, and trailing commas for data we do not set.
hdr = ' Lcl Date, Lcl Time, UTCOfst, AtvWpt, Latitude, Longitude, AltB, BaroA, AltMSL, OAT, IAS, GndSpd, VSpd, Pitch, Roll, LatAc, NormAc, HDG, TRK, volt1, FQtyL, FQtyR, E1 FFlow, E1 FPres, E1 OilT, E1 OilP, E1 MAP, E1 RPM, E1 CHT1, E1 CHT2, E1 CHT3, E1 CHT4, E1 EGT1, E1 EGT2, E1 EGT3, E1 EGT4, AltGPS, TAS, HSIS, CRS, NAV1, NAV2, COM1, COM2, HCDI, VCDI, WndSpd, WndDr, WptDst, WptBrg, MagVar, AfcsOn, RollM, PitchM, RollC, PichC, VSpdG, GPSfix, HAL, VAL, HPLwas, HPLfd, VPLwas'
fmt = '{date}, {time}, 00:00, , {lat: >12}, {lng: >12}, , , {alt: >7}, , , {gspd: >6}'
tail = ', , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , '
fmt = '{date},{time},00:00,,{lat: >12},{lng: >12},,,{alt: >7},,,{gspd: >6}'
tail = ',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'

tree = ET.parse(kml)
root = tree.getroot()
Expand All @@ -67,16 +77,24 @@ def export(kml, folder=None):
# This is a very rough estimate based on the reported breadcrumbs.
# FlightAware appears to collect actual data from ADS-B, but does not include it in the kml unfortuantely.
to = (float(lat), float(lng))
end = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S')
end = parse_datetime(date + ' ' + time)

# strip fractional sections such as exported from ADSBExchange, which is not compatible with ForeFlight
timenofraction = end.strftime('%H:%M:%S')

gspd = calcSpeed(fm, to, start, end) if fm and start else 0
fm = to
start = end

# FlightAware KLM altitude is in meters, while G1000 wants feet.
alt = round(float(alt) * 3.28084)

# round lat, long to 4 decimal places because ForeFlight will fail if more than 4 decimal places and ADSBExchange exports 6 decimal places
lat = round(float(lat), 4)
lng = round(float(lng), 4)

# Append data with trailing commas for unset values.
csv.append(fmt.format(date=date, time=time, lat=lat, lng=lng, alt=alt, gspd=gspd) + tail)
csv.append(fmt.format(date=date, time=timenofraction, lat=lat, lng=lng, alt=alt, gspd=gspd) + tail)

# Write file to disk.
with open(fileName, 'w') as f:
Expand Down