Post-traitement de données Géonaute

Temps de lecture estimé : 11 mn

Depuis 2016 ou 2017, j’ai une montre de sport. Comme beaucoup de monde, je m’en sers pour enregistrer mes sorties (de la course à pied au début, plutôt du vélo désormais, avec parfois des marches/randos plus ponctuellement). Cependant, la chaîne de traitement des données se fait uniquement avec des logiciels/services propriétaires. Dans cet article, je vais expliquer comment je m’y suis pris pour faire moi-même le post-traitement en partant directement des enregistrements.

La situation de base

J’ai une montre OnMove 120. Vue de loin, cette montre est une sorte de clé USB à laquelle est relié un capteur GPS. Pour chaque enregistrement, la montre enregistre différentes données (date, heure, positions GPS, etc.). Ces données sont rassemblées en 2 fichiers : OMH (OnMove Header) et OMD (OnMove Data). Puisqu’ils partagent les deux mêmes premières lettres, on utilise souvent OMx pour désigner le couple de fichiers.

Le traitement de ces données se fait d’abord avec le logiciel OnConnect. Lorsque la montre est branchée, celui-ci reconnaît les données présentes, propose quelques options supplémentaires (pour indiquer de quel type de sport il s’agit) et propose d’exporter les données directement vers le site Décathlon Coach. C’est sur ce site qu’on peut principalement interagir avec les données : observer son parcours, voir l’évolution de sa vitesse, comparer avec des sorties similaires, etc. Il y a aussi des fonctionnalités sociales mais je ne m’en sers pas assez pour pouvoir en parler.

Pourquoi je veux post-traiter moi-même les données ?

Je dirais qu’il y a trois motivations : technique, éthique et personnelle.

La première est une motivation technique. Depuis quelques temps, OnConnect ne marche plus sur mon ordinateur. Je ne sais pas pourquoi et c’est assez difficile de trouver de l’aide sur Internet (la montre et le logiciel sont anciens). La montre n’ayant pas de mode Bluetooth et le OnConnect étant le seul moyen de sortir les données, s’il ne marche pas alors elle devient inutile. De plus, OnConnect n’est disponible que sur Windows. Ayant récemment passé mon ordinateur sous Linux, c’est dommage de garder tout un OS et un dual boot juste pour sortir des données de sport.

La deuxième est une motivation éthique. Comme je l’ai dit plus haut, la chaîne de traitement est fortement contrôlée : il faut utiliser un logiciel spécifique pour sortir les données, et celui-ci est directement connecté au site de visualisation. C’est super (lorsque tout marche bien), mais ça laisse peu de liberté si l’on souhaite traiter les données autrement. Typiquement, je me retrouvais souvent à devoir uploader les données sur Décathlon Coach, les télécharger en GPX en local, puis les uploader sur un autre site qui m’allait mieux.

La dernière est une motivation personnelle. J’étais à la recherche d’un exercice de programmation pour pratiquer Python, Git et GitLab, les mouvements Vim, mais aussi ChatGPT, à propos duquel j’étais suspicieux et à qui je voulais donner une chance. J’aime beaucoup le traitement de données et c’était l’exercice parfait pour faire du parsing, du traitement, de la visualisation, de la sérialisation, etc.

Est-ce que d’autres personnes se sont déjà intéressées à ce problème ?

Il se trouve que oui ! Il y a un outil de référence qui s’appelle omx2gpx. J’en ai entendu parler pour la première fois en lisant cette publication sur un forum. Encore mieux, il y a un lien vers le dépôt du code source. L’outil vient décoder les fichiers OMH et OMD, et il propose quelques fonctionnalités supplémentaires telles que la détermination de l’élévation (grâce à l’API Google Maps) et la définition du point de départ avec des coordonnées GPS de son choix.

D’autres outils ont été construits autour d’omx2gpx. En réutilisation directe, on peut citer OnRunning Free qui propose une interface graphique simple pour convertir les données. Enfin, je suis tombé sur cet article qui s’inspire du code d’omx2gpx. Ce dernier article est très bien car il propose une implémentation Python, mais celle-ci porte uniquement sur le fichier OMH qui est le moins intéressant des deux.

