Files
aman-sys/aman/sys/Worker.py
2021-12-16 16:08:11 +01:00

141 lines
6.1 KiB
Python

#!/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 0 != report.distanceToIAF and '' != report.initialApproachFix:
inbound = Inbound(report, self.PerformanceData)
Node(inbound, inbound.ReportTime, self.WeatherModel, self.Configuration, self.SequencingConfiguration)
if None != inbound.InitialArrivalTime:
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
preceedingInbounds = {}
for runway in self.SequencingConfiguration.ActiveArrivalRunways:
inbound = self.RecedingHorizonControl.lastFixedInboundOnRunway(runway.Runway.Name)
if None != inbound:
preceedingInbounds[runway.Runway.Name] = Node(inbound, None, None, None, None)
# configure the ACO run
acoConfig = Configuration(constraints = self.SequencingConfiguration, config = self.Configuration,
earliest = earliestArrivalTime, weather = self.WeatherModel,
preceeding = None if 0 == len(preceedingInbounds) else preceedingInbounds,
ants = 5 * len(relevantInbounds), generations = 5 * len(relevantInbounds))
# perform the ACO run
aco = Colony(relevantInbounds, acoConfig)
aco.optimize()
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()