#!/usr/bin/env python from threading import Thread, Lock import time from aman.com import Weather from aman.config.Airport import Airport from aman.sys.aco.Configuration import Configuration from aman.sys.WeatherModel import WeatherModel from aman.sys.RecedingHorizonControl import RecedingHorizonControl from aman.types.Inbound import Inbound from aman.types.PerformanceData import PerformanceData class Worker(Thread): def __init__(self): Thread.__init__(self) self.stopThread = None self.icao = None self.configuration = None self.arrivalRoutes = None self.performanceData = None self.updateLock = None self.reportQueue = {} self.weatherModel = None self.RecedingHorizonControl = None def __del__(self): self.release() def acquire(self, icao : str, configuration : Airport, weather : Weather, performance : PerformanceData): self.stopThread = None self.icao = icao self.configuration = configuration self.sequencingConfiguration = self.configuration.DefaultSequencing self.performanceData = performance self.arrivalRoutes = configuration.GngData.arrivalRoutes self.updateLock = Lock() self.reportQueue = {} self.weatherModel = WeatherModel(self.configuration.GaforId, weather) self.RecedingHorizonControl = RecedingHorizonControl(self.configuration.RecedingHorizonControl) self.start() def acquireLock(self): if None != self.updateLock: self.updateLock.acquire() def release(self): self.stopThread = True self.join() def releaseLock(self): if None != self.updateLock: self.updateLock.release() def run(self): counter = 0 while None == self.stopThread: time.sleep(1) counter += 1 if 0 != (counter % 10): continue self.acquireLock() # perform some book-keeping self.RecedingHorizonControl.cleanupWindows() # update the aircraft information in RHC for callsign in self.reportQueue: report = self.reportQueue[callsign] if 0 != report.distanceToIAF and '' != report.initialApproachFix: inbound = Inbound(report, self.sequencingConfiguration, self.configuration.GngData, self.performanceData, self.weatherModel) if None != inbound.PlannedRunway and None != inbound.PlannedStar: self.RecedingHorizonControl.update(inbound) else: print('Unable to find all data of ' + report.aircraft.callsign) self.reportQueue.clear() if 0 != len(self.RecedingHorizonControl.Windows): print('FCFS run:') for window in self.RecedingHorizonControl.Windows: for inbound in window.Inbounds: print(' ' + inbound.Report.aircraft.callsign + ': ' + str(inbound.EstimatedArrivalTime)) # get the last landing aircrafts per runway before the RHC stage to check for constraints # this is required to handle the overlap between windows preceedingInbounds = {} for runway in self.sequencingConfiguration.ActiveArrivalRunways: inbound = self.RecedingHorizonControl.lastFixedInboundOnRunway(runway.Runway.name) if None != inbound: preceedingInbounds[runway.Runway.name] = inbound # search the ACO relevant aircrafts relevantInbounds = self.RecedingHorizonControl.optimizationRelevantInbounds() if None != relevantInbounds: print('Relevant inbounds: ' + str(len(relevantInbounds))) # configure the ACO run acoConfig = Configuration(self.sequencingConfiguration, 5 * len(relevantInbounds), 5 * len(relevantInbounds)) if 0 != len(preceedingInbounds): acoConfig.PreceedingInbounds = preceedingInbounds acoConfig.Inbounds = relevantInbounds # TODO perform the ACO run # TODO update the RHC stages based on the ACO run result else: print('No relevant inbounds found for the optimization in ' + self.icao) self.releaseLock()