Hello Fellow Yuneec Pilot!
Join our free Yuneec community and remove this annoying banner!
Sign up

Quick and dirty FlightLog to KML parser in Perl

Joined
Sep 6, 2016
Messages
3
Reaction score
7
Age
48
Use and modify as you see fit.
You need to copy the entire FlightLog directory from the ST16. It uses both the RemoteGPS and Telemetry files.

[EDIT] Fixed bug, improved KML output styling. Added example image from Google Earth.

log2kml.pl, code below.

Code:
#!perl.exe -W
#
# Quick and dirty flight log parser (V0.2)
# writes to KML file
#
# Minimal error checking!
#
# parses BOTH RemoteGPS and Telemetry
# calculates drone absolute altitude from RemoteGPS + Telemetry (I think this works)
#
# USAGE:
# log2kml [path to FlightLog dir] [log number]
#
# Examples:
# FlightLog folder is in the directory from wich you are running the script.
# log2kml . 15
#
# Flightlog folder is located at C:\Users\Me\Destop\FlightLog
# log2kml C:\Users\Me\Destop 26

use strict;
use warnings;

my @telTime;
my @telLoc;
my @telDir;

my @remTime;
my @remLoc;
my @remDir;

my %remAlt = ();

my $logPath   = $ARGV[0]; # path to location of FlightLog directory '.' for current, etc.
my $flightNum = $ARGV[1]; # flight number to process

my $telFile = sprintf("%s\\FlightLog\\Telemetry\\Telemetry_%05d.csv", $logPath, $flightNum);
my $remFile = sprintf("%s\\FlightLog\\RemoteGPS\\RemoteGPS_%05d.csv", $logPath, $flightNum);

open (TELFILE, $telFile) || die "Can't Open $telFile: $!\n";
my @TEL=<TELFILE>;
chomp @TEL;
shift @TEL;
close(TELFILE);

open (REMFILE, $remFile) || die "Can't Open $remFile: $!\n";
my @REM=<REMFILE>;
chomp @REM;
shift @REM;
close(REMFILE);

#    0   1   2   3        4     5     6
# date,lon,lat,alt,accuracy,speed,angle
foreach my $line (@REM) {
  my @tokens = split(/,/, $line);
  my @datetime = split(/ /, $tokens[0]);
  my $date = substr($datetime[0],0,4) . '-' . substr($datetime[0],4,2) . '-' . substr($datetime[0],6,2);
  my @time = split(/:./, $datetime[1]);
  push(@remTime, '<when>' . $date . 'T' . substr($datetime[1],0,8) . 'Z</when>');
  push(@remLoc, '<gx:coord>' . $tokens[1] . ' ' . $tokens[2] . ' ' . $tokens[3] . '</gx:coord>');
  push(@remDir, '<gx:angles>' . $tokens[6] . ' 0.0 0.0</gx:angles>');
  $remAlt{substr($datetime[1],0,8)} = $tokens[3];
}

#    0        1       2       3        4        5         6   7        8        9             10   11  12    13           14         15                   16     17         18           19           20       21
# date,fsk_rssi,voltage,current,altitude,latitude,longitude,tas,gps_used,fix_type,satellites_num,roll,yaw,pitch,motor_status,imu_status,press_compass_status,f_mode,gps_status,vehicle_type,error_flags1,gps_accH
my $sec = -1;
my $alt = 0;
foreach my $line (@TEL) {
  my @tokens = split(/,/, $line);
  if($tokens[10] >= 10) {
    my @datetime = split(/ /, $tokens[0]);
    my $date = substr($datetime[0],0,4) . '-' . substr($datetime[0],4,2) . '-' . substr($datetime[0],6,2);
    my @time = split(/:./, $datetime[1]);
    my $thisSec = $time[2];
    if($thisSec ne $sec) {
      if(exists $remAlt{substr($datetime[1],0,8)}) {
        $alt = $remAlt{substr($datetime[1],0,8)} + $tokens[4];     
      }
      push(@telTime, '<when>' . $date . 'T' . substr($datetime[1],0,8) . 'Z</when>');
      push(@telLoc, '<gx:coord>' . $tokens[6] . ' ' . $tokens[5] . ' ' . $alt . '</gx:coord>');
      push(@telDir, '<gx:angles>' . $tokens[12] . ' ' . $tokens[13] . ' ' . $tokens[11] . '</gx:angles>');
      $sec = $thisSec;
    }
  }
}

my $kmlFile = 'flight' . $flightNum . '.kml';
open (my $kml, ">", $kmlFile) || die "Can't Open $kmlFile: $!\n";

print $kml '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
print $kml '<kml xmlns="http://www.opengis.net/kml/2.2"' . "\n";
print $kml 'xmlns:gx="http://www.google.com/kml/ext/2.2">' . "\n";
print $kml '<Document>' . "\n";
print $kml '<Style id="aircraft">' . "\n";
print $kml '<IconStyle><scale>0.5</scale><Icon><href>http://maps.google.com/mapfiles/kml/shapes/airports.png</href></Icon><hotSpot x="0.5" y="0" xunits="fraction" yunits="fraction"/></IconStyle>' . "\n";
print $kml '<LineStyle><color>ffffff55</color><width>2</width></LineStyle>' . "\n";
print $kml '<PolyStyle><color>54ffff55</color></PolyStyle>' . "\n";
print $kml '</Style>' . "\n";
print $kml '<Style id="pilot">' . "\n";
print $kml '<IconStyle><scale>0.5</scale><Icon><href>http://maps.google.com/mapfiles/kml/shapes/track.png</href></Icon><hotSpot x="0.5" y="0" xunits="fraction" yunits="fraction"/></IconStyle>' . "\n";
print $kml '</Style>' . "\n";
print $kml '<Folder>' . "\n";
print $kml '<name>Flight Telemetry</name>' . "\n";
print $kml '<Placemark>' . "\n";
print $kml '<name>Typhoon H</name>' . "\n";
print $kml '<styleUrl>#aircraft</styleUrl>' . "\n";
print $kml '<gx:Track>' . "\n";
print $kml '<extrude>1</extrude>' . "\n";
print $kml '<altitudeMode>absolute</altitudeMode>' . "\n";
foreach my $time (@telTime) {
  print $kml $time . "\n";
}
foreach my $loc (@telLoc) {
  print $kml $loc . "\n";
}
foreach my $dir (@telDir) {
  print $kml $dir . "\n";
}
print $kml '</gx:Track>' . "\n";
print $kml '</Placemark>' . "\n";
print $kml '<Placemark>' . "\n";
print $kml '<name>Pilot</name>' . "\n";
print $kml '<styleUrl>#pilot</styleUrl>' . "\n";
print $kml '<gx:Track>' . "\n";
print $kml '<altitudeMode>clampToGround</altitudeMode>' . "\n";
foreach my $time (@remTime) {
  print $kml $time . "\n";
}
foreach my $loc (@remLoc) {
  print $kml $loc . "\n";
}
# direction of remote from GPS, so, only accurate when moving.
#foreach my $dir (@remDir) {
#  print $kml $dir . "\n";
#}
print $kml '</gx:Track>' . "\n";
print $kml '</Placemark>' . "\n";
print $kml '</Folder>' . "\n";
print $kml '</Document>' . "\n";
print $kml '</kml>' . "\n";
close $kml;

track.png
 
Last edited:
  • Like
Reactions: h-elsner

New Posts

Members online

Forum statistics

Threads
20,977
Messages
241,826
Members
27,376
Latest member
DHYradio