def test_retrieving_single_greenyellow_interval(self):
        """ test retrieving a single greenyellow interval of a signal group """
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        sg1 = SignalGroup(
            id="sg1",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)
        sg2 = SignalGroup(
            id="sg2",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        # WHEN
        fts = FixedTimeSchedule(**input_dict)

        # THEN
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=0),
                         input_dict["greenyellow_intervals"]["sg1"][0])
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=1),
                         input_dict["greenyellow_intervals"]["sg1"][1])
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg2, k=0),
                         input_dict["greenyellow_intervals"]["sg2"][0])
    def test_retrieving_single_interval_for_unkown_signalgroup(self):
        """ test retrieving greenyellow intervals of an unkown signal group """
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        # unkown signal group
        sg3 = SignalGroup(
            id="sg3",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        fts = FixedTimeSchedule(**input_dict)

        with self.assertRaises(ValueError):
            # WHEN trying to access greenyellow intervals of an unkown signal group
            fts.get_greenyellow_interval(sg3, k=0)
    def test_retrieving_single_interval_with_id(self):
        # GIVEN
        input_dict = TestFTSMethods.get_default_fts_inputs()
        sg1 = SignalGroup(
            id="sg1",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)
        sg2 = SignalGroup(
            id="sg2",
            traffic_lights=[TrafficLight(capacity=800, lost_time=1)],
            min_greenyellow=10,
            max_greenyellow=80,
            min_red=10,
            max_red=80)

        # WHEN
        fts = FixedTimeSchedule(**input_dict)

        # THEN using id should give the same information
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=0),
                         fts.get_greenyellow_interval(signalgroup=sg1.id, k=0))
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg1, k=1),
                         fts.get_greenyellow_interval(signalgroup=sg1.id, k=1))
        self.assertEqual(fts.get_greenyellow_interval(signalgroup=sg2, k=0),
                         fts.get_greenyellow_interval(signalgroup=sg2.id, k=0))
Example #4
0
def validate_fixed_order(intersection: Intersection, fts: FixedTimeSchedule,
                         periodic_order: PeriodicOrder) -> None:
    """ Validate that the the signalgroups indeed receive their greenyellow intervals
    in the requested periodic order (for only the periodic order that is given as argument).
    :return: -
    :raises SafetyException: if the requested order is not satisfied"""
    first_signalgroup = intersection.get_signalgroup(
        signalgroup_id=periodic_order.order[0])
    first_interval_start = fts.get_greenyellow_interval(first_signalgroup,
                                                        k=0).start_greenyellow
    prev_switch = 0
    for signalgroup in periodic_order.order:
        for interval in fts.get_greenyellow_intervals(signalgroup):
            # shift schedule such that first greenyellow interval of the first signalgroup in the order starts at time=0
            switch = (interval.start_greenyellow - first_interval_start +
                      EPSILON) % fts.period - EPSILON
            if switch < prev_switch:
                raise SafetyViolation(
                    f"Periodic order {periodic_order.to_json()} is violated")
            prev_switch = switch
Example #5
0
def find_other_sg_relation_matches(
    other_relation: Union[SyncStart, Offset, GreenyellowLead,
                          GreenyellowTrail],
    fts: FixedTimeSchedule,
    index_from: int,
    tolerance: float = 10**(-2)) -> List[bool]:
    """
    Find the greenyellow intervals of the signal group with id 'other_relation.to_id' that satisfies the specified
    inter signalgroup relation w.r.t. the greenyellow interval of signal group other_relation.from_id at index
    'index_from'
    :param other_relation: the other relation (sync start, offset or greenyellow-lead)
    :param fts: fixed-time schedule
    :param index_from: see above
    :param tolerance: tolerance in seconds for violating safety restrictions
    :return: boolean list indicating the matches.
    """
    # Get the greenyellow intervals of the associated signal groups
    interval_from = fts.get_greenyellow_interval(
        signalgroup=other_relation.from_id, k=index_from)
    intervals_to = fts.get_greenyellow_intervals(
        signalgroup=other_relation.to_id)

    matches = [False] * len(intervals_to)

    if isinstance(other_relation, (SyncStart, Offset, GreenyellowLead)):
        time_from = interval_from.start_greenyellow
    elif isinstance(other_relation, GreenyellowTrail):
        time_from = interval_from.end_greenyellow
    else:
        raise ValueError(UNKNOWN_TYPE_OTHER_RELATION)
    for index_to in range(len(intervals_to)):
        if isinstance(other_relation, (SyncStart, Offset, GreenyellowLead)):
            time_to = intervals_to[index_to].start_greenyellow
        elif isinstance(other_relation, GreenyellowTrail):
            time_to = intervals_to[index_to].end_greenyellow
        else:
            raise ValueError(UNKNOWN_TYPE_OTHER_RELATION)

        # determine the desired range of the time between time_from and time_to.
        if isinstance(other_relation, SyncStart):
            min_time = 0
            max_time = 0
        elif isinstance(other_relation, Offset):
            min_time = other_relation.seconds
            max_time = other_relation.seconds
        elif isinstance(other_relation, (GreenyellowLead, GreenyellowTrail)):
            min_time = other_relation.min_seconds
            max_time = other_relation.max_seconds
        else:
            raise ValueError(UNKNOWN_TYPE_OTHER_RELATION)

        # Determine the actual time between time_from and time_to. We correct for min_time potentially being negative.
        time_between = (time_to - time_from -
                        (min_time - tolerance)) % fts.period + (min_time -
                                                                tolerance)

        # Note that result is time_between in [other_relation.min_time, other_relation.min_time + period]
        if min_time - tolerance < time_between < max_time + tolerance:
            matches[index_to] = True

    return matches