def __init__(self, country=CountryCodes.US): self.STD_ROADMARK = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2, rule=pyodrx.MarkRule.no_passing) self.STD_START_CLOTH = 1 / 1000000000 self.country = country self.laneBuilder = LaneBuilder() pass
def setUp(self): self.configuration = Configuration() self.esminiPath = self.configuration.get("esminipath") self.roadBuilder = RoadBuilder() self.laneBuilder = LaneBuilder() self.laneLinker = LaneLinker() self.straightRoadBuilder = StraightRoadBuilder()
def __init__(self, country=CountryCodes.US): self.STD_ROADMARK = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2, rule=pyodrx.MarkRule.no_passing) self.STD_START_CLOTH = 1 / 1000000000 self.country = country self.laneBuilder = LaneBuilder() self.configuration = Configuration() self.name = 'StraightRoadBuilder' pass
def __init__(self, roadBuilder=None, straightRoadLen=10, minAngle=np.pi / 6, maxAngle=None, country=CountryCodes.US, random_seed=39): self.config = Configuration() self.roadBuilder = roadBuilder if self.roadBuilder is None: self.roadBuilder = RoadBuilder() self.straightRoadBuilder = StraightRoadBuilder() self.laneBuilder = LaneBuilder() self.straightRoadLen = straightRoadLen self.minAngle = minAngle self.maxAngle = maxAngle if self.maxAngle == np.pi: self.maxAngle = 0.99 * np.pi self.laneWidth = self.config.get("default_lane_width") self.minConnectionLength = self.config.get("min_connection_length") self.maxConnectionLength = self.config.get("max_connection_length") self.curveBuilder = CurveRoadBuilder(country=country) self.connectionBuilder = ConnectionBuilder() self.countryCode = country np.random.seed(random_seed) pass
class CurveRoadBuilder: def __init__(self, country=CountryCodes.US): self.STD_ROADMARK = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2, rule=pyodrx.MarkRule.no_passing) self.STD_START_CLOTH = 1 / 1000000000 self.country = country self.laneBuilder = LaneBuilder() pass def getJunctionSelection(self, isJunction): if isJunction: return 1 return -1 def createPVForArcWithCloths(self, arcCurvature, arcAngle, clothAngle, clothCurvatureStart=None, clothCurvatureEnd=None): """[summary] Args: arcCurvature ([type]): [description] arcAngle ([type]): [description] clothAngle ([type]): [description] clothCurvatureStart ([type], optional): [description]. Defaults to None. clothCurvatureEnd ([type], optional): [description]. Defaults to None. Returns: [type]: [description] """ if clothCurvatureStart is None: clothCurvatureStart = self.STD_START_CLOTH if clothCurvatureEnd is None: clothCurvatureEnd = self.STD_START_CLOTH pv = extensions.ExtendedPlanview() spiral1 = extensions.ExtendedSpiral(clothCurvatureStart, arcCurvature, angle=clothAngle) arc = pyodrx.Arc(arcCurvature, angle=arcAngle) spiral2 = extensions.ExtendedSpiral(arcCurvature, clothCurvatureEnd, angle=clothAngle) pv.add_geometry(spiral1) pv.add_geometry(arc) pv.add_geometry(spiral2) return pv def create(self, roadId, angleBetweenEndpoints, isJunction=False, curvature=StandardCurvature.Medium.value, curveType=StandardCurveTypes.Simple, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): """[summary] Args: angleBetweenEndpoints (radian): (0, 180) range in radian curvature (float): (-inf, +inf) Raises: Exception: [description] Returns: [type]: [description] """ if angleBetweenEndpoints < 0: angleBetweenEndpoints *= -1 curvature *= -1 if curveType is StandardCurveTypes.Simple: return self.createSimple(roadId, angleBetweenEndpoints, isJunction, curvature, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) elif curveType is StandardCurveTypes.LongArc: return self.createSimpleCurveWithLongArc(roadId, angleBetweenEndpoints, isJunction, curvature) elif curveType is StandardCurveTypes.S: return self.createS(roadId, angleBetweenEndpoints, isJunction, curvature) else: error = f"Unkown curveType {curveType} or not supported for random creation" raise Exception(error) def createSimple(self, roadId, angleBetweenEndpoints, isJunction=False, curvature=StandardCurvature.Medium.value, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): junction = extensions.getJunctionSelection(isJunction) totalRotation = np.pi - angleBetweenEndpoints arcAngle = np.pi / 10000000 clothAngle = totalRotation / 2 return self.createCurveGeoAndLanes(roadId, isJunction, curvature, arcAngle, clothAngle, n_lanes, lane_offset, laneSides, isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane) def createCurveGeoAndLanes(self, roadId, isJunction, curvature, arcAngle, clothAngle, n_lanes, lane_offset, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): junction = extensions.getJunctionSelection(isJunction) pv = self.createPVForArcWithCloths(curvature, arcAngle, clothAngle) length = pv.getTotalLength() laneSections = self.laneBuilder.getStandardLanes( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction, curveType=StandardCurveTypes.LongArc) return road def createSimpleCurveWithLongArc(self, roadId, angleBetweenEndpoints, isJunction=False, curvature=StandardCurvature.Medium.value, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): junction = extensions.getJunctionSelection(isJunction) totalRotation = np.pi - angleBetweenEndpoints # most of the angleBetweenEndpoints should be assigned to the Arc arcAngle = totalRotation * 0.9 # main curve clothAngle = (totalRotation * 0.1) / 2 # curve more. return self.createCurveGeoAndLanes(roadId, isJunction, curvature, arcAngle, clothAngle, n_lanes, lane_offset, laneSides, isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane) def createS(self, roadId, angleBetweenEndpoints, isJunction=False, curvature=StandardCurvature.Medium.value, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): """Here the angleBetweenEndpoints are used for the first road and S mid point, and S mid point and Second road Args: roadId ([type]): [description] angleBetweenEndpoints ([type]): used for the first road and S mid point, and S mid point and Second road. Use negative angles for interesting Ss isJunction (bool, optional): [description]. Defaults to False. curvature ([type], optional): [description]. Defaults to StandardCurvature.Medium.value. Returns: [type]: [description] """ junction = extensions.getJunctionSelection(isJunction) totalRotation = np.pi - angleBetweenEndpoints # most of the angleBetweenEndpoints should be assigned to the Arc arcAngle = totalRotation * 0.9 clothAngle = (totalRotation * 0.1) / 2 # curve more. arc_curv = curvature arc_angle = arcAngle cloth_angle = clothAngle cloth_start = self.STD_START_CLOTH pv = ExtendedPlanview() # 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 # we are changing the second half of the S to have different arc angle and curvature. multiplier = np.random.choice(9) / 10 arc_angle2 = arc_angle - arc_angle * multiplier arc_curv2 = -(arc_curv + arc_curv * multiplier ) # the angle needs to be opposite for the second half. # create geometries spiral1 = extensions.ExtendedSpiral(cloth_start, arc_curv, angle=cloth_angle) arc = pyodrx.Arc(arc_curv, angle=arc_angle) arc2 = pyodrx.Arc(arc_curv2, angle=-arc_angle2) spiral2 = extensions.ExtendedSpiral(-arc_curv, cloth_start, angle=-cloth_angle) pv.add_geometry(spiral1) pv.add_geometry(arc) pv.add_geometry(arc2) pv.add_geometry(spiral2) length = pv.getTotalLength() laneSections = self.laneBuilder.getStandardLanes( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction, curveType=StandardCurveTypes.S) return road def createCurveByLength(self, roadId, length, isJunction=False, curvature=StandardCurvature.Medium.value, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): junction = self.getJunctionSelection(isJunction) pv = ExtendedPlanview() arc = pyodrx.Arc(curvature, length=length) pv.add_geometry(arc) length = pv.getTotalLength() laneSections = self.laneBuilder.getStandardLanes( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction, curveType=StandardCurveTypes.LongArc) return road def createParamPoly3(self, roadId, isJunction=False, au=0, bu=20, cu=20, du=10, av=0, bv=2, cv=20, dv=10, prange='normalized', length=None, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False): junction = self.getJunctionSelection(isJunction) pv = ExtendedPlanview() poly = pyodrx.ParamPoly3(au, bu, cu, du, av, bv, cv, dv, prange, length) # poly = extensions.IntertialParamPoly(au,bu,cu,du,av,bv,cv,dv,prange,length) pv.add_geometry(poly) length = pv.getTotalLength() laneSections = self.laneBuilder.getStandardLanes( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) # create lanes road = ExtendedRoad(roadId, pv, laneSections, road_type=junction, curveType=StandardCurveTypes.Poly) return road
class test_RoadLiner(unittest.TestCase): def setUp(self): self.configuration = Configuration() self.esminiPath = self.configuration.get("esminipath") self.roadBuilder = RoadBuilder() self.laneBuilder = LaneBuilder() self.laneLinker = LaneLinker() self.straightRoadBuilder = StraightRoadBuilder() self.curveBuilder = CurveRoadBuilder() self.roadLinker = RoadLinker() def test_getAngleBetweenStraightRoads(self): roads = [] roads.append( self.straightRoadBuilder.createWithDifferentLanes(0, 10, n_lanes_left=1, n_lanes_right=1)) connectionRoad = self.curveBuilder.create(1, np.pi / 4, isJunction=True, curvature=0.2, n_lanes=1) roads.append(connectionRoad) roads.append( self.straightRoadBuilder.createWithDifferentLanes(2, 10, n_lanes_left=1, n_lanes_right=2)) connectionRoad2 = self.curveBuilder.create(3, np.pi / 2, isJunction=True, curvature=0.1, n_lanes=1) roads.append(connectionRoad2) roads.append( self.straightRoadBuilder.createWithDifferentLanes(4, 10, n_lanes_left=1, n_lanes_right=1)) roads[0].addExtendedSuccessor(roads[1], 0, pyodrx.ContactPoint.start) roads[1].addExtendedPredecessor(roads[0], 0, pyodrx.ContactPoint.end) roads[1].addExtendedSuccessor(roads[2], 0, pyodrx.ContactPoint.start) roads[2].addExtendedPredecessor(roads[1], 0, pyodrx.ContactPoint.end) roads[2].addExtendedSuccessor(roads[3], 0, pyodrx.ContactPoint.start) roads[3].addExtendedPredecessor(roads[2], 0, pyodrx.ContactPoint.start) roads[3].addExtendedSuccessor(roads[4], 0, pyodrx.ContactPoint.start) roads[4].addExtendedPredecessor(roads[3], 0, pyodrx.ContactPoint.end) self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0], roads[2]) self.laneBuilder.createLanesForConnectionRoad(connectionRoad2, roads[2], roads[4]) odrName = "test_DifferentLaneConfigurations" odr = extensions.createOdrByPredecessor(odrName, roads, []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[0], roads[2]))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[0], roads[4]))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[2], roads[4]))) # xmlPath = f"output/test_DifferentLaneConfigurations.xodr" # odr.write_xml(xmlPath) def test_StartEnd(self): roads = [] roads.append( self.straightRoadBuilder.createWithDifferentLanes(0, 10, n_lanes_left=1, n_lanes_right=1)) connectionRoad = self.curveBuilder.create(1, np.pi / 4, isJunction=True, curvature=0.1, n_lanes=1) roads.append(connectionRoad) roads.append( self.straightRoadBuilder.createWithDifferentLanes(2, 10, n_lanes_left=1, n_lanes_right=1)) roads[0].addExtendedSuccessor(roads[1], 0, pyodrx.ContactPoint.start) roads[1].addExtendedPredecessor(roads[0], 0, pyodrx.ContactPoint.start) roads[1].addExtendedSuccessor(roads[2], 0, pyodrx.ContactPoint.start) roads[2].addExtendedPredecessor(roads[1], 0, pyodrx.ContactPoint.end) self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0], roads[2]) odrName = "test_StartEnd" odr = extensions.createOdrByPredecessor(odrName, roads, []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[0], roads[2]))) xmlPath = f"output/test_StartEnd.xodr" odr.write_xml(xmlPath) def test_fails(self): roads = [] roads.append( self.straightRoadBuilder.createWithDifferentLanes(0, 10, n_lanes_left=1, n_lanes_right=1)) connectionRoad = self.curveBuilder.create(1, np.pi / 4, isJunction=True, curvature=0.2, n_lanes=1) roads.append(connectionRoad) roads.append( self.straightRoadBuilder.createWithDifferentLanes(2, 10, n_lanes_left=1, n_lanes_right=2)) connectionRoad2 = self.curveBuilder.create(3, np.pi / 2, isJunction=True, curvature=0.1, n_lanes=1) roads.append(connectionRoad2) roads.append( self.straightRoadBuilder.createWithDifferentLanes(4, 10, n_lanes_left=1, n_lanes_right=3)) roads[0].addExtendedSuccessor(roads[1], 0, pyodrx.ContactPoint.start) roads[1].addExtendedPredecessor(roads[0], 0, pyodrx.ContactPoint.end) roads[1].addExtendedSuccessor(roads[2], 0, pyodrx.ContactPoint.start) roads[2].addExtendedPredecessor(roads[1], 0, pyodrx.ContactPoint.end) roads[2].addExtendedSuccessor(roads[3], 0, pyodrx.ContactPoint.start) roads[3].addExtendedPredecessor(roads[2], 0, pyodrx.ContactPoint.start) roads[3].addExtendedSuccessor(roads[4], 0, pyodrx.ContactPoint.start) roads[4].addExtendedPredecessor(roads[3], 0, pyodrx.ContactPoint.end) self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0], roads[2]) self.laneBuilder.createLanesForConnectionRoad(connectionRoad2, roads[2], roads[4]) odrName = "test_DifferentLaneConfigurations" odr = extensions.createOdrByPredecessor(odrName, roads, []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[0], roads[2]))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[0], roads[4]))) print( math.degrees( self.roadLinker.getAngleBetweenStraightRoads( roads[2], roads[4])))
class StraightRoadBuilder: def __init__(self, country=CountryCodes.US): self.STD_ROADMARK = pyodrx.RoadMark(pyodrx.RoadMarkType.solid, 0.2, rule=pyodrx.MarkRule.no_passing) self.STD_START_CLOTH = 1 / 1000000000 self.country = country self.laneBuilder = LaneBuilder() self.configuration = Configuration() self.name = 'StraightRoadBuilder' pass def createPVForLine(self, length): line1 = pyodrx.Line(length) # create planviews pv = extensions.ExtendedPlanview() pv.add_geometry(line1) return pv def createRandom(self, roadId, randomState=None, length=20, junction=-1, lane_offset=None, maxLanePerSide=2, minLanePerSide=0, turns=False, merges=False, medianType=None, medianWidth=3, skipEndpoint=None, force3Section=False): if randomState is not None: np.random.set_state(randomState) if lane_offset is None: lane_offset = self.configuration.get("default_lane_width") if maxLanePerSide < 1: raise Exception( f"{self.name}: createRandom: maxLanePerSide cannot be less than 1" ) laneRange = np.arange(minLanePerSide, maxLanePerSide + 1) n_lanes_left = np.random.choice(laneRange) n_lanes_right = np.random.choice(laneRange) if (n_lanes_left == 0) and (n_lanes_right == 0): return self.createRandom(roadId, randomState=randomState, length=length, junction=junction, lane_offset=lane_offset, maxLanePerSide=maxLanePerSide, minLanePerSide=minLanePerSide, turns=turns, merges=merges, medianType=medianType, medianWidth=3, skipEndpoint=skipEndpoint, force3Section=force3Section) numLeftTurnsOnLeft = 0 numRightTurnsOnRight = 0 numLeftMergeOnLeft = 0 numRightMergeOnRight = 0 numberOfLeftTurnLanesOnRight = 0 numberOfRightTurnLanesOnLeft = 0 mergeLaneOnTheOppositeSideForInternalTurn = np.random.choice( [True, False]) if turns: numLeftTurnsOnLeft = np.random.choice([0, 1]) numRightTurnsOnRight = np.random.choice([0, 1]) numberOfLeftTurnLanesOnRight = np.random.choice([0, 1]) numberOfRightTurnLanesOnLeft = np.random.choice([0, 1]) elif merges: numLeftMergeOnLeft = np.random.choice([0, 1]) numRightMergeOnRight = np.random.choice([0, 1]) if medianType is None: return self.create( roadId, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right, length=length, junction=junction, lane_offset=lane_offset, laneSides=LaneSides.BOTH, numLeftTurnsOnLeft=numLeftTurnsOnLeft, numRightTurnsOnRight=numRightTurnsOnRight, numLeftMergeOnLeft=numLeftMergeOnLeft, numRightMergeOnRight=numRightMergeOnRight, numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight, numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn, force3Section=force3Section) else: return self.createWithMedianRestrictedLane( roadId, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right, length=length, junction=junction, lane_offset=lane_offset, laneSides=LaneSides.BOTH, numLeftTurnsOnLeft=numLeftTurnsOnLeft, numRightTurnsOnRight=numRightTurnsOnRight, numLeftMergeOnLeft=numLeftMergeOnLeft, numRightMergeOnRight=numRightMergeOnRight, numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight, numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn, medianType=medianType, medianWidth=medianWidth, skipEndpoint=skipEndpoint) pass def create(self, roadId, n_lanes_left=1, n_lanes_right=1, length=20, junction=-1, lane_offset=3, laneSides=LaneSides.BOTH, numLeftTurnsOnLeft=0, numRightTurnsOnRight=0, numLeftMergeOnLeft=0, numRightMergeOnRight=0, numberOfLeftTurnLanesOnRight=0, numberOfRightTurnLanesOnLeft=0, mergeLaneOnTheOppositeSideForInternalTurn=True, force3Section=False): # create geometry pv = self.createPVForLine(length) # laneSections = self.laneBuilder.getStandardLanes(n_lanes, lane_offset, laneSides, # roadLength=length, # isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, # isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane) singleSide = False if laneSides != LaneSides.BOTH: singleSide = True laneSections = self.laneBuilder.getLanes( n_lanes_left, n_lanes_right, lane_offset=lane_offset, singleSide=singleSide, roadLength=length, numLeftTurnsOnLeft=numLeftTurnsOnLeft, numRightTurnsOnRight=numRightTurnsOnRight, numLeftMergeOnLeft=numLeftMergeOnLeft, numRightMergeOnRight=numRightMergeOnRight, numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight, numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn, force3Section=force3Section) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction) return road def createWithMedianRestrictedLane( self, roadId, n_lanes_left=1, n_lanes_right=1, length=20, junction=-1, lane_offset=3, laneSides=LaneSides.BOTH, numLeftTurnsOnLeft=0, numRightTurnsOnRight=0, numLeftMergeOnLeft=0, numRightMergeOnRight=0, numberOfLeftTurnLanesOnRight=0, numberOfRightTurnLanesOnLeft=0, mergeLaneOnTheOppositeSideForInternalTurn=True, medianType='partial', medianWidth=3, skipEndpoint=None): road = self.create( roadId, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right, length=length, junction=junction, lane_offset=lane_offset, laneSides=laneSides, numLeftTurnsOnLeft=numLeftTurnsOnLeft, numRightTurnsOnRight=numRightTurnsOnRight, numLeftMergeOnLeft=numLeftMergeOnLeft, numRightMergeOnRight=numRightMergeOnRight, numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight, numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn, force3Section=True) if medianType == 'partial': if skipEndpoint is None: raise Exception( f"{self.name}: createWithMedianRestrictedLane skipEndpoint cannot be None for partial median lanes." ) self.laneBuilder.addMedianIslandsTo2Of3Sections( road, roadLength=length, skipEndpoint=skipEndpoint, width=medianWidth) else: self.laneBuilder.addMedianIslandsToAllSections(road, width=medianWidth) return road def createWithRightTurnLanesOnLeft( self, roadId, length=100, junction=-1, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False, numberOfRightTurnLanesOnLeft=1, mergeLaneOnTheOppositeSideForInternalTurn=True): # create geometry pv = self.createPVForLine(length) laneSections = self.laneBuilder.getStandardLanesWithInternalTurns( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane, numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction) return road def createWithLeftTurnLanesOnRight( self, roadId, length=100, junction=-1, n_lanes=1, lane_offset=3, laneSides=LaneSides.BOTH, isLeftTurnLane=False, isRightTurnLane=False, isLeftMergeLane=False, isRightMergeLane=False, numberOfLeftTurnLanesOnRight=1, mergeLaneOnTheOppositeSideForInternalTurn=True): """Will create numberOfLeftTurnLanesOnRight left turn lanes on the right side of the center line. Equal number of mergelanes will be created on the left side of the center lane, too. Args: roadId ([type]): [description] length (int, optional): [description]. Defaults to 100. junction (int, optional): [description]. Defaults to -1. n_lanes (int, optional): [description]. Defaults to 1. lane_offset (int, optional): [description]. Defaults to 3. laneSides ([type], optional): [description]. Defaults to LaneSides.BOTH. isLeftTurnLane (bool, optional): [description]. Defaults to False. isRightTurnLane (bool, optional): [description]. Defaults to False. isLeftMergeLane (bool, optional): [description]. Defaults to False. isRightMergeLane (bool, optional): [description]. Defaults to False. numberOfLeftTurnLanesOnRight (int, optional): [description]. Defaults to 1. Returns: [type]: [description] """ # create geometry pv = self.createPVForLine(length) laneSections = self.laneBuilder.getStandardLanesWithInternalTurns( n_lanes, lane_offset, laneSides, roadLength=length, isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane, isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane, numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight, mergeLaneOnTheOppositeSideForInternalTurn= mergeLaneOnTheOppositeSideForInternalTurn) road = ExtendedRoad(roadId, pv, laneSections, road_type=junction) return road def createWithDifferentLanes(self, roadId, length=100, junction=-1, n_lanes_left=1, n_lanes_right=1, lane_offset=3, force3Section=False): return self.create(roadId, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right, length=length, junction=junction, lane_offset=lane_offset, force3Section=force3Section)
def setUp(self): self.configuration = Configuration() self.laneBuilder = LaneBuilder()
class test_LaneBuilder(unittest.TestCase): def setUp(self): self.configuration = Configuration() self.laneBuilder = LaneBuilder() def test_widths(self): roadLength = 10 #1 simple Lanes lanes = self.laneBuilder.getStandardLanes(1, 3) for laneSec in lanes.lanesections: widths = laneSec.widths(roadLength) assert widths[0] == 6 assert widths[1] == 6 #1 turn lanes lanes = self.laneBuilder.getStandardLanes(1, 3, roadLength=roadLength, isLeftTurnLane=True, isRightTurnLane=True) widths = lanes.lanesections[0].widths(roadLength, LaneOffset(s=0), LaneOffset(s=1)) print(widths) assert widths[0] == 6 assert widths[1] == 6 widths = lanes.lanesections[1].widths(roadLength, LaneOffset(s=1), LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 6 assert widths[1] == 12 widths = lanes.lanesections[2].widths(roadLength, LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 12 assert widths[1] == 12 #2 merge lanes lanes = self.laneBuilder.getStandardLanes(1, 3, roadLength=roadLength, isLeftMergeLane=True, isRightMergeLane=True) widths = lanes.lanesections[0].widths(roadLength, LaneOffset(s=0), LaneOffset(s=1)) print(widths) assert widths[0] == 12 assert widths[1] == 12 widths = lanes.lanesections[1].widths(roadLength, LaneOffset(s=1), LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 12 assert widths[1] == 6 widths = lanes.lanesections[2].widths(roadLength, LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 6 assert widths[1] == 6 #2 internal lanes lanes = self.laneBuilder.getStandardLanesWithInternalTurns( 1, 3, roadLength=roadLength, numberOfLeftTurnLanesOnRight=2) widths = lanes.lanesections[0].widths(roadLength, LaneOffset(s=0), LaneOffset(s=1)) print(widths) assert widths[0] == 12 assert widths[1] == 12 widths = lanes.lanesections[1].widths(roadLength, LaneOffset(s=1), LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 12 assert widths[1] == 12 widths = lanes.lanesections[2].widths(roadLength, LaneOffset(s=roadLength - 1)) print(widths) assert widths[0] == 12 assert widths[1] == 12
class test_LaneBuilder(unittest.TestCase): def setUp(self): self.configuration = Configuration() self.esminiPath = self.configuration.get("esminipath") self.roadBuilder = RoadBuilder() self.laneBuilder = LaneBuilder() self.laneLinker = LaneLinker() self.straightRoadBuilder = StraightRoadBuilder() def test_RightLane(self): # test scenario for connection road roads = [] roads.append(pyodrx.create_straight_road(0, 10)) # roads.append(self.roadBuilder.createSimpleCurve(1, np.pi/4, True, curvature = 0.2)) # roads.append(pyodrx.create_straight_road(2, 10)) # roads[0].add_successor(pyodrx.ElementType.junction,1) # roads[1].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.end) # # roads[1].add_predecessor(pyodrx.ElementType.road,0,pyodrx.ContactPoint.start) # roads[1].add_successor(pyodrx.ElementType.road,2,pyodrx.ContactPoint.start) # roads[2].add_predecessor(pyodrx.ElementType.junction,1, pyodrx.ContactPoint.end) odrName = "test_connectionRoad" odr = extensions.createOdrByPredecessor(odrName, roads, []) self.laneBuilder.addRightTurnLaneUS(roads[0], 3) # self.laneBuilder.addRightLaneUS(roads[1]) odr.resetAndReadjust(byPredecessor=True) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) xmlPath = f"output/test-RightLane.xodr" odr.write_xml(xmlPath) def test_DifferentLaneConfigurations(self): roads = [] roads.append( self.straightRoadBuilder.createWithDifferentLanes(0, 10, n_lanes_left=1, n_lanes_right=1)) connectionRoad = self.straightRoadBuilder.createWithDifferentLanes( 1, 10, n_lanes_left=2, n_lanes_right=2) roads.append(connectionRoad) roads.append( self.straightRoadBuilder.createWithDifferentLanes(2, 10, n_lanes_left=1, n_lanes_right=2)) roads[0].addExtendedSuccessor(roads[1], 0, pyodrx.ContactPoint.start) roads[1].addExtendedPredecessor(roads[0], 0, pyodrx.ContactPoint.end) roads[1].addExtendedSuccessor(roads[2], 0, pyodrx.ContactPoint.start) roads[2].addExtendedPredecessor(roads[1], 0, pyodrx.ContactPoint.end) self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0], roads[2]) odrName = "test_DifferentLaneConfigurations" odr = extensions.createOdrByPredecessor(odrName, roads, []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) xmlPath = f"output/test_DifferentLaneConfigurations.xodr" odr.write_xml(xmlPath) def test_addMedianIslandsToAllSections(self): roads = [] roads.append( self.straightRoadBuilder.createWithDifferentLanes(0, 10, n_lanes_left=1, n_lanes_right=1)) self.laneBuilder.addMedianIslandsToAllSections( roads[0], self.configuration.get('default_lane_width')) odrName = "test_DifferentLaneConfigurations" odr = extensions.createOdrByPredecessor(odrName, roads, []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) xmlPath = f"output/test_addMedianIslandsToAllSections.xodr" odr.write_xml(xmlPath) def test_addMedianIslandsTo3Sections(self): road = self.straightRoadBuilder.create(1, n_lanes_left=1, n_lanes_right=1, length=20, force3Section=False) try: self.laneBuilder.addMedianIslandsTo2Of3Sections( road, 20, skipEndpoint=pyodrx.ContactPoint.start, width=3) assert False except: assert True road = self.straightRoadBuilder.create(1, n_lanes_left=1, n_lanes_right=1, length=20, force3Section=True) self.laneBuilder.addMedianIslandsTo2Of3Sections( road, 20, skipEndpoint=pyodrx.ContactPoint.start, width=3) assert len(road.lanes.lanesections[0].leftlanes) == 1 assert len(road.lanes.lanesections[0].rightlanes) == 1 assert len(road.lanes.lanesections[1].leftlanes) == 2 assert len(road.lanes.lanesections[1].rightlanes) == 2 assert len(road.lanes.lanesections[2].leftlanes) == 2 assert len(road.lanes.lanesections[2].rightlanes) == 2 road = self.straightRoadBuilder.create(1, n_lanes_left=1, n_lanes_right=1, length=20, force3Section=True) self.laneBuilder.addMedianIslandsTo2Of3Sections( road, 20, skipEndpoint=pyodrx.ContactPoint.end, width=3) assert len(road.lanes.lanesections[0].leftlanes) == 2 assert len(road.lanes.lanesections[0].rightlanes) == 2 assert len(road.lanes.lanesections[1].leftlanes) == 2 assert len(road.lanes.lanesections[1].rightlanes) == 2 assert len(road.lanes.lanesections[2].leftlanes) == 1 assert len(road.lanes.lanesections[2].rightlanes) == 1 odrName = "test_DifferentLaneConfigurations" odr = extensions.createOdrByPredecessor(odrName, [road], []) extensions.view_road( odr, os.path.join('..', self.configuration.get("esminipath"))) xmlPath = f"output/test_addMedianIslandsTo3Sections.xodr" odr.write_xml(xmlPath)