From here:
https://www.movable-type.co.uk/scripts/latlong.html
Formula: θ = atan2( sin Δλ ⋅ cos φ2 , cos φ1 ⋅ sin φ2 − sin φ1 ⋅ cos φ2 ⋅ cos Δλ )
You don’t say how you get the lat and long into your system. I’m going to assume you have a sensor.gpsd
with a timestamp as the state, and lat/long as attributes.
Then we set up a trigger-based template sensor updated whenever that gpsd sensor changes (the from: null
ensures it triggers only when the state changes):
template:
- trigger:
- trigger: state
entity_id: sensor.gpsd
from: null
sensor:
- name: Bearing
unit_of_measurement: '°'
state: >
{% set lat1 = trigger.from_state.attributes.latitude * pi / 180 %}
{% set long1 = trigger.from_state.attributes.longitude * pi / 180 %}
{% set lat2 = trigger.to_state.attributes.latitude * pi / 180 %}
{% set long2 = trigger.to_state.attributes.longitude * pi / 180 %}
{% set y = sin(long2-long1) * cos(lat2) %}
{% set x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(long2-long1) %}
{% set r = atan2(y, x) %}
{{ (r * 180 / pi + 360) % 360 }}
That gives the initial bearing between the two points, although if you’re updating with any reasonable frequency, that’s a distinction that doesn’t matter.