Aller au contenu principal

Informatique · Seconde · 5 min de lecture

Lire une position GPS dans une trame NMEA

Un récepteur GPS fournit sa position sous forme de trames texte normalisées NMEA 0183, champs séparés par des virgules ; dans une trame GGA, la latitude est écrite ddmm.mmm (deux chiffres de degrés, puis les minutes avec leur partie décimale) suivie de N ou S, la longitude dddmm.mmm (trois chiffres de degrés) suivie de E ou W ; un dernier champ, après « * », est une somme de contrôle ; conversion en degrés décimaux : degrés + minutes / 60, avec un signe négatif au sud et à l'ouest.

Chapitre du programme : Sciences numériques et technologie

Bloc 1 sur 7 · Comprendre

Comprendre : une ligne de texte, des champs

Un récepteur GPS transmet sa position sous forme de trames de texte normalisées par le protocole NMEA 0183. Chaque trame commence par le caractère « dollar » (omis dans les affichages de cette leçon), suivi d'un identifiant, puis de champs séparés par des virgules. Elle se termine par « * » et une somme de contrôle de deux caractères.

Voici une trame de type GGA (position) :

GPGGA,123519,4851.200,N,00221.000,E,1,08,0.9,35.0,M,46.9,M,,*78
Tableau : Champ, Valeur, Signification
ChampValeurSignification
1123519heure : 12 h 35 min 19 s, en temps universel (UTC)
24851.200latitude, format ddmm.mmm
3Nnord (S : sud)
400221.000longitude, format dddmm.mmm
5Eest (W : ouest)
6 et suivants1, 08, 0.9, 35.0, M…qualité, nombre de satellites, précision, altitude en mètres…

La latitude 4851.200 se lit : les deux premiers chiffres sont les degrés (48), la suite est un nombre de minutes (51,200). La longitude 00221.000 a trois chiffres de degrés (002) puis les minutes (21,000).

Bloc 2 sur 7 · Approfondir

Approfondir : degrés décimaux et somme de contrôle

Conversion en degrés décimaux. Un degré vaut 60 minutes : valeur = degrés + minutes / 60. Au sud et à l'ouest, la valeur est négative.

Pour la trame ci-dessus : 48 + 51,2 / 60 ≈ 48,8533 et 2 + 21 / 60 = 2,35.

Vérification par programme (facultative). Dans l'extrait ci-dessous, trame.split(",") découpe la trame à chaque virgule et donne la liste des champs (champs[0] est GPGGA, champs[2] la latitude) ; champs[2][:2] désigne les deux premiers caractères du champ et champs[2][2:] tous les suivants ; int et float transforment ces textes en nombre entier et en nombre à virgule ; round(lat, 4) arrondit au dix-millième.

trame = "GPGGA,123519,4851.200,N,00221.000,E,1,08,0.9,35.0,M,46.9,M,,*78"
champs = trame.split(",")
print(champs[1], champs[2], champs[3], champs[4], champs[5])
lat = int(champs[2][:2]) + float(champs[2][2:]) / 60
lon = int(champs[4][:3]) + float(champs[4][3:]) / 60
print(round(lat, 4), round(lon, 4))
123519 4851.200 N 00221.000 E
48.8533 2.35

Somme de contrôle. Elle permet au destinataire de détecter une trame abîmée pendant la transmission. On combine par ou exclusif les codes de tous les caractères situés entre le « dollar » et « * », et on écrit le résultat en hexadécimal sur deux chiffres. Dans l'extrait (facultatif), ord(c) donne le code du caractère c, ^ est l'opérateur ou exclusif de Python, et format(x, "02X") écrit x en hexadécimal sur deux chiffres. Si le calcul ne redonne pas les deux caractères reçus, la trame a été altérée : on ne s'y fie pas.

corps = "GPGGA,123519,4851.200,N,00221.000,E,1,08,0.9,35.0,M,46.9,M,,"
x = 0
for c in corps:
    x = x ^ ord(c)
print(format(x, "02X"))
78

On retrouve bien le 78 écrit après « * ».

Bloc 3 sur 7 · Exemple

Exemple guidé : une position au sud et à l'ouest

Énoncé. Un récepteur envoie la trame suivante. Donner la latitude et la longitude en degrés décimaux, arrondies au dix-millième.

GPGGA,081530,3352.128,S,07400.360,W,1,07,1.1,12.0,M,30.2,M,,*7D

Méthode.

  1. Latitude : champ 3352.128, suivi de S. Degrés : 33 ; minutes : 52,128. 33 + 52,128 / 60 = 33,8688. Au sud : −33,8688.
  2. Longitude : champ 07400.360, suivi de W. Degrés : 074 (trois chiffres) ; minutes : 00,360. 74 + 0,36 / 60 = 74,0060. À l'ouest : −74,0060.
trame = "GPGGA,081530,3352.128,S,07400.360,W,1,07,1.1,12.0,M,30.2,M,,*7D"
champs = trame.split(",")
lat = int(champs[2][:2]) + float(champs[2][2:]) / 60
lon = int(champs[4][:3]) + float(champs[4][3:]) / 60
if champs[3] == "S":
    lat = -lat
if champs[5] == "W":
    lon = -lon
print(round(lat, 4), round(lon, 4))
-33.8688 -74.006

Dans ce programme, if champs[3] == "S": change le signe de la latitude au sud, et de même pour W. Python n'affiche pas le zéro final : −74,006 et −74,0060 sont la même valeur.

Bloc 4 sur 7 · Visualiser

Voir : découper les champs de position

Tableau : Champ, Découpage, Degrés, Minutes, Calcul, Lettre, Degrés décimaux
ChampDécoupageDegrésMinutesCalculLettreDegrés décimaux
4851.200dd + mm.mmm4851,20048 + 51,2 / 60N48,8533
00221.000ddd + mm.mmm221,0002 + 21 / 60E2,3500
3352.128dd + mm.mmm3352,12833 + 52,128 / 60S−33,8688
07400.360ddd + mm.mmm740,36074 + 0,36 / 60W−74,0060

Continuez sur votre lancée

Vous avez découvert l’essentiel et un exemple. Retrouvez la suite du cours et les points à retenir, puis passez à l’entraînement guidé dans votre compte.

  • Les formules et les repères à retenir
  • Les erreurs fréquentes expliquées
  • Un exercice avec des aides et sa correction

L’accès gratuit comprend les cours et exercices de votre niveau choisi.

Sources

  • BO spécial n°1 du 22 janvier 2019 — programme de sciences numériques et technologie de seconde générale et technologique, annexe (https://cache.media.education.gouv.fr/file/SP1-MEN-22-1-2019/08/5/spe641_annexe_1063085.pdf) — thème « Localisation, cartographie et mobilité », protocole NMEA 0183
  • NMEA 0183, Standard for Interfacing Marine Electronic Devices, National Marine Electronics Association — phrase GGA, somme de contrôle

Vous pensez avoir trouvé une erreur dans cette leçon ? Signalez-la par e-mail.

Explorer les autres cours

Accès rapide