Browse Source

use a new function to create the fixed preceedings and use the information in the runway manager

Sven Czarnian 3 years ago
parent
commit
13837fdb62

+ 49 - 9
aman/sys/RecedingHorizonControl.py

@@ -7,7 +7,10 @@ from datetime import timedelta
 
 import pytz
 
+from aman.config.Airport import Airport
+from aman.config.AirportSequencing import AirportSequencing
 from aman.config.RHC import RHC
+from aman.sys.aco.Node import Node
 from aman.sys.RecedingHorizonWindow import RecedingHorizonWindow
 from aman.types.Inbound import Inbound
 
@@ -106,19 +109,56 @@ class RecedingHorizonControl:
             inbound.FixedSequence = index < self.FreezedIndex
             self.Windows[index].Inbounds.sort(key = lambda x: x.PlannedArrivalTime if None != x.PlannedArrivalTime else x.EnrouteArrivalTime)
 
-    def lastFixedInboundOnRunway(self, runway : str):
-        # no inbounds available
+    def latestFixedInbounds(self, configuration : Airport, sequenceConfiguration : AirportSequencing):
         if 0 == len(self.Windows):
-            return None
+            return None, None
+
+        # create the runway tree
+        runwayInbounds = {}
+        for runway in sequenceConfiguration.ActiveArrivalRunways:
+            runwayInbounds[runway.Runway.Name] = None
+
+        # create the IAF tree
+        iafInbounds = {}
+        for star in configuration.ArrivalRouteConstraints:
+            altitude = configuration.ArrivalRouteConstraints[star][0].Altitude
+            iaf = configuration.ArrivalRouteConstraints[star][0].Name
 
-        # search from the back to the front to find the last inbound
+            if iaf not in iafInbounds:
+                iafInbounds[iaf] = { altitude : None }
+            elif altitude not in iafInbounds[iaf]:
+                iafInbounds[iaf][altitude] = None
+
+        # associate the inbounds to the runways and the IAFs
         for i in range(min(self.FreezedIndex, len(self.Windows)), -1, -1):
             for inbound in self.Windows[i].Inbounds:
-                if None != inbound.PlannedRunway and runway == inbound.PlannedRunway.Name:
-                    return inbound
-
-        # no inbound found
-        return None
+                if None == inbound.PlannedRunway or None == inbound.PlannedArrivalRoute:
+                    continue
+
+                node = Node(inbound, None, None, None, None)
+                node.EstimatedTouchdownTime = inbound.PlannedArrivalTime
+                node.EstimatedIafAltitude = inbound.PlannedArrivalRoute[0].Altitude
+                node.EstimatedIafTime = inbound.PlannedArrivalRoute[0].PTA
+
+                if inbound.PlannedRunway.Name in runwayInbounds:
+                    if None == runwayInbounds[inbound.PlannedRunway.Name] or runwayInbounds[inbound.PlannedRunway.Name].EstimatedTouchdownTime < node.EstimatedTouchdownTime:
+                        runwayInbounds[inbound.PlannedRunway.Name] = node
+
+                if inbound.PlannedArrivalRoute[0].Name in iafInbounds:
+                    delta = 100000.0
+                    targetLevel = None
+                    for level in iafInbounds[inbound.PlannedArrivalRoute[0].Name]:
+                        difference = abs(level - inbound.PlannedArrivalRoute[0].Altitude)
+                        if difference < delta:
+                            delta = difference
+                            targetLevel = level
+
+                    if None == iafInbounds[inbound.PlannedArrivalRoute[0].Name][targetLevel]:
+                        iafInbounds[inbound.PlannedArrivalRoute[0].Name][targetLevel] = Node
+                    elif iafInbounds[inbound.PlannedArrivalRoute[0].Name][targetLevel].EstimatedIafTime < node.EstimatedIafTime:
+                        iafInbounds[inbound.PlannedArrivalRoute[0].Name][targetLevel] = Node
+
+        return runwayInbounds, iafInbounds
 
     def optimizationRelevantInbounds(self):
         # no new inbounds

+ 2 - 6
aman/sys/Worker.py

@@ -102,16 +102,12 @@ class Worker(Thread):
 
                 # 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)
+                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,
-                                          preceeding = None if 0 == len(preceedingInbounds) else preceedingInbounds,
+                                          preceedingRunways = runways, preceedingIafs = iafs,
                                           ants = 5 * len(relevantInbounds), generations = 5 * len(relevantInbounds))
 
                 # perform the ACO run

+ 2 - 1
aman/sys/aco/Configuration.py

@@ -6,7 +6,8 @@ class Configuration:
     def __init__(self, **kwargs):
         # the AMAN specific information
         self.RunwayConstraints = kwargs.get('constraints', None)
-        self.PreceedingInbounds = kwargs.get('preceeding', None)
+        self.PreceedingRunwayInbounds = kwargs.get('preceedingRunways', None)
+        self.PreceedingIafInbounds = kwargs.get('preceedingIafs', None)
         self.EarliestArrivalTime = kwargs.get('earliest', None)
         self.WeatherModel = kwargs.get('weather', None)
         self.AirportConfiguration = kwargs.get('config', None)

+ 4 - 8
aman/sys/aco/RunwayManager.py

@@ -1,5 +1,7 @@
 #!/usr/bin/env python
 
+import copy
+
 from datetime import datetime, timedelta
 
 from aman.config.RunwaySequencing import RunwayAssignmentType
@@ -11,15 +13,9 @@ class RunwayManager:
     def __init__(self, configuration : Configuration):
         self.Spacings = SpacingConstraints()
         self.Configuration = configuration
+        self.RunwayInbounds = copy.deepcopy(configuration.PreceedingRunwayInbounds)
+        self.IafInbounds = copy.deepcopy(configuration.PreceedingIafInbounds)
 
-        # initialize the tracker which inbound arrives at which runway
-        self.RunwayInbounds = {}
-        if None != configuration.PreceedingInbounds:
-            for runway in configuration.PreceedingInbounds:
-                self.RunwayInbounds[runway] = configuration.PreceedingInbounds[runway]
-        for runway in configuration.RunwayConstraints.ActiveArrivalRunways:
-            if not runway.Runway.Name in self.RunwayInbounds:
-                self.RunwayInbounds[runway.Runway.Name] = None
 
     def calculateEarliestArrivalTime(self, runway : str, node : Node, earliestArrivalTime : datetime):
         constrainedETA = None