Beispiel #1
0
    def createLastConnectionForLastAndFirstRoad(self,
                                                nextRoadId,
                                                roads,
                                                junction,
                                                cp1=pyodrx.ContactPoint.end,
                                                cp2=pyodrx.ContactPoint.start):

        lastConnectionId = nextRoadId
        lastConnection = self.roadBuilder.getConnectionRoadBetween(
            lastConnectionId, roads[-1], roads[0], cp2, cp1)

        RoadLinker.createExtendedPredSuc(predRoad=roads[-1],
                                         predCp=cp2,
                                         sucRoad=lastConnection,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=lastConnection,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[0],
                                         sucCP=cp1)

        connectionL = pyodrx.Connection(roads[-1].id, lastConnectionId,
                                        pyodrx.ContactPoint.start)
        connectionL.add_lanelink(-1, -1)
        junction.add_connection(connectionL)

        # roads.append(lastConnection) # dangerous. do not add the road

        return lastConnection
Beispiel #2
0
    def test_normalRoadLinks(self):

        roads = []
        roads.append(self.straightRoadBuilder.create(0))
        roads.append(
            self.roadBuilder.curveBuilder.createSimple(1,
                                                       np.pi / 4,
                                                       False,
                                                       curvature=0.2))
        roads.append(self.straightRoadBuilder.create(2))

        RoadLinker.createExtendedPredSuc(predRoad=roads[0],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[1],
                                         sucCP=pyodrx.ContactPoint.start)

        RoadLinker.createExtendedPredSuc(predRoad=roads[1],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[2],
                                         sucCP=pyodrx.ContactPoint.start)

        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")))
Beispiel #3
0
    def setUp(self):

        self.configuration = Configuration()
        self.roadBuilder = junctions.RoadBuilder()

        self.straightRoadBuilder = StraightRoadBuilder()
        self.roadLinker = RoadLinker()
    def test_getMaxCurvatureMaxRoadWidth(self):

        roads = []

        numberofLanes = 1
        laneOffset = 3
        angle = np.pi * .75

        maxCurve = AngleCurvatureMap.getMaxCurvatureAgainstMaxRoadWidth(
            angle, numberofLanes * laneOffset)

        curve = maxCurve * 1.1

        print(f"max curve {maxCurve}, current curve {curve}")

        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(
                0,
                length=10,
                junction=-1,
                n_lanes_left=numberofLanes,
                n_lanes_right=numberofLanes))
        roads.append(
            self.curveRoadBuilder.createSimpleCurveWithLongArc(
                1,
                angleBetweenEndpoints=angle,
                curvature=curve,
                isJunction=True,
                n_lanes=numberofLanes))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(
                2,
                length=10,
                junction=-1,
                n_lanes_left=numberofLanes,
                n_lanes_right=numberofLanes))

        RoadLinker.createExtendedPredSuc(predRoad=roads[0],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[1],
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=roads[1],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[2],
                                         sucCP=pyodrx.ContactPoint.start)

        odrName = "test_createSingleLaneConnectionRoad"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])
        # extensions.printRoadPositions(odr)

        road = roads[1]
        print(f"{road.id} has length {road.planview.get_total_length()}")

        for geom in road.planview._adjusted_geometries:
            print(geom.length)

        extensions.view_road(odr, os.path.join('..', self.esminipath))
    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()
Beispiel #6
0
    def createConnectionFor2Roads(self,
                                  nextRoadId,
                                  road1,
                                  road2,
                                  junction,
                                  cp1,
                                  cp2,
                                  n_lanes=1,
                                  lane_offset=3,
                                  laneSides=LaneSides.BOTH):
        """Does not modify predecessor or successor of the given roads.

        Args:
            junction: the junction object to add links.

        Returns:
            [type]: connection road with first road as the predecessor and second road as the successor
        """

        newConnectionId = nextRoadId
        newConnectionRoad = self.roadBuilder.getConnectionRoadBetween(
            newConnectionId,
            road1,
            road2,
            cp1,
            cp2,
            isJunction=True,
            n_lanes=n_lanes,
            lane_offset=lane_offset,
            laneSides=laneSides)

        RoadLinker.createExtendedPredSuc(predRoad=road1,
                                         predCp=cp1,
                                         sucRoad=newConnectionRoad,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=newConnectionRoad,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=road2,
                                         sucCP=cp2)

        if junction is not None:
            if laneSides == LaneSides.LEFT or laneSides == LaneSides.BOTH:
                connectionL = pyodrx.Connection(road2.id, newConnectionId,
                                                pyodrx.ContactPoint.end)
                connectionL.add_lanelink(-1, -1)
                junction.add_connection(connectionL)
            else:
                connectionL = pyodrx.Connection(road1.id, newConnectionId,
                                                pyodrx.ContactPoint.start)
                connectionL.add_lanelink(1, 1)
                junction.add_connection(connectionL)

        return newConnectionRoad
Beispiel #7
0
    def createLanesForConnectionRoad(self, connectionRoad: ExtendedRoad, 
                                    predRoad: ExtendedRoad, 
                                    sucRoad: ExtendedRoad, 
                                    strategy = LaneConfigurationStrategies.MERGE_EDGE, 
                                    countryCode=extensions.CountryCodes.US):
        """Assumes start of connection road is connected to predRoad and end to sucRoad and connection road's lanes are not connected to either of the roads.
        It can connect roads with two different lane configurations.

        Args:
            connectionRoad (ExtendedRoad): 
            predRoad (ExtendedRoad): Extended predecessor road of connectionRoad. That means connection road's start is connected to predRoad
            sucRoad (ExtendedRoad): Extended successor road of connectionRoad. That means connection road's end is connected to sucRoad
            strategy ([type], optional): [description]. Defaults to LaneConfigurationStrategies.MERGE_EDGE.
        """


        try:
            cp1, cp1Con = RoadLinker.getContactPoints(predRoad, connectionRoad)
            cp2, cp2Con = RoadLinker.getContactPoints(sucRoad, connectionRoad)

            laneSection1 = predRoad.getLaneSectionByCP(cp1)
            laneSection2 = sucRoad.getLaneSectionByCP(cp2)

            connectionRoad.clearLanes()

            leftConnections, rightConnections = LaneConfiguration.getLaneLinks(laneSection1, laneSection2, (cp1 == cp2), strategy)

            # now we need to workout the number of straight lanes, merge lanes, and turn lanes on each side.


            # switch lane sides if cp1 and cp1Con are the same, because the lane orientation is reversed

            if cp1 == cp1Con:
                leftNumStandard, leftNumMerge, leftNumTurn = LaneConfiguration.getNumberDifferentLanes(rightConnections)
                rightNumStandard, rightNumMerge, rightNumTurn = LaneConfiguration.getNumberDifferentLanes(leftConnections)
            else:
                leftNumStandard, leftNumMerge, leftNumTurn = LaneConfiguration.getNumberDifferentLanes(leftConnections)
                rightNumStandard, rightNumMerge, rightNumTurn = LaneConfiguration.getNumberDifferentLanes(rightConnections)


            connectionRoad.lanes = self.getLanes(n_lanes_left=leftNumStandard, n_lanes_right=rightNumStandard,
                                 roadLength=connectionRoad.length(),
                                 numLeftTurnsOnLeft=leftNumTurn, numLeftMergeOnLeft=leftNumMerge,
                                 numRightTurnsOnRight= rightNumTurn, numRightMergeOnRight=rightNumMerge)





        
        except Exception as e:
            raise e
