1313from geographiclib .geodesic import Geodesic
1414from pyproj import Proj , transform # needed for transforming from Lat/Long to CH Lv93 coordinates
1515from openburst .functions import basefunctions
16+ from openburst .constants .pclconstants import _USE_CARTESIAN
1617
1718def 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+
108111def 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
121126def 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+
248296def 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