Worker.py 6.2 KB

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