Driving Log Version 2.1: Track Gap Fix

I’ve been using my KML/KMZ driving log storage for about a year now, and it’s generally worked really well for me. I can use a single script to import GPX files from my Garmin GPS unit; it handles merging new tracks with existing tracks without duplication, generating a human-readable KML file to act as my canonical driving log storage, and generating a compressed KMZ file for me to open on portable devices.

However, one issue that I haven’t solved is that the GPX data I’m importing often shows gaps on the map:

A Google Earth map, showing a driving log line with two visible gaps in it.

Gaps in the driving log

The main cause of this has to do with how the Garmin unit itself logs data.

Track Segments

As a refresher, GPX files are XML files which store track data in the following tree:

So as I’m driving along, the Garmin unit is appending trackpoints to the most recent track segment of the most recent track. When I import the Garmin’s GPX file into my KML driving log, I simply create a KML <LineString> for each GPX <trkseg> (in any <track>), using the <trkpt> elements as coordinates.

A collection of trackpoints can be connected to show the path I took on a map. All trackpoints in a track segment can be connected to show the path I took. However, if one track segment were to end in the middle of a drive, followed immediately by a new track segment, there would be a small gap in the path—the final trackpoint of the first segment would not be connected to the first trackpoint of the next segment.

Diagram showing a track with six track segments. A line connects all trackpoints within each segment, leaving a gap in the line between segments.

Splitting a drive into multiple track segments results in gaps in the driving log (shown here by an orange line). Some track segments even have just a single trackpoint, leading to an even bigger gap since two or more trackpoints are required to create a line.

Normally, this splitting of the tracks is a good thing. If I stop driving for a while, I probably want to start a new track segment. I especially want to create a new track segment if the Garmin is going to be moved while it’s off. For example, if I turn it off in an airport parking lot, pack it in my bag, and fly with it to a new destination to put in a rental car, then I don’t want to connect the trackpoints on either end with a straight line clear across the country. Even locally, I don’t have my Garmin running in my car 100% of the time (there’s no point in running the Garmin for local trips where all the roads are already logged), so I don’t need a bunch of straight lines running across town.

The problem I run into is that turning the car (and Garmin) off isn’t the only time that it starts a new track segment.

The same Google Earth map with two gaps, but with trackpoints shown as well.

The same driving log map as above, overlaying the track points on my path. I reached a destination, creating one gap in the data. I then started a new route but immediately realized I had the wrong destination, so I manually stopped the route, creating a second gap.

Track Segment Merging Concerns

For a lot of these paths with gaps, the correct thing to do would be to merge two or more GPX <trkseg> elements into a single KML <LineString> element. However, just merging the track segments isn’t as simple as it sounds.

I needed to come up with a solution that would still allow me to keep track of all which track segments were already in my driving log data–otherwise, so that I could make sure that I didn’t accidentally import a track segment that was already in my driving data.

Secondly, I wouldn’t be able to automatically decide which track segments to merge and which to leave separate. While I could have potentially put some sort of rules in place on whether or not to merge (e.g. the two segments are less than a certain number of seconds apart and a certain distance apart), there would be too many edge cases driving false positives and false negatives no matter what rules I put in place. So I needed a way to manually designate which segments should be merged together.

KML Folder Solution

As discussed in my prior post, I have a KML file as my official driving log data store, and I also export a compressed KMZ file. Up until now, these two files have been essentially identical; the latter has been just a zipped copy of the former, but they both have had the same XML layout.

But there’s no reason they necessarily have to have the same layout; I could store information in the canonical KML file that could be used to process the output KMZ file in a certain way. Specifically, I could store all of the unmerged <LineString> elements in the canonical KML file to keep track of which <trkseg> elements were already imported, while also indicating in that KML file which of the <LineString> elements should be merged together. Then, when I created the output KMZ file, I could use that information to merge <LineString> elements appropriately as I exported them.

I decided to accomplish this by using KML <Folder> elements.

Diagram showing two groups: a canonical KML file, and an output KMZ file. The canonical KML file has a root Document with two Placemarks and a Folder under it, and the Folder has three of its own Placemarks under it. The output KML file has only Placemarks under the root Document, but one of the Placemarks is made up from a merge of the three Placemarks that were under the Folder in the canonical KML file.

Before this update, the KML file stored all <LineString> elements in Placemark elements under the root Document. Now, I can create a <Folder> in the KML file, and put two or more Placemark elements in it. If I do that, then all <LineString> elements in the Placemark elements in a particular folder will be merged when my script creates the output KMZ file.

Screenshot of Google Earth, showing some Placemarks in a Folder

Grouping several consecutive driving track segments into a folder.

The same Google Earth map, but with no gaps.

The output KMZ file with the track segments connected, leaving no gaps.