Beispiel #8
0
    def combine(odrList: List[ExtendedOpenDrive], name):

        """Does not readjust

        Returns:
            [type]: [description]
        """
          
        laneLinker = LaneLinker()
        roadLinker = RoadLinker()
        
        combinedOdr = ExtendedOpenDrive(name, laneLinker=laneLinker)

        for odr in odrList:
            roads = list(odr.roads.values())
            junctions = odr.junctions

            combinedOdr.addFirstRoad(roads[0])

            for r in roads:
                combinedOdr.add_road(r)
            
            for junction in junctions:
                combinedOdr.add_junction(junction)
        
        return combinedOdr
def createOdrByPredecessor(name, roads, junctions):

    laneLinker = LaneLinker()
    roadLinker = RoadLinker()

    odr = ExtendedOpenDrive(name, laneLinker=laneLinker)
    for r in roads:
        odr.add_road(r)

    for junction in junctions:
        odr.add_junction(junction)

    roadLinker.adjustLaneOffsetsForOdr(odr)
    logging.info(
        f"moreHelpers: createOdrByPredecessor: starting adjustment. May freeze!!!!!!!!!!!!!"
    )
    odr.adjust_roads_and_lanesByPredecessor()

    return odr
    def setUp(self):

        self.configuration = Configuration()
        self.esminipath = self.configuration.get("esminipath")
        self.roadBuilder = junctions.RoadBuilder()

        self.straightRoadBuilder = StraightRoadBuilder()
        self.roadLinker = RoadLinker()
        self.connectionBuilder = ConnectionBuilder()
        self.curveRoadBuilder = CurveRoadBuilder()
    def createInternalConnectionsForMissingSequentialRoads(self, roads, junction, cp1 = pyodrx.ContactPoint.start, rebuildLanes=False):

        """Does not add connection to any junction. When are junction has all the roads connected to at least one connection road in a sequential manner, you can use
        this method to connect roads which are not already connected. 
        """


        # for first road:
        # fromId = 0
        # toId = roads[2].id
        # nextRoadId = roads[-1].id + 1
        # countOldRoads = len(roads)
        # while(toId < countOldRoads):
        #     connectionRoad = self.createConnectionFor2Roads(nextRoadId, roads[fromId], roads[toId], junction, cp1=cp1)
        #     roads.append(connectionRoad)
        #     toId += 2
        #     nextRoadId += 1

        newConnectionRoads = []        
        
        connectionRoads = self.getConnectionRoadsForSequentialRoads(roads)

        fromIndex = 0
        countOldRoads = len(roads)
        nextRoadId = roads[-1].id + 1

        while fromIndex < countOldRoads:
            toIndex = fromIndex + 4

            while toIndex < countOldRoads:
                if toIndex == fromIndex:
                    toIndex += 2
                    continue
                
                if not RoadLinker.areRoadsConnected(roads[fromIndex], roads[toIndex], connectionRoads):
                    if fromIndex == 0:
                        connectionRoad = self.createConnectionFor2Roads(nextRoadId, roads[fromIndex], roads[toIndex], junction, cp1=cp1, cp2=pyodrx.ContactPoint.start)
                    else:
                        connectionRoad = self.createConnectionFor2Roads(nextRoadId, roads[fromIndex], roads[toIndex], junction, cp1=pyodrx.ContactPoint.start, cp2=pyodrx.ContactPoint.start)
                    roads.append(connectionRoad)
                    newConnectionRoads.append(connectionRoad)
                    if rebuildLanes:
                        self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[fromIndex], roads[toIndex])

                toIndex += 2
                nextRoadId += 1
                pass

            fromIndex += 2

        return newConnectionRoads        
    def test_getLength(self):

        angleBetweenEndpoints = 1.5708
        curvature = 0.333333
        curveType = StandardCurveTypes.Simple
        currentLength = AngleCurvatureMap.getLength(angleBetweenEndpoints,
                                                    curvature, curveType)

        print(f"test length: {currentLength}")

        numberofLanes = 5
        laneOffset = 3

        angle = angleBetweenEndpoints
        length = currentLength

        maxCurve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
            angle, numberofLanes * laneOffset, curveType=curveType)
        curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
            angle, length, curveType=curveType)

        # curve = 0.066666667

        print(f"max curve {maxCurve}, current curve {curve}")

        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(
                0,
                length=10,
                junction=-1,
                n_lanes_left=numberofLanes,
                n_lanes_right=numberofLanes))
        # roads.append(self.curveRoadBuilder.createSimpleCurveWithLongArc(1, angleBetweenEndpoints = angle, curvature=curve, isJunction=True, n_lanes=numberofLanes))
        roads.append(
            self.curveRoadBuilder.createSimple(1,
                                               angleBetweenEndpoints=angle,
                                               curvature=curve,
                                               isJunction=True,
                                               n_lanes=numberofLanes))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(
                2,
                length=10,
                junction=-1,
                n_lanes_left=numberofLanes,
                n_lanes_right=numberofLanes))

        RoadLinker.createExtendedPredSuc(predRoad=roads[0],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[1],
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=roads[1],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[2],
                                         sucCP=pyodrx.ContactPoint.start)

        odrName = "test_createSingleLaneConnectionRoad"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])
        # extensions.printRoadPositions(odr)

        road = roads[1]
        print(f"{road.id} has length {road.planview.get_total_length()}")

        # for geom in road.planview._adjusted_geometries:
        #     print(geom.length)

        assert round(road.planview.get_total_length(), 0) == round(length, 0)
