Worker.py 6.1 KB

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