예제 #1
0
def rank_origins(origins, destinations):
    
    p('debug', 'Ranking origins: %s' % origins)

    midpoint_origins = midpoint(origins)
    midpoint_destinations = midpoint(destinations)
    hub_route = Segment(midpoint_origins, midpoint_destinations)
    for origin in origins:
        
        AC = Segment(midpoint_origins, origin)
        orthogonal_heading = hub_route.get_initial_bearing() + 90    
        (a, b) = project_segment(
            abs(orthogonal_heading - AC.get_initial_bearing()),
            AC.get_length()
        )
        projection = midpoint_origins.get_position(
            orthogonal_heading, a
        )
        midpoint_to_projection = Segment(
            midpoint_origins,
            projection
        )
        
        angle = abs(
            hub_route.get_initial_bearing() - 
            midpoint_to_projection.get_initial_bearing()
        )
        if abs(angle - 90) < 0.1:
            distance = -1 * midpoint_to_projection.get_length()
        else:
            distance = midpoint_to_projection.get_length()
        origin.distance_to_midpoint = distance
        
    return sorted(origins, key = lambda point: point.distance_to_midpoint)
예제 #2
0
def rank_origins(origins, destinations):

    p('debug', 'Ranking origins: %s' % origins)

    midpoint_origins = midpoint(origins)
    midpoint_destinations = midpoint(destinations)
    hub_route = Segment(midpoint_origins, midpoint_destinations)
    for origin in origins:

        AC = Segment(midpoint_origins, origin)
        orthogonal_heading = hub_route.get_initial_bearing() + 90
        (a, b) = project_segment(
            abs(orthogonal_heading - AC.get_initial_bearing()),
            AC.get_length())
        projection = midpoint_origins.get_position(orthogonal_heading, a)
        midpoint_to_projection = Segment(midpoint_origins, projection)

        angle = abs(hub_route.get_initial_bearing() -
                    midpoint_to_projection.get_initial_bearing())
        if abs(angle - 90) < 0.1:
            distance = -1 * midpoint_to_projection.get_length()
        else:
            distance = midpoint_to_projection.get_length()
        origin.distance_to_midpoint = distance

    return sorted(origins, key=lambda point: point.distance_to_midpoint)
def is_valid_formation(aircraft_list):

    # Get the segments
    segments = map(lambda aircraft: aircraft.route.segments[0], aircraft_list)

    # Find the reference point collection of segments
    midpoints = map(lambda x: x.midpoint, segments)
    reference = util.midpoint (midpoints)
    deviation_sum = 0
    
    for segment in segments:

        crosstrack = Segment(segment.start, reference)
        
        deviation = util.cross_track_distance (
            crosstrack.get_length(),
            crosstrack.get_initial_bearing(),
            segment.get_initial_bearing()
        )
        deviation_sum = deviation_sum + abs(deviation)

        if abs(deviation) > config.max_deviation:
            return False

        #print '%s (ref = %s) crosstrack distance: %.1f' %\
              #(segment, reference, d_x)

    return deviation_sum
def get_exit(hub, trunk_route, flight):
    dest = flight['route'].waypoints[-1]
    hub_to_dest = Segment(hub, dest)
    theta = abs(hub_to_dest.get_initial_bearing() -
                trunk_route.get_initial_bearing())
    (a, b) = project_segment(theta, hub_to_dest.get_length())
    Q = get_hookoff_quotient(a, b, config.alpha)
    d_hub_to_exit = a * Q
    
    # Exit to destination must be long enough to allow for safe descent
    # TOD is at 150NM out of dest, so exit->dest must be longer than 150NM
    d_exit_to_dest = 0
    while d_exit_to_dest < 150:
        exit_point = hub.get_position(
            trunk_route.get_initial_bearing(),
            d_hub_to_exit
        )
        d_hub_to_exit -= 1
        exit_dest = Segment(exit_point, dest)
        d_exit_to_dest = exit_dest.get_length()
    assert exit_dest.get_length() > 150
    print 'For flight %s, the exit point is %dNM away from dest' % (
        flight['route'], d_exit_to_dest
    )
    return exit_point
