Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Calculate bearing between two lat/long

I am attempting to calculate the bearing between two lat/long.

I don't have a question regarding the function/formula per se,

provided:

def get_bearing(lat1, long1, lat2, long2):
    dLon = (long2 - long1)

    y = math.sin(dLon) * math.cos(lat2)
    x = math.cos(lat1) * math.sin(lat2) - math.sin(lat1) * math.cos(lat2) * math.cos(dLon)

    brng = math.atan2(y, x)

    brng = np.rad2deg(brng)

    return brng

the problem is that the result isn't what is expected.

The intended usage of the function returns the bearing between two lat/long pairs in a (very long) list i.e.

    lat1 = path[int(len(path) * location / 1000)][0]
    lat2 = path[int(len(path) * location / 1000) + 1][0]
    lng1 = path[int(len(path) * location / 1000)][1]
    lng2 = path[int(len(path) * location / 1000) + 1][1]

The bearing result then alters the view orientation of the plot where bearing can assume a value in the range [-180, 180]. Ideally, the result would appear such that the line formed between lat1, lng1 and lat2, lng2 is perfectly "vertical" in the plot (lat/lon annotations are switched in plot), see below

enter image description here

enter image description here

I am hoping that someone might be able to deduce the problem from the bearing returned from the function and what the expected bearing should be. A few instances below:

Current Location: 30.07134 -97.23076
Next in path: 30.0709 -97.22907
Calculated Bearing: 88.39967863143139
Expected Bearing: ~-70.67

Current Location: 29.91581 -96.85068
Next in path: 29.91556 -96.85021
Calculated Bearing: 118.9170342272798
Expected Bearing: ~122.67

Current Location: 29.69419 -96.53487
Next in path: 29.69432 -96.53466
Calculated Bearing 141.0271357781952
Expected Bearing: ~56

Current Location: 29.77357 -96.07924
Next in path: 29.77349 -96.07876
Calculated Bearing 165.24612555483893
Expected Bearing: ~104

Happy to provide additional information, thanks in advance for any/all help.

like image 338
Sterling Butters Avatar asked Feb 25 '19 20:02

Sterling Butters


People also ask

How do you find the bearing between two latitude and longitude?

latitude of second point = la2 = asin(sin la1 * cos Ad + cos la1 * sin Ad * cos θ), and. longitude of second point = lo2 = lo1 + atan2(sin θ * sin Ad * cos la1 , cos Ad – sin la1 * sin la2)

How do you calculate bearings in navigation?

How to Calculate Bearing. A bearing angle is determined by measuring the clockwise angle between two points. Measure clockwise from the northern point on a compass to the point at which the point in question rests. If the angle is between north and east on the compass, it'll measure between 0 degrees and 90 degrees.

How do you calculate bearings?

Bearings are angles, measured clockwise from north. To measure a bearing, we must first know which direction is north. This north direction is usually provided in the maths exam question. We then measure the required angle in a clockwise direction.


2 Answers

Have you considered using pyproj to do the calculations instead of rolling your own?:

import pyproj
geodesic = pyproj.Geod(ellps='WGS84')
fwd_azimuth,back_azimuth,distance = geodesic.inv(long1, lat1, long2, lat2)

In this example fwd_azimuth is the bearing you are after and back_azimuth is inverse bearing (going the opposite direction).

I used WGS84 here, so you would need to replace with correct coordinate system, and need to rewrite ensure lat/long are correct type of coordinates for geodesic.inv(). But using a well-tested, existing geo-spatial lib will likely save you a lot of hair pulling.

like image 99
J. Taylor Avatar answered Sep 30 '22 06:09

J. Taylor


Ended up changing the function:

from geographiclib.geodesic import Geodesic
...
def get_bearing(lat1, lat2, long1, long2):
    brng = Geodesic.WGS84.Inverse(lat1, long1, lat2, long2)['azi1']
    return brng
like image 27
Sterling Butters Avatar answered Sep 30 '22 07:09

Sterling Butters