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))
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
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