Files
aman-sys/aman/sys/Worker.py
2021-10-17 17:12:40 +02:00

138 lines
5.9 KiB
Python

#!/usr/bin/env python
from threading import Thread, Lock
import sys
import time
from aman.com import Weather
from aman.config.Airport import Airport
from aman.sys.aco.Colony import Colony
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.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 = configuration.DefaultSequencing
self.PerformanceData = performance
self.UpdateLock = Lock()
self.ReportQueue = {}
self.WeatherModel = WeatherModel(configuration.GaforId, weather)
self.RecedingHorizonControl = RecedingHorizonControl(configuration.RecedingHorizonControl)
# 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.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()
# search the ACO relevant aircrafts
relevantInbounds, earliestArrivalTime = self.RecedingHorizonControl.optimizationRelevantInbounds()
if None != relevantInbounds:
# 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
print('Relevant inbounds: ' + str(len(relevantInbounds)))
# configure the ACO run
acoConfig = Configuration(earliestArrivalTime, self.sequencingConfiguration, 5 * len(relevantInbounds), 5 * len(relevantInbounds))
if 0 != len(preceedingInbounds):
acoConfig.PreceedingInbounds = preceedingInbounds
acoConfig.Inbounds = relevantInbounds
# perform the ACO run
aco = Colony(acoConfig)
aco.optimize()
if None != aco.Result:
print('ACO-Sequence:')
for inbound in aco.Result:
print(' ' + inbound.Report.aircraft.callsign + ': ' + inbound.PlannedRunway.Name + ' @ ' + str(inbound.PlannedArrivalTime) +
' dt=' + str((inbound.PlannedArrivalTime - inbound.InitialArrivalTime).total_seconds()))
print('Delays: FCFS=' + str(aco.FcfsDelay.total_seconds()) + ', ACO=' + str(aco.ResultDelay.total_seconds()))
else:
print('No relevant inbounds found for the optimization in ' + self.Icao)
self.releaseLock()