Skip to content

Commit 6b5d0f1

Browse files
committed
added "az_elev_dist" function to coordinates and test
1 parent 7187e15 commit 6b5d0f1

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

src/skaero/geometry/coordinates.py

+48-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""
66

77
import numpy as np
8-
from numpy import sin, cos, deg2rad, array
8+
from numpy import sin, cos, deg2rad, rad2deg, array
99

1010

1111
def lla2ecef(lat, lng, h):
@@ -289,3 +289,50 @@ def wind2body(v_wind, alpha, beta):
289289
v_body = Lbw.dot(v_wind)
290290

291291
return v_body
292+
293+
294+
def az_elev_dist(lla, lla_ref):
295+
"""
296+
Returns distance, azimuth angle and elevation angle that define the
297+
position in the sky of a point (defined using lla coordinates) as viewed
298+
from a point of reference (also defined by lla coordinates)
299+
Parameters
300+
----------
301+
lla : array-like
302+
contains latitude and longitude (in degrees) and geometric altitude
303+
above sea level in meters
304+
lla_ref : array-like
305+
contains reference point latitude and longitude (in degrees) and
306+
geometric altitude above sea level in meters
307+
Returns
308+
-------
309+
out : tuple-like
310+
distance aircraft to reference point in m
311+
azimuth angle (from the reference point) in degrees
312+
elevation angle (from the reference point) in degrees
313+
"""
314+
lat, lng, h = lla
315+
lat_ref, lng_ref, h_ref = lla_ref
316+
317+
if abs(lat) > 90 or abs(lat_ref) > 90:
318+
raise ValueError('latitude should be -90º <= latitude <= 90º')
319+
320+
if abs(lng) > 180 or abs(lng_ref) > 180:
321+
raise ValueError('longitude should be -180º <= longitude <= 180º')
322+
323+
v = lla2ecef(lat, lng, h) - lla2ecef(lat_ref, lng_ref, h_ref)
324+
325+
v_unit_ecef = v / np.linalg.norm(v)
326+
v_unit_ned = ecef2ned(v_unit_ecef, lat_ref, lng_ref)
327+
328+
azimuth = np.arctan2(-v_unit_ned[1], v_unit_ned[0])
329+
330+
if v_unit_ned[0] == v_unit_ned[1] == 0:
331+
elevation = np.pi / 2
332+
else:
333+
elevation = np.arctan(-v_unit_ned[2] / np.sqrt(v_unit_ned[0]**2 +
334+
v_unit_ned[1]**2))
335+
336+
distance = np.linalg.norm(v)
337+
338+
return rad2deg(azimuth), rad2deg(elevation), distance

tests/test_coordinates.py

+46
Original file line numberDiff line numberDiff line change
@@ -821,3 +821,49 @@ def test_wind2body2wind(self):
821821
expected_value = v
822822
self.assertTrue(np.allclose(body2wind(v_body, alpha, beta),
823823
expected_value))
824+
825+
826+
class Test_az_elev_dist(ut.TestCase):
827+
"""
828+
Test function that calculates distance, azimuth and elevation of a point
829+
as seen from a reference point
830+
"""
831+
def test_latitude_wrong_input(self):
832+
lla = array([91, 0, 0])
833+
lla_ref = array([0, 0, 0])
834+
self.assertRaises(ValueError, az_elev_dist, lla, lla_ref)
835+
836+
lla = array([0, 0, 0])
837+
lla_ref = array([-210, 0, 0])
838+
self.assertRaises(ValueError, az_elev_dist, lla, lla_ref)
839+
840+
lla = array(['a', 0, 0])
841+
lla_ref = array([0, 0, 0])
842+
self.assertRaises(TypeError, az_elev_dist, lla, lla_ref)
843+
844+
def test_longitude_wrong_input(self):
845+
lla = array([0, -181, 0])
846+
lla_ref = array([0, 0, 0])
847+
self.assertRaises(ValueError, az_elev_dist, lla, lla_ref)
848+
849+
lla = array([0, 0, 0])
850+
lla_ref = array([0, 189, 0])
851+
self.assertRaises(ValueError, az_elev_dist, lla, lla_ref)
852+
853+
lla = array([0, 0, 0])
854+
lla_ref = array([0, 'a', 0])
855+
self.assertRaises(TypeError, az_elev_dist, lla, lla_ref)
856+
857+
def test_1(self):
858+
lla = array([0, 0, 0])
859+
lla_ref = array([0, 0.00001, 0])
860+
expected_value = (90, 0, 1.113)
861+
self.assertTrue(np.allclose(az_elev_dist(lla, lla_ref),
862+
expected_value, atol=1e-3))
863+
864+
def test_2(self):
865+
lla = array([0, 0, 0])
866+
lla_ref = array([0, 0, 10])
867+
expected_value = (0, 90, 10)
868+
self.assertTrue(np.allclose(az_elev_dist(lla, lla_ref),
869+
expected_value))

0 commit comments

Comments
 (0)