Worker.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python
  2. from threading import Thread, Lock
  3. import sys
  4. import time
  5. from aman.com import Weather
  6. from aman.com.WebUI import WebUI
  7. from aman.config.Airport import Airport
  8. from aman.sys.aco.Colony import Colony
  9. from aman.sys.aco.Configuration import Configuration
  10. from aman.sys.WeatherModel import WeatherModel
  11. from aman.sys.RecedingHorizonControl import RecedingHorizonControl
  12. from aman.types.Inbound import Inbound
  13. from aman.types.PerformanceData import PerformanceData
  14. class Worker(Thread):
  15. def __init__(self):
  16. Thread.__init__(self)
  17. self.StopThread = None
  18. self.Icao = None
  19. self.Configuration = None
  20. self.PerformanceData = None
  21. self.UpdateLock = None
  22. self.ReportQueue = {}
  23. self.WeatherModel = None
  24. self.RecedingHorizonControl = None
  25. self.WebUi = None
  26. def __del__(self):
  27. self.release()
  28. def acquire(self, icao : str, configuration : Airport, weather : Weather, performance : PerformanceData, webui : WebUI):
  29. self.StopThread = None
  30. self.Icao = icao
  31. self.Configuration = configuration
  32. self.sequencingConfiguration = configuration.DefaultSequencing
  33. self.PerformanceData = performance
  34. self.UpdateLock = Lock()
  35. self.ReportQueue = {}
  36. self.WeatherModel = WeatherModel(configuration.GaforId, weather)
  37. self.RecedingHorizonControl = RecedingHorizonControl(configuration.RecedingHorizonControl)
  38. self.WebUi = webui
  39. # merge the constraint information with the GNG information
  40. for runway in self.Configuration.GngData.ArrivalRoutes:
  41. for star in self.Configuration.GngData.ArrivalRoutes[runway]:
  42. for name in self.Configuration.ArrivalRouteConstraints:
  43. if name == star.Name:
  44. for constraint in self.Configuration.ArrivalRouteConstraints[name]:
  45. foundWaypoint = False
  46. for waypoint in star.Route:
  47. if constraint.Name == waypoint.Name:
  48. waypoint.Altitude = constraint.Altitude
  49. waypoint.Speed = constraint.Speed
  50. waypoint.BaseTurn = constraint.BaseTurn
  51. waypoint.FinalTurn = constraint.FinalTurn
  52. foundWaypoint = True
  53. break
  54. if False == foundWaypoint:
  55. sys.stderr.write('Unable to find ' + constraint.Name + ' in ' + name)
  56. sys.exit(-1)
  57. break
  58. self.start()
  59. def acquireLock(self):
  60. if None != self.UpdateLock:
  61. self.UpdateLock.acquire()
  62. def release(self):
  63. self.StopThread = True
  64. self.join()
  65. def releaseLock(self):
  66. if None != self.UpdateLock:
  67. self.UpdateLock.release()
  68. def run(self):
  69. counter = 0
  70. while None == self.StopThread:
  71. time.sleep(1)
  72. counter += 1
  73. if 0 != (counter % 10):
  74. continue
  75. self.acquireLock()
  76. # perform some book-keeping
  77. self.RecedingHorizonControl.cleanupWindows()
  78. # update the aircraft information in RHC
  79. for callsign in self.ReportQueue:
  80. report = self.ReportQueue[callsign]
  81. if 0 != report.distanceToIAF and '' != report.initialApproachFix:
  82. inbound = Inbound(report, self.sequencingConfiguration, self.Configuration.GngData, self.PerformanceData, self.WeatherModel)
  83. if None != inbound.PlannedRunway and None != inbound.PlannedStar:
  84. self.RecedingHorizonControl.updateReport(inbound)
  85. else:
  86. print('Unable to find all data of ' + report.aircraft.callsign)
  87. self.ReportQueue.clear()
  88. # search the ACO relevant aircrafts
  89. relevantInbounds, earliestArrivalTime = self.RecedingHorizonControl.optimizationRelevantInbounds()
  90. if None != relevantInbounds:
  91. start = time.process_time()
  92. # get the last landing aircrafts per runway before the RHC stage to check for constraints
  93. # this is required to handle the overlap between windows
  94. preceedingInbounds = {}
  95. for runway in self.sequencingConfiguration.ActiveArrivalRunways:
  96. inbound = self.RecedingHorizonControl.lastFixedInboundOnRunway(runway.Runway.Name)
  97. if None != inbound:
  98. preceedingInbounds[runway.Runway.Name] = inbound
  99. # configure the ACO run
  100. acoConfig = Configuration(constraints = self.sequencingConfiguration, inbounds = relevantInbounds,
  101. earliest = earliestArrivalTime, weather = self.WeatherModel,
  102. preceeding = None if 0 == len(preceedingInbounds) else preceedingInbounds,
  103. ants = 5 * len(relevantInbounds), generations = 5 * len(relevantInbounds))
  104. # perform the ACO run
  105. aco = Colony(acoConfig)
  106. aco.optimize()
  107. if None != aco.Result:
  108. print('ACO-Sequence:')
  109. for inbound in aco.Result:
  110. self.RecedingHorizonControl.resequenceInbound(inbound)
  111. print('Delays: FCFS=' + str(aco.FcfsDelay.total_seconds()) + ', ACO=' + str(aco.ResultDelay.total_seconds()))
  112. # measure the exuction time of the overall optimization process
  113. print('Execution time: ' + str(time.process_time() - start) + ' seconds')
  114. else:
  115. print('No relevant inbounds found for the optimization in ' + self.Icao)
  116. # send the sequence to the GUI
  117. self.WebUi.sendSequence(self.Icao, self.RecedingHorizonControl.sequence())
  118. # TODO send the sequence to EuroScope
  119. self.releaseLock()