Skip to content

Commit a122684

Browse files
committed
implemented switching between Cartesian (ECEF) and Haversine distance computations between WGS84 points
1 parent bbfc391 commit a122684

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

openburst/constants/pclconstants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@
1717

1818
# we set a minimal bistatic rcs for online detection (i.e. the target is only detected if its bistatic RCS is above this value)
1919
MIN_BISTATIC_RCS_ONLINE_DETECTION = 10.0 # [m]
20+
21+
# set to TRUE to use Cartesian bistatic_range computation (if false the haversine function is used)
22+
_USE_CARTESIAN = True

openburst/functions/geofunctions.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from geographiclib.geodesic import Geodesic
1414
from pyproj import Proj, transform # needed for transforming from Lat/Long to CH Lv93 coordinates
1515
from openburst.functions import basefunctions
16+
from openburst.constants.pclconstants import _USE_CARTESIAN
1617

1718
def get_azimuth_between_locs(lat1, lon1, lat2, lon2):
1819

@@ -105,6 +106,8 @@ def get_chf_from_deg(lat, lon):
105106
lv = transform(p_world,p_ch, lon, lat, 0)
106107
return lv
107108

109+
110+
108111
def get_bistatic_range(tx_latlonalt, rx_latlonalt, tgt_latlonalt):
109112
""" returns bistatic range [km], tgt_rx_range [km], tgt_tx_range [km], baseline_range [km])
110113
for given Tx, Rx and Target
@@ -113,9 +116,11 @@ def get_bistatic_range(tx_latlonalt, rx_latlonalt, tgt_latlonalt):
113116
input tgt: lat, lon, alt[masl]
114117
definition bistatic range [km] = distance(Tx -> Tgt -> Rx ) - distance(Rx->Tx)
115118
"""
119+
116120
tx_tgt_range = get_2d_distance_between_locs_heights(tx_latlonalt[0], tx_latlonalt[1], tx_latlonalt[2], tgt_latlonalt[0], tgt_latlonalt[1], tgt_latlonalt[2])
117121
tgt_rx_range = get_2d_distance_between_locs_heights(rx_latlonalt[0], rx_latlonalt[1], rx_latlonalt[2], tgt_latlonalt[0], tgt_latlonalt[1], tgt_latlonalt[2])
118122
tx_rx_range = get_2d_distance_between_locs_heights(tx_latlonalt[0], tx_latlonalt[1], tx_latlonalt[2], rx_latlonalt[0], rx_latlonalt[1], rx_latlonalt[2])
123+
119124
return (tx_tgt_range + tgt_rx_range - tx_rx_range, tgt_rx_range, tx_tgt_range, tx_rx_range)
120125

121126
def calculate_bistatic_doppler(rx, tgt, tx):
@@ -132,6 +137,7 @@ def calculate_bistatic_doppler(rx, tgt, tx):
132137
The returned bistatic Doppler [Hz] value can be negative, depending on the
133138
velocity vector of the target
134139
"""
140+
135141
rr1 = (
136142
get_2d_distance_between_locs_heights(
137143
tgt.lat, tgt.lon, tgt.height, rx.lat, rx.lon, rx.masl+rx.ahmagl
@@ -166,6 +172,7 @@ def calculate_bistatic_doppler(rx, tgt, tx):
166172
new_z = tgt.height + time_diff * tgt.vz
167173

168174
# now compute bistatic range components R_T and R_R for the new target position
175+
169176
rr2 = (
170177
get_2d_distance_between_locs_heights(
171178
new_lat, new_lon, new_z, rx.lat, rx.lon, rx.masl+rx.ahmagl
@@ -177,7 +184,8 @@ def calculate_bistatic_doppler(rx, tgt, tx):
177184
tx.lat, tx.lon, tx.masl+tx.ahmagl, new_lat, new_lon, new_z
178185
)
179186
* 1000.0
180-
)
187+
)
188+
181189
# compute the rate of change for R_T (tx to target range) and R_R (tgt to rx range)
182190

183191
rt_rate_of_change = (rt2-rt1)/time_diff
@@ -245,9 +253,49 @@ def get_clear_sky_attenuation(transmitter_freq):
245253

246254
return atten_db
247255

256+
def get_ecef_cartesian_from_lat_lon_height(lat_deg, lon_deg, h):
257+
"""
258+
WGS84 to cooordinates
259+
returns cartesian coordinates given lat, lon and height using ecef cartesian transformation
260+
h: height in meters
261+
"""
262+
263+
#lat_deg, lon_deg, h = ll
264+
a = 6378137.0 # semi-major axis
265+
#f = 1 / 298.257223563 # flattening
266+
e2 = 0.006694380004260827 # first eccentricity squared
267+
268+
# Umwandlung in Radiant
269+
lat = np.radians(lat_deg)
270+
lon = np.radians(lon_deg)
271+
272+
sin_lat = np.sin(lat)
273+
cos_lat = np.cos(lat)
274+
sin_lon = np.sin(lon)
275+
cos_lon = np.cos(lon)
276+
277+
N = a / np.sqrt(1 - e2 * sin_lat**2)
278+
279+
x = (N + h) * cos_lat * cos_lon
280+
y = (N + h) * cos_lat * sin_lon
281+
z = (N * (1 - e2) + h) * sin_lat
282+
283+
return([x,y,z])
284+
285+
def get_2d_distance_between_locs_heights_ecef(lat1, lon1, h1, lat2, lon2, h2):
286+
"""
287+
returns distance in kilometers between two lat lons and heights using ecef cartesian transformation
288+
h1, h2: meters
289+
"""
290+
p1 = get_ecef_cartesian_from_lat_lon_height(lat1, lon1, h1)
291+
p2 = get_ecef_cartesian_from_lat_lon_height(lat2, lon2, h2)
292+
dist = np.linalg.norm(np.array(p1)-np.array(p2))
293+
return dist/1000.0 # [km]
294+
295+
248296
def get_2d_distance_between_locs_heights(lat1, lon1, h1, lat2, lon2, h2):
249297
"""
250-
returns distance in kilometers between two lat lons and heights.
298+
returns distance in kilometers between two lat lons and heights using the haversine formula
251299
geopy.distance does NOT consider altitude!! the solution below with haversine formula compared to geopy.distance without height are at 220km are identical upto a difference below 50m
252300
the solution here is not exactly correct, but good enough for our purposes
253301
for large geodesic distances (ie large distance on the ellipsoid surface) the difference is less than a few hundred meters
@@ -256,6 +304,9 @@ def get_2d_distance_between_locs_heights(lat1, lon1, h1, lat2, lon2, h2):
256304
h1, h2: meters
257305
"""
258306

307+
if (_USE_CARTESIAN):
308+
return get_2d_distance_between_locs_heights_ecef(lat1, lon1, h1, lat2, lon2, h2)
309+
259310
p1 = (lat1, lon1)
260311
p2 = (lat2, lon2)
261312
hav = haversine(p1, p2)

0 commit comments

Comments
 (0)