Beispiel #13
0
class test_ExtendedRoad(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.roadBuilder = junctions.RoadBuilder()

        self.straightRoadBuilder = StraightRoadBuilder()
        self.roadLinker = RoadLinker()

    def test_getArcAngle(self):

        for _ in range(1, 10):
            for i in range(1, 10):
                inputAngle = (np.pi * i) / 10
                road = self.roadBuilder.createRandomCurve(0, inputAngle)

                if road.curveType == StandardCurveTypes.S:
                    continue

                outputAngle = road.getArcAngle()
                deviation = abs(inputAngle - outputAngle) * 100 / inputAngle

                print(
                    f"curveType: {road.curveType} inputAngle: {math.degrees(inputAngle)} outputAngle: {math.degrees(outputAngle)} deviation: {deviation}"
                )
                assert deviation < 50.0

    def test_getBorderDistanceOfLane(self):

        roads = []

        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))
        roads.append(
            self.straightRoadBuilder.createWithRightTurnLanesOnLeft(
                1,
                length=10,
                n_lanes=1,
                junction=1,
                isLeftTurnLane=True,
                isRightTurnLane=True,
                numberOfRightTurnLanesOnLeft=2,
                mergeLaneOnTheOppositeSideForInternalTurn=False))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=4,
                                                              n_lanes_right=2))
        self.roadLinker.linkConsecutiveRoadsWithNoBranches(roads)

        assert roads[0].getBorderDistanceOfLane(1,
                                                pyodrx.ContactPoint.start) == 3
        assert roads[0].getBorderDistanceOfLane(-1,
                                                pyodrx.ContactPoint.start) == 3
        assert roads[1].getBorderDistanceOfLane(1,
                                                pyodrx.ContactPoint.start) == 3
        assert roads[1].getBorderDistanceOfLane(2,
                                                pyodrx.ContactPoint.end) == 6
        assert roads[1].getBorderDistanceOfLane(3,
                                                pyodrx.ContactPoint.end) == 9
        assert roads[1].getBorderDistanceOfLane(4,
                                                pyodrx.ContactPoint.end) == 12
        assert roads[1].getBorderDistanceOfLane(-1,
                                                pyodrx.ContactPoint.start) == 3

        roads[1].updatePredecessorOffset(-1)

        odrName = "test_getBorderDistanceOfLane"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_getBorderDistanceOfLane.xodr"
        odr.write_xml(xmlPath)

        roads = []

        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=2))
        roads.append(
            self.straightRoadBuilder.createWithRightTurnLanesOnLeft(
                1,
                length=10,
                n_lanes=2,
                junction=1,
                isLeftTurnLane=True,
                isRightTurnLane=True,
                numberOfRightTurnLanesOnLeft=2,
                mergeLaneOnTheOppositeSideForInternalTurn=False))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=5,
                                                              n_lanes_right=3))
        self.roadLinker.linkConsecutiveRoadsWithNoBranches(roads)

        roads[1].updatePredecessorOffset(-2)

        odrName = "test_getBorderDistanceOfLane"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_getBorderDistanceOfLane.xodr"
        odr.write_xml(xmlPath)

    def test_getLanePosition(self):

        roads = []

        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=2))
        roads.append(
            self.straightRoadBuilder.createWithRightTurnLanesOnLeft(
                1,
                length=10,
                n_lanes=2,
                junction=1,
                isLeftTurnLane=True,
                isRightTurnLane=True,
                numberOfRightTurnLanesOnLeft=2,
                mergeLaneOnTheOppositeSideForInternalTurn=False))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=5,
                                                              n_lanes_right=3))
        self.roadLinker.linkConsecutiveRoadsWithNoBranches(roads)

        roads[1].updatePredecessorOffset(-2)

        odrName = "test_getBorderDistanceOfLane"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])

        extensions.printRoadPositions(odr)

        print(roads[0].getLanePosition(0, pyodrx.ContactPoint.end))
        print(roads[0].getLanePosition(1, pyodrx.ContactPoint.end))
        print(roads[0].getLanePosition(2, pyodrx.ContactPoint.end))

        positionLeftMost = roads[0].getLanePosition(2, pyodrx.ContactPoint.end)
        assert positionLeftMost[0] == 10.0
        assert positionLeftMost[1] == 6.0
        assert positionLeftMost[2] == 0

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
    def test_createSingleLaneConnectionRoad(self):

        roads = []

        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=2))
        roads.append(
            self.curveRoadBuilder.createSimple(1,
                                               np.pi / 3,
                                               isJunction=True,
                                               n_lanes=2))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=2))

        RoadLinker.createExtendedPredSuc(predRoad=roads[0],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[1],
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=roads[1],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[2],
                                         sucCP=pyodrx.ContactPoint.start)

        odrName = "test_createSingleLaneConnectionRoad"
        odr = extensions.createOdrByPredecessor(odrName, roads, [])

        # extensions.view_road(odr, os.path.join('..', self.configuration.get("esminipath")))

        newConnection = self.connectionBuilder.createSingleLaneConnectionRoad(
            3, roads[0], roads[2], -2, -2, pyodrx.ContactPoint.end,
            pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=roads[0],
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=newConnection,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=newConnection,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[2],
                                         sucCP=pyodrx.ContactPoint.start)
        newConnection.updatePredecessorOffset(-1)

        roads.append(newConnection)
        odr.add_road(newConnection)

        newConnection = self.connectionBuilder.createSingleLaneConnectionRoad(
            4, roads[2], roads[0], 2, 2, pyodrx.ContactPoint.start,
            pyodrx.ContactPoint.end)
        RoadLinker.createExtendedPredSuc(predRoad=roads[2],
                                         predCp=pyodrx.ContactPoint.start,
                                         sucRoad=newConnection,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=newConnection,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=roads[0],
                                         sucCP=pyodrx.ContactPoint.end)
        newConnection.updatePredecessorOffset(1)

        roads.append(newConnection)
        odr.add_road(newConnection)

        odr.resetAndReadjust(byPredecessor=True)
        extensions.printRoadPositions(odr)

        extensions.view_road(odr, os.path.join('..', self.esminipath))
        xmlPath = f"output/test_createSingleLaneConnectionRoad.xodr"
        odr.write_xml(xmlPath)
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])))
Beispiel #16
0
    def _create_links_connecting_road(self,
                                      connecting: ExtendedRoad,
                                      road: ExtendedRoad,
                                      ignoreMismatch=True):
        """ _create_links_connecting_road will create lane links between a connecting road and a normal road

            Parameters
            ----------
                connecting (Road): a road of type connecting road (not -1)

                road (Road): a that connects to the connecting road

        """
        linktype, sign, connecting_lanesec = self._get_related_lanesection(
            connecting, road)
        _, _, road_lanesection_id = self._get_related_lanesection(
            road, connecting)

        # invert lanes if contact points are the same
        try:
            roadCp, conCp = RoadLinker.getContactPoints(road, connecting)
        except:
            # lane linking not possible because they are not neighbours
            return

        if roadCp == conCp:
            logging.debug(
                f"{self.name}: switching lane sides for {connecting.id} and {road.id}"
            )

        if connecting_lanesec != None:
            laneSectionForConnection = connecting.lanes.lanesections[
                connecting_lanesec]
            laneSectionForRoad = road.lanes.lanesections[road_lanesection_id]
            if laneSectionForConnection.leftlanes:
                # do left lanes
                connectionLanes = laneSectionForConnection.leftlanes
                roadLanes = laneSectionForRoad.leftlanes

                if roadCp == conCp:
                    roadLanes = laneSectionForRoad.rightlanes

                if len(connectionLanes) == len(roadLanes):
                    for i in range(len(roadLanes)):
                        linkid = roadLanes[i].lane_id
                        connectionLanes[i].add_link(linktype, linkid)
                elif ignoreMismatch:
                    # raise NotImplementedError()
                    # logging.warn(f"number of left lanes are not the same for {connecting.id} and {road.id}")
                    self.connectMinLanesOnOneSide(connectionLanes, roadLanes,
                                                  linktype, None)

                else:
                    raise NotSameAmountOfLanesError(
                        'Connecting road ', connecting.id, ' and road ',
                        road.id, 'do not have the same number of left lanes.')
            if laneSectionForConnection.rightlanes:
                # do right lanes
                connectionLanes = laneSectionForConnection.rightlanes
                roadLanes = laneSectionForRoad.rightlanes

                if roadCp == conCp:
                    roadLanes = laneSectionForRoad.leftlanes

                if len(connectionLanes) == len(roadLanes):
                    for i in range(len(roadLanes)):
                        linkid = roadLanes[i].lane_id
                        connectionLanes[i].add_link(linktype, linkid)
                elif ignoreMismatch:
                    # raise NotImplementedError()
                    # logging.warn(f"number of left lanes are not the same for {connecting.id} and {road.id}")
                    self.connectMinLanesOnOneSide(connectionLanes, roadLanes,
                                                  linktype, None)
                else:
                    raise NotSameAmountOfLanesError(
                        'Connecting road ', connecting.id, ' and road ',
                        road.id, 'do not have the same number of right lanes.')
