Airport.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. #!/usr/bin/env python
  2. import configparser
  3. import glob
  4. import os
  5. import sys
  6. from aman.config.RHC import RHC
  7. from aman.config.AirportSequencing import AirportSequencing
  8. from aman.config.RunwaySequencing import RunwaySequencing
  9. from aman.formats.SctEseFormat import SctEseFormat
  10. class Airport:
  11. def findGngData(data, path):
  12. if None == data.get('gngwildcard'):
  13. return None, None
  14. # find the newest ESE file
  15. files = glob.glob(os.path.join(path, data['gngwildcard'] + '.ese'))
  16. latestEse = max(files, key=os.path.getctime)
  17. # search for the corresponding SCT file
  18. latestSct = os.path.splitext(latestEse)[0] + '.sct'
  19. # check if the files exist
  20. if False == os.path.isfile(latestEse) or False == os.path.isfile(latestSct):
  21. return None, None
  22. return latestSct, latestEse
  23. def parsePlanning(self, planning):
  24. if None == planning.get('routes'):
  25. return []
  26. return planning['routes'].split(':')
  27. def parseDefaultSequencingConfiguration(self, icao : str, planning):
  28. if None == planning.get('activearrivalrunwaydefault'):
  29. sys.stderr.write('No "activearrivalrunwaydefault" entry found!')
  30. sys.exit(-1)
  31. if None == planning.get('activearrivalmodedefault'):
  32. sys.stderr.write('No "activearrivalmodedefault" entry found!')
  33. sys.exit(-1)
  34. if None == planning.get('arrivalspacingdefault'):
  35. sys.stderr.write('No "arrivalspacingdefault" entry found!')
  36. sys.exit(-1)
  37. if not icao in self.GngData.runways:
  38. sys.stderr.write('Unable to find' + icao + 'in the SCT data!')
  39. sys.exit(-1)
  40. # parse the default arrival mode
  41. if 'STAGGERED' == planning['activearrivalmodedefault']:
  42. staggered = True
  43. elif 'IPA' == planning['activearrivalmodedefault']:
  44. staggered = False
  45. else:
  46. sys.stderr.write('Unknown arrival mode in "" found! (STAGGERED or IPA needs to be set)')
  47. sys.exit(-1)
  48. # translate the spacing into a map
  49. ident = ''
  50. spacings = {}
  51. spacingConfig = list(filter(None, planning['arrivalspacingdefault'].split(':')))
  52. for i in range(0, len(spacingConfig)):
  53. if 0 == i % 2:
  54. ident = spacingConfig[i]
  55. elif '' != ident:
  56. spacings[ident] = int(spacingConfig[i])
  57. else:
  58. sys.stderr.write('No runway defined in "arrivalspacingdefault"!')
  59. sys.exit(-1)
  60. # create the sequencing data per runway
  61. self.DefaultSequencing = AirportSequencing(icao)
  62. for ident in list(filter(None, planning['activearrivalrunwaydefault'].split(':'))):
  63. if not ident in spacings:
  64. sys.stderr.write('Unable to find sequencing data for ' + ident + ' of ' + icao)
  65. sys.exit(-1)
  66. found = False
  67. for runway in self.GngData.runways[icao]:
  68. if ident == runway.name:
  69. sequence = RunwaySequencing(runway)
  70. sequence.Spacing = spacings[ident]
  71. self.DefaultSequencing.activateRunway(sequence)
  72. found = True
  73. break
  74. if False == found:
  75. sys.stderr.write('Unable to find the runway for ' + ident + ' of ' + icao + ' in SCT data!')
  76. sys.exit(-1)
  77. # create the dependencies, if needed
  78. if True == staggered:
  79. if None == planning.get('runwaydependenciesdefault'):
  80. sys.stderr.write('Unable to find the runway dependencies for staggered approaches of ' + icao + '!')
  81. sys.exit(-1)
  82. dependencies = list(filter(None, planning['runwaydependenciesdefault'].split(':')))
  83. if 0 != len(dependencies) % 2:
  84. sys.stderr.write('No valid set of runway dependencies found!')
  85. sys.exit(-1)
  86. for i in range(0, len(dependencies), 2):
  87. self.DefaultSequencing.addDependency(dependencies[i], dependencies[i + 1])
  88. def __init__(self, filepath : str, icao : str):
  89. self.arrivalRoutes = {}
  90. config = configparser.ConfigParser()
  91. config.read(filepath)
  92. dataConfig = None
  93. planningConfig = None
  94. rhcConfig = None
  95. # search the required sections
  96. for key in config:
  97. if 'DATA' == key:
  98. dataConfig = config['DATA']
  99. elif 'PLANNING' == key:
  100. planningConfig = config['PLANNING']
  101. elif 'RHC' == key:
  102. rhcConfig = config['RHC']
  103. # find the GNG-file data
  104. sctFile, eseFile = Airport.findGngData(dataConfig, os.path.dirname(filepath))
  105. if None == sctFile or None == eseFile:
  106. sys.stderr.write('No GNG-files found')
  107. sys.exit(-1)
  108. # parse the planning information
  109. if None == planningConfig or False == self.parsePlanning(planningConfig):
  110. sys.stderr.write('No planning configuration found')
  111. sys.exit(-1)
  112. requiredArrivalRoutes = self.parsePlanning(planningConfig)
  113. if 0 == len(requiredArrivalRoutes):
  114. sys.stderr.write('No valid planning configuration found')
  115. sys.exit(-1)
  116. # parse the RHC information
  117. if None == rhcConfig:
  118. sys.stderr.write('No RHC configuration found')
  119. sys.exit(-1)
  120. self.RecedingHorizonControl = RHC(rhcConfig)
  121. # parse the GNG data
  122. print('Used GNG-Data: ' + eseFile)
  123. self.GngData = SctEseFormat(sctFile, eseFile, icao, requiredArrivalRoutes)
  124. # get the GAFOR id
  125. if None == dataConfig.get('gaforid'):
  126. sys.stderr.write('No GAFOR-ID found!')
  127. sys.exit(-1)
  128. self.GaforId = dataConfig['gaforid']
  129. # get the default sequencing data
  130. self.parseDefaultSequencingConfiguration(icao, planningConfig)