def get_hub(flights):
    o = []
    d = []
    for flight in flights:
        o.append(flight['route'].waypoints[0])
        d.append(flight['route'].waypoints[-1])
    mid_o = midpoint(o)
    mid_d = midpoint(d)
    trunk_route = Segment(mid_o, mid_d)
    return mid_o.get_position(trunk_route.get_initial_bearing(),
                              trunk_route.get_length() * config.Z)
예제 #6
0
        def heading_filter(buddy):

            segment = Segment(buddy.hub, buddy.destination)
            buddy_heading = segment.get_initial_bearing()
            phi_obs = abs(leader_heading - buddy_heading)
            p(
                'debug',
                'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)'
                ': %.2f degrees' %
                (aircraft, leader_heading, buddy, buddy_heading, phi_obs))
            return phi_obs <= (config.phi_max / 2)
예제 #7
0
def handle_alive(event):

    global vars

    formation = event.sender
    
    # We should have a hookoff point for each participant, and it should be
    # the current segment
    for aircraft in formation:
        assert aircraft.hookoff_point
        # The remaining segment should be hookoff-destination
        #debug.print_object(aircraft)
        assert len(aircraft.route.segments) > 0

        # Let the aircraft know in which formation it belongs
        aircraft.formation = formation

        #assert aircraft.route.segments[0].end.coincides(
        #    aircraft.hookoff_point
        #)
    
    vars["formation_count"] += 1
    vars['formation_aircraft_count'] += len(formation)
    
    formation_phi = 0
    for aircraft in formation:
        
        hub_to_dest = Segment(aircraft.hub, aircraft.destination)
        hub_to_hookoff = Segment(aircraft.hub, aircraft.hookoff_point)
        
        bearing = hub_to_dest.get_initial_bearing()
        formation_bearing = hub_to_hookoff.get_initial_bearing()
        phi_obs = abs(bearing - formation_bearing)
        p('debug', 'Aircraft %s, phi_obs: %.2f' % (aircraft, phi_obs))
        #assert phi_obs <= config.phi_max
        formation_phi += phi_obs
        #print aircraft.route.segments[0].initial_bearing()
    vars['phi_obs_sum'] += formation_phi
        
    for aircraft in formation:
        vars['Q_sum']   = vars['Q_sum'] + aircraft.Q
예제 #8
0
def handle_alive(event):

    global vars

    formation = event.sender

    # We should have a hookoff point for each participant, and it should be
    # the current segment
    for aircraft in formation:
        assert aircraft.hookoff_point
        # The remaining segment should be hookoff-destination
        #debug.print_object(aircraft)
        assert len(aircraft.route.segments) > 0

        # Let the aircraft know in which formation it belongs
        aircraft.formation = formation

        #assert aircraft.route.segments[0].end.coincides(
        #    aircraft.hookoff_point
        #)

    vars["formation_count"] += 1
    vars['formation_aircraft_count'] += len(formation)

    formation_phi = 0
    for aircraft in formation:

        hub_to_dest = Segment(aircraft.hub, aircraft.destination)
        hub_to_hookoff = Segment(aircraft.hub, aircraft.hookoff_point)

        bearing = hub_to_dest.get_initial_bearing()
        formation_bearing = hub_to_hookoff.get_initial_bearing()
        phi_obs = abs(bearing - formation_bearing)
        p('debug', 'Aircraft %s, phi_obs: %.2f' % (aircraft, phi_obs))
        #assert phi_obs <= config.phi_max
        formation_phi += phi_obs
        #print aircraft.route.segments[0].initial_bearing()
    vars['phi_obs_sum'] += formation_phi

    for aircraft in formation:
        vars['Q_sum'] = vars['Q_sum'] + aircraft.Q
