Guest User

Untitled

a guest
Dec 13th, 2017
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.32 KB | None | 0 0
  1. from math import asin, sqrt, cos, sin, atan, acos
  2.  
  3. # Earth radius in meters (https://rechneronline.de/earth-radius/)
  4. E_RADIUS = 6367 * 1000 # at 45°N - Adjust as required
  5.  
  6.  
  7. def step_0(r_e, h_u, h_s, h_a, d_ua, d_sa):
  8. # Determine angles centered on Earth between stations and aircraft
  9.  
  10. a = (d_ua - h_a + h_u) * (d_ua + h_a - h_u)
  11. b = (r_e + h_u) * (r_e + h_a)
  12. theta_ua = asin(.5 * sqrt(a / b))
  13.  
  14. a = (d_sa - h_a + h_s) * (d_sa + h_a - h_s)
  15. b = (r_e + h_s) * (r_e + h_a)
  16. theta_sa = asin(.5 * sqrt(a / b))
  17.  
  18. return theta_ua, theta_sa
  19.  
  20.  
  21. def step_1(lat_u, lon_u, lat_s, lon_s):
  22. # Determine Earth centered angle between the two stations
  23. # and the relative azimuth of one to the other.
  24.  
  25. a = sin(.5 * (lat_s - lat_u))
  26. b = sin(.5 * (lon_s - lon_u))
  27. c = sqrt(a * a + cos(lat_s) * cos(lat_u) * b * b)
  28. theta_us = 2 * asin(c)
  29.  
  30. a = lon_s - lon_u
  31. b = cos(lat_s) * sin(a)
  32. c = sin(lat_s) * cos(lat_u)
  33. d = cos(lat_s) * sin(lat_u) * cos(a)
  34. psi_su = atan(b / (c - d))
  35.  
  36. return theta_us, psi_su
  37.  
  38.  
  39. def step_2(theta_us, theta_ua, theta_sa):
  40. # Determine whether DME spheres intersect
  41.  
  42. if (theta_ua + theta_sa) < theta_us:
  43. # Spheres are too remote to intersect
  44. return False
  45. if abs(theta_ua - theta_sa) > theta_us:
  46. # Spheres are concentric and don't intersect
  47. return False
  48.  
  49. # Spheres intersect
  50. return True
  51.  
  52.  
  53. def step_3(theta_us, theta_ua, theta_sa):
  54. # Determine one angle of the USA triangle
  55.  
  56. a = cos(theta_sa) - cos(theta_us) * cos(theta_ua)
  57. b = sin(theta_us) * sin(theta_ua)
  58. beta_u = acos(a / b)
  59.  
  60. return beta_u
  61.  
  62.  
  63. def step_4(ac_south, lat_u, lon_u, beta_u, psi_su, theta_ua):
  64. # Determine aircraft coordinates
  65.  
  66. psi_au = psi_su
  67. if ac_south:
  68. psi_au += beta_u
  69. else:
  70. psi_au -= beta_u
  71.  
  72. # Determine aircraft latitude
  73. a = sin(lat_u) * cos(theta_ua)
  74. b = cos(lat_u) * sin(theta_ua) * cos(psi_au)
  75. lat_a = asin(a + b)
  76.  
  77. # Determine aircraft longitude
  78. a = sin(psi_au) * sin(theta_ua)
  79. b = cos(lat_u) * cos(theta_ua)
  80. c = sin(lat_u) * sin(theta_ua) * cos(psi_au)
  81. lon_a = atan(a / (b - c)) + lon_u
  82.  
  83. return lat_a, lon_a
  84.  
  85.  
  86. def main():
  87. # Program entry point
  88. # -------------------
  89.  
  90. # For this test, I'm using three locations in France:
  91. # VOR Caen, VOR Evreux and VOR L'Aigle.
  92. # The angles and horizontal distances between them are known
  93. # by looking at the low-altitude enroute chart which I've posted
  94. # here: https://i.stack.imgur.com/m8Wmw.png
  95. # We know there coordinates and altitude by looking at the AIP France too.
  96. # For DMS <--> Decimal degrees, this tool is handy:
  97. # https://www.rapidtables.com/convert/number/degrees-minutes-seconds-to-degrees.html
  98.  
  99. # Let's pretend the aircraft is at LGL
  100. # lat = 48.79061, lon = 0.5302778
  101.  
  102. # Stations U and S are:
  103. u = {'label': 'CAN', 'lat': 49.17319, 'lon': -0.4552778, 'alt': 82}
  104. s = {'label': 'EVX', 'lat': 49.03169, 'lon': 1.220861, 'alt': 152}
  105.  
  106. # We know the aircraft altitude
  107. a_alt = 296 # meters
  108.  
  109. # We know the approximate slant ranges to stations U and S
  110. au_range = 45 * 1852 # 1 NM = 1,852 m
  111. as_range = 31 * 1852
  112.  
  113. # Compute angles station - earth center - aircraft for U and S
  114. theta_ua, theta_sa = step_0(
  115. r_e=E_RADIUS, # Earth
  116. h_u=u['alt'], # Station U altitude
  117. h_s=s['alt'], # Station S altitude
  118. h_a=a_alt, d_ua=au_range, d_sa=as_range # aircraft data
  119. )
  120.  
  121. # Compute angle between station, and their relative azimuth
  122. theta_us, psi_su = step_1(
  123. lat_u=u['lat'], lon_u=u['lon'], # Station U coordinates
  124. lat_s=s['lat'], lon_s=s['lon']) # Station S coordinates
  125.  
  126. # Check validity of ranges
  127. if not step_2(
  128. theta_us=theta_us,
  129. theta_ua=theta_ua,
  130. theta_sa=theta_sa):
  131. # Cannot compute, spheres don't intersect
  132. print('Cannot compute, ranges are not consistant')
  133. return 1
  134.  
  135. # Solve one angle of the USA triangle
  136. beta_u = step_3(
  137. theta_us=theta_us,
  138. theta_ua=theta_ua,
  139. theta_sa=theta_sa)
  140.  
  141. # Compute aircraft coordinates.
  142. # The first parameter is whether the aircraft is south of the line
  143. # between U and S. If you don't know, then you need to compute
  144. # both, once with ac_south = False, once with ac_south = True.
  145. # You will get the two possible positions, one must be eliminated.
  146.  
  147. # North position
  148. lat_n, lon_n = step_4(
  149. ac_south=False, # See comment above
  150. lat_u=u['lat'], lon_u=u['lon'], # Station U
  151. beta_u=beta_u, psi_su=psi_su, theta_ua=theta_ua # previously computed
  152. )
  153. pn = {'label': 'P north', 'lat': lat_n, 'lon': lon_n, 'alt': a_alt}
  154.  
  155. # South position
  156. lat_s, lon_s = step_4(
  157. ac_south=True,
  158. lat_u=u['lat'], lon_u=u['lon'],
  159. beta_u=beta_u, psi_su=psi_su, theta_ua=theta_ua)
  160. ps = {'label': 'P south', 'lat': lat_s, 'lon': lon_s, 'alt': a_alt}
  161.  
  162. # Print results
  163. fmt = '{}: lat {}, lon {}, alt {}'
  164. for p in u, s, pn, ps:
  165. print(fmt.format(p['label'], p['lat'], p['lon'], p['alt']))
  166.  
  167. # The expected result is:
  168. # CAN: lat 49.17319, lon -0.4552778, alt 82
  169. # EVX: lat 49.03169, lon 1.220861, alt 152
  170. # P north: lat ??????, lon ??????, alt 296
  171. # P south: lat 48.79061, lon 0.5302778, alt 296
  172.  
  173.  
  174. if __name__ == '__main__':
  175. main()
Add Comment
Please, Sign In to add comment