#!/usr/bin/env python from threading import Thread, Lock import sys import time from aman.com import Weather from aman.com.Euroscope import Euroscope from aman.config.Airport import Airport from aman.config.AirportSequencing import AirportSequencing from aman.sys.aco.Colony import Colony from aman.sys.aco.Configuration import Configuration from aman.sys.aco.Node import Node 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, icao : str, configuration : Airport, weather : Weather, performance : PerformanceData, euroscope : Euroscope): Thread.__init__(self) self.StopThread = None self.Icao = icao self.Configuration = configuration self.SequencingConfiguration = configuration.DefaultSequencing self.PerformanceData = performance self.UpdateLock = Lock() self.ReportQueue = {} if None != weather: self.WeatherModel = WeatherModel(configuration.GaforId, weather) else: self.WeatherModel = WeatherModel(0, None) self.RecedingHorizonControl = RecedingHorizonControl(configuration.RecedingHorizonControl) self.Euroscope = euroscope # merge the constraint information with the GNG information for runway in self.Configuration.GngData.ArrivalRoutes: for star in self.Configuration.GngData.ArrivalRoutes[runway]: for name in self.Configuration.ArrivalRouteConstraints: if name == star.Name: for constraint in self.Configuration.ArrivalRouteConstraints[name]: foundWaypoint = False for waypoint in star.Route: if constraint.Name == waypoint.Name: waypoint.Altitude = constraint.Altitude waypoint.Speed = constraint.Speed waypoint.BaseTurn = constraint.BaseTurn waypoint.FinalTurn = constraint.FinalTurn foundWaypoint = True break if False == foundWaypoint: sys.stderr.write('Unable to find ' + constraint.Name + ' in ' + name) sys.exit(-1) break self.setDaemon(True) self.start() def acquireLock(self): if None != self.UpdateLock: self.UpdateLock.acquire() 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 % 60): 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 '' != report.initialApproachFix: inbound = Inbound(report, self.PerformanceData) Node(inbound, inbound.ReportTime, self.WeatherModel, self.Configuration, self.SequencingConfiguration) if None != inbound.EnrouteArrivalTime: self.RecedingHorizonControl.updateReport(inbound) else: print('Unable to find all data of ' + report.aircraft.callsign) self.ReportQueue.clear() # search the ACO relevant aircrafts relevantInbounds, earliestArrivalTime = self.RecedingHorizonControl.optimizationRelevantInbounds() if None != relevantInbounds: start = time.process_time() # get the last landing aircrafts per runway before the RHC stage to check for constraints # this is required to handle the overlap between windows runways, iafs = self.RecedingHorizonControl.latestFixedInbounds(self.Configuration, self.SequencingConfiguration) # configure the ACO run acoConfig = Configuration(constraints = self.SequencingConfiguration, config = self.Configuration, earliest = earliestArrivalTime, weather = self.WeatherModel, preceedingRunways = runways, preceedingIafs = iafs, ants = 5 * len(relevantInbounds), generations = 5 * len(relevantInbounds)) # run the optimizer outside the locking functions self.releaseLock() # perform the ACO run aco = Colony(relevantInbounds, acoConfig) aco.optimize() self.acquireLock() if None != aco.Result: for node in aco.Result: self.RecedingHorizonControl.resequenceInbound(node.Inbound) # measure the exuction time of the overall optimization process executionTime = time.process_time() - start if 60.0 <= executionTime: print('Optimized ' + str(len(aco.Result)) + ' inbounds in ' + str(executionTime) + ' seconds') self.releaseLock() def inboundSequence(self): self.acquireLock() sequence = self.RecedingHorizonControl.sequence() self.releaseLock() return sequence def configure(self, configuration : AirportSequencing): self.acquireLock() self.SequencingConfiguration = configuration self.releaseLock()