Source code for commonroad.scenario.intersection

import warnings
from typing import Dict, List, Set

from commonroad.common.validity import is_natural_number


[docs]class IntersectionIncomingElement: """ This class represents an incoming element of an intersection. An incoming can consist of several adjacent lanelets which lead to an intersection, right, straight, and left successor lanelets, and a reference to the incoming located on the left side. The right/straight/left successors are used to infer for which lanelets the traffic light is valid for and to facilitate the calculation of priorities at intersections. The left incoming is used to infer the right-before-left-rule. """ def __init__( self, incoming_id: int, incoming_lanelets: Set[int] = None, successors_right: Set[int] = None, successors_straight: Set[int] = None, successors_left: Set[int] = None, left_of: int = None, ): """ :param incoming_id: incoming element ID :param incoming_lanelets: set of IDs of incoming lanelets :param successors_right: set of IDs of incoming lanelets which turn right :param successors_straight: set of IDs of incoming lanelets which go straight :param successors_left: set of IDs of incoming lanelets which turn left :param left_of: incoming element ID of incoming element located left of this incoming element """ self._incoming_id = None self._incoming_lanelets = None self.incoming_id = incoming_id self.incoming_lanelets = incoming_lanelets self.successors_right = successors_right self.successors_straight = successors_straight self.successors_left = successors_left self._left_of = left_of def __eq__(self, other): if not isinstance(other, IntersectionIncomingElement): warnings.warn( f"Inequality between IntersectionIncomingElement " f"{repr(self)} and different type {type(other)}" ) return False return ( self._incoming_id == other.incoming_id and self._incoming_lanelets == other.incoming_lanelets and self._successors_right == other.successors_right and self._successors_straight == other.successors_straight and self._successors_left == other.successors_left and self._left_of == other.left_of ) def __hash__(self): return hash( ( self._incoming_id, frozenset(self._incoming_lanelets), frozenset(self._successors_right), frozenset(self._successors_straight), frozenset(self._successors_left), self._left_of, ) ) def __str__(self): return ( f"IntersectionIncomingElement with id {self._incoming_id} represents the incoming " f"lanelets {self._incoming_lanelets} and has right successors {self._successors_right}, " f"straight successors {self._successors_straight}, and left successors {self._successors_left}" ) def __repr__(self): return ( f"IntersectionIncomingElement(incoming_id={self._incoming_id}, " f"incoming_lanelets={self._incoming_lanelets}, successors_right={self._successors_right}, " f"successors_straight={self._successors_straight}, successors_left={self._successors_left}, " f"left_of={self._left_of})" ) @property def incoming_id(self) -> int: """ ID of incoming """ return self._incoming_id @incoming_id.setter def incoming_id(self, i_id: int): """ :param i_id ID of incoming """ assert is_natural_number( i_id ), "<IntersectionIncomingElement/incoming_id>: Provided incoming_id is not " "valid! id={}".format(i_id) self._incoming_id = i_id @property def incoming_lanelets(self) -> Set[int]: """ set of IDs of incoming lanelets """ return self._incoming_lanelets @incoming_lanelets.setter def incoming_lanelets(self, incoming_lanelets: Set[int]): """ :param incoming_lanelets: set of IDs of incoming lanelets """ self._incoming_lanelets = incoming_lanelets @property def successors_right(self) -> Set[int]: """ set of IDs of incoming lanelets which turn right """ return self._successors_right @successors_right.setter def successors_right(self, successors_right: Set[int]): """ :param successors_right: set of IDs of incoming lanelets which turn right """ if successors_right is None: self._successors_right = set() else: self._successors_right = successors_right @property def successors_straight(self) -> Set[int]: """ set of IDs of incoming lanelets which go straight """ return self._successors_straight @successors_straight.setter def successors_straight(self, successors_straight: Set[int]): """ :param successors_straight: set of IDs of incoming lanelets which go straight """ if successors_straight is None: self._successors_straight = set() else: self._successors_straight = successors_straight @property def successors_left(self) -> Set[int]: """ set of IDs of incoming lanelets which turn left """ return self._successors_left @successors_left.setter def successors_left(self, successors_left: Set[int]): """ :param successors_left: set of IDs of incoming lanelets which turn left """ if successors_left is None: self._successors_left = set() else: self._successors_left = successors_left @property def left_of(self) -> int: """ incoming element ID of incoming element located left of this incoming element """ return self._left_of @left_of.setter def left_of(self, left_of: int): """ :param left_of: incoming element ID of incoming element located left of this incoming element """ self._left_of = left_of
[docs]class Intersection: """ This class represent an intersection. An intersection element is defined by at least one incoming and an optional crossing element. The crossing element models lanelets which cross other lanelets, e.g., these are usually lanelets of type crosswalk. """ def __init__(self, intersection_id: int, incomings: List[IntersectionIncomingElement], crossings: Set[int] = None): """ :param intersection_id: ID of intersection element :param incomings: set of incoming elements in intersection :param crossings: set of crossing elements in intersection """ self._intersection_id = None self._incomings = None self._crossings = None self.intersection_id = intersection_id self.incomings = incomings self.crossings = crossings def __eq__(self, other): if not isinstance(other, Intersection): warnings.warn(f"Inequality between Intersection {repr(self)} and different type {type(other)}") return False list_elements_eq = True incomings = {incoming.incoming_id: incoming for incoming in self._incomings} incomings_other = {incoming.incoming_id: incoming for incoming in other.incomings} intersection_eq = len(incomings) == len(incomings_other) for k in incomings.keys(): if k not in incomings_other: intersection_eq = False continue if incomings.get(k) != incomings_other.get(k): list_elements_eq = False return ( list_elements_eq and intersection_eq and self._intersection_id == other.intersection_id and self._crossings == other.crossings ) def __hash__(self): return hash((self._intersection_id, frozenset(self._incomings), frozenset(self._crossings))) def __str__(self): return ( f"Intersection with id {self._intersection_id} consisting of {len(self._incomings)} incoming elements " f"and crossings {self._crossings}" ) def __repr__(self): return ( f"Intersection(intersection_id={self._intersection_id}, incomings={repr(self._incomings)}, " f"crossings={self._crossings})" ) @property def intersection_id(self) -> int: """ ID of intersection element """ return self._intersection_id @intersection_id.setter def intersection_id(self, i_id: int): """ :param i_id ID of intersection element """ assert is_natural_number( i_id ), "<Intersection/intersection_id>: Provided intersection_id is not " "valid! id={}".format(i_id) self._intersection_id = i_id @property def incomings(self) -> List[IntersectionIncomingElement]: """ set of incoming elements in intersection """ return self._incomings @incomings.setter def incomings(self, incomings: List[IntersectionIncomingElement]): """ :param incomings: i_id ID of intersection element """ self._incomings = incomings @property def crossings(self) -> Set[int]: """ set of crossing elements in intersection """ return self._crossings @crossings.setter def crossings(self, crossings: Set[int]): """ :param crossings: set of crossing elements in intersection """ if crossings is None: self._crossings = set() else: self._crossings = crossings @property def map_incoming_lanelets(self) -> Dict[int, IntersectionIncomingElement]: """ Maps all incoming lanelet ids to IntersectionIncomingElement """ return {l_id: inc for inc in self.incomings for l_id in inc.incoming_lanelets}