예제 #9
0
        def heading_filter(buddy):

            segment = Segment(buddy.hub, buddy.destination)
            buddy_heading = segment.get_initial_bearing()
            phi_obs = abs(leader_heading - buddy_heading)
            p(
                'debug',
                'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)'
                ': %.2f degrees' % (
                    aircraft, leader_heading, buddy, buddy_heading, phi_obs
                )
            )
            return phi_obs <= (config.phi_max/2)
def get_hub(flights):
    o = []
    d = []
    for flight in flights:
        o.append(flight['route'].waypoints[0])
        d.append(flight['route'].waypoints[-1])
    mid_o = midpoint(o)
    mid_d = midpoint(d)
    trunk_route = Segment(mid_o, mid_d)
    return mid_o.get_position(
        trunk_route.get_initial_bearing(),
        trunk_route.get_length() * config.Z
    )
예제 #11
0
def construct_hub(origins, destinations, Z):

    midpoint_origins = midpoint(origins)
    midpoint_destinations = midpoint(destinations)

    hub_route = Segment(midpoint_origins, midpoint_destinations)
    hub = hub_route.start.get_position(hub_route.get_initial_bearing(),
                                       hub_route.get_length() * Z)

    hub.origins = origins
    hub.destinations = destinations

    p('debug', 'Constructed hub at %s' % (hub))

    return hub
예제 #12
0
def construct_hub(origins, destinations, Z):

    midpoint_origins      = midpoint(origins)
    midpoint_destinations = midpoint(destinations)
    
    hub_route = Segment(midpoint_origins, midpoint_destinations)
    hub = hub_route.start.get_position(
        hub_route.get_initial_bearing(),
        hub_route.get_length() * Z
    )
    
    hub.origins      = origins
    hub.destinations = destinations
    
    p('debug', 'Constructed hub at %s' % (hub))
    
    return hub
def get_exit(hub, trunk_route, flight):
    dest = flight['route'].waypoints[-1]
    hub_to_dest = Segment(hub, dest)
    theta = abs(hub_to_dest.get_initial_bearing() -
                trunk_route.get_initial_bearing())
    (a, b) = project_segment(theta, hub_to_dest.get_length())
    Q = get_hookoff_quotient(a, b, config.alpha)
    d_hub_to_exit = a * Q

    # Exit to destination must be long enough to allow for safe descent
    # TOD is at 150NM out of dest, so exit->dest must be longer than 150NM
    d_exit_to_dest = 0
    while d_exit_to_dest < 150:
        exit_point = hub.get_position(trunk_route.get_initial_bearing(),
                                      d_hub_to_exit)
        d_hub_to_exit -= 1
        exit_dest = Segment(exit_point, dest)
        d_exit_to_dest = exit_dest.get_length()
    assert exit_dest.get_length() > 150
    print 'For flight %s, the exit point is %dNM away from dest' % (
        flight['route'], d_exit_to_dest)
    return exit_point
