Calcul de distances
Afin de pouvoir évaluer des distances, puis des vitesses à partir des coordonnées
GPS contenues dans un fichier GPX, nous allons nous intéresser aux fonctions mathématiques,
notamment trigonométriques, du module math
.
Ce chapitre sera aussi l'occasion d'aborder la création de fonctions au sens informatique.
Le module math
Ce module est préinstallé avec Python, donc pas besoin d'opération particulière pour l'utiliser. Parmi les fonctions les plus courantes, on peut citer :
Fonction | Description |
---|---|
floor(x) |
plus grand entier inférieur à x |
ceil(x) |
plus petit entier supétieur à x |
fabs(x) |
valeur absolue de x |
sqrt(x) |
racine carrée de x |
pow(x,y) |
x à la puissance y |
degrees(x) |
conversion de l'angle x des radians en degrés |
radians(x) |
conversion de l'angle x des degrés en radians |
cos(x) |
cosinus de l'angle x exprimé en radians |
sin(x) |
sinus de l'angle x exprimé en radians |
tan(x) |
tangente de l'angle x exprimé en radians |
acos(x) |
arc cosinus de x , le résultat est exprimé en radians |
asin(x) |
arc sinus de x , le résultat est exprimé en radians |
atan(x) |
arc tangente de x , le résultat est exprimé en radians |
atan2(y,x) |
atan(y/x) |
from math import *
# Calcul de l'hypoténuse d'un triangle rectangle
a = 3
b = 4
c = sqrt(a**2 + b**2)
Définition de fonctions
Nous avons vu que nous pouvions utiliser des modules en Python pour
accéder à de nouvelles fonctions. Mais il est aussi possible de créer
ses propres fonctions à l'aide de la clause def
.
from math import *
# Définition de la fonction distance
def distance(x1, y1, z1, x2, y2, z2):
dx = x2 - x1
dy = y2 - y1
dz = z2 - z1
return sqrt( dx*dx + dy*dy + dz*dz )
# Utilisation de la fonction distance
d = distance(0, 0, 0.5, 1, 2, -4.5)
Les valeurs entre parenthèses, séparées par une virgule, qui suivent le nom de la fonction sont ses paramètres : ils sont utilisés comme des variables locales au sein de la fonction.
Exercice
Écrivez un script gpsutils.py
au sein duquel vous définirez
une fonction great_circle_distance(lat1, lon1, lat2, lon2)
qui
calcule la distance orthodromique entre deux points de coordoonées polaires
(lat1
,lon1
) et (lat2
,lon2
)
en utilisant la formule
de Vincenty.
from math import *
#
# Rayon de la Terre au niveau de l'équateur (en mètres)
# a = 6378137
#
# Rayon de la Terre au niveau des pôles (en mètres)
# b = 6356752
#
# Rayon moyen de la Terre (en mètres)
# R = (2*a+b)/3 = 6371009
#
def great_circle_distance(lat1, lon1, lat2, lon2):
lat1 = radians(lat1)
lat2 = radians(lat2)
dLon = radians(fabs(lon2-lon1))
cosLat1 = cos(lat1)
sinLat1 = sin(lat1)
cosLat2 = cos(lat2)
sinLat2 = sin(lat2)
cosDLon = cos(dLon)
sinDLon = sin(dLon)
A = cosLat2*sinDLon
B = cosLat1*sinLat2 - sinLat1*cosLat2*cosDLon
return 6371009 * atan2(sqrt(A*A + B*B),
sinLat1*sinLat2 + cosLat1*cosLat2*cosDLon)
Pour utliser cette nouvelle fonction dans un autre script Python, nous pouvons l'importer comme un module :
from gpsutils import *
d = great_circle_distance(49.5, 4.9, 48, 7.12)
Le module geopy
Même si la formule de Vincenty est sophistiquée, elle repose sur l'hypothèse que la Terre est une sphère parfaite alors qu'en réalité, elle a la forme d'un ellipsoïde légèrement écrasé au niveau des pôles. Pour une estimation plus précise de la distance entre deux points sur la surface du globe, il convient d'utiliser la distance géodésique.
Si ce n'est pas déjà fait, vous devez installer ce module dans un terminal (invite de commandes sous Windows) en tapant la commande suivante :
Windows :
pip.exe install geopy
macOS ou Linux :
pip3 install geopy
Le module distance
de geopy
propose des fonctions pour calculer les distances
orthodromiques et géodésiques entre deux points du globe à partir de leurs coordonnées polaires.
from geopy import distance as dst
paris = (48.864716, 2.349014)
lisbon = (38.736946, -9.142685)
print('PARIS - LISBONNE\n')
print('Distance orthodromique :', dst.great_circle(paris, lisbon).km, 'km')
print('Distance géodésique :', dst.geodesic(paris, lisbon).km, 'km')
PARIS - LISBONNE
Distance orthodromique : 1452.2743880698056 km
Distance géodésique : 1453.1714413569523 km
Exercice
Complétez le script gpxplorer.py
en ajoutant une colonne distance
au DataFrame
qui contiendra,
après parcours de l'arborescence XML, les distances cumulées le long du parcours.
from bs4 import BeautifulSoup as bs
import pandas as pd
from geopy import distance as dst
df = pd.DataFrame([], columns = [ 'datetime', 'latitude', 'longitude', 'elevation', 'distance' ])
# Chargement du fichier GPX
content = open('RATJ2012-21km-herve.schely.gpx')
# Construction de l'arborescnce
root = bs(content, features='xml')
# Remplissage du DataFrame
k = 0
for point in root.find_all('trkpt'):
df.loc[k, 'datetime'] = point.find('time').string
df.loc[k, 'latitude'] = float(point['lat'])
df.loc[k, 'longitude'] = float(point['lon'])
df.loc[k, 'elevation'] = float(point.find('ele').string)
k = k + 1
# Calcul des distances cumulées
df.loc[0, 'distance'] = 0
for k in df.index[1:]:
p1 = (df['latitude'][k-1], df['longitude'][k-1])
p2 = (df['latitude'][k], df['longitude'][k])
df.loc[k, 'distance'] = df.loc[k-1, 'distance'] + dst.geodesic(p1, p2).m
print('Distance parcourue :', round(df['distance'].iloc[-1]), 'm')
Félicitations, il semble que rien ne vous arrête ! Penchons-nous maintenant sur la gestion du temps afin d'enrichir notre script avec le calcul de la vitesse moyenne par exemple. On se donne rendez-vous au chapitre suivant dans quelques dixièmes de secondes...