RunwayManager.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env python
  2. from datetime import datetime, timedelta
  3. from aman.config.RunwaySequencing import RunwayAssignmentType
  4. from aman.sys.aco.Configuration import Configuration
  5. from aman.sys.aco.Constraints import SpacingConstraints
  6. from aman.sys.aco.Node import Node
  7. class RunwayManager:
  8. def __init__(self, configuration : Configuration):
  9. self.Spacings = SpacingConstraints()
  10. self.Configuration = configuration
  11. # initialize the tracker which inbound arrives at which runway
  12. self.RunwayInbounds = {}
  13. if None != configuration.PreceedingInbounds:
  14. for runway in configuration.PreceedingInbounds:
  15. self.RunwayInbounds[runway] = configuration.PreceedingInbounds[runway]
  16. for runway in configuration.RunwayConstraints.ActiveArrivalRunways:
  17. if not runway.Runway.Name in self.RunwayInbounds:
  18. self.RunwayInbounds[runway.Runway.Name] = None
  19. def calculateEarliestArrivalTime(self, runway : str, node : Node, earliestArrivalTime : datetime):
  20. constrainedETA = None
  21. if None != self.RunwayInbounds[runway]:
  22. # get the WTC based ETA
  23. if None == self.RunwayInbounds[runway].Inbound.WTC or None == node.Inbound.WTC:
  24. spacingWTC = 3
  25. else:
  26. spacingWTC = self.Spacings[self.RunwayInbounds[runway].Inbound.WTC][node.Inbound.WTC]
  27. # get the runway time spacing
  28. spacingRunway = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
  29. constrainedETA = self.RunwayInbounds[runway].Inbound.PlannedArrivalTime + timedelta(minutes = max(spacingWTC, spacingRunway) / (node.Inbound.PerformanceData.SpeedApproach / 60))
  30. # calculate the arrival times for the dependent inbounds
  31. for dependentRunway in self.Configuration.RunwayConstraints.findDependentRunways(runway):
  32. if None != self.RunwayInbounds[dependentRunway.Runway.Name]:
  33. candidate = self.RunwayInbounds[dependentRunway.Runway.Name].Inbound.PlannedArrivalTime + timedelta(minutes = 3 / (node.Inbound.PerformanceData.SpeedApproach / 60))
  34. if None == constrainedETA or candidate > constrainedETA:
  35. constrainedETA = candidate
  36. if None == constrainedETA:
  37. eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, earliestArrivalTime)
  38. else:
  39. eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, max(constrainedETA, earliestArrivalTime))
  40. return eta, eta - node.ArrivalCandidates[runway].InitialArrivalTime
  41. def selectShallShouldMayArrivalRunway(self, node : Node, runways, earliestArrivalTime : datetime):
  42. candidate = None
  43. delay = None
  44. for runway in runways:
  45. eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  46. if None == delay:
  47. delay = eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
  48. candidate = runway
  49. elif delay > (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime):
  50. delay = eta- node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
  51. candidate = runway
  52. return candidate
  53. def executeShallShouldMayAssignment(self, node : Node, earliestArrivalTime : datetime):
  54. shallRunways = []
  55. shouldRunways = []
  56. mayRunways = []
  57. for runway in self.Configuration.RunwayConstraints.ActiveArrivalRunways:
  58. # test the shall assignments
  59. if RunwayAssignmentType.AircraftType in runway.ShallAssignments:
  60. if node.Inbound.Report.aircraft.type in runway.ShallAssignments[RunwayAssignmentType.AircraftType]:
  61. shallRunways.append(runway)
  62. if RunwayAssignmentType.GateAssignment in runway.ShallAssignments:
  63. if node.Inbound.Report.plannedGate in runway.ShallAssignments[RunwayAssignmentType.GateAssignment]:
  64. shallRunways.append(runway)
  65. # test the should assignments
  66. if RunwayAssignmentType.AircraftType in runway.ShouldAssignments:
  67. if node.Inbound.Report.aircraft.type in runway.ShouldAssignments[RunwayAssignmentType.AircraftType]:
  68. shouldRunways.append(runway)
  69. if RunwayAssignmentType.GateAssignment in runway.ShouldAssignments:
  70. if node.Inbound.Report.plannedGate in runway.ShouldAssignments[RunwayAssignmentType.GateAssignment]:
  71. shouldRunways.append(runway)
  72. # test the may assignments
  73. if RunwayAssignmentType.AircraftType in runway.MayAssignments:
  74. if node.Inbound.Report.aircraft.type in runway.MayAssignments[RunwayAssignmentType.AircraftType]:
  75. eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  76. if (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime) <= self.Configuration.AirportConfiguration.MaxDelayMay:
  77. mayRunways.append(runway)
  78. if RunwayAssignmentType.GateAssignment in runway.MayAssignments:
  79. if node.Inbound.Report.plannedGate in runway.MayAssignments[RunwayAssignmentType.GateAssignment]:
  80. eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  81. if (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime) <= self.Configuration.AirportConfiguration.MaxDelayMay:
  82. mayRunways.append(runway)
  83. runway = self.selectShallShouldMayArrivalRunway(node, shallRunways, earliestArrivalTime)
  84. if None != runway:
  85. return [ runway ]
  86. runway = self.selectShallShouldMayArrivalRunway(node, shouldRunways, earliestArrivalTime)
  87. if None != runway:
  88. return [ runway ]
  89. runway = self.selectShallShouldMayArrivalRunway(node, mayRunways, earliestArrivalTime)
  90. if None != runway:
  91. return [ runway ]
  92. return self.Configuration.RunwayConstraints.ActiveArrivalRunways
  93. def selectArrivalRunway(self, node : Node, earliestArrivalTime : datetime):
  94. availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
  95. if True == self.Configuration.RunwayConstraints.UseShallShouldMay:
  96. availableRunways = self.executeShallShouldMayAssignment(node, earliestArrivalTime)
  97. else:
  98. availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
  99. if 0 == len(availableRunways):
  100. runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
  101. return runway, self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  102. # start with the beginning
  103. selectedRunway = None
  104. lostTime = None
  105. eta = None
  106. # get the runway with the earliest ETA
  107. for runway in availableRunways:
  108. candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  109. if None == eta or eta > candidate:
  110. selectedRunway = runway.Runway
  111. lostTime = delta
  112. eta = candidate
  113. return selectedRunway, eta, lostTime