RunwayManager.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. if self.RunwayInbounds[runway].Inbound.WTC not in self.Spacings.WtcSpacing:
  27. spacingWTC = 3
  28. elif node.Inbound.WTC not in self.Spacings.WtcSpacing[self.RunwayInbounds[runway].Inbound.WTC]:
  29. spacingWTC = self.Spacings.WtcSpacing[self.RunwayInbounds[runway].Inbound.WTC]['L']
  30. else:
  31. spacingWTC = self.Spacings.WtcSpacing[self.RunwayInbounds[runway].Inbound.WTC][node.Inbound.WTC]
  32. # get the runway time spacing
  33. spacingRunway = self.Configuration.RunwayConstraints.findRunway(runway).Spacing
  34. constrainedETA = self.RunwayInbounds[runway].Inbound.PlannedArrivalTime + timedelta(minutes = max(spacingWTC, spacingRunway) / (node.Inbound.PerformanceData.SpeedApproach / 60))
  35. # calculate the arrival times for the dependent inbounds
  36. for dependentRunway in self.Configuration.RunwayConstraints.findDependentRunways(runway):
  37. if None != self.RunwayInbounds[dependentRunway.Runway.Name]:
  38. candidate = self.RunwayInbounds[dependentRunway.Runway.Name].Inbound.PlannedArrivalTime + timedelta(minutes = 3 / (node.Inbound.PerformanceData.SpeedApproach / 60))
  39. if None == constrainedETA or candidate > constrainedETA:
  40. constrainedETA = candidate
  41. if None == constrainedETA:
  42. eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, earliestArrivalTime)
  43. else:
  44. eta = max(node.ArrivalCandidates[runway].InitialArrivalTime, max(constrainedETA, earliestArrivalTime))
  45. return eta, eta - node.ArrivalCandidates[runway].InitialArrivalTime
  46. def selectShallShouldMayArrivalRunway(self, node : Node, runways, earliestArrivalTime : datetime):
  47. candidate = None
  48. delay = None
  49. for runway in runways:
  50. eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  51. if None == delay:
  52. delay = eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
  53. candidate = runway
  54. elif delay > (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime):
  55. delay = eta- node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime
  56. candidate = runway
  57. return candidate
  58. def executeShallShouldMayAssignment(self, node : Node, earliestArrivalTime : datetime):
  59. shallRunways = []
  60. shouldRunways = []
  61. mayRunways = []
  62. for runway in self.Configuration.RunwayConstraints.ActiveArrivalRunways:
  63. # test the shall assignments
  64. if RunwayAssignmentType.AircraftType in runway.ShallAssignments:
  65. if node.Inbound.Report.aircraft.type in runway.ShallAssignments[RunwayAssignmentType.AircraftType]:
  66. shallRunways.append(runway)
  67. if RunwayAssignmentType.GateAssignment in runway.ShallAssignments:
  68. if node.Inbound.Report.plannedGate in runway.ShallAssignments[RunwayAssignmentType.GateAssignment]:
  69. shallRunways.append(runway)
  70. # test the should assignments
  71. if RunwayAssignmentType.AircraftType in runway.ShouldAssignments:
  72. if node.Inbound.Report.aircraft.type in runway.ShouldAssignments[RunwayAssignmentType.AircraftType]:
  73. shouldRunways.append(runway)
  74. if RunwayAssignmentType.GateAssignment in runway.ShouldAssignments:
  75. if node.Inbound.Report.plannedGate in runway.ShouldAssignments[RunwayAssignmentType.GateAssignment]:
  76. shouldRunways.append(runway)
  77. # test the may assignments
  78. if RunwayAssignmentType.AircraftType in runway.MayAssignments:
  79. if node.Inbound.Report.aircraft.type in runway.MayAssignments[RunwayAssignmentType.AircraftType]:
  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. if RunwayAssignmentType.GateAssignment in runway.MayAssignments:
  84. if node.Inbound.Report.plannedGate in runway.MayAssignments[RunwayAssignmentType.GateAssignment]:
  85. eta, _ = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  86. if (eta - node.ArrivalCandidates[runway.Runway.Name].InitialArrivalTime) <= self.Configuration.AirportConfiguration.MaxDelayMay:
  87. mayRunways.append(runway)
  88. runway = self.selectShallShouldMayArrivalRunway(node, shallRunways, earliestArrivalTime)
  89. if None != runway:
  90. return [ runway ]
  91. runway = self.selectShallShouldMayArrivalRunway(node, shouldRunways, earliestArrivalTime)
  92. if None != runway:
  93. return [ runway ]
  94. runway = self.selectShallShouldMayArrivalRunway(node, mayRunways, earliestArrivalTime)
  95. if None != runway:
  96. return [ runway ]
  97. return self.Configuration.RunwayConstraints.ActiveArrivalRunways
  98. def selectArrivalRunway(self, node : Node, earliestArrivalTime : datetime):
  99. availableRunways = self.Configuration.RunwayConstraints.ActiveArrivalRunways
  100. if 0 == len(availableRunways):
  101. return None, None, None
  102. if True == self.Configuration.RunwayConstraints.UseShallShouldMay and None == node.Inbound.RequestedRunway:
  103. availableRunways = self.executeShallShouldMayAssignment(node, earliestArrivalTime)
  104. elif None != node.Inbound.RequestedRunway:
  105. for runway in availableRunways:
  106. if node.Inbound.RequestedRunway == runway.Runway.Name:
  107. availableRunways = [ runway ]
  108. break
  109. if 0 == len(availableRunways):
  110. runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
  111. eta, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  112. return runway, eta, delta
  113. # start with the beginning
  114. selectedRunway = None
  115. lostTime = None
  116. eta = None
  117. # get the runway with the earliest ETA
  118. for runway in availableRunways:
  119. candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  120. if None == eta or eta > candidate:
  121. selectedRunway = runway.Runway
  122. lostTime = delta
  123. eta = candidate
  124. return selectedRunway, eta, lostTime