예제 #14
0
    def allocate(self, aircraft):
        
        p('debug', 'Starting formation allocation for %s' % aircraft)
        
        # Do not perform allocation if no hub exists in the flight route.
        if len(aircraft.route.segments) == 0:
            return

        self.formations = []
        intervals       = []
        candidates      = self.aircraft_queue
        hub             = aircraft.route.waypoints[0]

        # This is bad. We don't want to filter anything. 
        # @todo: pre-process at a higher level.
        # Only consider other aircraft flying to the same hub
        candidates = filter(lambda a: a.route.waypoints[0] is hub, 
                            candidates)
        
        p('debug', 'Full candidate set: %s' % candidates)

        # Only consider aircraft having a maximum heading difference between
        # the hub and their destination
        segment = Segment(aircraft.hub, aircraft.destination)
        leader_heading = segment.get_initial_bearing()

        def heading_filter(buddy):

            segment = Segment(buddy.hub, buddy.destination)
            buddy_heading = segment.get_initial_bearing()
            phi_obs = abs(leader_heading - buddy_heading)
            p(
                'debug',
                'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)'
                ': %.2f degrees' % (
                    aircraft, leader_heading, buddy, buddy_heading, phi_obs
                )
            )
            return phi_obs <= (config.phi_max/2)

        candidates = filter(heading_filter, candidates)

        # Other interesting filters
        if 'same-airline' in config.restrictions:
            airline = aircraft.label[0:2]
            candidates = filter(lambda a: a.label[0:2] == airline,
                                candidates)
        if 'same-aircraft-type' in config.restrictions:
            aircraft_type = aircraft.aircraft_type
            candidates = filter(lambda a: a.aircraft_type == aircraft_type,
                                candidates)
        
        p('debug', 'Reduced candidate set: %s' % candidates)

        for candidate in candidates:

            # Quick and dirty: recalc position. Instead, pull eta from var.
            candidate.controller.update_position()
            tth = candidate.time_to_waypoint() # time to hub
            hub_eta = sim.time + tth
            
            # From the moment the aircraft enters the lock area, the slack
            # decreases linearly to zero upon hub arrival.
            if tth < config.lock_time:
                slack = tth * config.etah_slack / config.lock_time
            else:
                slack = config.etah_slack

            p('Time = %s, Hub (= %s) eta %s for candidate %s' %\
              (sim.time, hub, hub_eta, candidate))
            intervals.append(Interval(
                candidate,
                int(hub_eta) - slack,
                int(hub_eta) + slack
            ))
            
        for interval_group in group(intervals):
            formation = Formation()
            for interval in interval_group:
                formation.append(interval.obj)
            self.formations.append(formation)
예제 #15
0
    def allocate(self, aircraft):

        p('debug', 'Starting formation allocation for %s' % aircraft)

        # Do not perform allocation if no hub exists in the flight route.
        if len(aircraft.route.segments) == 0:
            return

        self.formations = []
        intervals = []
        candidates = self.aircraft_queue
        hub = aircraft.route.waypoints[0]

        # This is bad. We don't want to filter anything.
        # @todo: pre-process at a higher level.
        # Only consider other aircraft flying to the same hub
        candidates = filter(lambda a: a.route.waypoints[0] is hub, candidates)

        p('debug', 'Full candidate set: %s' % candidates)

        # Only consider aircraft having a maximum heading difference between
        # the hub and their destination
        segment = Segment(aircraft.hub, aircraft.destination)
        leader_heading = segment.get_initial_bearing()

        def heading_filter(buddy):

            segment = Segment(buddy.hub, buddy.destination)
            buddy_heading = segment.get_initial_bearing()
            phi_obs = abs(leader_heading - buddy_heading)
            p(
                'debug',
                'delta phi observed for %s (phi: %.2f) against %s (phi: %.2f)'
                ': %.2f degrees' %
                (aircraft, leader_heading, buddy, buddy_heading, phi_obs))
            return phi_obs <= (config.phi_max / 2)

        candidates = filter(heading_filter, candidates)

        # Other interesting filters
        if 'same-airline' in config.restrictions:
            airline = aircraft.label[0:2]
            candidates = filter(lambda a: a.label[0:2] == airline, candidates)
        if 'same-aircraft-type' in config.restrictions:
            aircraft_type = aircraft.aircraft_type
            candidates = filter(lambda a: a.aircraft_type == aircraft_type,
                                candidates)

        p('debug', 'Reduced candidate set: %s' % candidates)

        for candidate in candidates:

            # Quick and dirty: recalc position. Instead, pull eta from var.
            candidate.controller.update_position()
            tth = candidate.time_to_waypoint()  # time to hub
            hub_eta = sim.time + tth

            # From the moment the aircraft enters the lock area, the slack
            # decreases linearly to zero upon hub arrival.
            if tth < config.lock_time:
                slack = tth * config.etah_slack / config.lock_time
            else:
                slack = config.etah_slack

            p('Time = %s, Hub (= %s) eta %s for candidate %s' %\
              (sim.time, hub, hub_eta, candidate))
            intervals.append(
                Interval(candidate,
                         int(hub_eta) - slack,
                         int(hub_eta) + slack))

        for interval_group in group(intervals):
            formation = Formation()
            for interval in interval_group:
                formation.append(interval.obj)
            self.formations.append(formation)