diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bec3c5c..9c6525ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - `DynamicObstacle` cannot be hashed if some optional attributes are missing +- `TrafficLightCycle` does not invalidate cached cycle init timesteps after modification ## [2024.2] - 2024-07-22 diff --git a/commonroad/scenario/traffic_light.py b/commonroad/scenario/traffic_light.py index e46fc15a..d5856895 100644 --- a/commonroad/scenario/traffic_light.py +++ b/commonroad/scenario/traffic_light.py @@ -143,6 +143,9 @@ def cycle_elements(self) -> Union[None, List[TrafficLightCycleElement]]: @cycle_elements.setter def cycle_elements(self, cycle_elements: Union[None, List[TrafficLightCycleElement]]): self._cycle_elements = cycle_elements + # Invalidate cached attribute which was calculated based on the previous cycle elements + if hasattr(self, "_cycle_init_timesteps"): + del self._cycle_init_timesteps @property def time_offset(self) -> int: @@ -152,6 +155,9 @@ def time_offset(self) -> int: @time_offset.setter def time_offset(self, time_offset: int): self._time_offset = time_offset + # Invalidate cached attribute which was calculated based on the previous time offset + if hasattr(self, "_cycle_init_timesteps"): + del self._cycle_init_timesteps @property def active(self) -> bool: diff --git a/tests/scenario/test_traffic_light.py b/tests/scenario/test_traffic_light.py index 547167d4..f01a63f6 100644 --- a/tests/scenario/test_traffic_light.py +++ b/tests/scenario/test_traffic_light.py @@ -82,6 +82,33 @@ def test_get_state_at_time_step(self): light_cycle2 = TrafficLightCycle(cycle_elements=cycle, time_offset=10) assert light_cycle2.get_state_at_time_step(12) == cycle[1].state + def test_update_cycle_elements(self): + # Verify that get_state_at_time_step is still correct after the cycle was updated + cycle = [ + TrafficLightCycleElement(TrafficLightState.GREEN, 2), + TrafficLightCycleElement(TrafficLightState.YELLOW, 3), + TrafficLightCycleElement(TrafficLightState.RED, 2), + ] + light_cycle = TrafficLightCycle(cycle_elements=cycle, time_offset=0) + assert light_cycle.get_state_at_time_step(7) == cycle[0].state + + new_cycle = cycle + [TrafficLightCycleElement(TrafficLightState.RED_YELLOW, 1)] + light_cycle.cycle_elements = new_cycle + assert light_cycle.get_state_at_time_step(7) == new_cycle[-1].state + + def test_update_time_offset(self): + # Verify that get_state_at_time_step is still correct after the time offset was updated + cycle = [ + TrafficLightCycleElement(TrafficLightState.GREEN, 2), + TrafficLightCycleElement(TrafficLightState.YELLOW, 3), + TrafficLightCycleElement(TrafficLightState.RED, 2), + ] + light_cycle = TrafficLightCycle(cycle_elements=cycle, time_offset=0) + assert light_cycle.get_state_at_time_step(1) == cycle[0].state + + light_cycle.time_offset = 5 + assert light_cycle.get_state_at_time_step(1) == cycle[1].state + class TestTrafficLight(unittest.TestCase): def test_translate_rotate(self):