Beispiel #17
0
    def ThreeWayJunctionWithAngle(
            self,
            odrId,
            angleBetweenRoads=np.pi / 4,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            randomState=None,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            uTurnLanes=1):

        if angleBetweenRoads < np.pi / 9 or angleBetweenRoads > np.pi / 2:
            raise Exception("Come up with a better angle")

        outsideRoad = []
        roads = []

        if cp1 == pyodrx.ContactPoint.end:
            firstRoad = self.createRandomStraightRoad(
                0,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                skipEndpoint=pyodrx.ContactPoint.start)  # first road
        else:
            firstRoad = self.createRandomStraightRoad(
                0,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                skipEndpoint=pyodrx.ContactPoint.end)  # first road

        roads.append(firstRoad)
        outsideRoad.append(firstRoad)

        # second road

        secondRoad = self.createRandomStraightRoad(
            2,
            maxLanePerSide=maxLanePerSide,
            minLanePerSide=minLanePerSide,
            skipEndpoint=pyodrx.ContactPoint.end)
        outsideRoad.append(secondRoad)
        prevLanes, nextLanes = self.laneBuilder.getClockwiseAdjacentLanes(
            firstRoad=roads[0],
            firstCp=cp1,
            secondRoad=secondRoad,
            secondCP=pyodrx.ContactPoint.start)

        maxLaneWidth = self.getMaxLaneWidth(prevLanes, nextLanes)
        secondConnectionRoad = self.createConnectionRoadWithAngle(
            roadId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLaneWidth=maxLaneWidth)
        # firstRoad.addExtendedSuccessor(secondConnectionRoad, 0, pyodrx.ContactPoint.start)
        # secondConnectionRoad.addExtendedPredecessor(firstRoad, 0, cp1)
        RoadLinker.createExtendedPredSuc(predRoad=firstRoad,
                                         predCp=cp1,
                                         sucRoad=secondConnectionRoad,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=secondConnectionRoad,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=secondRoad,
                                         sucCP=pyodrx.ContactPoint.start)
        roads.append(secondConnectionRoad)
        roads.append(secondRoad)
        odrName = 'ThreeWay' + 'givenAngle' + str(odrId)
        odr = extensions.createOdrByPredecessor(odrName, roads, [])

        # third road
        thirdRoad = self.createRandomStraightRoad(
            4,
            maxLanePerSide=maxLanePerSide,
            minLanePerSide=minLanePerSide,
            skipEndpoint=pyodrx.ContactPoint.end)
        outsideRoad.append(thirdRoad)
        roadLen = roads[1].length()
        thirdConnectionRoad = self.straightRoadBuilder.create(roadId=3,
                                                              length=roadLen)
        RoadLinker.createExtendedPredSuc(predRoad=firstRoad,
                                         predCp=cp1,
                                         sucRoad=thirdConnectionRoad,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=thirdConnectionRoad,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=thirdRoad,
                                         sucCP=pyodrx.ContactPoint.start)
        roads.append(thirdConnectionRoad)
        roads.append(thirdRoad)
        odr.add_road(thirdConnectionRoad)
        odr.add_road(thirdRoad)
        odr.resetAndReadjust(byPredecessor=True)

        # last connection
        connectioRoadSecondAndThird = self.createConnectionFor2Roads(
            nextRoadId=5,
            road1=secondRoad,
            road2=thirdRoad,
            junction=None,
            cp1=pyodrx.ContactPoint.start,
            cp2=pyodrx.ContactPoint.start)
        roads.append(connectioRoadSecondAndThird)
        odr.add_road(connectioRoadSecondAndThird)
        self.fixNumOutgoingLanes(outsideRoad, cp1)

        if internalConnections:
            internalConnections = self.connectionBuilder.createSingleLaneConnectionRoads(
                6, outsideRoad, cp1, internalLinkStrategy)
            roads += internalConnections
            odr.updateRoads(roads)

        odr.resetAndReadjust(byPredecessor=True)
        return odr
