Beispiel #1
0
class test_LaneLinker(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.roadLinker = RoadLinker()

    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")))

    def test_DifferentCPs(self):

        # same cps
        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=20,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=1))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(1,
                                                              length=10,
                                                              junction=-1,
                                                              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.start)

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

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

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

        # same cps 2
        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              length=20,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=1))
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(1,
                                                              length=10,
                                                              junction=-1,
                                                              n_lanes_left=2,
                                                              n_lanes_right=1))

        roads[0].addExtendedSuccessor(roads[1], 0, pyodrx.ContactPoint.start)
        roads[1].addExtendedPredecessor(roads[0], 0, pyodrx.ContactPoint.end)

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

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

        xmlPath = f"output/test_DifferentCPs2.xodr"
        odr.write_xml(xmlPath)
Beispiel #2
0
class JunctionBuilder:
    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

    def createJunctionForASeriesOfRoads(self, roads, id=0):
        """[summary]

        Args:
            roads ([type]): even indices are roads, odd indices are connection roads  of the junction

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

        # TODO it does not support all lanes.
        # ID is wrong
        junction = pyodrx.Junction("spiderJunction", id)

        connectionId = 1

        while (connectionId < len(roads)):

            print(f"connecting roads {connectionId-1} {connectionId}")
            connectionL = pyodrx.Connection(connectionId - 1, connectionId,
                                            pyodrx.ContactPoint.start)
            connectionL.add_lanelink(-1, -1)

            # if (connectionId + 1) < len(roads):
            #     connectionR = pyodrx.Connection(connectionId+1, connectionId, pyodrx.ContactPoint.end)
            # else:
            #     connectionR = pyodrx.Connection(0, connectionId, pyodrx.ContactPoint.end)

            # connectionR.add_lanelink(1,1)

            junction.add_connection(connectionL)
            # junction.add_connection(connectionR)

            connectionId += 2

        return junction

    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

    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

    def createInternalConnectionsForConnectionSeres(self, roads,
                                                    connectionSeres, junction):
        """Assumes last road has the largest id. Used to create internal connections inside a junction. Assumes a connection series has middle roads which are connected by an internal connection road. Normally each series will have 3 roads.

        Args:
            roads ([type]): [description]
            connectionSeres ([type]): list of ConnectionSeries type
        """

        # for each last road in a series, connect with the next first road
        length = len(connectionSeres)
        nextRoadId = connectionSeres[-1].getLast().id + 1  # last id so far.

        for i in range(length):
            currentConnectionS = connectionSeres[i]

            if (i + 1) < length:
                nextConnectionS = connectionSeres[i + 1]
            else:
                nextConnectionS = connectionSeres[0]

            # traffic will go from current to next

            fromRoad = currentConnectionS.getMiddle()
            toRoad = nextConnectionS.getMiddle()

            print(
                f"creating internal connection from {fromRoad.id} to {toRoad.id}"
            )

            newConnection = self.createConnectionFor2Roads(
                nextRoadId,
                fromRoad,
                toRoad,
                cp1=pyodrx.ContactPoint.end,
                cp2=pyodrx.ContactPoint.start,
                junction=junction,
                laneSides=LaneSides.RIGHT)

            roads.append(newConnection)

            nextRoadId += 1

        return nextRoadId

    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 createConnectionRoads(self,
                              roads,
                              adjusted=False,
                              areaType=JunctionAreaTypes.SQUARE):

        if adjusted is False:
            # set up x,y positions and headings for the roads around the boundary of the area

            if areaType == JunctionAreaTypes.SQUARE:
                # maximum roads to connect to a side
                maxRoadsPerSide = math.floor(len(roads) / 4) + 1

    def createWithRandomLaneConfigurations(self, numRoads=3):

        raise NotImplementedError()
Beispiel #3
0
class test_LaneConfiguration(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()

        self.straightRoadBuilder = StraightRoadBuilder()

    def test_getLaneLinksByMergingEdge(self):

        # 1
        centerLane = ExtendedLane(pyodrx.LaneType.median)
        section1 = ExtendedLaneSection(0, centerLane)
        section2 = ExtendedLaneSection(0, centerLane)

        section1.add_left_lane(ExtendedLane(a=3))
        section1.add_right_lane(ExtendedLane(a=3))

        section2.add_left_lane(ExtendedLane(a=3))

        ls, rs = LaneConfiguration.getLaneLinksByMergingEdge(
            section1, section2, False)

        assert len(ls) == max(len(section1.leftlanes), len(section2.leftlanes))
        assert len(rs) == 0

        # [(1, 1, False)]
        assert ls[0][0] == 1 and ls[0][1] == 1 and ls[0][2] == False

        print("test 1")
        print(ls)
        print(rs)

        #2

        section2.add_right_lane(ExtendedLane(a=3))
        ls, rs = LaneConfiguration.getLaneLinksByMergingEdge(
            section1, section2, False)
        assert len(ls) == max(len(section1.leftlanes), len(section2.leftlanes))
        assert len(rs) == max(len(section1.rightlanes),
                              len(section2.rightlanes))
        assert ls[0][0] == 1 and ls[0][1] == 1 and ls[0][2] == False
        assert rs[0][0] == -1 and rs[0][1] == -1 and rs[0][2] == False

        print("test 2")
        print(ls)
        print(rs)

        section1.add_left_lane(ExtendedLane(a=3))
        section1.add_left_lane(ExtendedLane(a=3))

        ls, rs = LaneConfiguration.getLaneLinksByMergingEdge(
            section1, section2, False)
        print("test 3")
        print(ls)
        print(rs)
        assert len(ls) == max(len(section1.leftlanes), len(section2.leftlanes))
        assert len(rs) == max(len(section1.rightlanes),
                              len(section2.rightlanes))
        assert ls[0][0] == 1 and ls[0][1] == 1 and ls[0][2] == False
        assert rs[0][0] == -1 and rs[0][1] == -1 and rs[0][2] == False

        section2.add_right_lane(ExtendedLane(a=3))

        ls, rs = LaneConfiguration.getLaneLinksByMergingEdge(
            section1, section2, False)
        print("test 4")
        print(ls)
        print(rs)
        assert len(ls) == max(len(section1.leftlanes), len(section2.leftlanes))
        assert len(rs) == max(len(section1.rightlanes),
                              len(section2.rightlanes))
        assert ls[0][0] == 1 and ls[0][1] == 1 and ls[0][2] == False
        assert rs[0][0] == -1 and rs[0][1] == -1 and rs[0][2] == False

        section2.add_left_lane(ExtendedLane(a=3))
        section2.add_left_lane(ExtendedLane(a=3))
        section2.add_left_lane(ExtendedLane(a=3))
        section2.add_left_lane(ExtendedLane(a=3))
        section1.add_right_lane(ExtendedLane(a=3))
        section1.add_right_lane(ExtendedLane(a=3))

        ls, rs = LaneConfiguration.getLaneLinksByMergingEdge(
            section1, section2, False)
        print("test 5")
        print(ls)
        print(rs)
        assert len(ls) == max(len(section1.leftlanes), len(section2.leftlanes))
        assert len(rs) == max(len(section1.rightlanes),
                              len(section2.rightlanes))
        assert ls[0][0] == 1 and ls[0][1] == 1 and ls[0][2] == False
        assert rs[0][0] == -1 and rs[0][1] == -1 and rs[0][2] == False

        straightLanesLeft = set([i for i, _, conType in ls if conType == 0])
        print(straightLanesLeft)

    def test_getIntersectionLinks1ToMany(self):

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1']

        try:
            LaneConfiguration.getIntersectionLinks1ToMany(
                incomingLanes, outgoingLanes)
            assert False
        except Exception as e:
            print(e)
            pass

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2']

        try:
            connections = LaneConfiguration.getIntersectionLinks1ToMany(
                incomingLanes, outgoingLanes)
            assert connections[0][0] == '1:-1'
            assert connections[0][1] == '2:1'
            assert connections[0][2] == 0
            assert connections[1][0] == '1:-2'
            assert connections[1][1] == '2:2'
            assert connections[1][2] == 0
            # print(connections)
        except Exception as e:
            print(e)
            assert False

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2', '3:1']

        try:
            connections = LaneConfiguration.getIntersectionLinks1ToMany(
                incomingLanes, outgoingLanes)
            assert connections[0][0] == '1:-1'
            assert connections[0][1] == '2:1'
            assert connections[0][2] == 0
            assert connections[1][0] == '1:-2'
            assert connections[1][1] == '2:2'
            assert connections[1][2] == 0
            assert connections[2][0] == '1:-2'
            assert connections[2][1] == '3:1'
            assert connections[2][2] == 2
            print(connections)
        except Exception as e:
            print(e)
            assert False

    def test_getUniqueLaneIds(self):

        roads = []
        roads.append(self.straightRoadBuilder.create(0, length=10, n_lanes=2))
        laneIds = LaneConfiguration.getUniqueLaneIds(
            roads[0],
            roads[0].getLaneSectionByCP(pyodrx.ContactPoint.start).leftlanes)
        # print(laneIds)
        assert laneIds[0] == '0:1'
        assert laneIds[1] == '0:2'

        laneIds = LaneConfiguration.getUniqueLaneIds(
            roads[0],
            roads[0].getLaneSectionByCP(pyodrx.ContactPoint.start).rightlanes)
        assert laneIds[0] == '0:-1'
        assert laneIds[1] == '0:-2'

    def test_getOutgoingLanesFromARoad(self):

        roads = []
        roads.append(
            self.straightRoadBuilder.create(0,
                                            length=10,
                                            n_lanes_left=2,
                                            n_lanes_right=2))
        roads.append(
            self.straightRoadBuilder.create(1,
                                            length=10,
                                            n_lanes_left=1,
                                            n_lanes_right=1))
        roads.append(
            self.straightRoadBuilder.create(2,
                                            length=10,
                                            n_lanes_left=2,
                                            n_lanes_right=2))

        inLanes = LaneConfiguration.getIncomingLaneIdsOnARoad(
            roads[0], pyodrx.ContactPoint.end, CountryCodes.US)
        outLanes = LaneConfiguration.getOutgoingLanesIdsFromARoad(
            roads[0],
            roads,
            cp1=pyodrx.ContactPoint.end,
            countryCode=CountryCodes.US)
        assert inLanes[0] == '0:-1'
        assert inLanes[1] == '0:-2'
        assert outLanes[0] == '1:-1'
        assert outLanes[1] == '2:-1'
        assert outLanes[2] == '2:-2'

        inLanes = LaneConfiguration.getIncomingLaneIdsOnARoad(
            roads[1], pyodrx.ContactPoint.start, CountryCodes.US)
        outLanes = LaneConfiguration.getOutgoingLanesIdsFromARoad(
            roads[1],
            roads,
            cp1=pyodrx.ContactPoint.end,
            countryCode=CountryCodes.US)
        print(inLanes)
        print(outLanes)
        assert inLanes[0] == '1:1'
        assert outLanes[0] == '2:-1'
        assert outLanes[1] == '2:-2'
        assert outLanes[2] == '0:1'
        assert outLanes[3] == '0:2'

        inLanes = LaneConfiguration.getIncomingLaneIdsOnARoad(
            roads[2], pyodrx.ContactPoint.start, CountryCodes.US)
        outLanes = LaneConfiguration.getOutgoingLanesIdsFromARoad(
            roads[2],
            roads,
            cp1=pyodrx.ContactPoint.end,
            countryCode=CountryCodes.US)
        print(inLanes)
        print(outLanes)
        assert inLanes[0] == '2:1'
        assert inLanes[1] == '2:2'
        assert outLanes[0] == '0:1'
        assert outLanes[1] == '0:2'
        assert outLanes[2] == '1:-1'

        linkConfig = LaneConfiguration.getIntersectionLinks1ToMany(
            inLanes, outLanes)

        print(linkConfig)

    def test_get1To1Connections(self):

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2']

        connections = LaneConfiguration.get1To1Connections(
            incomingLanes, outgoingLanes, True)
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '2:1'
        assert connections[0][2] == 0
        assert connections[1][0] == '1:-2'
        assert connections[1][1] == '2:2'
        assert connections[1][2] == 0

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2', '3:1']
        connections = LaneConfiguration.get1To1Connections(
            incomingLanes, outgoingLanes, True)

        assert len(connections) == 2
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '2:1'
        assert connections[0][2] == 0
        assert connections[1][0] == '1:-2'
        assert connections[1][1] == '2:2'
        assert connections[1][2] == 0
        connections = LaneConfiguration.get1To1Connections(
            incomingLanes, outgoingLanes, False)

        # print(connections)
        assert len(connections) == 2
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '2:2'
        assert connections[0][2] == 0
        assert connections[1][0] == '1:-2'
        assert connections[1][1] == '3:1'
        assert connections[1][2] == 0

        incomingLanes = ['1:-1']
        outgoingLanes = ['2:1', '2:2', '3:1']
        connections = LaneConfiguration.get1To1Connections(
            incomingLanes, outgoingLanes, False)

        # print(connections)
        assert len(connections) == 1
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '3:1'
        assert connections[0][2] == 0

    def test_getIntersectionLinks1ToManyBySplittingFirst(self):

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2']

        connections = LaneConfiguration.getIntersectionLinks1ToManyBySplittingFirst(
            incomingLanes, outgoingLanes)
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '2:1'
        assert connections[0][2] == 0
        assert connections[1][0] == '1:-2'
        assert connections[1][1] == '2:2'
        assert connections[1][2] == 0

        incomingLanes = ['1:-1', '1:-2']
        outgoingLanes = ['2:1', '2:2', '3:1']
        connections = LaneConfiguration.getIntersectionLinks1ToManyBySplittingFirst(
            incomingLanes, outgoingLanes)

        print(connections)
        assert len(connections) == 3
        assert connections[0][0] == '1:-1'
        assert connections[0][1] == '2:1'
        assert connections[0][2] == 2
        assert connections[1][0] == '1:-1'
        assert connections[1][1] == '2:2'
        assert connections[1][2] == 0
        assert connections[2][0] == '1:-2'
        assert connections[2][1] == '3:1'
        assert connections[2][2] == 0
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)