Module scenariogeneration.xodr.generators
scenariogeneration https://github.com/pyoscx/scenariogeneration
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
Copyright (c) 2022 The scenariogeneration Authors.
Functions
def create_3cloths(cloth1_start: float,
cloth1_end: float,
cloth1_length: float,
cloth2_start: float,
cloth2_end: float,
cloth2_length: float,
cloth3_start: float,
cloth3_end: float,
cloth3_length: float,
r_id: int,
junction: int = 1,
n_lanes: int = 1,
lane_offset: int = 3,
road_marks: RoadMark = <scenariogeneration.xodr.lane.RoadMark object>)-
Expand source code
def create_3cloths( cloth1_start: float, cloth1_end: float, cloth1_length: float, cloth2_start: float, cloth2_end: float, cloth2_length: float, cloth3_start: float, cloth3_end: float, cloth3_length: float, r_id: int, junction: int = 1, n_lanes: int = 1, lane_offset: int = 3, road_marks: RoadMark = std_roadmark_broken(), ): """Create a curved road with a Spiral-Spiral-Spiral and two lanes. Parameters ---------- cloth1_start : float Initial curvature of spiral 1. cloth1_end : float Ending curvature of spiral 1. cloth1_length : float Total length of spiral 1. cloth2_start : float Initial curvature of spiral 2. cloth2_end : float Ending curvature of spiral 2. cloth2_length : float Total length of spiral 2. cloth3_start : float Initial curvature of spiral 3. cloth3_end : float Ending curvature of spiral 3. cloth3_length : float Total length of spiral 3. r_id : int The ID of the road. junction : int, optional Indicates if the road belongs to a junction. Default is 1. n_lanes : int, optional Number of lanes. Default is 1. lane_offset : int, optional Width of the road. Default is 3. road_marks : RoadMark, optional Road mark used for the standard lane. Default is RoadMark(broken). Returns ------- Road A road built up of a Spiral-Spiral-Spiral. """ warn( "create_cloth_arc_cloth should not be used anymore, please use the create_road (see exampels/xodr/clothoid_generation.py) function instead", DeprecationWarning, 2, ) pv = PlanView() # create geometries spiral1 = Spiral(cloth1_start, cloth1_end, length=cloth1_length) spiral2 = Spiral(cloth2_start, cloth2_end, length=cloth2_length) spiral3 = Spiral(cloth3_start, cloth3_end, length=cloth3_length) pv.add_geometry(spiral1) pv.add_geometry(spiral2) pv.add_geometry(spiral3) # create lanes center_lane = Lane() if road_marks: center_lane.add_roadmark(road_marks) lsec = LaneSection(0, center_lane) for i in range(1, n_lanes + 1, 1): rl = Lane(a=lane_offset) ll = Lane(a=lane_offset) if road_marks: rl.add_roadmark(road_marks) ll.add_roadmark(road_marks) lsec.add_right_lane(rl) lsec.add_left_lane(ll) lanes = Lanes() lanes.add_lanesection(lsec) # create road return Road(r_id, pv, lanes, road_type=junction)Create a curved road with a Spiral-Spiral-Spiral and two lanes.
Parameters
cloth1_start:float- Initial curvature of spiral 1.
cloth1_end:float- Ending curvature of spiral 1.
cloth1_length:float- Total length of spiral 1.
cloth2_start:float- Initial curvature of spiral 2.
cloth2_end:float- Ending curvature of spiral 2.
cloth2_length:float- Total length of spiral 2.
cloth3_start:float- Initial curvature of spiral 3.
cloth3_end:float- Ending curvature of spiral 3.
cloth3_length:float- Total length of spiral 3.
r_id:int- The ID of the road.
junction:int, optional- Indicates if the road belongs to a junction. Default is 1.
n_lanes:int, optional- Number of lanes. Default is 1.
lane_offset:int, optional- Width of the road. Default is 3.
road_marks:RoadMark, optional- Road mark used for the standard lane. Default is RoadMark(broken).
Returns
Road- A road built up of a Spiral-Spiral-Spiral.
def create_cloth_arc_cloth(arc_curv: float,
arc_angle: float,
cloth_angle: float,
r_id: int,
junction: int = 1,
cloth_start: float = 1e-09,
n_lanes: int = 1,
lane_offset: int = 3)-
Expand source code
def create_cloth_arc_cloth( arc_curv: float, arc_angle: float, cloth_angle: float, r_id: int, junction: int = 1, cloth_start: float = STD_START_CLOTH, n_lanes: int = 1, lane_offset: int = 3, ): """Create a curved road with a Spiral-Arc-Spiral and two lanes. Parameters ---------- arc_curv : float Curvature of the arc (and max clothoid of clothoids). arc_angle : float How much of the curve should be the arc. cloth_angle : float How much of the curve should be the clothoid (will be doubled since there are two clothoids). r_id : int The ID of the road. junction : int, optional Indicates if the road belongs to a junction. Default is 1. cloth_start : float, optional Starting curvature of clothoids. Default is 1 / 1000000000. n_lanes : int, optional Number of lanes. Default is 1. lane_offset : int, optional Width of the road. Default is 3. Returns ------- Road A road built up of a Spiral-Arc-Spiral. """ warn( "create_cloth_arc_cloth should not be used anymore, please use the create_road (see exampels/xodr/clothoid_generation.py) function instead", DeprecationWarning, 2, ) pv = PlanView() # adjust sign if angle is negative if cloth_angle < 0 and arc_curv > 0: cloth_angle = -cloth_angle arc_curv = -arc_curv cloth_start = -cloth_start arc_angle = -arc_angle # create geometries spiral1 = Spiral(cloth_start, arc_curv, angle=cloth_angle) arc = Arc(arc_curv, angle=arc_angle) spiral2 = Spiral(arc_curv, cloth_start, angle=cloth_angle) pv.add_geometry(spiral1) pv.add_geometry(arc) pv.add_geometry(spiral2) # create lanes lsec = LaneSection(0, standard_lane()) for i in range(1, n_lanes + 1, 1): lsec.add_right_lane(standard_lane(lane_offset)) lsec.add_left_lane(standard_lane(lane_offset)) lanes = Lanes() lanes.add_lanesection(lsec) # create road return Road(r_id, pv, lanes, road_type=junction)Create a curved road with a Spiral-Arc-Spiral and two lanes.
Parameters
arc_curv:float- Curvature of the arc (and max clothoid of clothoids).
arc_angle:float- How much of the curve should be the arc.
cloth_angle:float- How much of the curve should be the clothoid (will be doubled since there are two clothoids).
r_id:int- The ID of the road.
junction:int, optional- Indicates if the road belongs to a junction. Default is 1.
cloth_start:float, optional- Starting curvature of clothoids. Default is 1 / 1000000000.
n_lanes:int, optional- Number of lanes. Default is 1.
lane_offset:int, optional- Width of the road. Default is 3.
Returns
Road- A road built up of a Spiral-Arc-Spiral.
def create_direct_junction(roads: List[Road],
id: int,
name: str = 'my direct junction') ‑> Junction-
Expand source code
def create_direct_junction( roads: List[Road], id: int, name: str = "my direct junction" ) -> Junction: """Create the junction structure for a set of roads, for a direct junction. Parameters ---------- roads : list of Road All roads that are building up the direct junction. id : int The ID of the junction. name : str, optional Name of the junction. Default is "my direct junction". Returns ------- Junction The junction structure ready to use. Raises ------ RemovedFunctionality If the function is called, as it has been deprecated. """ raise RemovedFunctionality( "The create_direct_junction has been removed, due to its very limited functionality, please try the xodr.DirectJunctionCreator instead." )Create the junction structure for a set of roads, for a direct junction.
Parameters
roads:listofRoad- All roads that are building up the direct junction.
id:int- The ID of the junction.
name:str, optional- Name of the junction. Default is "my direct junction".
Returns
Junction- The junction structure ready to use.
Raises
RemovedFunctionality- If the function is called, as it has been deprecated.
def create_junction(junction_roads: List[Road],
id: int,
roads: List[Road],
name: str = 'my junction') ‑> Junction-
Expand source code
def create_junction( junction_roads: List[Road], id: int, roads: List[Road], name: str = "my junction", ) -> Junction: """Create a junction structure for a set of roads. Parameters ---------- junction_roads : list of Road All connecting roads in the junction. id : int The ID of the junction. roads : list of Road All incoming roads to the junction. name : str, optional Name of the junction. Default is "my junction". Returns ------- Junction The junction structure ready to use. """ junc = Junction(name, id) for jr in junction_roads: # handle succesor lanes conne1 = Connection(jr.successor.element_id, jr.id, ContactPoint.end) _, sign, _ = _get_related_lanesection( jr, get_road_by_id(roads, jr.successor.element_id) ) _create_junction_links( conne1, len(jr.lanes.lanesections[-1].rightlanes), -1, sign, to_offset=jr.lane_offset_suc[str(jr.successor.element_id)], ) _create_junction_links( conne1, len(jr.lanes.lanesections[-1].leftlanes), 1, sign, to_offset=jr.lane_offset_suc[str(jr.successor.element_id)], ) junc.add_connection(conne1) # handle predecessor lanes conne2 = Connection( jr.predecessor.element_id, jr.id, ContactPoint.start ) _, sign, _ = _get_related_lanesection( jr, get_road_by_id(roads, jr.predecessor.element_id) ) _create_junction_links( conne2, len(jr.lanes.lanesections[0].rightlanes), -1, sign, from_offset=jr.lane_offset_pred[str(jr.predecessor.element_id)], ) _create_junction_links( conne2, len(jr.lanes.lanesections[0].leftlanes), 1, sign, from_offset=jr.lane_offset_pred[str(jr.predecessor.element_id)], ) junc.add_connection(conne2) return juncCreate a junction structure for a set of roads.
Parameters
junction_roads:listofRoad- All connecting roads in the junction.
id:int- The ID of the junction.
roads:listofRoad- All incoming roads to the junction.
name:str, optional- Name of the junction. Default is "my junction".
Returns
Junction- The junction structure ready to use.
def create_junction_roads(roads: List[Road],
angles: List[float],
R: float | List[float],
junction: int = 1,
arc_part: float = 0.3333333333333333,
startnum: int = 100,
inner_road_marks: RoadMark | None = None,
outer_road_marks: RoadMark = <scenariogeneration.xodr.lane.RoadMark object>) ‑> List[Road]-
Expand source code
def create_junction_roads( roads: List[Road], angles: List[float], R: Union[float, List[float]], junction: int = 1, arc_part: float = 1 / 3, startnum: int = 100, inner_road_marks: Optional[RoadMark] = None, outer_road_marks: RoadMark = std_roadmark_solid(), ) -> List[Road]: """Create all needed roads for some simple junctions. The curved parts of the junction are created as a spiral-arc-spiral combination. `R` is the radius of the whole junction, meaning the distance between the center of the junction and any external road attached to the junction. Supports all angles and numbers of roads. Parameters ---------- roads : list of Road All roads that should go into the junction. angles : list of float The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road [0, +2π]. R : list of float The radius of the whole junction, meaning the distance between roads and the center of the junction. If only one value is specified, then all roads will have the same distance. junction : int, optional The ID of the junction. Default is 1. spiral_part : float, optional The part of the curve that should be spirals (two of these). `spiral_part * 2 + arc_part = angle of the turn`. Default is 1/3. startnum : int, optional Start number of the roads in the junction (will increase by 1 for each road). Default is 100. inner_road_marks : RoadMark, optional The RoadMark that all lanes inside the junction will have (outer will be solid). Default is None. outer_road_marks : RoadMark, optional The RoadMark that will be on the edge of the connecting roads (limits the junction). Default is std_roadmark_solid(). Returns ------- list of Road A list of all roads needed for all traffic connecting the roads. """ warn( "create_junction_roads_from_arc should not be used anymore, please use the CommonJunctionCreator function instead", DeprecationWarning, 2, ) if len(roads) is not len(angles): raise GeneralIssueInputArguments( "roads and angles do not have the same size." ) if len(R) == 1: R = R * np.ones(len(roads)) elif len(R) > 1 and len(R) is not len(roads): raise GeneralIssueInputArguments( "roads and R do not have the same size." ) # linelength = 2*R junction_roads = [] # loop over the roads to get all possible combinations of connecting roads for i in range(len(roads) - 1): # for now the first road is place as base, if i == 0: cp = ContactPoint.end roads[i].add_successor(ElementType.junction, junction) else: cp = ContactPoint.start roads[i].add_predecessor(ElementType.junction, junction) for j in range(1 + i, len(roads)): # check angle needed for junction [-pi, +pi] an1 = angles[j] - angles[i] - np.pi # adjust angle if multiple of pi if an1 > np.pi: an1 = -(2 * np.pi - an1) sig = np.sign(an1) # create road, either straight or curved n_lanes, lanes_offset = get_lanes_offset(roads[i], roads[j], cp) if sig == 0: # create straight road linelength = R[i] + R[j] tmp_junc = create_straight_road( startnum, length=linelength, junction=junction, n_lanes=n_lanes, lane_offset=lanes_offset, ) if inner_road_marks: for l in tmp_junc.lanes.lanesections[0].leftlanes: l.roadmark[0] = inner_road_marks for r in tmp_junc.lanes.lanesections[0].rightlanes: r.roadmark[0] = inner_road_marks tmp_junc.lanes.lanesections[0].centerlane.roadmark[ 0 ] = inner_road_marks if len(roads) == 3: # not sure all will be needed since angles have to be in increasing order, but it "should work" k = [x for x in [0, 1, 2] if x != j and x != i][0] if (angles[i] > angles[j]) and ( (angles[k] > angles[j]) or (angles[k] < angles[i]) ): tmp_junc.lanes.lanesections[0].rightlanes[-1].roadmark[ 0 ] = outer_road_marks elif (angles[i] < angles[j]) and ( (angles[k] > angles[j]) or (angles[k] < angles[i]) ): tmp_junc.lanes.lanesections[0].rightlanes[-1].roadmark[ 0 ] = outer_road_marks elif (angles[i] < angles[j]) and ( (angles[k] < angles[j]) or (angles[k] > angles[i]) ): tmp_junc.lanes.lanesections[0].leftlanes[-1].roadmark[ 0 ] = outer_road_marks else: tmp_junc.lanes.lanesections[0].rightlanes[-1].roadmark[ 0 ] = outer_road_marks else: clothoids = pcloth.SolveG2( -R[i], 0, 0, STD_START_CLOTH, R[j] * np.cos(an1), R[j] * np.sin(an1), an1, STD_START_CLOTH, ) tmp_junc = create_3cloths( clothoids[0].KappaStart, clothoids[0].KappaEnd, clothoids[0].length, clothoids[1].KappaStart, clothoids[1].KappaEnd, clothoids[1].length, clothoids[2].KappaStart, clothoids[2].KappaEnd, clothoids[2].length, startnum, junction, n_lanes=n_lanes, lane_offset=lanes_offset, road_marks=inner_road_marks, ) if tmp_junc.planview._raw_geometries[1].curvstart > 0: tmp_junc.lanes.lanesections[0].leftlanes[-1].add_roadmark( outer_road_marks ) if tmp_junc.planview._raw_geometries[1].curvstart < 0: tmp_junc.lanes.lanesections[0].rightlanes[-1].add_roadmark( outer_road_marks ) # add predecessor and successor tmp_junc.add_predecessor(ElementType.road, roads[i].id, cp) tmp_junc.add_successor( ElementType.road, roads[j].id, ContactPoint.start ) startnum += 1 junction_roads.append(tmp_junc) # add junction to the last road aswell since it's not part of the loop roads[-1].add_predecessor(ElementType.junction, junction) return junction_roadsCreate all needed roads for some simple junctions.
The curved parts of the junction are created as a spiral-arc-spiral combination.
Ris the radius of the whole junction, meaning the distance between the center of the junction and any external road attached to the junction. Supports all angles and numbers of roads.Parameters
roads:listofRoad- All roads that should go into the junction.
angles:listoffloat- The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road [0, +2π].
R:listoffloat- The radius of the whole junction, meaning the distance between roads and the center of the junction. If only one value is specified, then all roads will have the same distance.
junction:int, optional- The ID of the junction. Default is 1.
spiral_part:float, optional- The part of the curve that should be spirals (two of these).
spiral_part * 2 + arc_part = angle of the turn. Default is 1/3. startnum:int, optional- Start number of the roads in the junction (will increase by 1 for each road). Default is 100.
inner_road_marks:RoadMark, optional- The RoadMark that all lanes inside the junction will have (outer will be solid). Default is None.
outer_road_marks:RoadMark, optional- The RoadMark that will be on the edge of the connecting roads (limits the junction). Default is std_roadmark_solid().
Returns
listofRoad- A list of all roads needed for all traffic connecting the roads.
def create_junction_roads_from_arc(roads: List[Road],
angles: List[float],
r: float = 0,
junction: int = 1,
arc_part: float = 0.3333333333333333,
startnum: int = 100) ‑> List[Road]-
Expand source code
def create_junction_roads_from_arc( roads: List[Road], angles: List[float], r: float = 0, junction: int = 1, arc_part: float = 1 / 3, startnum: int = 100, ) -> List[Road]: """Create all needed roads for simple junctions. The curved parts of the junction are created as a spiral-arc-spiral combination. Supported junctions include: - 3-way crossings (either a T-junction or 120-degree junction). - 4-way crossings (all 90-degree turns). Parameters ---------- roads : list of Road All roads that should go into the junction. angles : list of float The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road [0, +2π]. r : float The radius of the arcs in the junction (determines the size of the junction). junction : int, optional The ID of the junction. Default is 1. arc_part : float, optional The part of the curve that should be an arc: `spiral_part * 2 + arc_part = angle of the turn`. Default is 1/3. startnum : int, optional Start number of the roads in the junction (will increase by 1 for each road). Default is 100. Returns ------- list of Road A list of all roads needed for all traffic connecting the roads. """ warn( "create_junction_roads_from_arc should not be used anymore, please use the CommonJunctionCreator function instead", DeprecationWarning, 2, ) # arc_part = 1 - 2*spiral_part spiral_part = (1 - arc_part) / 2 angle = np.pi / 2 angle_cloth = angle * spiral_part spiral_length = 2 * abs(angle_cloth * r) cloth = pcloth.Clothoid.StandardParams( 0, 0, 0, STD_START_CLOTH, (1 / r - STD_START_CLOTH) / spiral_length, spiral_length, ) X0 = cloth.XEnd - r * np.sin(angle_cloth) Y0 = cloth.YEnd - r * (1 - np.cos(angle_cloth)) linelength = 2 * (X0 + r + Y0) junction_roads = [] # loop over the roads to get all possible combinations of connecting roads for i in range(len(roads) - 1): # for now the first road is place as base, if i == 0: cp = ContactPoint.end roads[i].add_successor(ElementType.junction, junction) else: cp = ContactPoint.start roads[i].add_predecessor(ElementType.junction, junction) for j in range(1 + i, len(roads)): # check angle needed for junction [-pi, +pi] an1 = angles[j] - angles[i] - np.pi # adjust angle if multiple of pi if an1 > np.pi: an1 = -(2 * np.pi - an1) angle_arc = an1 * arc_part angle_cloth = an1 * spiral_part sig = np.sign(an1) # create road, either straight or curved n_lanes, lanes_offset = get_lanes_offset(roads[i], roads[j], cp) if sig == 0: # create straight road tmp_junc = create_straight_road( startnum, length=linelength, junction=junction, n_lanes=n_lanes, lane_offset=lanes_offset, ) else: # create the cloth-arc-cloth road given the radius fo the arc tmp_junc = create_cloth_arc_cloth( 1 / r, angle_arc, angle_cloth, startnum, junction, n_lanes=n_lanes, lane_offset=lanes_offset, ) # add predecessor and successor tmp_junc.add_predecessor(ElementType.road, roads[i].id, cp) tmp_junc.add_successor( ElementType.road, roads[j].id, ContactPoint.start ) startnum += 1 junction_roads.append(tmp_junc) # add junction to the last road aswell since it's not part of the loop roads[-1].add_predecessor(ElementType.junction, junction) return junction_roadsCreate all needed roads for simple junctions.
The curved parts of the junction are created as a spiral-arc-spiral combination. Supported junctions include: - 3-way crossings (either a T-junction or 120-degree junction). - 4-way crossings (all 90-degree turns).
Parameters
roads:listofRoad- All roads that should go into the junction.
angles:listoffloat- The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road [0, +2π].
r:float- The radius of the arcs in the junction (determines the size of the junction).
junction:int, optional- The ID of the junction. Default is 1.
arc_part:float, optional- The part of the curve that should be an arc:
spiral_part * 2 + arc_part = angle of the turn. Default is 1/3. startnum:int, optional- Start number of the roads in the junction (will increase by 1 for each road). Default is 100.
Returns
listofRoad- A list of all roads needed for all traffic connecting the roads.
def create_junction_roads_standalone(angles: List[float],
r: float,
junction: int = 1,
spiral_part: float = 0.3333333333333333,
arc_part: float = 0.3333333333333333,
startnum: int = 100,
n_lanes: int = 1,
lane_width: float = 3) ‑> List[Road]-
Expand source code
def create_junction_roads_standalone( angles: List[float], r: float, junction: int = 1, spiral_part: float = 1 / 3, arc_part: float = 1 / 3, startnum: int = 100, n_lanes: int = 1, lane_width: float = 3, ) -> List[Road]: """Create all needed roads for simple junctions. The curved parts of the junction are created as a spiral-arc-spiral combination. Supported junctions include: - 3-way crossings (either a T-junction or 120-degree junction). - 4-way crossings (all 90-degree turns). Note ---- This function does not generate any links or add any successors/ predecessors to the roads. These must be added manually. If you have the connecting roads, use `create_junction_roads` instead. Parameters ---------- angles : list of float The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road. r : float The radius of the arcs in the junction (determines the size of the junction). junction : int, optional The ID of the junction. Default is 1. spiral_part : float, optional The part of the curve that should be spirals (two of these). `spiral_part * 2 + arc_part = angle of the turn`. Default is 1/3. arc_part : float, optional The part of the curve that should be an arc. `spiral_part * 2 + arc_part = angle of the turn`. Default is 1/3. startnum : int, optional Start number of the roads in the junction (will increase by 1 for each road). Default is 100. n_lanes : int, optional The number of lanes in the junction. Default is 1. lane_width : float, optional The lane width of the lanes in the junction. Default is 3. Returns ------- list of Road A list of all roads in a junction without connections added. """ warn( "create_junction_roads_standalone should not be used anymore, please use the CommonJunctionCreator function instead", DeprecationWarning, 2, ) angle = np.pi / 2 angle_cloth = angle * spiral_part spiral_length = 2 * abs(angle_cloth * r) cloth = pcloth.Clothoid.StandardParams( 0, 0, 0, STD_START_CLOTH, (1 / r - STD_START_CLOTH) / spiral_length, spiral_length, ) X0 = cloth.XEnd - r * np.sin(angle_cloth) Y0 = cloth.YEnd - r * (1 - np.cos(angle_cloth)) linelength = 2 * (X0 + r + Y0) junction_roads = [] for i in range(len(angles) - 1): for j in range(1 + i, len(angles)): # check angle needed for junction an = np.sign(angles[j] - angles[i] - np.pi) an1 = angles[j] - angles[i] - np.pi angle_arc = an1 * arc_part angle_cloth = an1 * spiral_part # adjust angle if multiple of pi if an1 > np.pi: an1 = -(2 * np.pi - an1) # create road, either straight or curved if an == 0: tmp_junc = create_straight_road( startnum, length=linelength, junction=junction, n_lanes=n_lanes, lane_offset=lane_width, ) else: tmp_junc = create_cloth_arc_cloth( 1 / r, angle_arc, angle_cloth, startnum, junction, n_lanes=n_lanes, lane_offset=lane_width, ) # add predecessor and successor startnum += 1 junction_roads.append(tmp_junc) return junction_roadsCreate all needed roads for simple junctions.
The curved parts of the junction are created as a spiral-arc-spiral combination. Supported junctions include: - 3-way crossings (either a T-junction or 120-degree junction). - 4-way crossings (all 90-degree turns).
Note
This function does not generate any links or add any successors/ predecessors to the roads. These must be added manually. If you have the connecting roads, use
create_junction_roads()instead.Parameters
angles:listoffloat- The angles from where the roads should be coming in (see description for what is supported). Angles should be defined in mathematically positive order, beginning with the first incoming road.
r:float- The radius of the arcs in the junction (determines the size of the junction).
junction:int, optional- The ID of the junction. Default is 1.
spiral_part:float, optional- The part of the curve that should be spirals (two of these).
spiral_part * 2 + arc_part = angle of the turn. Default is 1/3. arc_part:float, optional- The part of the curve that should be an arc.
spiral_part * 2 + arc_part = angle of the turn. Default is 1/3. startnum:int, optional- Start number of the roads in the junction (will increase by 1 for each road). Default is 100.
n_lanes:int, optional- The number of lanes in the junction. Default is 1.
lane_width:float, optional- The lane width of the lanes in the junction. Default is 3.
Returns
listofRoad- A list of all roads in a junction without connections added.
def create_road(geometry: Line | Spiral | ForwardRef('ParamPoly3') | Arc | List[Line | Spiral | ForwardRef('ParamPoly3') | Arc] | AdjustablePlanview,
id: int,
left_lanes: List[LaneDef] | int = 1,
right_lanes: List[LaneDef] | int = 1,
road_type: int = -1,
center_road_mark: RoadMark = <scenariogeneration.xodr.lane.RoadMark object>,
lane_width: float = 3,
lane_width_end: float | None = None) ‑> Road-
Expand source code
def create_road( geometry: Union[ Line, Spiral, "ParamPoly3", Arc, List[Union[Line, Spiral, "ParamPoly3", Arc]], AdjustablePlanview, ], id: int, left_lanes: Union[List[LaneDef], int] = 1, right_lanes: Union[List[LaneDef], int] = 1, road_type: int = -1, center_road_mark: RoadMark = std_roadmark_solid(), lane_width: float = 3, lane_width_end: Optional[float] = None, ) -> Road: """Create a road with one lane section and different numbers of lanes. Lane marks will be of type broken, except for the outer lane, which will be solid. The `lane_width_end` parameter can only be used when inputs for `left_lanes` and `right_lanes` are integers. Parameters ---------- geometry : Line, Spiral, ParamPoly3, Arc, list of (Line, Spiral, ParamPoly3, Arc), or AdjustablePlanview Geometries to build the road. id : int ID of the new road. left_lanes : list of LaneDef or int, optional A list of the splits/merges that are wanted on the left side of the road. If an integer, it specifies a constant number of lanes. Default is 1. right_lanes : list of LaneDef or int, optional A list of the splits/merges that are wanted on the right side of the road. If an integer, it specifies a constant number of lanes. Default is 1. road_type : int, optional Type of road. Use -1 for a normal road, or another value for a connecting road. Default is -1. center_road_mark : RoadMark, optional Road mark for the center line. Default is RoadMark(solid). lane_width : float, optional The width of all lanes. Default is 3. lane_width_end : float, optional The end width of all lanes. Can only be used when `left_lanes` and `right_lanes` are integers. Returns ------- Road A straight road. """ if isinstance(left_lanes, LaneDef): left_lanes = [left_lanes] if isinstance(right_lanes, LaneDef): right_lanes = [right_lanes] pv = PlanView() raw_length = 0 if isinstance(geometry, list): for g in geometry: pv.add_geometry(g) raw_length += g.length elif isinstance(geometry, AdjustablePlanview): pv = geometry pv.left_lane_defs = left_lanes pv.right_lane_defs = right_lanes pv.center_road_mark = center_road_mark pv.lane_width = lane_width pv.lane_width_end = lane_width_end # create a dummy length raw_length = 0 if isinstance(left_lanes, list) and any( isinstance(x, LaneDef) for x in left_lanes ): raw_length = max(raw_length, max([x.s_end for x in left_lanes])) if isinstance(right_lanes, list) and any( isinstance(x, LaneDef) for x in right_lanes ): raw_length = max(raw_length, max([x.s_end for x in right_lanes])) if raw_length == 0: raw_length = 100 # just a dummy value else: pv.add_geometry(geometry) raw_length += geometry.length if (lane_width_end is not None) and ( (type(left_lanes) != int) or (type(right_lanes) != int) ): raise RuntimeError( "lane_width_end can only be used when left_lanes and right_lanes are int" ) if ( right_lanes is not None and left_lanes is not None or center_road_mark is not None ): lanes = create_lanes_merge_split( right_lanes, left_lanes, raw_length, center_road_mark, lane_width, lane_width_end=lane_width_end, ) else: lanes = Lanes() road = Road(id, pv, lanes, road_type=road_type) return roadCreate a road with one lane section and different numbers of lanes.
Lane marks will be of type broken, except for the outer lane, which will be solid. The
lane_width_endparameter can only be used when inputs forleft_lanesandright_lanesare integers.Parameters
geometry:Line, Spiral, ParamPoly3, Arc, listof(Line, Spiral,- ParamPoly3, Arc), or AdjustablePlanview Geometries to build the road.
id:int- ID of the new road.
left_lanes:listofLaneDeforint, optional- A list of the splits/merges that are wanted on the left side of the road. If an integer, it specifies a constant number of lanes. Default is 1.
right_lanes:listofLaneDeforint, optional- A list of the splits/merges that are wanted on the right side of the road. If an integer, it specifies a constant number of lanes. Default is 1.
road_type:int, optional- Type of road. Use -1 for a normal road, or another value for a connecting road. Default is -1.
center_road_mark:RoadMark, optional- Road mark for the center line. Default is RoadMark(solid).
lane_width:float, optional- The width of all lanes. Default is 3.
lane_width_end:float, optional- The end width of all lanes. Can only be used when
left_lanesandright_lanesare integers.
Returns
Road- A straight road.
def create_straight_road(road_id: int,
length: float = 100,
junction: int = -1,
n_lanes: int = 1,
lane_offset: int = 3) ‑> Road-
Expand source code
def create_straight_road( road_id: int, length: float = 100, junction: int = -1, n_lanes: int = 1, lane_offset: int = 3, ) -> Road: """Create a standard straight road with two lanes. Parameters ---------- road_id : int ID of the road to create. length : float, optional Length of the road. Default is 100. junction : int, optional Indicates if the road belongs to a junction. Default is -1. n_lanes : int, optional Number of lanes. Default is 1. lane_offset : int, optional Width of the road. Default is 3. Returns ------- Road A straight road. """ warn( "create_straight_road should not be used anymore, please use the create_road function instead", DeprecationWarning, 2, ) # create geometry line1 = Line(length) # create planviews planview1 = PlanView() planview1.add_geometry(line1) # create lanesections lanesec1 = LaneSection(0, standard_lane()) for i in range(1, n_lanes + 1, 1): lanesec1.add_right_lane(standard_lane(lane_offset)) lanesec1.add_left_lane(standard_lane(lane_offset)) # create lanes lanes1 = Lanes() lanes1.add_lanesection(lanesec1) # finally create the roads return Road(road_id, planview1, lanes1, road_type=junction)Create a standard straight road with two lanes.
Parameters
road_id:int- ID of the road to create.
length:float, optional- Length of the road. Default is 100.
junction:int, optional- Indicates if the road belongs to a junction. Default is -1.
n_lanes:int, optional- Number of lanes. Default is 1.
lane_offset:int, optional- Width of the road. Default is 3.
Returns
Road- A straight road.
def get_lanes_offset(road1: Road,
road2: Road,
contactpoint: ContactPoint) ‑> tuple[int, int]-
Expand source code
def get_lanes_offset( road1: Road, road2: Road, contactpoint: ContactPoint ) -> tuple[int, int]: """Return the number of lanes and their offset. Assumes that the number of left lanes equals the number of right lanes and that the offset is constant. Parameters ---------- road1 : Road The first road. road2 : Road The second road. contactpoint : ContactPoint The contact point indicating the connection type. Returns ------- tuple[int, int] A tuple containing: - n_lanes (int): The number of lanes. - lane_offset (int): The offset of the lanes. Raises ------ NotSameAmountOfLanesError If the incoming and outgoing roads do not have the same number of left lanes. """ # now we always look at lanesection[0] to take the number of lanes # TO DO - understand if the roads are connect through end or start and then take the relative lane section if contactpoint == ContactPoint.end: n_lanesection = 0 else: n_lanesection = -1 if len(road1.lanes.lanesections[n_lanesection].leftlanes) == len( road2.lanes.lanesections[0].leftlanes ) and len(road1.lanes.lanesections[n_lanesection].rightlanes) == len( road2.lanes.lanesections[0].rightlanes ): n_lanes = len(road1.lanes.lanesections[n_lanesection].leftlanes) lane_offset = ( road1.lanes.lanesections[n_lanesection].leftlanes[0].widths[0].a ) else: raise NotSameAmountOfLanesError( "Incoming road ", road1.id, " and outcoming road ", road2.id, "do not have the same number of left lanes.", ) return n_lanes, lane_offsetReturn the number of lanes and their offset.
Assumes that the number of left lanes equals the number of right lanes and that the offset is constant.
Parameters
road1:Road- The first road.
road2:Road- The second road.
contactpoint:ContactPoint- The contact point indicating the connection type.
Returns
tuple[int, int]- A tuple containing: - n_lanes (int): The number of lanes. - lane_offset (int): The offset of the lanes.
Raises
NotSameAmountOfLanesError- If the incoming and outgoing roads do not have the same number of left lanes.
def get_road_by_id(roads: List[Road],
id: int) ‑> Road-
Expand source code
def get_road_by_id(roads: List[Road], id: int) -> Road: """Return a road based on the road ID. Parameters ---------- roads : list of Road A list of roads to search through. id : int The ID of the road to retrieve. Returns ------- Road The road with the specified ID. """ for r in roads: if r.id == id: return rReturn a road based on the road ID.
Parameters
roads:listofRoad- A list of roads to search through.
id:int- The ID of the road to retrieve.
Returns
Road- The road with the specified ID.
def standard_lane(offset: int = 3,
rm: RoadMark = <scenariogeneration.xodr.lane.RoadMark object>) ‑> Lane-
Expand source code
def standard_lane( offset: int = 3, rm: RoadMark = std_roadmark_broken() ) -> Lane: """Create a simple lane with an offset and a roadmark. Parameters ---------- offset : int, optional Width of the lane. Default is 3. rm : RoadMark, optional Road mark used for the standard lane. Default is RoadMark(solid). Returns ------- Lane The created lane. """ lc = Lane(a=offset) if rm is not None: lc.add_roadmark(rm) return lcCreate a simple lane with an offset and a roadmark.
Parameters
offset:int, optional- Width of the lane. Default is 3.
rm:RoadMark, optional- Road mark used for the standard lane. Default is RoadMark(solid).
Returns
Lane- The created lane.