Beispiel #18
0
    def createSingleLaneConnectionRoad(self, newRoadId, incomingRoad,
                                       outgoingRoad, incomingLaneId,
                                       outgoingLaneId, incomingCp, outgoingCp):
        """Warining: uses default lane width. Works only after roads has been adjusted.

        Args:
            incomingRoad ([type]): [description]
            outgoingRoad ([type]): [description]
            incomingLaneId ([type]): [description]
            outgoingLaneId ([type]): [description]
            incomingCp ([type]): [description]
            outgoingCp ([type]): [description]
        """
        laneSides = None
        if self.countryCode == CountryCodes.US:
            laneSides = LaneSides.RIGHT
        if self.countryCode == CountryCodes.UK:
            laneSides = LaneSides.LEFT

        incomingBoundaryId = incomingLaneId - 1
        if incomingLaneId < 0:
            incomingBoundaryId = incomingLaneId + 1

        outgoingBoundaryId = outgoingLaneId - 1
        if outgoingLaneId < 0:
            outgoingBoundaryId = outgoingLaneId + 1

        # TODO, get lane widths from road and create an equation.
        width = self.config.get("default_lane_width")

        x1, y1, h1 = incomingRoad.getLanePosition(incomingBoundaryId,
                                                  incomingCp)
        x2, y2, h2 = outgoingRoad.getLanePosition(outgoingBoundaryId,
                                                  outgoingCp)

        # special case for U turns from -1 to 1 or 1 to -1
        if x1 == x2 and y1 == y2:
            #     x1 = 0.9 * x1
            #     y1 = 0.9 * y1
            width -= self.uTurnFirstLaneShift

        logging.debug(f"{self.name}: createSingleLaneConnectionRoad: start: ",
                      x1, y1, h1)
        logging.debug(f"{self.name}: createSingleLaneConnectionRoad: end: ",
                      x2, y2, h2)

        xCoeffs, yCoeffs = Geometry.getCoeffsForParamPoly(
            x1,
            y1,
            h1,
            x2,
            y2,
            h2,
            incomingCp,
            outgoingCp,
            vShiftForSamePoint=self.uTurnFirstLaneShift)

        # scipy coefficient and open drive coefficents have opposite order.
        newConnection = self.curveBuilder.createParamPoly3(newRoadId,
                                                           isJunction=True,
                                                           au=xCoeffs[3],
                                                           bu=xCoeffs[2],
                                                           cu=xCoeffs[1],
                                                           du=xCoeffs[0],
                                                           av=yCoeffs[3],
                                                           bv=yCoeffs[2],
                                                           cv=yCoeffs[1],
                                                           dv=yCoeffs[0],
                                                           n_lanes=1,
                                                           lane_offset=width,
                                                           laneSides=laneSides)

        newConnection.predecessorOffset = incomingBoundaryId

        newConnection.isSingleLaneConnection = True

        RoadLinker.createExtendedPredSuc(predRoad=incomingRoad,
                                         predCp=incomingCp,
                                         sucRoad=newConnection,
                                         sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(predRoad=newConnection,
                                         predCp=pyodrx.ContactPoint.end,
                                         sucRoad=outgoingRoad,
                                         sucCP=outgoingCp)

        return newConnection
    def setUp(self):

        self.configuration = Configuration()

        self.curveRoadBuilder = CurveRoadBuilder()
        self.roadLinker = RoadLinker()
Beispiel #20
0
    def buildSimpleRoundAbout(self,
                              odrId=0,
                              numRoads=4,
                              radius=10,
                              cp1=pyodrx.ContactPoint.start,
                              direction=CircularDirection.COUNTERCLOCK_WISE):
        """In a simple roundabout, there is a circle inside the junction, the connection roads reside in the circle.

        Args:
            numRoads (int, optional): [description]. Defaults to 4.
            radius : in meters.
            cp1: contact point on the first road.
        """

        anglePerRoad = (np.pi * 2) / numRoads

        roads = []
        roads.append(
            self.straightRoadBuilder.create(0, length=self.straightRoadLen))
        nextRoadId = 1

        roadsCreated = 1

        connectionSeres = [
        ]  # holds all the connection road series so that we can create internal connections later.

        while roadsCreated < numRoads:
            previousRoadId = nextRoadId - 1
            newConnectionId = nextRoadId

            # 1. create a new connection road series and increase nextRoadId
            newConnectionSeries = self.roadBuilder.createRoundAboutConnection(
                newConnectionId, anglePerRoad, radius)
            connectionSeres.append(newConnectionSeries)

            nextRoadId += newConnectionSeries.length()
            newRoadId = nextRoadId
            nextRoadId += 1

            # 2. create a road
            newRoad = self.straightRoadBuilder.create(
                newRoadId, length=self.straightRoadLen)

            # 3 add new roads
            roads += newConnectionSeries.getAll()
            roads.append(newRoad)

            roads[previousRoadId].addExtendedSuccessor(
                newConnectionSeries.getFirst(), 0, pyodrx.ContactPoint.start)

            if newConnectionSeries.getFirst().id == 1:
                newConnectionSeries.getFirst().addExtendedPredecessor(
                    roads[previousRoadId], 0, cp1)
                # TODO this is a hack. It will not eventually work because outgoing roads' ends will come to join other junctions.
            else:
                newConnectionSeries.getFirst().addExtendedPredecessor(
                    roads[previousRoadId], 0, pyodrx.ContactPoint.start)

            RoadLinker.createExtendedPredSuc(
                predRoad=newConnectionSeries.getLast(),
                predCp=pyodrx.ContactPoint.end,
                sucRoad=newRoad,
                sucCP=pyodrx.ContactPoint.start)

            # 6 get next action
            roadsCreated += 1

            pass

        lastRoad = roads[-1]
        # 3. create connections and junction

        junction = self.createJunctionForASeriesOfRoads(roads)

        # print(f"number of roads created {len(roads)}")
        odrName = 'Simple-Roundabout-' + str(numRoads) + '_L2_' + str(odrId)
        odr = extensions.createOdrByPredecessor(odrName, roads, [junction])

        # The last connection and resetting odr

        finalConnectionSeries = self.roadBuilder.createRoundAboutConnection(
            nextRoadId, anglePerRoad, radius)
        connectionSeres.append(finalConnectionSeries)

        roads += finalConnectionSeries.getAll()

        RoadLinker.createExtendedPredSuc(
            predRoad=lastRoad,
            predCp=pyodrx.ContactPoint.start,
            sucRoad=finalConnectionSeries.getFirst(),
            sucCP=pyodrx.ContactPoint.start)
        RoadLinker.createExtendedPredSuc(
            predRoad=finalConnectionSeries.getLast(),
            predCp=pyodrx.ContactPoint.end,
            sucRoad=roads[0],
            sucCP=cp1)

        odr.updateRoads(roads)
        odr.resetAndReadjust(byPredecessor=True)

        # Last step, link connection series by curves

        self.createInternalConnectionsForConnectionSeres(
            roads, connectionSeres, junction)

        odr.updateRoads(roads)
        odr.resetAndReadjust(byPredecessor=True)

        return odr
    def createWithRandomLaneConfigurations(self, 
                                            straightRoadsPath, 
                                            id, 
                                            maxNumberOfRoadsPerJunction, 
                                            firstRoadId=0,
                                            maxLanePerSide=2, 
                                            minLanePerSide=0, 
                                            internalConnections=True, 
                                            cp1=pyodrx.ContactPoint.end, 
                                            randomState=None,
                                            internalLinkStrategy = LaneConfigurationStrategies.SPLIT_ANY, 
                                            uTurnLanes=1,
                                            equalAngles=False,
                                            getAsOdr=True):
        """All the incoming roads, except for the first, will have their start endpoint connected to the junction.

        Args:
            straightRoadsPath ([type]): [description]
            odrId ([type]): [description]
            maxNumberOfRoadsPerJunction ([type]): [description]
            maxLanePerSide (int, optional): [description]. Defaults to 2.
            minLanePerSide (int, optional): [description]. Defaults to 0.
            internalConnections (bool, optional): [description]. Defaults to True.
            cp1 ([type], optional): [description]. Defaults to pyodrx.ContactPoint.start.
            randomState ([type], optional): [description]. Defaults to None.

        Raises:
            Exception: [description]

        Returns:
            [type]: [description]
        """


        if maxNumberOfRoadsPerJunction < 2:
            raise Exception("Please add more than 1 roads")

        if uTurnLanes > 1:
            raise Exception("U-turn from more than one lanes is not implemented")

        harvestedStraightRoads = []

        # if restrictedLanes:
        #     harvestedStraightRoads = []
        # else:
        #     harvestedStraightRoads = extensions.getObjectsFromDill(straightRoadsPath)

        if randomState is not None:
            np.random.set_state(randomState)

        incidentContactPoints = []
        outsideRoads = [] # all the incoming/outgoing roads in this junction
        geoConnectionRoads = [] # connections roads which are for geometric positions, having no lanes
        laneConnectionRoads = [] # connection roads that have lanes.
        roads = []

        if cp1 == pyodrx.ContactPoint.end:
            roads.append(self.createRandomStraightRoad(0, maxLanePerSide=maxLanePerSide, minLanePerSide=minLanePerSide, skipEndpoint=pyodrx.ContactPoint.start)) # first road
        else:
            roads.append(self.createRandomStraightRoad(0, maxLanePerSide=maxLanePerSide, minLanePerSide=minLanePerSide, skipEndpoint=pyodrx.ContactPoint.end)) # first road
        

        # if restrictedLanes:
        #     if cp1 == pyodrx.ContactPoint.end:
        #         roads.append(self.createRandomStraightRoad(0, maxLanePerSide=maxLanePerSide, minLanePerSide=minLanePerSide, skipEndpoint=pyodrx.ContactPoint.start)) # first road
        #     else:
        #         roads.append(self.createRandomStraightRoad(0, maxLanePerSide=maxLanePerSide, minLanePerSide=minLanePerSide, skipEndpoint=pyodrx.ContactPoint.end)) # first road
        # else:
        #     roads.append(self.getRandomHarvestedStraightRoad(0, harvestedStraightRoads, maxLanePerSide, minLanePerSide)) # first road

        roads[0].id = firstRoadId
        outsideRoads.append(roads[0])
        incidentContactPoints.append(cp1)

        availableAngle = 1.8 * np.pi # 360 degrees
        if equalAngles:
            availableAngle = np.pi * 2
        maxAnglePerConnection = availableAngle / maxNumberOfRoadsPerJunction
        action = self.actionAfterDrawingOne(roads, availableAngle, maxNumberOfRoadsPerJunction)
        nextRoadId = firstRoadId + 1
        otherContactPoints = pyodrx.ContactPoint.start
        nIncidentAdded = 1
        while (action != "end"):

            logging.debug(f"{self.name}: availableAngle {math.degrees(availableAngle)}, number of roads: {len(roads) / 2}")

            # 0. road id generation
            previousRoadId = nextRoadId - 1
            prevIncidentRoad = roads[-1]
            newConnectionId = nextRoadId
            nextRoadId += 1
            newRoadId = nextRoadId
            nextRoadId += 1
            prevCp = otherContactPoints
            if len(roads) == 1: # first road
                prevCp = cp1

            # 1. create a road
            # newRoad = self.getRandomHarvestedStraightRoad(newRoadId, harvestedStraightRoads, maxLanePerSide, minLanePerSide)
            newRoad = self.createRandomStraightRoad(newRoadId, maxLanePerSide, minLanePerSide, skipEndpoint=pyodrx.ContactPoint.end) 
            # if restrictedLanes:
            #     newRoad = self.createRandomStraightRoad(newRoadId, maxLanePerSide, minLanePerSide, skipEndpoint=pyodrx.ContactPoint.end) 
            # else:
            #     newRoad = self.getRandomHarvestedStraightRoad(newRoadId, harvestedStraightRoads, maxLanePerSide, minLanePerSide)

            outsideRoads.append(newRoad)
            incidentContactPoints.append(otherContactPoints)

            # 2. create a new connection road

            prevLanes, nextLanes = self.laneBuilder.getClockwiseAdjacentLanes(prevIncidentRoad, prevCp, newRoad, otherContactPoints)
            # maxLaneWidth = ((len(prevLanes) + len(nextLanes)) * self.laneWidth) / 2
            maxLaneWidth = max(len(prevLanes), len(nextLanes)) * self.laneWidth
            if len(prevLanes) == 0 or len(nextLanes) == 0:
                maxLaneWidth = ((len(prevLanes) + len(nextLanes)) * self.laneWidth) / 2

            availableAngle -= (maxNumberOfRoadsPerJunction - nIncidentAdded - 1) * self.minAngle
            # print(f"Before connection road: minAngle: remaining roads:{maxNumberOfRoadsPerJunction - nIncidentAdded - 1}, {math.degrees(self.minAngle)}, available Angle: {math.degrees(availableAngle)}")

            newConnection, availableAngle = self.createGeoConnectionRoad(action, newConnectionId, availableAngle, maxAnglePerConnection, maxLaneWidth=maxLaneWidth, equalAngles=equalAngles)
            geoConnectionRoads.append(newConnection)

            availableAngle += (maxNumberOfRoadsPerJunction - nIncidentAdded - 1) * self.minAngle
            # print(f"after connection road: minAngle: {math.degrees(self.minAngle)}, available Angle: {math.degrees(availableAngle)}")
            
            # 5 add new roads
            roads.append(newConnection)
            roads.append(newRoad)
            
            RoadLinker.createExtendedPredSuc(predRoad=prevIncidentRoad, predCp=prevCp, sucRoad=newConnection, sucCP=pyodrx.ContactPoint.start)
            RoadLinker.createExtendedPredSuc(predRoad=newConnection, predCp=pyodrx.ContactPoint.end, sucRoad=newRoad, sucCP=otherContactPoints)

            self.laneBuilder.createLanesForConnectionRoad(newConnection, prevIncidentRoad, newRoad)

            # 6 get next action
            action = self.actionAfterDrawingOne(roads, availableAngle, maxNumberOfRoadsPerJunction)
            nIncidentAdded += 1
            pass
        
        # 3.0 fix outgoing lane numbers

        self.fixNumOutgoingLanes(outsideRoads, cp1)

        # 3. create connections and junction
        # TODO this is not correct anymore.
        # junction = self.createJunctionForASeriesOfRoads(roads)
        junction = pyodrx.Junction("singleConnectionsJunction", id)
        # junction = pyodrx.Junction("singleConnectionsJunction", firstRoadId)

        odrName = 'Draw_Rmax' + str(maxNumberOfRoadsPerJunction) + '_L2_' + str(id)
        odr = extensions.createOdrByPredecessor(odrName, roads, [junction])

        
        logging.debug(f"{self.name}: roads before internal connections {len(roads)}")

        # Permanent connection roads
        if internalConnections:
            internalConnections = self.connectionBuilder.createSingleLaneConnectionRoads(nextRoadId, outsideRoads, cp1, internalLinkStrategy)
            nextRoadId += len(internalConnections)
            roads += internalConnections
            odr.updateRoads(roads)

            # remove lanes from connection roads which are used for geometric positioning of roads 
            for geoRoad in geoConnectionRoads:
                geoRoad.clearLanes()

            # TODO create the junction
            self.addInternalConnectionsToJunction(junction, internalConnections)

        # U-Turns
        if uTurnLanes == 1:
            uTurnConnections = self.connectionBuilder.createUTurnConnectionRoads(nextRoadId, outsideRoads, cp1)
            nextRoadId += 1
            roads += uTurnConnections
            odr.updateRoads(roads)
            self.addInternalConnectionsToJunction(junction, internalConnections)


        logging.debug(f"{self.name}: roads after internal connections {len(roads)}")

        odr.resetAndReadjust(byPredecessor=True)

        if getAsOdr:
            return odr

        intersection = Intersection(id, outsideRoads, incidentContactPoints, geoConnectionRoads=geoConnectionRoads, odr=odr)
        return intersection
    def test_getCurvatureForAngleAndLength(self):

        numberofLanes = 5
        laneOffset = 3
        # angle = np.pi * .75
        # angle = np.pi * (5/6)
        # length = 15

        # maxCurve = AngleCurvatureMap.getMaxCurvatureMaxRoadWidth(angle, numberofLanes * laneOffset)
        # curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(angle, length, StandardCurveTypes.Simple)

        # # curve = 0.066666667

        # print(f"max curve {maxCurve}, current curve {curve}")

        # roads = []
        # roads.append(self.straightRoadBuilder.createWithDifferentLanes(0, length=10, junction=-1, n_lanes_left=numberofLanes, n_lanes_right=numberofLanes))
        # # roads.append(self.curveRoadBuilder.createSimpleCurveWithLongArc(1, angleBetweenEndpoints = angle, curvature=curve, isJunction=True, n_lanes=numberofLanes))
        # roads.append(self.curveRoadBuilder.createSimple(1, angleBetweenEndpoints = angle, curvature=curve, isJunction=True, n_lanes=numberofLanes))
        # roads.append(self.straightRoadBuilder.createWithDifferentLanes(2, length=10, junction=-1, n_lanes_left=numberofLanes, n_lanes_right=numberofLanes))

        # RoadLinker.createExtendedPredSuc(predRoad=roads[0], predCp=pyodrx.ContactPoint.end, sucRoad=roads[1], sucCP=pyodrx.ContactPoint.start)
        # RoadLinker.createExtendedPredSuc(predRoad=roads[1], predCp=pyodrx.ContactPoint.end, sucRoad=roads[2], sucCP=pyodrx.ContactPoint.start)

        # odrName = "test_createSingleLaneConnectionRoad"
        # odr = extensions.createOdrByPredecessor(odrName, roads, [])
        # # extensions.printRoadPositions(odr)

        # road = roads[1]
        # print(f"{road.id} has length {road.planview.get_total_length()}")

        # # for geom in road.planview._adjusted_geometries:
        # #     print(geom.length)

        # assert round(road.planview.get_total_length(), 0) == length
        # extensions.view_road(odr, os.path.join('..', self.esminipath))

        angle = 0.5
        while angle < np.pi:

            length = 100

            while length > 0:

                curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
                    angle, length, StandardCurveTypes.Simple)
                roads = []
                curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
                    angle, length, StandardCurveTypes.Simple)
                roads.append(
                    self.straightRoadBuilder.createWithDifferentLanes(
                        0,
                        length=10,
                        junction=-1,
                        n_lanes_left=numberofLanes,
                        n_lanes_right=numberofLanes))
                roads.append(
                    self.curveRoadBuilder.createSimple(
                        1,
                        angleBetweenEndpoints=angle,
                        curvature=curve,
                        isJunction=True,
                        n_lanes=numberofLanes))
                roads.append(
                    self.straightRoadBuilder.createWithDifferentLanes(
                        2,
                        length=10,
                        junction=-1,
                        n_lanes_left=numberofLanes,
                        n_lanes_right=numberofLanes))

                RoadLinker.createExtendedPredSuc(
                    predRoad=roads[0],
                    predCp=pyodrx.ContactPoint.end,
                    sucRoad=roads[1],
                    sucCP=pyodrx.ContactPoint.start)
                RoadLinker.createExtendedPredSuc(
                    predRoad=roads[1],
                    predCp=pyodrx.ContactPoint.end,
                    sucRoad=roads[2],
                    sucCP=pyodrx.ContactPoint.start)
                odrName = "test_createSingleLaneConnectionRoad"
                odr = extensions.createOdrByPredecessor(odrName, roads, [])
                road = roads[1]

                assert round(road.planview.get_total_length(), 0) == length

                curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
                    angle, length, StandardCurveTypes.Simple)
                roads = []
                curve = AngleCurvatureMap.getCurvatureForAngleBetweenRoadAndLength(
                    angle, length, StandardCurveTypes.Simple)
                roads.append(
                    self.curveRoadBuilder.createSimpleCurveWithLongArc(
                        1,
                        angleBetweenEndpoints=angle,
                        curvature=curve,
                        isJunction=True,
                        n_lanes=numberofLanes))
                roads.append(
                    self.curveRoadBuilder.createSimple(
                        1,
                        angleBetweenEndpoints=angle,
                        curvature=curve,
                        isJunction=True,
                        n_lanes=numberofLanes))
                roads.append(
                    self.straightRoadBuilder.createWithDifferentLanes(
                        2,
                        length=10,
                        junction=-1,
                        n_lanes_left=numberofLanes,
                        n_lanes_right=numberofLanes))

                RoadLinker.createExtendedPredSuc(
                    predRoad=roads[0],
                    predCp=pyodrx.ContactPoint.end,
                    sucRoad=roads[1],
                    sucCP=pyodrx.ContactPoint.start)
                RoadLinker.createExtendedPredSuc(
                    predRoad=roads[1],
                    predCp=pyodrx.ContactPoint.end,
                    sucRoad=roads[2],
                    sucCP=pyodrx.ContactPoint.start)
                odrName = "test_createSingleLaneConnectionRoad"
                odr = extensions.createOdrByPredecessor(odrName, roads, [])
                road = roads[1]

                assert round(road.planview.get_total_length(), 0) == length

                length -= 10

            angle += 0.25
    def drawLikeAPainter2L(self, odrId, maxNumberOfRoadsPerJunction, save=True, internalConnections=True, cp1=pyodrx.ContactPoint.end):
        if maxNumberOfRoadsPerJunction < 3:
            raise Exception("drawLikeAPainter is not for the weak. Please add more than 3 roads")

        
        maxLaneWidth = self.laneWidth 

        roads = []
        roads.append(self.straightRoadBuilder.create(0, length=self.straightRoadLen * 4)) # first road

        availableAngle = 1.8 * np.pi # 360 degrees
        maxAnglePerConnection = availableAngle / (maxNumberOfRoadsPerJunction - 1)
        action = self.actionAfterDrawingOne(roads, availableAngle, maxNumberOfRoadsPerJunction)
        nextRoadId = 1
        while (action != "end"):

            logging.debug(f"{self.name}: availableAngle {math.degrees(availableAngle)}, number of roads: {len(roads) / 2}")
            previousRoadId = nextRoadId - 1
            newConnectionId = nextRoadId
            nextRoadId += 1
            newRoadId = nextRoadId
            nextRoadId += 1

            # 1. create a road
            newRoad = self.straightRoadBuilder.create(newRoadId, length=self.straightRoadLen)

            # 2. create a new connection road
            newConnection, availableAngle = self.createGeoConnectionRoad(action, newConnectionId, availableAngle, maxAnglePerConnection, maxLaneWidth=maxLaneWidth)
            
            # 5 add new roads and increase road id
            roads.append(newConnection)
            roads.append(newRoad)

            # roads[previousRoadId].add_successor(pyodrx.ElementType.junction, newConnection.id)
            roads[previousRoadId].addExtendedSuccessor(newConnection, 0, pyodrx.ContactPoint.start)

            if newConnection.id == 1:
                # TODO this is a hack. It will not eventually work because outgoing roads' ends will come to join other junctions.
                newConnection.addExtendedPredecessor(roads[previousRoadId], 0 , cp1)
            else:
                newConnection.addExtendedPredecessor(roads[previousRoadId], 0 , pyodrx.ContactPoint.start)
            
            RoadLinker.createExtendedPredSuc(predRoad=newConnection, predCp=pyodrx.ContactPoint.end, sucRoad=newRoad, sucCP=pyodrx.ContactPoint.start)


            # 6 get next action
            action = self.actionAfterDrawingOne(roads, availableAngle, maxNumberOfRoadsPerJunction)
            pass
        
        # 3. create connections and junction

        junction = self.createJunctionForASeriesOfRoads(roads, odrId)

        odrName = 'Draw_Rmax' + str(maxNumberOfRoadsPerJunction) + '_L2_' + str(odrId)
        odr = extensions.createOdrByPredecessor(odrName, roads, [junction])

        # The last connection and resetting odr

        lastConnection = self.createLastConnectionForLastAndFirstRoad(nextRoadId, roads, junction, cp1=cp1)
        roads.append(lastConnection)
        odr.add_road(lastConnection)

        logging.debug(f"{self.name}: roads before internal connections {len(roads)}")

        if internalConnections:
            self.createInternalConnectionsForMissingSequentialRoads(roads, junction, cp1=cp1)
            odr.updateRoads(roads)

        logging.debug(f"{self.name}: roads after internal connections {len(roads)}")

        odr.resetAndReadjust(byPredecessor=True)
        
        return odr
