RunwayManager.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env python
  2. from datetime import datetime, timedelta
  3. from aman.sys.aco.Configuration import Configuration
  4. from aman.sys.aco.Constraints import SpacingConstraints
  5. from aman.types.Inbound import Inbound
  6. class RunwayManager:
  7. def __init__(self, configuration : Configuration):
  8. self.Spacings = SpacingConstraints()
  9. self.Configuration = configuration
  10. # initialize the tracker which inbound arrives at which runway
  11. self.RunwayInbounds = {}
  12. if None != configuration.PreceedingInbounds:
  13. for runway in configuration.PreceedingInbounds:
  14. self.RunwayInbounds[runway] = configuration.PreceedingInbounds[runway]
  15. for runway in configuration.RunwayConstraints.ActiveArrivalRunways:
  16. if not runway.Runway.Name in self.RunwayInbounds:
  17. self.RunwayInbounds[runway.Runway.Name] = None
  18. def calculateEarliestArrivalTime(self, runway : str, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
  19. constrainedETA = None
  20. if None != self.RunwayInbounds[runway]:
  21. # get the WTC based ETA
  22. if None == self.RunwayInbounds[runway].WTC or None == inbound.WTC:
  23. spacingWTC = 3
  24. else:
  25. spacingWTC = self.Spacings[self.RunwayInbounds[runway].WTC][inbound.WTC]
  26. # get the runway time spacing
  27. spacingRunway = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
  28. constrainedETA = self.RunwayInbounds[runway].PlannedArrivalTime + timedelta(minutes = max(spacingWTC, spacingRunway) / (inbound.PerformanceData.SpeedApproach / 60))
  29. # calculate the arrival times for the dependent inbounds
  30. for dependentRunway in self.Configuration.RunwayConstraints.findDependentRunways(runway):
  31. if None != self.RunwayInbounds[dependentRunway.Runway.Name]:
  32. candidate = self.RunwayInbounds[dependentRunway.Runway.Name].PlannedArrivalTime + timedelta(minutes = 3 / (inbound.PerformanceData.SpeedApproach / 60))
  33. if None == constrainedETA or candidate > constrainedETA:
  34. constrainedETA = candidate
  35. # get the arrival time on the runway of the inbound
  36. if True == useITA:
  37. arrivalTime = inbound.ArrivalCandidates[runway].EarliestArrivalTime
  38. else:
  39. arrivalTime = inbound.ArrivalCandidates[runway].InitialArrivalTime
  40. if None == constrainedETA:
  41. return max(arrivalTime, earliestArrivalTime), timedelta(seconds = 0)
  42. else:
  43. eta = max(constrainedETA, earliestArrivalTime)
  44. if eta < arrivalTime:
  45. return arrivalTime, arrivalTime - eta
  46. else:
  47. return eta, timedelta(seconds = 0)
  48. def selectArrivalRunway(self, inbound : Inbound, useITA : bool, earliestArrivalTime : datetime):
  49. availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
  50. #if 1 < len(availableRunways):
  51. # TODO filter based on type
  52. # TODO filter based on airline
  53. # ensure that at least one runway is available
  54. # fallback to check if we have available runways
  55. if 0 == len(availableRunways):
  56. runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
  57. return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
  58. # start with the beginning
  59. selectedRunway = None
  60. lostTime = None
  61. eta = None
  62. # get the runway with the earliest ETA
  63. for runway in availableRunways:
  64. candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, inbound, useITA, earliestArrivalTime)
  65. if None == eta or eta > candidate:
  66. selectedRunway = runway.Runway
  67. lostTime = delta
  68. eta = candidate
  69. return selectedRunway, eta, lostTime