Search code examples
pythonpython-3.xgeolocationgeospatial

How to iterate between two geo locations with a certain speed in Python(3)


I want to simulate a movement on a real world map (spherical) and represent the actual position on (google|openStreet)maps.

I have an initial lat/long pair e.g. (51.506314, -0.088455) and want to move to e.g. (51.509359, -0.087221) on a certain speed by getting interpolated coordinates periodically.

Pseudocode for clarification:

loc_init = (51.509359, -0.087221)
loc_target = (51.509359, -0.087221)

move_path = Something.path(loc_init, loc_target, speed=50)

for loc in move_path.get_current_loc():
    map.move_to(loc)
    device.notify_new_loc(loc)
    ...
    time.sleep(1)

Retrieving the current interpolated position can happen in different ways e.g. calculating with a fixed refresh time (1 sec) or maybe running in a thread holding and calculating continuously new positions.

Unfortunately I never worked with geo data before and can't find something useful on the internet. Maybe there is already a module or an implementation doing that?


Solution

  • Solved my problem:

    Found a C++ library geographiclib which was ported to Python doing exactly what I was looking for. Example code to calculate a inverse geodesic line and get positions for a specific distance:

    from geographiclib.geodesic import Geodesic
    import math
    
    # define the WGS84 ellipsoid
    geod = Geodesic.WGS84
    
    loc_init = (51.501218, -0.093773)
    loc_target = (51.511020, -0.086563)
    
    g = geod.Inverse(loc_init[0], loc_init[1], loc_target[0], loc_target[1])
    l = geod.InverseLine(loc_init[0], loc_init[1], loc_target[0], loc_target[1])
    
    print ("The distance is {:.3f} m.".format(g['s12']))
    
    # interval in m for interpolated line between locations
    interval = 500
    step = int(math.ceil(l.s13 / interval))
    
    for i in range(step + 1):
        if i == 0:
            print ("distance latitude longitude azimuth")
        s = min(interval * i, l.s13)
        loc = l.Position(s, Geodesic.STANDARD | Geodesic.LONG_UNROLL)
        print ("{:.0f} {:.5f} {:.5f} {:.5f}".format(
            loc['s12'], loc['lat2'], loc['lon2'], loc['azi2']))
    

    Gives:

    The distance is 1199.958 m.
    distance latitude longitude azimuth
    0 51.50122 -0.09377 24.65388
    500 51.50530 -0.09077 24.65623
    1000 51.50939 -0.08776 24.65858
    1200 51.51102 -0.08656 24.65953