Beispiel #24
0
    def _create_links_roads(self,
                            pre_road: ExtendedRoad,
                            suc_road: ExtendedRoad,
                            ignoreMismatch=True):
        """ _create_links_roads takes two roads and connect the lanes with links, if they have the same amount. 

            Parameters
            ----------
                pre_road (Road): the predecessor road 

                suc_road (Road): the successor road

        """
        # invert lanes if contact points are the same
        try:
            roadCp, conCp = RoadLinker.getContactPoints(pre_road, suc_road)
        except:
            # lane linking not possible because they are not neighbours
            return

        if roadCp == conCp:
            logging.debug(
                f"{self.name}: switching lane sides for {pre_road.id} and {suc_road.id}"
            )

        pre_linktype, pre_sign, pre_connecting_lanesec = self._get_related_lanesection(
            pre_road, suc_road)
        suc_linktype, suc_sign, suc_connecting_lanesec = self._get_related_lanesection(
            suc_road, pre_road)
        preLaneSection = pre_road.lanes.lanesections[pre_connecting_lanesec]
        # TODO it may be wrong. shouldn't it be suc_connecting_lanesec
        # sucLaneSection = suc_road.lanes.lanesections[-1]
        sucLaneSection = suc_road.lanes.lanesections[suc_connecting_lanesec]

        # left
        preLanes = preLaneSection.leftlanes
        sucLanes = sucLaneSection.leftlanes
        if roadCp == conCp:
            sucLanes = sucLaneSection.rightlanes

        if len(preLanes) == len(sucLanes):
            for i in range(len(preLanes)):
                preLanes[i].add_link(pre_linktype, sucLanes[i].lane_id)
                sucLanes[i].add_link(suc_linktype, preLanes[i].lane_id)

        elif ignoreMismatch:

            # logging.warn(f"number of left lanes are not the same for {pre_road.id} and {suc_road.id}")
            self.connectMinLanesOnOneSide(preLanes, sucLanes, pre_linktype,
                                          suc_linktype)

        else:
            raise NotSameAmountOfLanesError(
                'Road ' + str(pre_road.id) + ' and road ' + str(suc_road.id) +
                ' does not have the same number of right lanes.')

        #right
        preLanes = preLaneSection.rightlanes
        sucLanes = sucLaneSection.rightlanes
        if roadCp == conCp:
            sucLanes = sucLaneSection.leftlanes

        if len(preLanes) == len(sucLanes):
            for i in range(len(preLanes)):
                preLanes[i].add_link(pre_linktype, sucLanes[i].lane_id)
                sucLanes[i].add_link(suc_linktype, preLanes[i].lane_id)

        elif ignoreMismatch:

            # logging.warn(f"number of left lanes are not the same for {pre_road.id} and {suc_road.id}")

            self.connectMinLanesOnOneSide(preLanes, sucLanes, pre_linktype,
                                          suc_linktype)

        else:
            raise NotSameAmountOfLanesError(
                'Road ' + str(pre_road.id) + ' and road ' + str(suc_road.id) +
                ' does not have the same number of right lanes.')