SctEseFormat.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #!/usr/bin/env python
  2. import copy
  3. import sys
  4. from aman.types.ArrivalRoute import ArrivalRoute
  5. from aman.types.Runway import Runway
  6. from aman.types.Waypoint import Waypoint
  7. class SctEseFormat:
  8. def readFile(filename : str):
  9. fileBlocks = {}
  10. block = None
  11. # read the file line by line and create segments based on []-entries
  12. with open(filename) as file:
  13. for line in file:
  14. line = line.strip()
  15. # found a new segment
  16. if line.startswith('['):
  17. block = line[1:-1]
  18. fileBlocks.setdefault(block, [])
  19. # append the last backend
  20. elif None != block and 0 != len(line):
  21. fileBlocks[block].append(line)
  22. return fileBlocks
  23. def parseWaypoint(waypoint : str, nameIdx : int, latitudeIdx : int, longitudeIdx : int):
  24. split = list(filter(None, waypoint.split(' ')))
  25. if len(split) <= longitudeIdx:
  26. sys.stderr.write('Invalid waypoint format: ' + waypoint)
  27. sys.exit(-1)
  28. return Waypoint(name = split[nameIdx], latitude = split[latitudeIdx], longitude = split[longitudeIdx])
  29. def parseRunway(runway : str):
  30. split = list(filter(None, runway.split(' ')))
  31. if 9 != len(split) or '' == split[8]:
  32. return None, None, None
  33. waypoint0 = Waypoint(name = split[0], latitude = split[4], longitude = split[5])
  34. waypoint1 = Waypoint(name = split[1], latitude = split[6], longitude = split[7])
  35. return split[8], Runway(waypoint0, waypoint1), Runway(waypoint1, waypoint0)
  36. def extractSctInformation(self, sctFilepath : str):
  37. config = SctEseFormat.readFile(sctFilepath)
  38. foundAirports = False
  39. foundRunways = False
  40. foundVOR = False
  41. foundNDB = False
  42. foundFix = False
  43. for key in config:
  44. if 'VOR' == key:
  45. foundVOR = True
  46. elif 'NDB' == key:
  47. foundNDB = True
  48. elif 'FIXES' == key:
  49. foundFix = True
  50. elif 'AIRPORT' == key:
  51. foundAirports = True
  52. elif 'RUNWAY' == key:
  53. foundRunways = True
  54. if False == foundVOR:
  55. sys.stderr.write('Unable to find VOR-entries in the sector file')
  56. sys.exit(-1)
  57. if False == foundNDB:
  58. sys.stderr.write('Unable to find NDB-entries in the sector file')
  59. sys.exit(-1)
  60. if False == foundFix:
  61. sys.stderr.write('Unable to find FIX-entries in the sector file')
  62. sys.exit(-1)
  63. if False == foundAirports:
  64. sys.stderr.write('Unable to find AIRPORT-entries in the sector file')
  65. sys.exit(-1)
  66. if False == foundRunways:
  67. sys.stderr.write('Unable to find RUNWAY-entries in the sector file')
  68. sys.exit(-1)
  69. # extract all waypoints
  70. for waypoint in config['VOR']:
  71. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 2, 3)
  72. self.Waypoints.setdefault(waypoint.Name, []).append(waypoint)
  73. for waypoint in config['NDB']:
  74. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2)
  75. self.Waypoints.setdefault(waypoint.Name, []).append(waypoint)
  76. for waypoint in config['FIXES']:
  77. waypoint = SctEseFormat.parseWaypoint(waypoint, 0, 1, 2)
  78. self.Waypoints.setdefault(waypoint.Name, []).append(waypoint)
  79. # extract the airports
  80. for airport in config['AIRPORT']:
  81. airport = SctEseFormat.parseWaypoint(airport, 0, 2, 3)
  82. self.Airports.setdefault(airport.Name, []).append(airport)
  83. # extract the runways
  84. for runway in config['RUNWAY']:
  85. airport, runway0, runway1 = SctEseFormat.parseRunway(runway)
  86. if None != airport:
  87. if not airport in self.Runways:
  88. self.Runways.setdefault(airport, [])
  89. self.Runways[airport].append(runway0)
  90. self.Runways[airport].append(runway1)
  91. def parseArrivalRoute(self, route : str, airport : Waypoint):
  92. # split the route and validate that it is a STAR for the airport
  93. split = route.split(':')
  94. if 5 != len(split) or 'STAR' != split[0] or split[1] != airport.Name:
  95. return None
  96. # find all waypoints
  97. waypoints = []
  98. route = list(filter(None, split[4].split(' ')))
  99. for waypoint in route:
  100. # find the waypoint in the route
  101. coordinates = self.Waypoints[waypoint]
  102. # no waypoint with this name defined
  103. if None == coordinates:
  104. sys.stderr.write('Unable to find waypoint ' + waypoint)
  105. sys.exit(-1)
  106. # multiple waypoints, but use Haversine distance to distinct between candidates
  107. elif 1 != len(coordinates):
  108. minDistance = sys.float_info.max
  109. nearest = None
  110. # we assume that waypoints with the same name are not close each other
  111. for coordinate in coordinates:
  112. distance = coordinate.haversine(airport)
  113. # found a closer waypoint
  114. if minDistance > distance:
  115. minDistance = distance
  116. nearest = coordinate
  117. if None == nearest:
  118. sys.stderr.write('Unable to find a close waypoint for ' + waypoint)
  119. sys.exit(-1)
  120. waypoints.append(copy.deepcopy(nearest))
  121. # extend the list of waypoints
  122. else:
  123. waypoints.append(copy.deepcopy(coordinates[0]))
  124. # create the arrival route
  125. return ArrivalRoute(split[3], split[2], waypoints)
  126. def extractArrivalRoutes(self, eseFilepath : str, airport : str, allowedRoutes : list):
  127. config = SctEseFormat.readFile(eseFilepath)
  128. foundSidsStars = False
  129. # search the airport in the extracted list
  130. if not airport in self.Airports:
  131. sys.stderr.write('Unable to find the requested airport')
  132. sys.exit(-1)
  133. airport = self.Airports[airport][0]
  134. for key in config:
  135. if 'SIDSSTARS' == key:
  136. foundSidsStars = True
  137. if False == foundSidsStars:
  138. sys.stderr.write('Unable to find SIDSSTARS-entries in the sector file')
  139. sys.exit(-1)
  140. # parse all arrival routes
  141. for line in config['SIDSSTARS']:
  142. route = self.parseArrivalRoute(line, airport)
  143. if None != route and route.Name in allowedRoutes:
  144. self.ArrivalRoutes.setdefault(route.Runway, []).append(route)
  145. def __init__(self, sctFilepath : str, eseFilepath : str, airport : str, allowedRoutes : list):
  146. self.ArrivalRoutes = {}
  147. self.Waypoints = {}
  148. self.Airports = {}
  149. self.Runways = {}
  150. self.extractSctInformation(sctFilepath)
  151. self.extractArrivalRoutes(eseFilepath, airport, allowedRoutes)