131 votes

Formule Haversine en Python (Relèvement et distance entre deux points GPS)

Problème

J'aimerais savoir comment obtenir le distance et relèvement entre 2 points GPS . J'ai fait des recherches sur la formule de l'haversine. Quelqu'un m'a dit que je pouvais aussi trouver le roulement en utilisant les mêmes données.

Modifier

Tout fonctionne bien mais le roulement ne fonctionne pas encore correctement. La sortie du relèvement est négative alors qu'elle devrait être comprise entre 0 et 360 degrés. Les données définies devraient faire en sorte que le relèvement horizontal 96.02166666666666 et l'est :

Start point: 53.32055555555556 , -1.7297222222222221   
Bearing:  96.02166666666666  
Distance: 2 km  
Destination point: 53.31861111111111, -1.6997222222222223  
Final bearing: 96.04555555555555

Voici mon nouveau code :

from math import *

Aaltitude = 2000
Oppsite  = 20000

lat1 = 53.32055555555556
lat2 = 53.31861111111111
lon1 = -1.7297222222222221
lon2 = -1.6997222222222223

lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
Base = 6371 * c

Bearing =atan2(cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon2-lon1), sin(lon2-lon1)*cos(lat2)) 

Bearing = degrees(Bearing)
print ""
print ""
print "--------------------"
print "Horizontal Distance:"
print Base
print "--------------------"
print "Bearing:"
print Bearing
print "--------------------"

Base2 = Base * 1000
distance = Base * 2 + Oppsite * 2 / 2
Caltitude = Oppsite - Aaltitude

a = Oppsite/Base
b = atan(a)
c = degrees(b)

distance = distance / 1000

print "The degree of vertical angle is:"
print c
print "--------------------"
print "The distance between the Balloon GPS and the Antenna GPS is:"
print distance
print "--------------------"

0 votes

L'implémentation de Python haversine peut être trouvée codecodex.com/wiki/ . Cependant, pour les calculs de courte distance, il existe des moyens très simples. Maintenant, quelle est votre distance maximale prévue ? Pouvez-vous obtenir vos coordonnées dans un système de coordonnées cartésiennes local ?

0 votes

Quelques implémentations en python : - code.activestate.com/recipes/ - platoscave.net/blog/2009/oct/5/

1 votes

James Dyson : avec des distances comme 15km, le cercle de créature ne compte pas. Ma suggestion : trouvez d'abord la solution avec les distances euclidiennes ! Cela vous donnera une solution fonctionnelle et plus tard, si vos distances sont beaucoup plus longues, adaptez votre application. Merci

280voto

Michael Dunn Points 2919

Voici une version Python :

from math import radians, cos, sin, asin, sqrt

def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r

13 votes

On pourrait utiliser la fonction math.radians() au lieu de multiplier par pi/180 - même effet, mais un peu plus auto-documenté.

1 votes

Merci beaucoup. Ma distance peut varier (horizontalement) entre 15 et 1 km.

1 votes

Corrigez-moi si je me trompe, mais ne pouvez-vous pas simplement dire : import math ?

16voto

Clay Points 132

La plupart de ces réponses consistent à "arrondir" le rayon de la terre. Si vous les comparez à d'autres calculateurs de distance (comme Geopy), ces fonctions seront fausses.

Cela fonctionne bien :

from math import radians, cos, sin, asin, sqrt

def haversine(lat1, lon1, lat2, lon2):

      R = 3959.87433 # this is in miles.  For Earth radius in kilometers use 6372.8 km

      dLat = radians(lat2 - lat1)
      dLon = radians(lon2 - lon1)
      lat1 = radians(lat1)
      lat2 = radians(lat2)

      a = sin(dLat/2)**2 + cos(lat1)*cos(lat2)*sin(dLon/2)**2
      c = 2*asin(sqrt(a))

      return R * c

# Usage
lon1 = -103.548851
lat1 = 32.0004311
lon2 = -103.6041946
lat2 = 33.374939

print(haversine(lat1, lon1, lat2, lon2))

2 votes

Celui-ci est beaucoup plus précis que les exemples ci-dessus !

1 votes

Cela ne tient pas compte de la variation de R. 6356,752 km aux pôles et 6378,137 km à l'équateur.

3 votes

Cette erreur est-elle vraiment importante pour votre application ? cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

10voto

Sergey Malyutin Points 128

Il existe également un implémentation vectorielle qui permet d'utiliser 4 tableaux numpy au lieu de valeurs scalaires pour les coordonnées :

def distance(s_lat, s_lng, e_lat, e_lng):

   # approximate radius of earth in km
   R = 6373.0

   s_lat = s_lat*np.pi/180.0                      
   s_lng = np.deg2rad(s_lng)     
   e_lat = np.deg2rad(e_lat)                       
   e_lng = np.deg2rad(e_lng)  

   d = np.sin((e_lat - s_lat)/2)**2 + np.cos(s_lat)*np.cos(e_lat) * np.sin((e_lng - s_lng)/2)**2

   return 2 * R * np.arcsin(np.sqrt(d))

6voto

Vamshi G Points 337

Vous pouvez essayer ce qui suit :

from haversine import haversine
haversine((45.7597, 4.8422),(48.8567, 2.3508), unit='mi')
243.71209416020253

0 votes

Comment l'utiliser dans une requête ORM de Django ?

5voto

Jon Anderson Points 88

Le calcul du roulement est incorrect, vous devez échanger les entrées avec atan2.

    bearing = atan2(sin(long2-long1)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(long2-long1))
    bearing = degrees(bearing)
    bearing = (bearing + 360) % 360

Vous obtiendrez ainsi le roulement correct.

0 votes

En fait, j'ai du mal à comprendre comment ces équations ont été dérivées alors que je suis en train de lire un article. Vous m'avez donné une indication : haversine formula C'est la première fois que j'entends ça, merci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X