RunwayManager.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 True == self.Configuration.RunwayConstraints.UseShallShouldMay and None == node.Inbound.RequestedRunway:
  101. availableRunways = self.executeShallShouldMayAssignment(node, earliestArrivalTime)
  102. elif None != node.Inbound.RequestedRunway:
  103. for runway in availableRunways:
  104. if node.Inbound.RequestedRunway == runway.Runway.Name:
  105. availableRunways = [ runway ]
  106. break
  107. if 0 == len(availableRunways):
  108. runway = self.Configuration.RunwayConstraints.ActiveArrivalRunways[0]
  109. eta, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  110. return runway, eta, delta
  111. # start with the beginning
  112. selectedRunway = None
  113. lostTime = None
  114. eta = None
  115. # get the runway with the earliest ETA
  116. for runway in availableRunways:
  117. candidate, delta = self.calculateEarliestArrivalTime(runway.Runway.Name, node, earliestArrivalTime)
  118. if None == eta or eta > candidate:
  119. selectedRunway = runway.Runway
  120. lostTime = delta
  121. eta = candidate
  122. return selectedRunway, eta, lostTime