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
示例#4
0
    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)
示例#8
0
 def setUp(self):
     self.configuration = Configuration()
     self.laneBuilder = LaneBuilder()
示例#9
0
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)