J’ai testé omx2gpx, j’ai fait quelques tests et effectivement ça marche bien. Mais j’y vois plusieurs limites. Tout d’abord, c’est codé en C. C’est un bien meilleur langage que Python, mais je le maîtrise assez peu, donc si je voulais faire des modifications au code, ça serait difficile. Ensuite, il repose sur l’utilisation de l’API Google Maps pour l’élévation. Donc même s’il libère en partie des outils propriétaires, le diable se cache dans les détails. Enfin, si je télécharge un outil clé-en-main, l’exercice de programmation devient d’un coup beaucoup moins pertinent !

Comment je m’y suis pris pour résoudre le problème ?

Le premier défi a été de lire les données avec Python. Pour le fichier OMH, aucune difficulté, il suffit de récupérer directement le code publié sur GitHub. Le plus dur vient plutôt du traitement des OMD. C’est là que le code d’omx2gpx nous aide car il est suffisamment commenté pour comprendre la structure des fichiers. Dans le cas des OMD, l’information est codée sur des morceaux de 20 octets qui marchent par groupes de 3. Le dernier octet permet de les différencier : pour chaque groupe de 3 morceaux, les deux premiers terminent par 0xF1 et le troisième par 0xF2. Les deux premiers sont deux points de mesure, et le troisième doit être divisé en deux et chaque moitié se rapporte à l’un des morceaux 0xF1 du même groupe. Une fois qu’on a compris ça, il faut pouvoir séparer les octets correctement. Une fois de plus, omx2gpx nous aide en indiquant le type précis des données.

Aparté : là, je vous le résume en quelques phrases, mais en vrai rien que comprendre ça m’a pris beaucoup de temps. Je ne suis pas du tout familier avec le traitement des données binaires, et encore moins en C. C’est là que ChatGPT m’a bien aidé car j’ai pu demander des explications de code. En comprenant le code en C et en voyant comment était implémenté la fonction de traitement des OMH, j’ai pu comprendre ce qui était attendu pour pouvoir traiter les OMD.

À ce stade, je récupère des listes de nombres, et donc je reviens à des choses que je sais manipuler. J’ai commencé par stocker ces données sous forme de DataFrame. Cela permet une manipulation des données bien plus facile, que ça soit pour faire des calculs ou de l’affichage. J’ai fait quelques conversions pour remettre les données dans les unités habituelles. Et grâce au parsing l’OMH, j’ai aussi pu passer du temps relatif (en secondes depuis le lancement de l’enregistrement) au temps absolu.

Le défi suivant a été de retrouver les données d’élévation. Comme dit plus haut, j’aurais pu utiliser l’API de Google Maps comme c’est le cas dans omx2gpx. Mais puisque l’un des objectifs était de s’émanciper des solutions propriétaires, j’ai cherché d’autres solutions. Je me suis d’abord tourné vers Open Topo Data, notamment son API publique, mais il y avait des limitations sur le nombre de requêtes. J’ai aussi trouvé Open-Elevation qui, si je ne me trompe pas, est utilisé par OpenStreetMap. Là aussi, l’API publique avait des limitations, donc j’ai auto-hébergé la mienne. Le dernier ingrédient nécessaire était un jeu de données couvrant la région de mes enregistrements, ce que j’ai trouvé sur le site de la SRTM.

Le dernier défi était d’exporter les données dans un format standard. Celui auquel je suis le plus habitué est le format GPX, qui est dérivé du XML. Bonne nouvelle, Python dispose d’un module natif permettant de rédiger des XML, donc il suffisait juste de connaître les bons noms de balises. ChatGPT m’a aussi aidé à cette étape pour rédiger automatiquement la fonction.

Quels sont les résultats ?

