Worker.py 6.3 KB

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