RunwayManager.py 7.7 KB

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