Le stockage de traces GPS se fait principalement avec deux types de fichiers : le KML, soutenu principalement par Google, et le GPX, le plus répandu dans les applications spécialisées. Je n’ai aucune préférence particulière pour l’un où l’autre des formats, que je trouve tous deux acceptable (ouverts, bien documentés, répandus, et relativement « lisibles » en mode texte), mais selon les outils qu’on utilise, on se retrouve parfois avec un type, parfois avec l’autre… Et il faut donc pratiquer quelques conversions…
En ce moment, je fais pas mal de randonnées. Mon « processus » classique est de préparer mon trajet sur Google Maps, que je trouve bien pratique pour cet usage, puis d’exporter la trace en KML pour ensuite la convertir en GPX et la charger dans My Trails. Au retour, nouveau passage sur Google Maps pour adapter la trace au parcours effectivement réalisé (je préfère ça plutôt que de sortir le GPX relevé par mon smartphone, moins propre à cause des imprécisions des mesures), nouvel export en KML, reconversion en GPX, puis import dans VisuGPX pour pouvoir afficher la carte et le profil sur mon blog perso.
On trouve facilement en ligne des outils de conversion, mais j’ai quand même eu envie de faire mon propre convertisseur, histoire d’avoir un truc autonome, que je peux même exécuter directement sur mon smartphone via Android Terminal Emulator.
Voici à quoi ressemble un fichier KML extrait de Google Maps :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.2"> <Document> <name>Lacs Robert</name> <description><![CDATA[]]></description> <Style id="style2"> <LineStyle> <color>73FF0000</color> <width>5</width> </LineStyle> </Style> <Style id="style3"> <LineStyle> <color>73FF0000</color> <width>5</width> </LineStyle> </Style> <Style id="style1"> <LineStyle> <color>73FF0000</color> <width>5</width> </LineStyle> </Style> <Placemark> <name>Montée</name> <description><![CDATA[]]></description> <styleUrl>#style2</styleUrl> <LineString> <tessellate>1</tessellate> <coordinates> 5.871020,45.154591,0.000000 5.871220,45.154732,0.000000 5.872250,45.155029,0.000000 </coordinates> </LineString> </Placemark> <Placemark> <name>Descente</name> <description><![CDATA[]]></description> <styleUrl>#style1</styleUrl> <LineString> <tessellate>1</tessellate> <coordinates> 5.916540,45.130680,0.000000 5.915900,45.130619,0.000000 5.915630,45.130562,0.000000 </coordinates> </LineString> </Placemark> </Document> </kml> |
Et le GPX correspondant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?xml version="1.0" encoding="UTF-8"?> <gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="kml2gpx.sed"> <name>Lacs Robert</name> <desc><![CDATA[]]></desc> <trk> <name>Montée</name> <desc><![CDATA[]]></desc> <trkseg> <trkpt lat="45.154591" lon="5.871020"><ele>0.000000</ele></trkpt> <trkpt lat="45.154732" lon="5.871220"><ele>0.000000</ele></trkpt> <trkpt lat="45.155029" lon="5.872250"><ele>0.000000</ele></trkpt> </trkseg> </trk> <trk> <name>Descente</name> <desc><![CDATA[]]></desc> <trkseg> <trkpt lat="45.130680" lon="5.916540"><ele>0.000000</ele></trkpt> <trkpt lat="45.130619" lon="5.915900"><ele>0.000000</ele></trkpt> <trkpt lat="45.130562" lon="5.915630"><ele>0.000000</ele></trkpt> </trkseg> </trk> </gpx> |
On a donc dans les deux cas du XML, avec une structure relativement simple. Le fichier KML contient un Document, contenant un Placemark pour chaque ligne tracée dans Google Maps, le Placemark contenant une ligne (LigneString) qui consiste essentiellement en un gros pavé de texte dans une balise coordinates, contenant des triplets longitude,lattitude,altitude séparés par un retour à la ligne (l’altitude est laissée à 0 par Google Maps).
Du côté du GPX, c’est même un peu plus simple. Le niveau Document n’existe pas, on trouve directement des traces (trk), composées chacune de segments (trkseg), qui sont eux même une liste de points (trkpt) dotés d’une latitude, d’une longitude et d’une altitude.
Du coup, même pas besoin de parser proprement le XML, les structures sont suffisamment proches pour pouvoir faire un petit script « quick & dirty » réalisant cette conversion uniquement à coup de commandes sed 🙂
On commence par le plus simple, c’est-à-dire supprimer les balises ouvrantes et fermantes Document et coordinates.
1 2 |
/<\/\?Document>/ d /<\/\?coordinates>/ d |
Il faut également supprimer les balises Style, tessellate et styleUrl, ainsi que leur contenu. Il y a peut-être des équivalents à ces balises en GPX, mais je n’en ai pas besoin, donc je n’ai pas cherché plus loin…
1 2 3 |
/<Style/,/\/Style>/ d /<tessellate>.*<\/tessellate>/ d /<styleUrl>.*<\/styleUrl>/ d |
Ensuite, on remplace les balises de début et de fin de fichier :
1 2 |
s|<kml[^>]*>|<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" version="1.1" creator="kml2gpx.sed">|g s|</kml|</gpx|g |
Puis on transforme les description en desc, les Placemark en trk et les LineString en trkseg :
1 2 3 |
s|<\(/\?\)description|<\1desc|g s|<\(/\?\)Placemark|<\1trk|g s|<\(/\?\)LineString|<\1trkseg|g |
Enfin, on termine en créant les points. Pour ce faire, on cherche toutes les lignes correspondant à un triplet de flottants pour les décomposer et insérer les valeurs dans un trkpt :
1 |
s|\([0-9.]\+\),\([0-9.]\+\),\([0-9.]\+\)|<trkpt lat="\2" lon="\1"><ele>\3</ele></trkpt>|g |
Bien que l’altitude ne soit jamais renseignée dans les fichiers produits par Google Maps, je l’ai quand même embarquée dans le script, dès fois que…
Et voilà ! Il n’y a plus qu’à regrouper toutes ces commandes dans un fichier kml2gpx.sed.
Pour faire une conversion, il n’y a alors plus qu’à ouvrir un terminal (sous Windows, vous pouvez utiliser Cygwin par exemple) et à taper cette commande pour convertir un fichier :
1 |
sed -f <chemin kml2gpx.sed> <chemin fichier kml> > <chemin fichier gpx> |
Bon par contre comme on ne fait pas un vrai parsing XML du fichier source, ça va être très sensible au format du fichier KML en entrée. Ça marche bien avec les fichiers KML tels qu’ils sont produits actuellement avec Google Maps, mais des ajustements seront peut-être nécessaires plus tard, ou pour un fichier KML provenant d’un autre outils.
Notez également que certains outils produisent des traces KML dans un format différent, avec des éléments <gx:Track>, qui ne sont pas supportés par ce petit script sed.