Pour montrer ce que fait le code, je vais utiliser un enregistrement récent entre chez moi et des amis qui m’avaient invités à regarder l’Eurovision (et la douloureuse seconde place de Käärijä). Pour l’instant, je traite ces données pour sortir deux figures : la trace de mon parcours et la comparaison de ma vitesse.

Concernant la trace de mon parcours, il s’agit d’un scatter plot assez simple qui affiche chaque point enregistré. Après avoir implémenté la détermination de l’élévation, j’ai pu changer la couleur des points pour se représenter un peu plus les choses. On voit assez bien que j’habite en haut d’une petite colline et qu’à un moment je longe une voie d’eau. Même si la base de données SRTM n’est pas la plus à jour, on voit donc que les résultats sont cohérents.

Visualisation de la trace traitée par mon script

La seconde visualisation est également simple et montre l’évolution de l’altitude et de la vitesse en fonction du temps. Décathlon Coach la propose également, et j’imagine qu’elle est utilisée pour comprendre comment l’inclinaison influe sur la vitesse. On peut voir que j’atteins ma pointe de vitesse dès le départ (normal, je descends de la colline), puis que ma vitesse réduit progressivement. J’attribue ça à trois facteurs : l’entrée en ville, le fait d’avoir volontairement ralenti car j’avais peur d’arriver trop en avance, et la fatigue.

Évolution de la vitesse et de l’élévation en fonction du temps.

Sur cette dernière image, on peut voir que les données d’élévation ne sont pas parfaites. Je ne sais pas exactement comment est implémentée leur détermination, mais j’attribuerais ça à un problème d’échantillonnage spatial, probablement car le jeu de données est ancien.

Concernant la sortie des données en GPX, les fonctions rédigées par ChatGPT se sont avérées fonctionnelles (que ça soit sans ou avec l’utilisation du module natif xml). Et en important les fichiers dans mon application de cartes ou en ligne, je n’ai eu aucun souci, ce qui me laisse penser que tout s’est bien passé de ce côté-là également.

Qu’est-ce que j’en pense ?

Eh bien je dois dire que je suis satisfait ! Sur le plan technique, je suis content de pouvoir disposer d’une solution fonctionnelle qui permet de traiter, afficher et convertir les données de ma montre. C’était tout de même le but premier ! Maintenant, je ne crains plus les soucis d’OnConnect et je peux rester sur Linux !

Sur le plan éthique, j’ai fait de mon mieux pour utiliser des solutions moins propriétaires. Il y a sûrement des possibilités pour aller plus loin, mais s’affranchir d’OnConnect et des connexions à Google est déjà une victoire !

Enfin, sur le plan personnel, j’étais très content de mettre à l’épreuve ChatGPT pour tester ses capacités. D’ailleurs, je parle des cas réussis dans l’article, mais il y a aussi eu des fois où il proposait des solutions vraisemblables qui faisaient en fait appel à des fonctions inexistantes. J’étais aussi très content de pouvoir utiliser le plugin des mouvements Vim pour Spyder. J’ai clairement une marge de progression, mais il fallait bien démarrer quelque part !

Quelles sont les prochaines étapes ?

Je vois deux grandes directions pour la suite. Tout d’abord, il y a l’ajout de fonctionnalités supplémentaires. L’exemple typique qui me vient en écrivant ça est le calcul de la vitesse moyenne par exemple. Sur le plan de la visualisation, on pourrait imaginer un affichage de la trace sur un fond de carte.

Ensuite, il y a la partie refactoring qui entre en jeu. Pour l’instant, il s’agit juste d’un script qui appelle des fonctions les unes après les autres, mais on pourrait imaginer quelque chose de plus structuré à la manière des modules Python. Et dans la même veine, il y a également la publication du code !

Évidemment, il y a toujours des manières de faire plus ou de faire mieux. Mais ce soir j’estime que j’arrive à un état suffisamment stable pour pouvoir en parler. J’espère que ça vous aura intéressé et que ça vous permettra aussi de traiter vos données OMx sans utiliser de solutions propriétaires !

Laisser un commentaire

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *