Kaynağa Gözat

fix some bugs in the runway manager during the ETA calculation

Sven Czarnian 3 yıl önce
ebeveyn
işleme
c09a5ffe77
2 değiştirilmiş dosya ile 48 ekleme ve 51 silme
  1. 6 6
      aman/config/AirportSequencing.py
  2. 42 45
      aman/sys/aco/RunwayManager.py

+ 6 - 6
aman/config/AirportSequencing.py

@@ -74,16 +74,16 @@ class AirportSequencing:
                 return runway
         return None
 
-    def findDependentRunway(self, identifier : str):
+    def findDependentRunways(self, identifier : str):
         # runway is unknown
         index = self.runwayIndex(identifier)
         if 0 > index:
-            return None
+            return []
 
         # search the dependency pair
+        dependencies = []
         for dependency in self.RunwayDependencies:
-            if index == dependency[0]:
-                return self.ActiveArrivalRunways[dependency[1]]
+            if index == dependency[0] and not self.ActiveArrivalRunways[dependency[1]] in dependencies:
+                dependencies.append(self.ActiveArrivalRunways[dependency[1]])
 
-        # no dependencies found
-        return None
+        return dependencies

+ 42 - 45
aman/sys/aco/RunwayManager.py

@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-from datetime import timedelta
+from datetime import datetime, timedelta
 
 from aman.sys.aco.Configuration import Configuration
 from aman.sys.aco.Constraints import SpacingConstraints
@@ -22,57 +22,52 @@ class RunwayManager:
 
     def validateWtc(inbound : Inbound):
         wtc = inbound.Report.aircraft.wtc.upper()
-        if 'L' == wtc or 'M' == wtc or 'H' == None or 'J' == None:
+        if 'L' == wtc or 'M' == wtc or 'H' == wtc or 'J' == wtc:
             return wtc
         else:
             return None
 
-    def calculateEarliestArrivalTime(self, runway : str, inbound : Inbound):
-        if None == self.RunwayInbounds[runway]:
-            return inbound.ArrivalCandidates[runway].EarliestArrivalTime
+    def calculateEarliestArrivalTime(self, runway : str, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
+        earliestArrivalTimes = []
 
-        preceedingInbound = self.RunwayInbounds[runway]
-
-        # get the WTC constrained ETA
-        wtcPre = RunwayManager.validateWtc(preceedingInbound)
-        wtcThis = RunwayManager.validateWtc(inbound)
-        if None == wtcPre or None == wtcThis:
-            spacing = 3
-        else:
-            spacing = self.Spacings[wtcPre][wtcThis]
-        delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
-        wtcEarliestArrivalTime = preceedingInbound.PlannedArrivalTime + delay
-
-        # get the staggered time spacing
-        dependentRunway = self.Configuration.RunwayConstraints.findDependentRunway(runway)
-        if None != dependentRunway and None != self.RunwayInbounds[dependentRunway.Runway.Name]:
-            # check if the one on the same runway lands before the one on the parallel runway
-            if preceedingInbound.PlannedArrivalTime < self.RunwayInbounds[dependentRunway.Runway.Name].PlannedArrivalTime:
-                delay = timedelta(minutes = 3 / (inbound.PerformanceData.SpeedApproach / 60))
-                staggeredEarliestArrivalTime = self.RunwayInbounds[dependentRunway.Runway.Name].PlannedArrivalTime + delay
-            # landing on the same runway
+        if None != self.RunwayInbounds[runway]:
+            # get the WTC based ETA
+            wtcPre = RunwayManager.validateWtc(self.RunwayInbounds[runway])
+            wtcThis = RunwayManager.validateWtc(inbound)
+            if None == wtcPre or None == wtcThis:
+                spacing = 3
             else:
-                staggeredEarliestArrivalTime = wtcEarliestArrivalTime
-        # no neighbor or no dependent runway (IPA)
-        else:
-            staggeredEarliestArrivalTime = wtcEarliestArrivalTime
-
-        # get the runway time spacing
-        spacing = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
-        delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
-        runwayEarliestArrivalTime = preceedingInbound.PlannedArrivalTime + delay
+                spacing = self.Spacings[wtcPre][wtcThis]
+            delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
+            earliestArrivalTimes.append(self.RunwayInbounds[runway].PlannedArrivalTime + delay)
+
+            # get the runway time spacing
+            spacing = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
+            delay = timedelta(minutes = spacing / (inbound.PerformanceData.SpeedApproach / 60))
+            earliestArrivalTimes.append(self.RunwayInbounds[runway].PlannedArrivalTime + delay)
+
+        # calculate the arrival times for the dependent inbounds
+        for dependentRunway in self.Configuration.RunwayConstraints.findDependentRunways(runway):
+            if None != self.RunwayInbounds[dependentRunway.Runway.Name]:
+                delay = timedelta(minutes = 3 / (inbound.PerformanceData.SpeedApproach / 60))
+                earliestArrivalTimes.append(self.RunwayInbounds[dependentRunway.Runway.Name].PlannedArrivalTime + delay)
 
-        # the candidate with the latest ETA is used -> ensure all safety and procedure constraints
-        candidate = max(max(wtcEarliestArrivalTime, staggeredEarliestArrivalTime), runwayEarliestArrivalTime)
+        # get the arrival time on the runway of the inbound
+        if True == useITA:
+            arrivalTime = inbound.ArrivalCandidates[runway].EarliestArrivalTime
+        else:
+            arrivalTime = inbound.ArrivalCandidates[runway].InitialArrivalTime
 
-        # check if inbound comes later than the latest possible ETA
-        if candidate < inbound.ArrivalCandidates[runway].EarliestArrivalTime:
-            return inbound.ArrivalCandidates[runway].EarliestArrivalTime
-        # candidate fits into earliest arrival time or is later than this
+        if 0 == len(earliestArrivalTimes):
+            return arrivalTime, timedelta(seconds = 0)
         else:
-            return candidate
+            eta = max(earliestArrivalTimes)
+            if eta < arrivalTime:
+                return arrivalTime, arrivalTime - eta
+            else:
+                return eta, timedelta(seconds = 0)
 
-    def selectArrivalRunway(self, inbound : Inbound):
+    def selectArrivalRunway(self, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
         availableRunways = []
         for runway in self.Configuration.RunwayConstraints.ActiveArrivalRunways:
             availableRunways.append(runway)
@@ -85,17 +80,19 @@ class RunwayManager:
         # fallback to check if we have available runways
         if 0 == len(availableRunways):
             runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
-            return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, inbound)
+            return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
 
         # start with the beginning
         selectedRunway = None
+        lostTime = None
         eta = None
 
         # get the runway with the earliest ETA
         for runway in availableRunways:
-            candidate = self.calculateEarliestArrivalTime(runway.Runway.Name, inbound)
+            candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
             if None == eta or eta > candidate:
                 selectedRunway = runway.Runway
+                lostTime = delta
                 eta = candidate
 
-        return selectedRunway, eta
+        return selectedRunway, eta, lostTime