Here’s the intent script I wrote for my own install (as a tool for the LLM to use) you should be able to adapt the math:
bearing_to_target:
description: >
"Returns the distance (in meters) and bearing from zone.home to a target location's GPS coordinates.
Test Target, SAT - San Antonio International Airport...
example: >
```json
{
'lat': '29.522664576',
'lon': '-98.469831454'
}
```"
parameters:
lat: # the latitude you want to query example: '29.522664576'
lon: # the longitude you want to query example: '-98.469831454'
action: []
speech:
text: >
{%-if (lat == '') or (lon == '') -%}
ERROR: {% if lat == '' -%}Latitude{%- else %}Longitude{%- endif %} is missing
{%-else -%}
{%- set current_lat = state_attr('zone.home', 'latitude') | float -%}
{%- set current_lon = state_attr('zone.home', 'longitude') | float -%}
{%- set target_lat = lat | float -%}
{%- set target_lon = lon | float -%}
{%- set rad = 0.017453292519943295 -%}
{%- set current_lat_rad= (current_lat * rad) | float -%}
{%- set current_lon_rad= (current_lon * rad) | float -%}
{%- set target_lat_rad= (target_lat * rad) | float -%}
{%- set target_lon_rad= (target_lon * rad) | float -%}
{%- set delta_lat = (target_lat_rad - current_lat_rad) | float -%}
{%- set delta_lon= (target_lon_rad - current_lon_rad) | float -%}
{%- set half_delta_lat = (delta_lat / 2.0) | float -%}
{%- set half_delta_lon = (delta_lon / 2.0) | float -%}
{%- set sin_half_delta_lat = half_delta_lat | float | sin -%}
{%- set sin_half_delta_lon = half_delta_lon | float | sin -%}
{%- set a = ((sin_half_delta_lat ** 2) + (cos(current_lat_rad) *
cos(target_lat_rad) * (sin_half_delta_lon ** 2))) | float -%}
{%- set c = (2.0 * atan2(sqrt(a), sqrt(1.0 - a))) | float -%}
{%- set dist = (6371000.0 * c) | round(1) -%}
{%- set y = (sin(delta_lon) | float) * (cos(target_lat_rad) | float) -%}
{%- set x = ( (cos(current_lat_rad) | float) * (sin(target_lat_rad) | float) -
(sin(current_lat_rad) | float) * (cos(target_lat_rad) | float) *
(cos(delta_lon) | float)) | float -%}
{%- set initial_bearing = ((atan2(y, x) * 57.2957795) + 360.0) % 360.0 | round(1) -%}
target:{'distance': {{dist}}, bearing: {{initial_bearing |round(2)}},}
{%-endif -%}
Put in Lat Long, machine go brrrr, out comes approximate bearing and distance to target. Uses the lat/lon of zone home for basis of calc for origin… (where you are)
You may need to add custom names into your custom sentences / lists if you want to use it directly. As-is no warranty ![]()
edit:
First if my math is wrong navigators - lmk…
Open to correction and this was from memory and some strategic searching.
If you need info about editing the lists in custom sentences:
Friday’s Party: Creating a Private, Agentic AI using Voice Assistant tools - Configuration / Voice Assistant - Home Assistant Community