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:
The main cause of this has to do with how the Garmin unit itself logs data.
Table of Contents
Track Segments
As a refresher, GPX files are XML files which store track data in the following tree:
- <gpx> (root of the GPX file)
- <trk> (track)
- <trkseg> (track segment)
- <trkpt> (trackpoint)
- <trkseg> (track segment)
- <trk> (track)
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.
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.
-
If I’m having the Garmin navigate me along a route and the route ends (because I reached a destination and decided to keep driving, or because I manually cancelled navigation), then the unit will end the current track segment and start a new one.
-
The Garmin unit sometimes starts new track segments when it’s running its rerouting algorithm, either because I missed a turn or because it’s trying to see if there’s a better route around traffic.
-
If I lose GPS signal entirely for more than a few seconds (for example, driving through a tunnel), then the Garmin will end a track segment with the last known point, and start a new track once it has signal again.
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.
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.