Esempio n. 1
0
class test_moreHelper(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.esminiPath = self.configuration.get("esminipath")
        self.rootPath = self.configuration.get('rootPath')

    def test_saveRoadImageFromFile(self):

        xodrPath = self.rootPath + "\\output\\test-RightLane.xodr"
        outputFile = extensions.saveRoadImageFromFile(
            xodrPath, self.configuration.get("esminipath"))
        assert os.path.isfile(outputFile)
class test_Intersection(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        outputDir = os.path.join(os.getcwd(), 'output')
        lastId = 0
        self.seed = 2
        self.builder = SequentialJunctionBuilder(minAngle=np.pi / 4,
                                                 maxAngle=np.pi * .75,
                                                 straightRoadLen=10,
                                                 probLongConnection=0.5,
                                                 probMinAngle=0.5,
                                                 probRestrictedLane=0.2,
                                                 maxConnectionLength=30,
                                                 minConnectionLength=12,
                                                 random_seed=self.seed)

        self.randomState = self.configuration.get("random_state")

        pass

    def test_getIncidentPoints(self):

        maxNumberOfRoadsPerJunction = 4
        path = self.configuration.get("harvested_straight_roads")
        intersection = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_FIRST,
            getAsOdr=False)

        odr = intersection.odr

        xmlPath = f"output/test_getIncidentPoints-split-first-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        incidentPoints = intersection.getIncidentPoints()
        translatedPoints = intersection.getIncidentPointsTranslatedToCenter()
        print(f"width and height: {intersection.getWH()}")
        print(incidentPoints)
        print(translatedPoints)

        extensions.printRoadPositions(odr)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
class test_RotateOpenDrive(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.threeWayJunctionBuilder = ThreeWayJunctionBuilder(
            minAngle=np.pi / 9, maxAngle=np.pi * .25, straightRoadLen=20)

    def test_RotateOpenDrive(self):
        angleBetweenRoads = np.pi / 4
        odr = self.threeWayJunctionBuilder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        # extensions.view_road(odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.printRoadPositions(odr)
        RotatedODR = extensions.rotateOpenDrive(odr=odr,
                                                startX=0.0,
                                                startY=0.0,
                                                heading=np.pi)
        extensions.printRoadPositions(RotatedODR)
        extensions.view_road(
            RotatedODR, os.path.join('..',
                                     self.configuration.get("esminipath")))
Esempio n. 4
0
class test_JunctionMerger(unittest.TestCase):

    def setUp(self):
        
        self.configuration = Configuration()
        with(open('F:\\myProjects\\av\\junction-art\\output\\harvested2R2LOrds.dill', 'rb')) as f:
            self.odrDic = dill.load(f)

        outputDir = os.path.join(os.getcwd(), 'output')
        self.merger = JunctionMerger(outputDir=outputDir, outputPrefix="test_")

    
    def test_merge2R2L(self):
        odrs = self.odrDic['0.3141592653589793']
        odrs2 = [odrs[0], odrs[2]]
        newOdr = self.merger.merge2R2L(odrs2)
        extensions.view_road(newOdr,os.path.join('..',self.configuration.get("esminipath")))
        # odrs = self.odrDic['0.3141592653589793']
        # odrs2 = [odrs[1], odrs[2]]
        # newOdr = self.merger.merge2R2L(odrs2)
        # extensions.view_road(newOdr,os.path.join('..',self.configuration.get("esminipath")))
        # odrs = self.odrDic['0.3141592653589793']
        # odrs2 = [odrs[3], odrs[4]]
        # newOdr = self.merger.merge2R2L(odrs2)
        # extensions.view_road(newOdr,os.path.join('..',self.configuration.get("esminipath")))

    def test_merge2R2L2(self):
        
        odrList = []
        for angleOdrList in self.odrDic.values():
            odrList += angleOdrList

        numberOfOds = len(odrList)

        for _ in range(5):

            try:
                selectedOdrs = [odrList[np.random.choice(numberOfOds)], odrList[np.random.choice(numberOfOds)]]
                newOdr = self.merger.merge2R2L(selectedOdrs)
                extensions.view_road(newOdr,os.path.join('..',self.configuration.get("esminipath")))
            except:
                pass
            # extensions.save_road_image(newOdr,os.path.join('..',self.configuration.get("esminipath")))
class test_CurveRoadBuilder(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()

        self.curveRoadBuilder = CurveRoadBuilder()
        self.roadLinker = RoadLinker()

    def test_SimpleCurve(self):

        roads = []
        roads.append(
            self.curveRoadBuilder.create(0,
                                         angleBetweenEndpoints=np.pi / 2,
                                         curvature=0.05,
                                         isLeftTurnLane=True))

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

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

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

        roads = []
        roads.append(
            self.curveRoadBuilder.create(0,
                                         angleBetweenEndpoints=np.pi / 2,
                                         curvature=0.05,
                                         isRightTurnLane=True))

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

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

        xmlPath = f"output/test_RightTurnLaneCurve.xodr"
        odr.write_xml(xmlPath)
Esempio n. 6
0
class test_JunctionHarvester(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.esminiPath = self.configuration.get("esminipath")
        self.harvester = JunctionHarvester(outputDir="./output",
                                           outputPrefix="test-harvest-",
                                           lastId=0,
                                           esminiPath=self.esminiPath)

    def test_harvestByPainting2L(self):

        self.harvester.harvestByPainting2L(maxNumberOfRoadsPerJunction=4,
                                           triesPerRoadCount=3,
                                           show=True)
Esempio n. 7
0
class test_HDMapBuilder(unittest.TestCase):
    def setUp(self) -> None:
        self.configuration = Configuration()
        self.hdMapBuilder = HDMapBuilder(30,
                                         mapSize=(300, 300),
                                         cellSize=(60, 60))
        with open(logfile, 'w') as f:
            f.truncate()
        pass

    def test_buildMap(self):
        name = 'first_hd_map'
        odr = self.hdMapBuilder.buildMap(name, plot=True)
        xmlPath = f"output/test_HDMapBuilder-{name}.xodr"
        odr.write_xml(xmlPath)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        pass
Esempio n. 8
0
class test_JunctionBuilder(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.junctionBuilder = JunctionBuilder()
        self.esminiPath = self.configuration.get("esminipath")

    def test_buildSimpleRoundAbout(self):

        numRoads = 6
        odr = self.junctionBuilder.buildSimpleRoundAbout(
            odrId=0, numRoads=numRoads, radius=10, cp1=pyodrx.ContactPoint.end)
        xmlPath = f"output/test-SimpleRoundAbout-{numRoads}.xodr"
        odr.write_xml(xmlPath)

        extensions.printRoadPositions(odr)
        extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)
        extensions.view_road(odr, os.path.join('..', self.esminiPath))

    def test_buildSimpleRoundAboutAndCheckInternalConnection(self):

        numRoads = 3
        odr = self.junctionBuilder.buildSimpleRoundAbout(
            odrId=0, numRoads=numRoads, radius=10, cp1=pyodrx.ContactPoint.end)
        xmlPath = f"output/test-SimpleRoundAbout-{numRoads}.xodr"
        odr.write_xml(xmlPath)

        extensions.printRoadPositions(odr)
        extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)
        extensions.view_road(odr, os.path.join('..', self.esminiPath))

        # what's the problem with internal connections?

        internalConnection = odr.roads['12'].shallowCopy()
        internalConnection.clearRoadLinks()

        odr = extensions.createOdr("12 only", [internalConnection], [])

        xmlPath = f"output/test-SimpleRoundAbout-{numRoads}-road-12.xodr"
        odr.write_xml(xmlPath)

        extensions.printRoadPositions(odr)
        extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)
        extensions.view_road(odr, os.path.join('..', self.esminiPath))
Esempio n. 9
0
class test_SequentialJunctionBuilder(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        outputDir = os.path.join(os.getcwd(), 'output')
        lastId = 0
        self.seed = 2
        self.builder = SequentialJunctionBuilder(minAngle=np.pi / 10,
                                                 maxAngle=np.pi * .75,
                                                 straightRoadLen=5,
                                                 probLongConnection=0.5,
                                                 probMinAngle=0.5,
                                                 probRestrictedLane=0.2,
                                                 maxConnectionLength=50,
                                                 minConnectionLength=20,
                                                 random_seed=self.seed)

        self.randomState = self.configuration.get("random_state")
        self.validator = IntersectionValidator()

        pass

    def test_drawLikeAPainter2L(self):
        maxNumberOfRoadsPerJunction = 3
        odr = self.builder.drawLikeAPainter2L(
            odrId=0, maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_drawLikeAPainter2L-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 4
        odr = self.builder.drawLikeAPainter2L(
            odrId=0, maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_drawLikeAPainter2L-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 5
        odr = self.builder.drawLikeAPainter2L(
            odrId=0, maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_drawLikeAPainter2L-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 6
        odr = self.builder.drawLikeAPainter2L(
            odrId=0, maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))

        xmlPath = f"output/test_drawLikeAPainter2L-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

    def test_drawLikeAPainter2LWihtoutInternalConnections(self):
        maxNumberOfRoadsPerJunction = 5
        odr = self.builder.drawLikeAPainter2L(
            odrId=0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            internalConnections=False)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_drawLikeAPainter2LWihtoutInternalConnections.xodr"
        odr.write_xml(xmlPath)

    def test_createWithRandomLaneConfigurations(self):

        maxNumberOfRoadsPerJunction = 4
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_FIRST,
            restrictedLanes=True)

        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-first-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

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

        maxNumberOfRoadsPerJunction = 3
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_LAST,
            uTurnLanes=1,
            restrictedLanes=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-last-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 5
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            restrictedLanes=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 6
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

    def test_equalAngles(self):

        maxNumberOfRoadsPerJunction = 4
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 4
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 3
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 5
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 6
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

    def test_6PlusLanes(self):

        maxNumberOfRoadsPerJunction = 7
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            equalAngles=True)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 9
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}.xodr"
        odr.write_xml(xmlPath)

    def test_TJunctions(self):

        maxNumberOfRoadsPerJunction = 3
        maxLanePerSide = 1
        minLanePerSide = 1

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            odr = self.builder.createWithRandomLaneConfigurations(
                path,
                0,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                uTurnLanes=0)

            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)

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

    def test_4WayJunctions(self):

        maxNumberOfRoadsPerJunction = 4
        maxLanePerSide = 1
        minLanePerSide = 1

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            intersection = self.builder.createWithRandomLaneConfigurations(
                path,
                sl,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                getAsOdr=False)

            odr = intersection.odr
            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)
            isValid = self.validator.validateIncidentPoints(
                intersection, self.builder.minConnectionLength)
            # if isValid == False:
            #     print(f"{sl} is an invalid intersection")
            plt = extensions.view_road(
                odr,
                os.path.join('..', self.configuration.get("esminipath")),
                returnPlt=True)
            if isValid == False:
                plt.title("Invalid")
            else:
                plt.title("Valid")
            plt.show()
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))

    def test_5WayJunctions(self):

        maxNumberOfRoadsPerJunction = 5
        maxLanePerSide = 3
        minLanePerSide = 0

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            intersection = self.builder.createWithRandomLaneConfigurations(
                path,
                sl,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                getAsOdr=False)

            odr = intersection.odr
            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)
            isValid = self.validator.validateIncidentPoints(
                intersection, self.builder.minConnectionLength)
            # if isValid == False:
            #     print(f"{sl} is an invalid intersection")
            plt = extensions.view_road(
                odr,
                os.path.join('..', self.configuration.get("esminipath")),
                returnPlt=True)
            if isValid == False:
                plt.title("Invalid")
            else:
                plt.title("Valid")
            plt.show()
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))

    def test_6WayJunctions(self):

        maxNumberOfRoadsPerJunction = 6
        maxLanePerSide = 2
        minLanePerSide = 0

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            intersection = self.builder.createWithRandomLaneConfigurations(
                path,
                sl,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                getAsOdr=False)

            odr = intersection.odr
            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)
            extensions.printRoadPositions(odr)
            isValid = self.validator.validateIncidentPoints(
                intersection, self.builder.minConnectionLength)
            # if isValid == False:
            #     print(f"{sl} is an invalid intersection")
            plt = extensions.view_road(
                odr,
                os.path.join('..', self.configuration.get("esminipath")),
                returnPlt=True)
            if isValid == False:
                plt.title(f"Invalid - {xmlPath}")
            else:
                plt.title(f"Valid - {xmlPath}")
            plt.show()
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))

    def test_7WayJunctions(self):

        maxNumberOfRoadsPerJunction = 7
        maxLanePerSide = 2
        minLanePerSide = 0

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            intersection = self.builder.createWithRandomLaneConfigurations(
                path,
                sl,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                getAsOdr=False)

            odr = intersection.odr
            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)
            extensions.printRoadPositions(odr)
            isValid = self.validator.validateIncidentPoints(
                intersection, self.builder.minConnectionLength)
            # if isValid == False:
            #     print(f"{sl} is an invalid intersection")
            plt = extensions.view_road(
                odr,
                os.path.join('..', self.configuration.get("esminipath")),
                returnPlt=True)
            if isValid == False:
                plt.title(f"Invalid - {xmlPath}")
            else:
                plt.title(f"Valid - {xmlPath}")
            plt.show()
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))

    def test_7WayJunctionsEQA(self):

        maxNumberOfRoadsPerJunction = 7
        maxLanePerSide = 2
        minLanePerSide = 0

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            intersection = self.builder.createWithRandomLaneConfigurations(
                path,
                sl,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                equalAngles=True,
                getAsOdr=False)

            odr = intersection.odr
            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)
            extensions.printRoadPositions(odr)
            isValid = self.validator.validateIncidentPoints(
                intersection, self.builder.minConnectionLength)
            # if isValid == False:
            #     print(f"{sl} is an invalid intersection")
            plt = extensions.view_road(
                odr,
                os.path.join('..', self.configuration.get("esminipath")),
                returnPlt=True)
            if isValid == False:
                plt.title(f"Invalid - {xmlPath}")
            else:
                plt.title(f"Valid - {xmlPath}")
            plt.show()
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))

    def test_8PlusWayJunctions(self):

        maxNumberOfRoadsPerJunction = 20
        maxLanePerSide = 2
        minLanePerSide = 0

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            odr = self.builder.createWithRandomLaneConfigurations(
                path,
                0,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY)

            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-{sl}.xodr"
            odr.write_xml(xmlPath)

            # extensions.view_road(odr,os.path.join('..',self.configuration.get("esminipath")))
            extensions.saveRoadImageFromFile(
                xmlPath, self.configuration.get("esminipath"))
            maxNumberOfRoadsPerJunction += 1

    def test_4WayJunctionsEqualAngles(self):

        maxNumberOfRoadsPerJunction = 4
        maxLanePerSide = 1
        minLanePerSide = 1

        for sl in range(5):
            path = self.configuration.get("harvested_straight_roads")
            odr = self.builder.createWithRandomLaneConfigurations(
                path,
                0,
                maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
                maxLanePerSide=maxLanePerSide,
                minLanePerSide=minLanePerSide,
                internalConnections=True,
                cp1=pyodrx.ContactPoint.end,
                internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
                equalAngles=True)

            # xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
            xmlPath = f"output/seed-{self.seed}-{maxNumberOfRoadsPerJunction}-way-eq-{sl}.xodr"
            odr.write_xml(xmlPath)

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

    def test_SafeMinConnectionLengthForEqualAngle(self):

        sl = 0

        maxNumberOfRoadsPerJunction = 8
        sl += 1
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=3,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            restrictedLanes=1,
            equalAngles=True)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        sl += 1
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            restrictedLanes=1,
            equalAngles=True)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        sl += 1
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            restrictedLanes=1,
            equalAngles=True)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
        odr.write_xml(xmlPath)

        maxNumberOfRoadsPerJunction = 8
        sl += 1
        path = self.configuration.get("harvested_straight_roads")
        odr = self.builder.createWithRandomLaneConfigurations(
            path,
            0,
            maxNumberOfRoadsPerJunction=maxNumberOfRoadsPerJunction,
            maxLanePerSide=2,
            minLanePerSide=0,
            internalConnections=True,
            cp1=pyodrx.ContactPoint.end,
            internalLinkStrategy=LaneConfigurationStrategies.SPLIT_ANY,
            restrictedLanes=1,
            equalAngles=True)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_createWithRandomLaneConfigurations-split-any-{maxNumberOfRoadsPerJunction}-{sl}.xodr"
        odr.write_xml(xmlPath)
Esempio n. 10
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)
class test_ExtendedRoad(unittest.TestCase):
    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 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)
Esempio n. 12
0
from classifiers.ClassifierManager import Classifiermanager
from flask import request
import numpy as np
import pprint
from library.Configuration import Configuration
from dataProcessors.DoodleDataStats import DoodleDataStats
import cv2
import numpy as np
import math
from gpt_run import RunGPT
from random import randint

configuration = Configuration()
classifierManager = Classifiermanager(configuration)
dataStats = DoodleDataStats()
dataStats.load(configuration.get('doodle.stats'))
classes = list(dataStats.stats['classes'].keys())

printer = pprint.PrettyPrinter(indent=4)
routesBluePrint = Blueprint('routes', __name__, template_folder=None)
responseProcessor = ResponseProcessor(debug=True)


@routesBluePrint.route('/')
def hello_world():
    data = 'Hello World'
    return responseProcessor.makeResponse(data)


@routesBluePrint.route("/api/doodle2story")
def doodle2Story():
Esempio n. 13
0
class test_ExtendedOpenDrive(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()

        self.roadBuilder = RoadBuilder()
        self.junctionBuilder = JunctionBuilder()
        outputDir = os.path.join(os.getcwd(), 'output')
        lastId = 0
        self.harvester = JunctionHarvester(outputDir=outputDir,
                                           outputPrefix='test_',
                                           lastId=lastId,
                                           minAngle=np.pi / 30,
                                           maxAngle=np.pi)

    def test_AdjustStartPointsForAnyRoadCombinations(self):
        # test scenario for connection road

        roads = []
        roads.append(pyodrx.create_straight_road(0, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimpleCurveWithLongArc(
                1, np.pi / 4, False, curvature=0.2))
        roads.append(pyodrx.create_straight_road(2, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimpleCurveWithLongArc(
                3, np.pi / 3, True, curvature=0.2))
        roads.append(pyodrx.create_straight_road(4, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimpleCurveWithLongArc(
                5, np.pi / 2, True, curvature=0.2))
        roads.append(pyodrx.create_straight_road(6, 10))

        roads[0].add_successor(pyodrx.ElementType.road, 1,
                               pyodrx.ContactPoint.start)

        # 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.road, 1,
                                 pyodrx.ContactPoint.end)
        roads[2].add_successor(pyodrx.ElementType.junction, 3)

        roads[3].add_predecessor(pyodrx.ElementType.road, 2,
                                 pyodrx.ContactPoint.start)
        roads[3].add_successor(pyodrx.ElementType.road, 4,
                               pyodrx.ContactPoint.start)

        roads[4].add_predecessor(pyodrx.ElementType.junction, 3)
        roads[4].add_successor(pyodrx.ElementType.junction, 5)

        roads[5].add_predecessor(pyodrx.ElementType.road, 4,
                                 pyodrx.ContactPoint.start)
        roads[5].add_successor(pyodrx.ElementType.road, 6,
                               pyodrx.ContactPoint.start)

        roads[6].add_predecessor(pyodrx.ElementType.junction, 5)

        junction = self.junctionBuilder.createJunctionForASeriesOfRoads(roads)

        odrName = "test_connectionRoad"
        odr = extensions.createOdr(odrName, roads, [junction])

        lastConnection = self.harvester.junctionBuilder.createLastConnectionForLastAndFirstRoad(
            7, roads, junction, cp1=pyodrx.ContactPoint.start)
        roads.append(lastConnection)
        odr.add_road(lastConnection)

        # randConnection = self.harvester.junctionBuilder.createConnectionFor2Roads(8, roads[0], roads[4], junction, cp1=pyodrx.ContactPoint.start)
        # roads.append(randConnection)
        # odr.add_road(randConnection)

        # randConnection2 = self.harvester.junctionBuilder.createConnectionFor2Roads(9, roads[2], roads[6], junction, cp1=pyodrx.ContactPoint.start)
        # roads.append(randConnection2)
        # odr.add_road(randConnection2)

        odr.resetAndReadjust()

        extensions.printRoadPositions(odr)

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        pass
Esempio n. 14
0
class LaneBuilder:


    def __init__(self):
        self.config = Configuration()
        self.defaultLaneWidth = self.config.get("default_lane_width")
        self.name = 'LaneBuilder'

    def getStandardLanes(self, n_lanes, lane_offset, laneSides=LaneSides.BOTH,
                            roadLength = None,
                            isLeftTurnLane=False,
                            isRightTurnLane=False,
                            isLeftMergeLane=False,
                            isRightMergeLane=False):
        """[summary] Don't allow both merge lanes and turn lanes in a road. Better split to two roads
        TODO allow merge and turn in opposite sides of a road

        Args:
            n_lanes ([type]): [description]
            lane_offset ([type]): width
            laneSides ([type], optional): where to put lanes wrt center lane. Defaults to LaneSides.BOTH.

        Returns:
            ExtenndedLanes: Road with one lane section if there is no merge or turn lanes. 3 sections otherwise. 
                            In case of turns, the first section will have no turn lanes. In case of merges, the last section will have no merge lanes.
                            In case of a single side, all the turns or merge will be added on the single side only. Otherside will have no lanes
        """
        if laneSides != LaneSides.BOTH:
            return self.getStandardTurnsOnSingleSide(n_lanes, lane_offset, laneSides,
                                            roadLength=roadLength, 
                                            isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane,
                                            isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane
                                        )
        elif self.anyTurnOrMerge(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane):
            return self.getStandardLanesWithInternalTurns(n_lanes, lane_offset, laneSides,
                                                                roadLength=roadLength, 
                                                                isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane,
                                                                isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane,
                                                                )
        else:
            return self.getStandardLanesWithDifferentLeftAndRight(n_lanes, n_lanes, lane_offset)                                

    def anyTurnOrMerge(self, isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane):
        return isLeftTurnLane or isRightTurnLane or isLeftMergeLane or isRightMergeLane


    def getStandardLanesWithDifferentLeftAndRight(self,
                            n_lanes_left, n_lanes_right,
                            lane_offset,
                            singleSide=False
                            ):
        """[summary]

        Args:
            n_lanes_left ([type]): [description]
            n_lanes_right ([type]): [description]
            lane_offset ([type]): [description]

        Returns:
            ExtendedLanes : An extended lanes object with 3 lane sections.
        """
                            

        firstSec = self.getStandardLaneSection(0, n_lanes_left, n_lanes_right, lane_offset, singleSide=singleSide)
        laneSections = extensions.ExtendedLanes()
        laneSections.add_lanesection(firstSec)
        return laneSections


    def getStandardTurnsOnSingleSide(self, n_lanes, lane_offset, laneSide=LaneSides.RIGHT,
                            roadLength = None,
                            isLeftTurnLane=False,
                            isRightTurnLane=False,
                            isLeftMergeLane=False,
                            isRightMergeLane=False,
                            laneOffset = 0):
        """[summary] Don't allow both merge lanes and turn lanes in a road. Better split to two roads
        TODO allow merge and turn in opposite sides of a road

        Args:
            n_lanes ([type]): [description]
            lane_offset ([type]): width
            laneSides ([type], optional): where to put lanes wrt center lane. Defaults to LaneSides.RIGHT.

        Returns:
            [type]: Road with one lane section if there is no merge or turn lanes. 3 sections otherwise. 
            In case of turns, the first section will have no turn lanes. In case of merges, the last section will have no merge lanes.
            One side will have no lanes.
        """

        if laneSide == LaneSides.BOTH:
            raise Exception(f"Lanes side can be left or right only.")

        self.checkTurnAndMergeConflict(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane)

        self.checkRoadLengthRequirement(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane, roadLength)


        
        n_lanes_left = 0
        n_lanes_right = 0

        if laneSide == LaneSides.RIGHT:
            n_lanes_right = n_lanes
        else:
            n_lanes_left = n_lanes

        firstSec = self.getStandardLaneSection(0, n_lanes_left, n_lanes_right, lane_offset=lane_offset, singleSide=True)
        extendedLanes = extensions.ExtendedLanes()
        extendedLanes.add_lanesection(firstSec)

        if self.anyTurnOrMerge(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane):

            turnOffSet, finalOffset, curveLaneLength = self.getOffsetsAndTurnLaneCurveLength(roadLength) 
            midSecWithTurns = self.getStandardLaneSection(turnOffSet, n_lanes_left, n_lanes_right, lane_offset=lane_offset, singleSide=True)
            finalSection = self.getStandardLaneSection(finalOffset, n_lanes_left, n_lanes_right, lane_offset=lane_offset, singleSide=True)

            

            # 1 add the turn Section
            # 2 final section should have no turns.

            turnLaneOffset = None
            finalLaneOffset = None

            if laneSide == LaneSides.RIGHT:
                if isLeftTurnLane:
                    # we need to change the center lane offset for mid and final

                    lane = self.createLinearSplitLane(TurnTypes.LEFT, lane_offset, curveLaneLength)
                    midSecWithTurns.prependLaneToRightLanes(lane)
                    finalSection.prependLaneToRightLanes(self.createStandardDrivingLane(lane_offset))

                    # now the offsets
                    # 1. one for turnOffset
                    # 2. one for finalOffset
                    turnLaneOffset = LaneOffset.createLinear(turnOffSet, maxWidth=lane_offset, laneLength=curveLaneLength)
                    finalLaneOffset = LaneOffset.createParallel(finalOffset, a=lane_offset)
                if isRightTurnLane:
                    lane = self.createLinearSplitLane(TurnTypes.RIGHT, lane_offset, curveLaneLength)
                    midSecWithTurns.add_right_lane(lane)
                    finalSection.add_right_lane(self.createStandardDrivingLane(lane_offset))
            
            if laneSide == LaneSides.LEFT:
                if isLeftTurnLane:
                    lane = self.createLinearSplitLane(TurnTypes.LEFT, lane_offset, curveLaneLength)
                    midSecWithTurns.add_left_lane(lane)
                    finalSection.add_left_lane(self.createStandardDrivingLane(lane_offset))

                if isRightTurnLane:
                    # we need to change the center lane offset for mid and final

                    lane = self.createLinearSplitLane(TurnTypes.RIGHT, lane_offset, curveLaneLength)
                    midSecWithTurns.prependLaneToLeftLanes(lane)
                    finalSection.prependLaneToLeftLanes(self.createStandardDrivingLane(lane_offset))

                    # now the offsets
                    # 1. one for turnOffset
                    # 2. one for finalOffset
                    turnLaneOffset = LaneOffset.createLinear(turnOffSet, maxWidth=-lane_offset, laneLength=curveLaneLength)
                    finalLaneOffset = LaneOffset.createParallel(finalOffset, a=-lane_offset)
                    

            extendedLanes.add_lanesection(midSecWithTurns)
            extendedLanes.add_lanesection(finalSection)

            self.addLaneOffsets(extendedLanes, turnLaneOffset, finalLaneOffset)

        

        return extendedLanes

            
    
    def getStandardLanesWithInternalTurns(self, n_lanes, lane_offset, laneSides=LaneSides.BOTH,
                            roadLength=None,
                            isLeftTurnLane=False,
                            isRightTurnLane=False,
                            isLeftMergeLane=False,
                            isRightMergeLane=False,
                            numberOfLeftTurnLanesOnRight=0,
                            numberOfRightTurnLanesOnLeft=0,
                            mergeLaneOnTheOppositeSideForInternalTurn=True):

        """Will create numberOfRightTurnLanesOnLeft right turn lanes on the left side of the center line. Equal number of mergelanes will be created on the right side of the center lane, too.
        Will create numberOfLeftTurnLanesOnRight left turn lanes on the right side of the center line. Equal number of mergelanes will be created on the left side of the center lane, too
        Args:
            n_lanes ([type]): [description]
            lane_offset ([type]): [description]
            laneSides ([type], optional): [description]. Defaults to LaneSides.BOTH.
            roadLength ([type], optional): [description]. Defaults to None.
            isLeftTurnLane (bool, optional): [description]. Defaults to False.
            isRightTurnLane (bool, optional): [description]. Defaults to False.
            isLeftMergeLane (bool, optional): [description]. Defaults to False.
            isRightMergeLane (bool, optional): [description]. Defaults to False.
            numberOfLeftTurnLanesOnRight (int, optional): [description]. Defaults to 1.
            numberOfRightTurnLanesOnLeft (int, optional): [description]. Defaults to 1.
        """

        
        if numberOfLeftTurnLanesOnRight > 0 and numberOfRightTurnLanesOnLeft > 0:
            raise Exception(f"Cannot add internal turn lanes on both sides.")

        self.checkTurnAndMergeConflict(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane)

        self.checkRoadLengthRequirement(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane, roadLength)


        turnOffSet, finalOffset, curveLaneLength = self.getOffsetsAndTurnLaneCurveLength(roadLength) 
        
        extendedLanes = self.get3SectionLanes(roadLength, turnOffSet, finalOffset, n_lanes_left=n_lanes, n_lanes_right=n_lanes, lane_offset=lane_offset)

        firstSection = extendedLanes.lanesections[0]
        midSection = extendedLanes.lanesections[1]
        finalSection = extendedLanes.lanesections[-1]

        
        # Add turn lanes section if necessary
        self.createTurnLanesAtTheEdges(isLeftTurnLane, isRightTurnLane, lane_offset, curveLaneLength, midSection, finalSection)
        self.createMergeLanesAtTheEdges(isLeftMergeLane, isRightMergeLane, lane_offset, curveLaneLength, midSection, firstSection)
        

        if numberOfRightTurnLanesOnLeft > 0:
            self.createRightTurnLanesOnLeft(numberOfRightTurnLanesOnLeft, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset)
        
        elif numberOfLeftTurnLanesOnRight > 0:
            self.createLeftTurnLanesOnRight(numberOfLeftTurnLanesOnRight, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset)


        return extendedLanes

    
    
    
    def getLanes(self, n_lanes_left, n_lanes_right, lane_offset = None, singleSide=False,
                roadLength=None,
                numLeftTurnsOnLeft=0,
                numRightTurnsOnRight=0,
                numLeftMergeOnLeft=0,
                numRightMergeOnRight=0,
                numberOfLeftTurnLanesOnRight=0,
                numberOfRightTurnLanesOnLeft=0,
                mergeLaneOnTheOppositeSideForInternalTurn=True,
                force3Section=False):
        
        """Always returns 3 lane sections if there is a turn or merge.
        """
        

        if lane_offset is None:
            lane_offset = self.defaultLaneWidth

        if (force3Section is False and numLeftTurnsOnLeft == 0 and numRightTurnsOnRight == 0
            and numLeftMergeOnLeft == 0 and numRightMergeOnRight == 0
            and numberOfLeftTurnLanesOnRight == 0  and numberOfRightTurnLanesOnLeft == 0):
            return self.getStandardLanesWithDifferentLeftAndRight(n_lanes_left, n_lanes_right, lane_offset, singleSide)     

        
        if numberOfLeftTurnLanesOnRight > 0 and numberOfRightTurnLanesOnLeft > 0:
            raise Exception(f"Cannot add internal turn lanes on both sides.")

        if roadLength is None:
            raise Exception("road length require for getLanes")

        # self.checkTurnAndMergeConflict(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane)

        # self.checkRoadLengthRequirement(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane, roadLength)


        turnOffSet, finalOffset, curveLaneLength = self.getOffsetsAndTurnLaneCurveLength(roadLength) 
        
        extendedLanes = self.get3SectionLanes(roadLength, turnOffSet, finalOffset, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right, lane_offset=lane_offset)

        firstSection = extendedLanes.lanesections[0]
        midSection = extendedLanes.lanesections[1]
        finalSection = extendedLanes.lanesections[-1]

        
        # TODO refactor to input number of turns
        self.createLeftTurnLanesOnLeftEdge(numLeftTurnsOnLeft, lane_offset, curveLaneLength, midSection, finalSection)
        self.createRightTurnLanesOnRightEdge(numRightTurnsOnRight, lane_offset, curveLaneLength, midSection, finalSection)

        self.createLeftMergesOnLeftEdge(numLeftMergeOnLeft, lane_offset, curveLaneLength, midSection, firstSection)
        self.createRightMergesOnRightEdge(numRightMergeOnRight, lane_offset, curveLaneLength, midSection, firstSection)


        if numberOfRightTurnLanesOnLeft > 0:
            self.createRightTurnLanesOnLeft(numberOfRightTurnLanesOnLeft, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset)
        
        elif numberOfLeftTurnLanesOnRight > 0:
            self.createLeftTurnLanesOnRight(numberOfLeftTurnLanesOnRight, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset)


        return extendedLanes



    def createLeftTurnLanesOnRight(self, numberOfLeftTurnLanesOnRight, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset):
        for _ in range(numberOfLeftTurnLanesOnRight):
            # 1. we need to change the center lane offset for mid and final

            lane = self.createLinearSplitLane(TurnTypes.LEFT, lane_offset, curveLaneLength)
            midSection.prependLaneToRightLanes(lane)
            finalSection.prependLaneToRightLanes(self.createStandardDrivingLane(lane_offset))

            if mergeLaneOnTheOppositeSideForInternalTurn:
                # 2. add a merge lane to left lanes
                lane = self.createLinearMergeLane(lane_offset, curveLaneLength)
                midSection.prependLaneToLeftLanes(lane)
                firstSection.prependLaneToLeftLanes(self.createStandardDrivingLane(lane_offset))


        # now the offsets
        # 1. one for turnOffset
        # 2. one for finalOffset
        # we need to shift center lane up.
        turnLaneOffset = LaneOffset.createLinear(turnOffSet, maxWidth=lane_offset * numberOfLeftTurnLanesOnRight, laneLength=curveLaneLength)
        finalLaneOffset = LaneOffset.createParallel(finalOffset, a=lane_offset * numberOfLeftTurnLanesOnRight)
        self.addLaneOffsets(extendedLanes, turnLaneOffset, finalLaneOffset)

        pass


    def createRightTurnLanesOnLeft(self, numberOfRightTurnLanesOnLeft, extendedLanes, lane_offset, curveLaneLength, firstSection, midSection, finalSection, mergeLaneOnTheOppositeSideForInternalTurn, turnOffSet, finalOffset):
        for _ in range(numberOfRightTurnLanesOnLeft):
            # 1. we need to change the center lane offset for mid and final

            lane = self.createLinearSplitLane(TurnTypes.RIGHT, lane_offset, curveLaneLength)
            midSection.prependLaneToLeftLanes(lane)
            finalSection.prependLaneToLeftLanes(self.createStandardDrivingLane(lane_offset))

            if mergeLaneOnTheOppositeSideForInternalTurn:
                # 2. add a merge lane to left lanes
                lane = self.createLinearMergeLane(lane_offset, curveLaneLength)
                midSection.prependLaneToRightLanes(lane)
                firstSection.prependLaneToRightLanes(self.createStandardDrivingLane(lane_offset))



        # now the offsets
        # 1. one for turnOffset
        # 2. one for finalOffset
        # we need to shift center lane down.

        turnLaneOffset = LaneOffset.createLinear(turnOffSet, maxWidth=-lane_offset * numberOfRightTurnLanesOnLeft, laneLength=curveLaneLength)
        finalLaneOffset = LaneOffset.createParallel(finalOffset, a=-lane_offset * numberOfRightTurnLanesOnLeft)
        self.addLaneOffsets(extendedLanes, turnLaneOffset, finalLaneOffset)

        pass


    def checkRoadLengthRequirement(self, isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane, roadLength):
        if self.anyTurnOrMerge(isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane):
            if roadLength is None:
                raise Exception("Road length cannot be None for turn lanes")



    def checkTurnAndMergeConflict(self, isLeftTurnLane, isRightTurnLane, isLeftMergeLane, isRightMergeLane):
        if (isLeftTurnLane or isRightTurnLane) and (isLeftMergeLane or isRightMergeLane):
            raise Exception("merge lane and turn lanes cannot appear in the same road. Please split the road into two for simpler calculations.")


    def getOffsetsAndTurnLaneCurveLength(self, roadLength):
        """returns soffsets for turn slope start and end

        Args:
            roadLength ([type]): [description]

        Returns:
            [type]: [description]
        """
        turnOffSet = 1
        finalOffset = roadLength - 1 # where the final lanesection resides.
        laneLength = finalOffset - turnOffSet 
        return turnOffSet, finalOffset, laneLength


    def addLaneOffsets(self, extendedLanes, turnLaneOffset, finalLaneOffset):

        if turnLaneOffset is not None:
            extendedLanes.addLaneOffset(turnLaneOffset)
        if finalLaneOffset is not None:
            extendedLanes.addLaneOffset(finalLaneOffset)
        pass


    def createLeftTurnLanesOnLeftEdge(self, numLeftTurnsOnLeft, maxWidth, laneLength, midSection, finalSection):

        for _ in range(numLeftTurnsOnLeft):
            lane = self.createLinearSplitLane(TurnTypes.LEFT, maxWidth, laneLength)
            midSection.add_left_lane(lane)
            finalSection.add_left_lane(self.createStandardDrivingLane(maxWidth))
        pass


    def createRightTurnLanesOnRightEdge(self, numRightTurnsOnRight, maxWidth, laneLength, midSection, finalSection):

        for _ in range(numRightTurnsOnRight):
            lane = self.createLinearSplitLane(TurnTypes.RIGHT, maxWidth, laneLength)
            midSection.add_right_lane(lane)
            finalSection.add_right_lane(self.createStandardDrivingLane(maxWidth))
        
        pass



    def createTurnLanesAtTheEdges(self, isLeftTurnLane, isRightTurnLane, maxWidth, laneLength, midSection, finalSection):
        """curve to the midSection, and parallel to the final section.

        Args:
            isLeftTurnLane (bool): [description]
            isRightTurnLane (bool): [description]
            maxWidth ([type]): [description]
            laneLength ([type]): [description]
            midSection ([type]): [description]
            finalSection ([type]): [description]
        """
        
        if isLeftTurnLane:
            lane = self.createLinearSplitLane(TurnTypes.LEFT, maxWidth, laneLength)
            midSection.add_left_lane(lane)
            finalSection.add_left_lane(self.createStandardDrivingLane(maxWidth))

        if isRightTurnLane:
            lane = self.createLinearSplitLane(TurnTypes.RIGHT, maxWidth, laneLength)
            midSection.add_right_lane(lane)
            finalSection.add_right_lane(self.createStandardDrivingLane(maxWidth))
        
        pass


    def createLeftMergesOnLeftEdge(self, numLeftMergeOnLeft, maxWidth, laneLength, midSection, firstSection):

        for _ in range(numLeftMergeOnLeft):
            lane = self.createLinearMergeLane(maxWidth, laneLength)
            midSection.add_left_lane(lane)

            firstSection.add_left_lane(self.createStandardDrivingLane(maxWidth))
        pass

    def createRightMergesOnRightEdge(self, numRightMergeOnRight, maxWidth, laneLength, midSection, firstSection):

        for _ in range(numRightMergeOnRight):
            lane = self.createLinearMergeLane(maxWidth, laneLength)
            midSection.add_right_lane(lane)

            firstSection.add_right_lane(self.createStandardDrivingLane(maxWidth))
        pass
     

    def createMergeLanesAtTheEdges(self, isLeftMergeLane, isRightMergeLane, maxWidth, laneLength, midSection, firstSection):
        if isLeftMergeLane:
            lane = self.createLinearMergeLane(maxWidth, laneLength)
            midSection.add_left_lane(lane)

            firstSection.add_left_lane(self.createStandardDrivingLane(maxWidth))

        if isRightMergeLane:
            lane = self.createLinearMergeLane(maxWidth, laneLength)
            midSection.add_right_lane(lane)

            firstSection.add_right_lane(self.createStandardDrivingLane(maxWidth))
        pass
    


    def getStandardLaneSection(self, soffset,  
                                n_lanes_left, n_lanes_right,
                                lane_offset,
                                singleSide=False
                                ):

        lsec = extensions.ExtendedLaneSection(soffset, self.createStandardDrivingLane(lane_offset), singleSide=singleSide)

        for _ in range(n_lanes_left):
            lsec.add_left_lane(self.createStandardDrivingLane(lane_offset))

        for _ in range(n_lanes_right):
            lsec.add_right_lane(self.createStandardDrivingLane(lane_offset))


        return lsec


    def createStandardDrivingLane(self, laneWidth):
        lane = ExtendedLane(a=laneWidth)
        lane.add_roadmark(STD_ROADMARK)
        return lane

    def createLane(self, laneType, a, b=0, c=0, d=0):
        lane = ExtendedLane(lane_type=laneType, a=a, b=b, c=c, d=d)
        lane.add_roadmark(STD_ROADMARK)
        return lane

    
    def get3SectionLanes(self, roadLength, turnOffSet, finalOffset, n_lanes_left=1, n_lanes_right=1, lane_offset=3):
        firstSec = self.getStandardLaneSection(0, n_lanes_left, n_lanes_right, lane_offset=lane_offset)
        midSection = self.getStandardLaneSection(turnOffSet, n_lanes_left, n_lanes_right, lane_offset=lane_offset)
        finalSection = self.getStandardLaneSection(finalOffset, n_lanes_left, n_lanes_right, lane_offset=lane_offset)
        extendedLanes = extensions.ExtendedLanes()
        extendedLanes.add_lanesection(firstSec)
        extendedLanes.add_lanesection(midSection)
        extendedLanes.add_lanesection(finalSection)

        return extendedLanes

    
    ### Section : Adding Lanes to existing roads

    def addOutgoingLanes(self, road, cp, num, countryCode, laneWidth=3):

        if countryCode == extensions.CountryCodes.US:
            if cp == pyodrx.ContactPoint.start:
                for _ in range(num):
                    self.addRightLaneUS(road, laneWidth=laneWidth)
            else:
                for _ in range(num):
                    self.addLefLaneUS(road, laneWidth=laneWidth)
            return
        
        raise NotImplementedError("Only us are implemented")


    def addIncomingLanes(self, road, cp, num, countryCode, laneWidth=3):

        if countryCode == extensions.CountryCodes.US:
            if cp == pyodrx.ContactPoint.start:
                for _ in range(num):
                    self.addLefLaneUS(road, laneWidth=laneWidth)
            else:
                for _ in range(num):
                    self.addRightLaneUS(road, laneWidth=laneWidth)
            return
        
        raise NotImplementedError("Only us are implemented")


    def createLinearSplitLane(self, turnType, maxWidth, laneLength, soffset=0, laneOffset = 0, laneType=pyodrx.LaneType.driving):

        if laneLength is None:
            raise Exception("Lane length cannot be None for turn lanes")

        if maxWidth is None:
            raise Exception("maxWidth cannot be None for turn lanes")

        a = laneOffset
        b = (maxWidth / laneLength)
        # c = 0
        # c = .1 * (maxWidth / laneLength)

        lane = ExtendedLane(lane_type=laneType, soffset=soffset, a=a, b=b, turnType=turnType)
        return lane


    def addLeftLane(self, road, laneWidth = 3, soffset=0, countryCode=extensions.CountryCodes.US):
        if countryCode == extensions.CountryCodes.US:
            return self.addLefLaneUS(road, laneWidth, soffset=soffset)

        raise NotImplementedError("Only us turns are implemented")


    def addLeftTurnLane(self, road, maxWidth, laneLength = None, countryCode=extensions.CountryCodes.US):
        """Assumes that the last lane section is longer than laneLength
        """

        if countryCode == extensions.CountryCodes.US:
            return self.addLeftTurnLaneUS(road, maxWidth, laneLength)

        raise NotImplementedError("Only us turns are implemented")

    

    def addLefLaneUS(self, road, laneWidth = 3, soffset=0):
        """Assumes that the last lane section is longer than laneLength
        """

        laneSections = road.getLaneSections()

        for laneSection in laneSections:
            lane = ExtendedLane(soffset=soffset, a=laneWidth)
            laneSection.add_left_lane(lane)

        pass


    def addLeftTurnLaneUS(self, road, maxWidth, laneLength = None):
        """Assumes that the last lane section is longer than laneLength
        """

        soffset = 0
        if laneLength is not None:
            soffset = road.length() - laneLength
        else:
            laneLength = road.length()

        lane = self.createLinearSplitLane(TurnTypes.LEFT, maxWidth, laneLength, soffset)

        # 2. add lane
        laneSection = road.getLastLaneSection()
        laneSection.add_left_lane(lane)

        raise NotImplementedError("addLeftTurnLaneForUS not implemented")


    def addRightLane(self, road, laneWidth = 3, soffset=0, countryCode=extensions.CountryCodes.US):
        if countryCode == extensions.CountryCodes.US:
            return self.addRightLaneUS(road, laneWidth, soffset=soffset)

        raise NotImplementedError("Only us turns are implemented")



    def addRightTurnLane(self, road, maxWidth, laneLength = None, countryCode=extensions.CountryCodes.US):
        """Assumes that the last lane section is longer than laneLength
        """

        if countryCode == extensions.CountryCodes.US:
            return self.addRightTurnLaneUS(road, maxWidth, laneLength)

        raise NotImplementedError("Only us turns are implemented")


    def addRightTurnLaneUS(self, road, maxWidth, laneLength = None):

        """Assumes that the last lane section is longer than laneLength
        Will not work for 3 lane section plan
        """

        # 1. define lane equation params
        soffset = 0
        if laneLength is not None:
            soffset = road.length() - laneLength
        else:
            laneLength = road.length()

        lane = self.createLinearSplitLane(TurnTypes.RIGHT, maxWidth, laneLength, soffset)

        # 2. add lane
        laneSection = road.getLastLaneSection()
        laneSection.add_right_lane(lane)

        pass


    def addRightLaneUS(self, road, laneWidth = 3, soffset=0):
        """Assumes that the last lane section is longer than laneLength
        """

        laneSections = road.getLaneSections()

        for laneSection in laneSections:
            lane = ExtendedLane(soffset=soffset, a=laneWidth)
            laneSection.add_right_lane(lane)

        pass


    ### Section: Merge Lanes

    def createLinearMergeLane(self, maxWidth, laneLength, soffset=0, laneType=pyodrx.LaneType.driving):


        if laneLength is None:
            raise Exception("Lane length cannot be None for turn lanes")

        if maxWidth is None:
            raise Exception("maxWidth cannot be None for turn lanes")

        a = maxWidth
        b = -(maxWidth / laneLength)
        # c = 0
        # c = .1 * (maxWidth / laneLength)

        lane = ExtendedLane(lane_type=laneType, soffset=soffset, a=a, b=b)
        return lane

    

    ### Section: Connecting roads

    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


    

    # Section Non-driving lanes.

    def addMedianIslandsToAllSections(self, road, width, laneType=pyodrx.LaneType.restricted):

        # 1. check if islands exists on left and right side.

        lanes = road.lanes

        for ls in lanes.lanesections:
            self.addMedianIslandsToSection(road, ls, width, laneType)
        
        pass
    

    def addMedianIslandsToSection(self, road, ls, width, laneType=pyodrx.LaneType.restricted):

            # lane = self.createLinearTurnLane(TurnTypes.RIGHT, lane_offset, curveLaneLength)
            # midSection.prependLaneToLeftLanes(lane)
            # finalSection.prependLaneToLeftLanes(self.createStandardDrivingLane(lane_offset))

        if len(ls.leftlanes) > 0:
            ls.prependLaneToLeftLanes(self.createLane(laneType, a=width/2))
        if len(ls.rightlanes) > 0:
            ls.prependLaneToRightLanes(self.createLane(laneType, a=width/2))

        pass
    
    def addMedianIslandsTo2Of3Sections(self, 
                road, 
                roadLength, 
                skipEndpoint, 
                width, 
                laneType=pyodrx.LaneType.restricted):
        """[summary]

        Args:
            road ([type]): [description]
            roadLength ([type]): [description]
            skipSection ([type]): valid values are: pyodrx ContactPoints. No new lane will be added to this end point.
            width ([type]): [description]
            laneType ([type], optional): [description]. Defaults to pyodrx.LaneType.restricted.

        Raises:
            Exception: [description]
        """

        # 1. check if islands exists on left and right side.

        extendedLanes = road.lanes

        if len(extendedLanes.lanesections) != 3:
            raise Exception(f"{self.name}: addMedianIslandsTo3Sections only works on 3 lane section roads")
        if roadLength is None or roadLength < 3:
            raise Exception(f"{self.name}: addMedianIslandsTo3Sections requires roadLength >= 3")

        firstSection = extendedLanes.lanesections[0]
        midSection = extendedLanes.lanesections[1]
        finalSection = extendedLanes.lanesections[-1]
        turnOffSet, finalOffset, curveLaneLength = self.getOffsetsAndTurnLaneCurveLength(roadLength) 

        if skipEndpoint == pyodrx.ContactPoint.start:
            if len(midSection.leftlanes) > 0:
                increasingLaneL = self.createLinearSplitLane(None, maxWidth=width/2, laneLength=curveLaneLength, laneType=laneType)
                midSection.prependLaneToLeftLanes(increasingLaneL)
            if len(midSection.rightlanes) > 0:
                increasingLaneR = self.createLinearSplitLane(None, maxWidth=width/2, laneLength=curveLaneLength, laneType=laneType)
                midSection.prependLaneToRightLanes(increasingLaneR)
            self.addMedianIslandsToSection(road, finalSection, width, laneType=laneType)
        else:
            if len(midSection.leftlanes) > 0:
                decreasingLaneL = self.createLinearMergeLane(maxWidth=width/2, laneLength=curveLaneLength, laneType=laneType)
                midSection.prependLaneToLeftLanes(decreasingLaneL)
            if len(midSection.rightlanes) > 0:
                decreasingLaneR = self.createLinearMergeLane(maxWidth=width/2, laneLength=curveLaneLength, laneType=laneType)
                midSection.prependLaneToRightLanes(decreasingLaneR)
            self.addMedianIslandsToSection(road, firstSection, width, laneType=laneType)

        
        pass


    def getClockwiseAdjacentLanes(self, firstRoad, firstCp, secondRoad, secondCP):

        firstLanes = firstRoad.getLaneSectionByCP(firstCp).rightlanes
        if firstCp == pyodrx.ContactPoint.end:
            firstLanes = firstRoad.getLaneSectionByCP(firstCp).leftlanes
        
        secondLanes = secondRoad.getLaneSectionByCP(secondCP).leftlanes
        if secondCP == pyodrx.ContactPoint.end:
            secondLanes = secondRoad.getLaneSectionByCP(secondCP).rightlanes
        
        return firstLanes, secondLanes
Esempio n. 15
0
class test_RoadBuilder(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.esminiPath = self.configuration.get("esminipath")
        self.configuration = Configuration()

        self.roadBuilder = RoadBuilder()
        self.junctionBuilder = JunctionBuilder()
        outputDir = os.path.join(os.getcwd(), 'output')
        lastId = 0
        self.harvester = JunctionHarvester(outputDir=outputDir,
                                           outputPrefix='test_',
                                           lastId=lastId,
                                           minAngle=np.pi / 30,
                                           maxAngle=np.pi)

    def test_ParamPoly(self):
        tangentX = np.array([9.389829642616592, -7.596531772501544])
        tangentY = np.array([0.0, 5.5192033616035365])

        t = np.array([0, 1])
        x = np.array([0, 17.8605173461395])
        y = np.array([0, -5.803233839653106])
        hermiteX = CubicHermiteSpline(t, x, tangentX)

        hermiteY = CubicHermiteSpline(t, y, tangentY)
        xCoeffs = hermiteX.c.flatten()
        yCoeffs = hermiteY.c.flatten()

        # scipy coefficient and open drive coefficents have opposite order.
        myRoad = self.roadBuilder.curveBuilder.createParamPoly3(
            0,
            isJunction=False,
            au=xCoeffs[3],
            bu=xCoeffs[2],
            cu=xCoeffs[1],
            du=xCoeffs[0],
            av=yCoeffs[3],
            bv=yCoeffs[2],
            cv=yCoeffs[1],
            dv=yCoeffs[0])

        odr = pyodrx.OpenDrive("test")
        odr.add_road(myRoad)
        odr.adjust_roads_and_lanes()

        extensions.printRoadPositions(odr)

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

    def test_getConnectionRoadBetween(self):
        # test scenario for connection road

        roads = []
        roads.append(pyodrx.create_straight_road(0, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimple(1,
                                                       np.pi / 4,
                                                       True,
                                                       curvature=0.2))
        roads.append(pyodrx.create_straight_road(2, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimple(3,
                                                       np.pi / 3,
                                                       True,
                                                       curvature=0.2))
        roads.append(pyodrx.create_straight_road(4, 10))
        roads.append(
            self.roadBuilder.curveBuilder.createSimple(5,
                                                       np.pi / 2,
                                                       True,
                                                       curvature=0.2))
        roads.append(pyodrx.create_straight_road(6, 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)
        roads[2].add_successor(pyodrx.ElementType.junction, 3)

        roads[3].add_predecessor(pyodrx.ElementType.road, 2,
                                 pyodrx.ContactPoint.start)
        roads[3].add_successor(pyodrx.ElementType.road, 4,
                               pyodrx.ContactPoint.start)

        roads[4].add_predecessor(pyodrx.ElementType.junction, 3)
        roads[4].add_successor(pyodrx.ElementType.junction, 5)

        roads[5].add_predecessor(pyodrx.ElementType.road, 4,
                                 pyodrx.ContactPoint.start)
        roads[5].add_successor(pyodrx.ElementType.road, 6,
                               pyodrx.ContactPoint.start)

        roads[6].add_predecessor(pyodrx.ElementType.junction, 5)

        junction = self.junctionBuilder.createJunctionForASeriesOfRoads(roads)

        odrName = "test_connectionRoad"
        odr = extensions.createOdr(odrName, roads, [junction])

        lastConnection = self.harvester.junctionBuilder.createLastConnectionForLastAndFirstRoad(
            7, roads, junction, cp1=pyodrx.ContactPoint.start)
        roads.append(lastConnection)
        odr.add_road(lastConnection)

        # randConnection = self.harvester.junctionBuilder.createConnectionFor2Roads(8, roads[0], roads[4], junction, cp1=pyodrx.ContactPoint.start)
        # roads.append(randConnection)
        # odr.add_road(randConnection)

        # randConnection2 = self.harvester.junctionBuilder.createConnectionFor2Roads(9, roads[2], roads[6], junction, cp1=pyodrx.ContactPoint.start)
        # roads.append(randConnection2)
        # odr.add_road(randConnection2)

        # odr.reset()
        # odr.add_road(lastConnection)
        # odr.adjust_roads_and_lanes()

        odr.resetAndReadjust()

        # pyodrx.prettyprint(odr.get_element())

        odr.write_xml(f"output/test_connectionRoad.xodr")

        # extensions.printRoadPositions(odr)

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

    def test_createMShape(self):

        roads = []
        roads.append(pyodrx.create_straight_road(0, 10))
        roads.append(self.roadBuilder.createMShape(1, 1, np.pi / 1.5, 10))
        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)

        junction = self.junctionBuilder.createJunctionForASeriesOfRoads(roads)

        odrName = "test_connectionRoad"
        odr = extensions.createOdr(odrName, roads, [junction])

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

        xmlPath = f"output/m-shape.xodr"
        odr.write_xml(xmlPath)

        extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

    def test_createMShapeLeftLanes(self):

        roads = []
        roads.append(pyodrx.create_straight_road(0, 10))
        roads.append(
            self.roadBuilder.createMShape(1,
                                          1,
                                          np.pi / 1.5,
                                          10,
                                          laneSides=junctions.LaneSides.LEFT))
        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)

        junction = self.junctionBuilder.createJunctionForASeriesOfRoads(roads)

        odrName = "test_connectionRoad"
        odr = extensions.createOdr(odrName, roads, [junction])

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

    def test_createMShapeRightLanes(self):

        roads = []
        roads.append(pyodrx.create_straight_road(0, 10))
        roads.append(
            self.roadBuilder.createMShape(
                1,
                1,
                -np.pi / 1.5,
                10,
                laneSides=junctions.LaneSides.RIGHT,
                direction=CircularDirection.COUNTERCLOCK_WISE))
        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)

        junction = self.junctionBuilder.createJunctionForASeriesOfRoads(roads)

        odrName = "test_connectionRoad"
        odr = extensions.createOdr(odrName, roads, [junction])

        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
Esempio n. 16
0
class test_StraightRoadHarvester(unittest.TestCase):
    
    def setUp(self):
        
        self.configuration = Configuration()
        self.esminiPath = self.configuration.get("esminipath")
        self.harvester = StraightRoadHarvester(outputDir="./output", outputPrefix="harvest-straight-", lastId=0, straightRoadLen=10, esminiPath=self.esminiPath)
        self.straightRoadBuilder = StraightRoadBuilder()
        self.pp = pprint.PrettyPrinter(indent=4)

    
    def test_getPossibleTurnsWRTLaneOnRight(self):
        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.RIGHT)
        assert len(possibleTurns) == 6

        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.STRAIGHT_RIGHT)
        assert len(possibleTurns) == 3

        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.STRAIGHT)
        print(possibleTurns)
        assert len(possibleTurns) == 3

        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.STRAIGHT_LEFT)
        print(possibleTurns)
        assert len(possibleTurns) == 1
        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.LEFT)
        print(possibleTurns)
        assert len(possibleTurns) == 1
        possibleTurns = self.harvester.getPossibleTurnsWRTLaneOnRight(TurnTypes.ALL)
        print(possibleTurns)
        assert len(possibleTurns) == 1
    

    def test_getLaneTurnCombinations(self):

        combinations = self.harvester.getLaneTurnCombinations(1)
        # self.pp.pprint(combinations)
        assert len(combinations) == 6

        combinations = self.harvester.getLaneTurnCombinations(2)
        self.pp.pprint(combinations)
        print(len(combinations))
        assert len(combinations) == 15

    
    def test_applyTurnCombinationOnLanes(self):
        
        road = self.straightRoadBuilder.createWithDifferentLanes(0, length=10, n_lanes_left=2, n_lanes_right=2)
        leftCombinations = self.harvester.getLaneTurnCombinations(2)
        rightCombinations = leftCombinations

        laneSectionForLeft = road.getFirstLaneSection()
        laneSectionForRight = road.getLastLaneSection()

        self.harvester.applyTurnCombinationOnLanes(laneSectionForLeft.leftlanes, leftCombinations[0])

        self.harvester.applyTurnCombinationOnLanes(laneSectionForRight.rightlanes, rightCombinations[0])

        assert laneSectionForLeft.leftlanes[0].turnType == leftCombinations[0][0]
        assert laneSectionForLeft.leftlanes[0].turnType == rightCombinations[0][0]

    
    def test_harvestUS(self):

        odrs = self.harvester.harvestUS(2, 2, False)

        print(len(odrs))

    
    def test_harvest(self):
        self.harvester.harvest(maxLeftLanes=2, maxRightLanes=2, countryCode=CountryCodes.US)
class StraightRoadBuilder:
    def __init__(self, country=CountryCodes.US):
        self.STD_ROADMARK = pyodrx.RoadMark(pyodrx.RoadMarkType.solid,
                                            0.2,
                                            rule=pyodrx.MarkRule.no_passing)
        self.STD_START_CLOTH = 1 / 1000000000
        self.country = country
        self.laneBuilder = LaneBuilder()
        self.configuration = Configuration()
        self.name = 'StraightRoadBuilder'
        pass

    def createPVForLine(self, length):
        line1 = pyodrx.Line(length)

        # create planviews
        pv = extensions.ExtendedPlanview()
        pv.add_geometry(line1)
        return pv

    def createRandom(self,
                     roadId,
                     randomState=None,
                     length=20,
                     junction=-1,
                     lane_offset=None,
                     maxLanePerSide=2,
                     minLanePerSide=0,
                     turns=False,
                     merges=False,
                     medianType=None,
                     medianWidth=3,
                     skipEndpoint=None,
                     force3Section=False):

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

        if lane_offset is None:
            lane_offset = self.configuration.get("default_lane_width")

        if maxLanePerSide < 1:
            raise Exception(
                f"{self.name}: createRandom: maxLanePerSide cannot be less than 1"
            )

        laneRange = np.arange(minLanePerSide, maxLanePerSide + 1)
        n_lanes_left = np.random.choice(laneRange)
        n_lanes_right = np.random.choice(laneRange)

        if (n_lanes_left == 0) and (n_lanes_right == 0):
            return self.createRandom(roadId,
                                     randomState=randomState,
                                     length=length,
                                     junction=junction,
                                     lane_offset=lane_offset,
                                     maxLanePerSide=maxLanePerSide,
                                     minLanePerSide=minLanePerSide,
                                     turns=turns,
                                     merges=merges,
                                     medianType=medianType,
                                     medianWidth=3,
                                     skipEndpoint=skipEndpoint,
                                     force3Section=force3Section)

        numLeftTurnsOnLeft = 0
        numRightTurnsOnRight = 0
        numLeftMergeOnLeft = 0
        numRightMergeOnRight = 0
        numberOfLeftTurnLanesOnRight = 0
        numberOfRightTurnLanesOnLeft = 0
        mergeLaneOnTheOppositeSideForInternalTurn = np.random.choice(
            [True, False])
        if turns:
            numLeftTurnsOnLeft = np.random.choice([0, 1])
            numRightTurnsOnRight = np.random.choice([0, 1])
            numberOfLeftTurnLanesOnRight = np.random.choice([0, 1])
            numberOfRightTurnLanesOnLeft = np.random.choice([0, 1])
        elif merges:
            numLeftMergeOnLeft = np.random.choice([0, 1])
            numRightMergeOnRight = np.random.choice([0, 1])

        if medianType is None:
            return self.create(
                roadId,
                n_lanes_left=n_lanes_left,
                n_lanes_right=n_lanes_right,
                length=length,
                junction=junction,
                lane_offset=lane_offset,
                laneSides=LaneSides.BOTH,
                numLeftTurnsOnLeft=numLeftTurnsOnLeft,
                numRightTurnsOnRight=numRightTurnsOnRight,
                numLeftMergeOnLeft=numLeftMergeOnLeft,
                numRightMergeOnRight=numRightMergeOnRight,
                numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight,
                numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft,
                mergeLaneOnTheOppositeSideForInternalTurn=
                mergeLaneOnTheOppositeSideForInternalTurn,
                force3Section=force3Section)
        else:
            return self.createWithMedianRestrictedLane(
                roadId,
                n_lanes_left=n_lanes_left,
                n_lanes_right=n_lanes_right,
                length=length,
                junction=junction,
                lane_offset=lane_offset,
                laneSides=LaneSides.BOTH,
                numLeftTurnsOnLeft=numLeftTurnsOnLeft,
                numRightTurnsOnRight=numRightTurnsOnRight,
                numLeftMergeOnLeft=numLeftMergeOnLeft,
                numRightMergeOnRight=numRightMergeOnRight,
                numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight,
                numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft,
                mergeLaneOnTheOppositeSideForInternalTurn=
                mergeLaneOnTheOppositeSideForInternalTurn,
                medianType=medianType,
                medianWidth=medianWidth,
                skipEndpoint=skipEndpoint)

        pass

    def create(self,
               roadId,
               n_lanes_left=1,
               n_lanes_right=1,
               length=20,
               junction=-1,
               lane_offset=3,
               laneSides=LaneSides.BOTH,
               numLeftTurnsOnLeft=0,
               numRightTurnsOnRight=0,
               numLeftMergeOnLeft=0,
               numRightMergeOnRight=0,
               numberOfLeftTurnLanesOnRight=0,
               numberOfRightTurnLanesOnLeft=0,
               mergeLaneOnTheOppositeSideForInternalTurn=True,
               force3Section=False):

        # create geometry
        pv = self.createPVForLine(length)

        # laneSections = self.laneBuilder.getStandardLanes(n_lanes, lane_offset, laneSides,
        #                                                     roadLength=length,
        #                                                     isLeftTurnLane=isLeftTurnLane, isRightTurnLane=isRightTurnLane,
        #                                                     isLeftMergeLane=isLeftMergeLane, isRightMergeLane=isRightMergeLane)
        singleSide = False
        if laneSides != LaneSides.BOTH:
            singleSide = True
        laneSections = self.laneBuilder.getLanes(
            n_lanes_left,
            n_lanes_right,
            lane_offset=lane_offset,
            singleSide=singleSide,
            roadLength=length,
            numLeftTurnsOnLeft=numLeftTurnsOnLeft,
            numRightTurnsOnRight=numRightTurnsOnRight,
            numLeftMergeOnLeft=numLeftMergeOnLeft,
            numRightMergeOnRight=numRightMergeOnRight,
            numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight,
            numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft,
            mergeLaneOnTheOppositeSideForInternalTurn=
            mergeLaneOnTheOppositeSideForInternalTurn,
            force3Section=force3Section)

        road = ExtendedRoad(roadId, pv, laneSections, road_type=junction)
        return road

    def createWithMedianRestrictedLane(
            self,
            roadId,
            n_lanes_left=1,
            n_lanes_right=1,
            length=20,
            junction=-1,
            lane_offset=3,
            laneSides=LaneSides.BOTH,
            numLeftTurnsOnLeft=0,
            numRightTurnsOnRight=0,
            numLeftMergeOnLeft=0,
            numRightMergeOnRight=0,
            numberOfLeftTurnLanesOnRight=0,
            numberOfRightTurnLanesOnLeft=0,
            mergeLaneOnTheOppositeSideForInternalTurn=True,
            medianType='partial',
            medianWidth=3,
            skipEndpoint=None):

        road = self.create(
            roadId,
            n_lanes_left=n_lanes_left,
            n_lanes_right=n_lanes_right,
            length=length,
            junction=junction,
            lane_offset=lane_offset,
            laneSides=laneSides,
            numLeftTurnsOnLeft=numLeftTurnsOnLeft,
            numRightTurnsOnRight=numRightTurnsOnRight,
            numLeftMergeOnLeft=numLeftMergeOnLeft,
            numRightMergeOnRight=numRightMergeOnRight,
            numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight,
            numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft,
            mergeLaneOnTheOppositeSideForInternalTurn=
            mergeLaneOnTheOppositeSideForInternalTurn,
            force3Section=True)
        if medianType == 'partial':
            if skipEndpoint is None:
                raise Exception(
                    f"{self.name}: createWithMedianRestrictedLane skipEndpoint cannot be None for partial median lanes."
                )

            self.laneBuilder.addMedianIslandsTo2Of3Sections(
                road,
                roadLength=length,
                skipEndpoint=skipEndpoint,
                width=medianWidth)
        else:
            self.laneBuilder.addMedianIslandsToAllSections(road,
                                                           width=medianWidth)

        return road

    def createWithRightTurnLanesOnLeft(
            self,
            roadId,
            length=100,
            junction=-1,
            n_lanes=1,
            lane_offset=3,
            laneSides=LaneSides.BOTH,
            isLeftTurnLane=False,
            isRightTurnLane=False,
            isLeftMergeLane=False,
            isRightMergeLane=False,
            numberOfRightTurnLanesOnLeft=1,
            mergeLaneOnTheOppositeSideForInternalTurn=True):

        # create geometry
        pv = self.createPVForLine(length)

        laneSections = self.laneBuilder.getStandardLanesWithInternalTurns(
            n_lanes,
            lane_offset,
            laneSides,
            roadLength=length,
            isLeftTurnLane=isLeftTurnLane,
            isRightTurnLane=isRightTurnLane,
            isLeftMergeLane=isLeftMergeLane,
            isRightMergeLane=isRightMergeLane,
            numberOfRightTurnLanesOnLeft=numberOfRightTurnLanesOnLeft,
            mergeLaneOnTheOppositeSideForInternalTurn=
            mergeLaneOnTheOppositeSideForInternalTurn)

        road = ExtendedRoad(roadId, pv, laneSections, road_type=junction)
        return road

    def createWithLeftTurnLanesOnRight(
            self,
            roadId,
            length=100,
            junction=-1,
            n_lanes=1,
            lane_offset=3,
            laneSides=LaneSides.BOTH,
            isLeftTurnLane=False,
            isRightTurnLane=False,
            isLeftMergeLane=False,
            isRightMergeLane=False,
            numberOfLeftTurnLanesOnRight=1,
            mergeLaneOnTheOppositeSideForInternalTurn=True):
        """Will create numberOfLeftTurnLanesOnRight left turn lanes on the right side of the center line. Equal number of mergelanes will be created on the left side of the center lane, too.

        Args:
            roadId ([type]): [description]
            length (int, optional): [description]. Defaults to 100.
            junction (int, optional): [description]. Defaults to -1.
            n_lanes (int, optional): [description]. Defaults to 1.
            lane_offset (int, optional): [description]. Defaults to 3.
            laneSides ([type], optional): [description]. Defaults to LaneSides.BOTH.
            isLeftTurnLane (bool, optional): [description]. Defaults to False.
            isRightTurnLane (bool, optional): [description]. Defaults to False.
            isLeftMergeLane (bool, optional): [description]. Defaults to False.
            isRightMergeLane (bool, optional): [description]. Defaults to False.
            numberOfLeftTurnLanesOnRight (int, optional): [description]. Defaults to 1.

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

        # create geometry
        pv = self.createPVForLine(length)

        laneSections = self.laneBuilder.getStandardLanesWithInternalTurns(
            n_lanes,
            lane_offset,
            laneSides,
            roadLength=length,
            isLeftTurnLane=isLeftTurnLane,
            isRightTurnLane=isRightTurnLane,
            isLeftMergeLane=isLeftMergeLane,
            isRightMergeLane=isRightMergeLane,
            numberOfLeftTurnLanesOnRight=numberOfLeftTurnLanesOnRight,
            mergeLaneOnTheOppositeSideForInternalTurn=
            mergeLaneOnTheOppositeSideForInternalTurn)

        road = ExtendedRoad(roadId, pv, laneSections, road_type=junction)
        return road

    def createWithDifferentLanes(self,
                                 roadId,
                                 length=100,
                                 junction=-1,
                                 n_lanes_left=1,
                                 n_lanes_right=1,
                                 lane_offset=3,
                                 force3Section=False):

        return self.create(roadId,
                           n_lanes_left=n_lanes_left,
                           n_lanes_right=n_lanes_right,
                           length=length,
                           junction=junction,
                           lane_offset=lane_offset,
                           force3Section=force3Section)
Esempio n. 18
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()
Esempio n. 19
0
class ConnectionBuilder:
    def __init__(self):
        self.config = Configuration()
        self.countryCode = CountryCodes.getByStr(
            self.config.get("countryCode"))
        self.curveBuilder = CurveRoadBuilder()
        self.name = "ConnectionBuilder"
        self.uTurnFirstLaneShift = self.config.get("uturn_firstlane_shift")

    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 createSingleLaneConnectionRoads(self, nextRoadId, outsideRoads, cp1,
                                        strategy):
        """Assumes all roads are connected by start point except for the first one

        Args:
            outsideRoads ([type]): [description]
            cp1 ([type]): [description]

        Returns:
            [type]: [description]
        """
        # return []

        roadDic = {}
        for road in outsideRoads:
            roadDic[road.id] = road

        newConnectionRoads = []

        firstRoadId = outsideRoads[0].id

        countOldRoads = len(outsideRoads)

        # count = 0

        for incomingRoad in outsideRoads:

            # count += 1
            # if count == 1:
            #     continue

            incomingLaneIds = []
            if firstRoadId == incomingRoad.id:
                incomingLaneIds = LaneConfiguration.getIncomingLaneIdsOnARoad(
                    incomingRoad, cp1, self.countryCode)
            else:
                incomingLaneIds = LaneConfiguration.getIncomingLaneIdsOnARoad(
                    incomingRoad, pyodrx.ContactPoint.start, self.countryCode)

            outgoingLaneIds = LaneConfiguration.getOutgoingLanesIdsFromARoad(
                incomingRoad,
                outsideRoads,
                cp1=cp1,
                countryCode=self.countryCode)

            try:
                linkConfig = LaneConfiguration.getIntersectionLinks1ToMany(
                    incomingLaneIds, outgoingLaneIds, strategy=strategy)

                # for each link, create a new connection road
                connectionRoadsForConfig = self.createRoadsForLinkConfig(
                    nextRoadId, roadDic, firstRoadId, incomingRoad, cp1,
                    linkConfig)
                nextRoadId += len(connectionRoadsForConfig)
                newConnectionRoads += connectionRoadsForConfig
            except Exception as e:
                logging.warn(f"{self.name}: {e}")
                raise e
            # break

        return newConnectionRoads

    def createUTurnConnectionRoads(
            self,
            nextRoadId,
            outsideRoads,
            cp1,
            strategy=LaneConfigurationStrategies.SPLIT_FIRST):

        # return []

        roadDic = {}
        for road in outsideRoads:
            roadDic[road.id] = road

        newConnectionRoads = []

        firstRoadId = outsideRoads[0].id

        incomingLaneIds = []

        cp = None
        for incomingRoad in outsideRoads:
            if firstRoadId == incomingRoad.id:
                cp = cp1
            else:
                cp = pyodrx.ContactPoint.start
            incomingLaneIds = LaneConfiguration.getIncomingLaneIdsOnARoad(
                incomingRoad, cp, self.countryCode)
            outgoingLaneIds = LaneConfiguration.getOutgoingLaneIdsOnARoad(
                incomingRoad, cp, self.countryCode)

            if len(incomingLaneIds) == 0 or len(outgoingLaneIds) == 0:
                continue

            incomingLaneIds = [incomingLaneIds[0]]  # only the median lane

            try:
                linkConfig = LaneConfiguration.getIntersectionLinks1ToMany(
                    incomingLaneIds, outgoingLaneIds, strategy=strategy)
                connectionRoadsForConfig = self.createRoadsForLinkConfig(
                    nextRoadId, roadDic, firstRoadId, incomingRoad, cp1,
                    linkConfig)
                nextRoadId += len(connectionRoadsForConfig)
                newConnectionRoads += connectionRoadsForConfig
            except Exception as e:
                logging.warn(f"{self.name}: {e}")
                raise e

        return newConnectionRoads

    def createRoadsForLinkConfig(self, nextRoadId, roadDic, firstRoadId,
                                 incomingRoad, cp1, linkConfig):
        newConnectionRoads = []
        for link in linkConfig:

            fromUniqueLaneId = link[0]
            incomingLaneId = int(fromUniqueLaneId.split(':')[1])

            toUniqueLaneId = link[1]
            outgoingRoadId = int(toUniqueLaneId.split(':')[0])
            outgoingLaneId = int(toUniqueLaneId.split(':')[1])

            outgoingRoad = roadDic[outgoingRoadId]

            if firstRoadId == incomingRoad.id and firstRoadId == outgoingRoad.id:  # for U-turns
                newConnection = self.createSingleLaneConnectionRoad(
                    nextRoadId, incomingRoad, outgoingRoad, incomingLaneId,
                    outgoingLaneId, cp1, cp1)
            elif firstRoadId == incomingRoad.id:
                newConnection = self.createSingleLaneConnectionRoad(
                    nextRoadId, incomingRoad, outgoingRoad, incomingLaneId,
                    outgoingLaneId, cp1, pyodrx.ContactPoint.start)
            elif firstRoadId == outgoingRoad.id:
                newConnection = self.createSingleLaneConnectionRoad(
                    nextRoadId, incomingRoad, outgoingRoad, incomingLaneId,
                    outgoingLaneId, pyodrx.ContactPoint.start, cp1)
            else:
                newConnection = self.createSingleLaneConnectionRoad(
                    nextRoadId, incomingRoad, outgoingRoad, incomingLaneId,
                    outgoingLaneId, pyodrx.ContactPoint.start,
                    pyodrx.ContactPoint.start)

            newConnectionRoads.append(newConnection)

            nextRoadId += 1

            logging.debug(f"{self.name}: created connection for link {link}")

        return newConnectionRoads
class StraightRoadHarvester:

    def __init__(self, 
                outputDir, 
                outputPrefix, 
                lastId=0,
                straightRoadBuilder=None,
                straightRoadLen = 2,
                esminiPath = None, 
                saveImage = False
                ):
        
        self.destinationPrefix = os.path.join(outputDir, outputPrefix)
        self.configuration = Configuration()
        self.lastId = lastId
        self.straightRoadLen = straightRoadLen

        self.straightRoadBuilder = straightRoadBuilder
        if straightRoadBuilder is None:
            self.straightRoadBuilder = StraightRoadBuilder()

        if esminiPath is None:
            self.esminiPath = self.configuration.get("esminipath")
        else:
            self.esminiPath = esminiPath

        self.saveImage = saveImage

        if os.path.isdir(self.esminiPath) is False:
            logging.warn(f"Esmini path not found {self.esminiPath}. Will break if you try to save images using harvester.")

        pass



    def getOutputPath(self, fname):
        return self.destinationPrefix + fname + '.xodr'


    def harvest(self, maxLeftLanes=2, maxRightLanes=2, countryCode=CountryCodes.US, show=False):
        """[summary]

        Args:
            maxLeftLanes (int, optional): [description]. Defaults to 2.
            maxRightLanes (int, optional): [description]. Defaults to 2.
            countryCode ([type], optional): [description]. Defaults to CountryCodes.US.
            show (bool, optional): [description]. Defaults to False.

        Raises:
            NotImplementedError: [description]
        
        Returns: dic with keys like "n_lanes_left-n_lanes_right" and list of odrs per key
        """

        if countryCode != CountryCodes.US:
            raise NotImplementedError("Only US is implemented")

        # permutations
        # no merge or extension
        # each lane can have one of the 5 traffic direction.

        odrs = {} # values are a list of odrs for each key

        for l in range(maxLeftLanes + 1):
            for r in range(maxRightLanes + 1):
                if l == 0 and r == 0:
                    continue
                odrs[f"{l}-{r}"] = self.harvestUS(l, r, show) # do not change the key convention
        
        # Save the odrs

        objectPath = self.destinationPrefix + f"{countryCode.value}.dill"
        with(open(objectPath, "wb")) as f:
            dill.dump(odrs, f)
            print("Odr objects saved to " + objectPath)

        print(f"keys {odrs.keys()}")

        return objectPath

    
    def harvestUS(self, n_lanes_left=2, n_lanes_right=2, show=False):

        # incoming lanes in a junction are right lanes if end point is connected, left lanes if start point is connected.
        # 5x5x5x5 for 2, 2

        print(f"harvestUS with {n_lanes_left} and {n_lanes_right}")

        odrs = []

        # now iterate through lanes and set types.

        leftCombinations = self.getLaneTurnCombinations(n_lanes_left)

        rightCombinations = self.getLaneTurnCombinations(n_lanes_right)


        # for each combinations on left and right, create a new road
        for leftComb in leftCombinations:
            for rightComb in rightCombinations:
                road = self.straightRoadBuilder.createWithDifferentLanes(self.lastId, length=self.straightRoadLen, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right)
                # right lanes, change last lane secion
                # left lanes, change first lane section.
                laneSectionForLeft = road.getFirstLaneSection()
                laneSectionForRight = road.getLastLaneSection()
    
                self.applyTurnCombinationOnLanes(laneSectionForLeft.leftlanes, leftComb)
                self.applyTurnCombinationOnLanes(laneSectionForRight.rightlanes, rightComb)

                name = f"straightRoad-{self.lastId}"
                self.lastId += 1
                odr = extensions.createOdrByPredecessor(name, roads=[road], junctions=[])
                # 1. save the xml file
                fname = odr.name
                xmlPath = self.getOutputPath(fname)
                odr.write_xml(xmlPath)

                # 2. save image
                if self.saveImage is True:
                    extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

                if show:
                    extensions.view_road(odr, os.path.join('..', self.esminiPath))

                odrs.append(odr)

        # handle cases where we dont need right lanes
        if n_lanes_right == 0:
            for leftComb in leftCombinations:
                road = self.straightRoadBuilder.createWithDifferentLanes(self.lastId, length=self.straightRoadLen, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right)
                # right lanes, change last lane secion
                # left lanes, change first lane section.
                laneSectionForLeft = road.getFirstLaneSection()
    
                self.applyTurnCombinationOnLanes(laneSectionForLeft.leftlanes, leftComb)

                name = f"straightRoad-{self.lastId}"
                self.lastId += 1
                odr = extensions.createOdrByPredecessor(name, roads=[road], junctions=[])
                # 1. save the xml file
                fname = odr.name
                xmlPath = self.getOutputPath(fname)
                odr.write_xml(xmlPath)

                # 2. save image
                if self.saveImage is True:
                    extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

                if show:
                    extensions.view_road(odr, os.path.join('..', self.esminiPath))

                odrs.append(odr)

        # handle cases where we dont need left lanes
        if n_lanes_left == 0:
            for rightComb in rightCombinations:
                road = self.straightRoadBuilder.createWithDifferentLanes(self.lastId, length=self.straightRoadLen, n_lanes_left=n_lanes_left, n_lanes_right=n_lanes_right)
                # right lanes, change last lane secion
                # left lanes, change first lane section.
                laneSectionForRight = road.getLastLaneSection()
                self.applyTurnCombinationOnLanes(laneSectionForRight.rightlanes, rightComb)

                name = f"straightRoad-{self.lastId}"
                self.lastId += 1
                odr = extensions.createOdrByPredecessor(name, roads=[road], junctions=[])
                # 1. save the xml file
                fname = odr.name
                xmlPath = self.getOutputPath(fname)
                odr.write_xml(xmlPath)

                # 2. save image
                if self.saveImage is True:
                    extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

                if show:
                    extensions.view_road(odr, os.path.join('..', self.esminiPath))

                odrs.append(odr)

        return odrs
        
    
    def applyTurnCombinationOnLanes(self, lanes, combination):

        for i in range(len(lanes)):
            lanes[i].turnType = combination[i]

        pass

    def getLaneTurnCombinations(self, n):
        """[summary]

        Args:
            n ([type]): [description]

        Returns:
            [type]: List of combinations. each combination is an ordered list
        """

    

        # from left to right

        if n == 0:
            return []

        if n == 1:
            return [[i] for i in TurnTypes.getAll()]

        combinations = []

        childrenCombinations = self.getLaneTurnCombinations(n-1)

        for childComb in childrenCombinations:
            possibleTurns = self.getPossibleTurnsWRTLaneOnRight(childComb[0])
            # push into child comb
            for possibleTurn in possibleTurns:
                childCopy = childComb.copy()
                childCopy.insert(0, possibleTurn)
                combinations.append(childCopy)
        
        return combinations
        

    
    def getPossibleTurnsWRTLaneOnRight(self, turnOnRight):

        if turnOnRight == TurnTypes.RIGHT:
            return TurnTypes.getAll()
        if turnOnRight in [TurnTypes.STRAIGHT_RIGHT, TurnTypes.STRAIGHT]:
            return (TurnTypes.LEFT, TurnTypes.STRAIGHT_LEFT, TurnTypes.STRAIGHT)
        
        return (TurnTypes.LEFT, ) # for ALL or LEFT types
Esempio n. 21
0
class JunctionHarvester:

    def __init__(self, 
                outputDir, 
                outputPrefix, 
                lastId=0, 
                minAngle = np.pi / 10, 
                maxAngle = np.pi, 
                straightRoadLen = 10,
                esminiPath = None, 
                saveImage = True):
        """The angle between two connected roads are >= self.minAngle <= self.maxAngle

        Args:
            outputDir ([type]): [description]
            outputPrefix ([type]): [description]
            lastId (int, optional): [description]. Defaults to 0.
            minAngle ([type], optional): [description]. Defaults to np.pi/10.
            maxAngle ([type], optional): [description]. Defaults to np.pi.
            straightRoadLen : used both for normal and connection roads
            esminiPath: Path to esmini to generate images for roads.
        """

        self.destinationPrefix = os.path.join(outputDir, outputPrefix)
        self.minAngle = minAngle
        self.maxAngle = maxAngle
        self.lastId = lastId
        self.straightRoadLen = straightRoadLen

        self.roadBuilder = RoadBuilder()
        self.straightRoadBuilder = StraightRoadBuilder()

        self.junctionBuilder = JunctionBuilder(self.roadBuilder)
        self.sequentialJunctionBuilder = SequentialJunctionBuilder(self.roadBuilder, self.straightRoadLen, minAngle=minAngle, maxAngle=maxAngle)

        self.junctionMerger = JunctionMerger(outputDir, outputPrefix, lastId)

        self.configuration = Configuration()

        if esminiPath is None:
            self.esminiPath = self.configuration.get("esminipath")
        else:
            self.esminiPath = esminiPath

        self.saveImage = saveImage

        if os.path.isdir(self.esminiPath) is False:
            logging.warn(f"Esmini path not found {self.esminiPath}. Will break if you try to save images using harvester.")

        pass


    

    def getOutputPath(self, fname):
        return self.destinationPrefix + fname + '.xodr'

    
    def createOdr(self, name, roads, junctions):

        return extensions.createOdr(name, roads, junctions)
        
        # odr = extensions.ExtendedOpenDrive(name)
        # for r in roads:
        #     odr.add_road(r)
        
        # for junction in junctions:
        #     odr.add_junction(junction)

        # print(f"starting adjustment. May freeze!!!!!!!!!!!!!")
        # odr.adjust_roads_and_lanes()

        # return odr


    def harvest2ways2Lanes(self, stepAngle=np.pi/20, maxTries = 100, seed=39):
        """We create junctions of two roads. Will create at least one road per angle.

        Args:
            stepAngle ([type], optional): used to generate angles between roads in conjunction with min and max angles. Defaults to np.pi/20.
            maxTries (int, optional): maximum number of junctions will be maxTries. Defaults to 1000.
            seed (int, optional): defaults to 39
        """
        np.random.seed(seed)
        # for each angle
        countCreated = 0
        roadsPerAngle = self.getRoadsPerAngle(maxTries, stepAngle)

        angleBetweenRoads = self.minAngle 
        odrObjectsPerAngle = {} # we will save the odrs keyed by angles

        while (countCreated < maxTries and angleBetweenRoads < self.maxAngle ):

            odrObjects = self.randomSome2ways2Lanes(angleBetweenRoads, roadsPerAngle)
            odrObjectsPerAngle[str(angleBetweenRoads)] = odrObjects
            countCreated += roadsPerAngle
            angleBetweenRoads += stepAngle
        
        print(f"created {countCreated} roads")

        # Save the odrs

        with(open(self.destinationPrefix + "harvested2R2LOrds.dill", "wb")) as f:
            dill.dump(odrObjectsPerAngle, f)
            print("Odr objects saved to " + self.destinationPrefix + "harvested2R2LOrds.dill" )

        pass


    def getRoadsPerAngle(self, maxTries, stepAngle):
        roadsPerAngle = round((maxTries * stepAngle)/(self.maxAngle - self.minAngle))
        if roadsPerAngle == 0:
            roadsPerAngle = 1
        return roadsPerAngle

    
    def randomSome2ways2Lanes(self, angleBetweenRoads, numberOfRoads):
        """Creates 2way junctions where the connected roads have fixed angle

        Args:
            angleBetweenRoads ([type]): The angle between the roads. The connecting road is a curve that ensures the angle is preserved.
            numberOfRoads ([type]): number of roads to be generated

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

        print( f"randomSome2ways2Lanes: creating {numberOfRoads} for angle: {math.degrees(angleBetweenRoads)}")
        odrObjects = []
        for i in range( numberOfRoads):
            odr = self.random2ways2Lanes(angleBetweenRoads)
            odrObjects.append(odr)

            # 1. save the xml file
            fname = "2R2L_" + str(round(math.degrees(angleBetweenRoads))) + "_no" + str(i)
            xmlPath = self.getOutputPath(fname)
            odr.write_xml(xmlPath)

            # 2. save image
            if self.saveImage is True:
                extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

        return odrObjects


    def random2ways2Lanes(self, angleBetweenRoads):
        # print( f"random2ways2Lanes: creating a road network for angle: {math.degrees(angleBetweenRoads)}")
        roads = []
        roads.append(pyodrx.create_straight_road(0, length=self.straightRoadLen)) # cannot reuse roads due to some references to links cannot be reinitialized with pyodrx lib.
        roads.append(self.createRandomConnectionConnectionRoad(1, angleBetweenRoads))
        roads.append(pyodrx.create_straight_road(2, length=self.straightRoadLen))

        self.link3RoadsWithMidAsJunction(roads)
        junction = self.create2RoadJunction(roads)

        self.lastId += 1

        odrName = 'R2_L2_' + str(self.lastId)
        odr = self.createOdr(odrName, roads, [junction])

        return odr


    def createRandomConnectionConnectionRoad(self, connectionRoadId, angleBetweenRoads):
        """The magic connectionRoad

        Args:
            angleBetweenRoads ([type]): The angle between the roads which this connectionRoad is suppose to connect together
            connectionRoadId ([type]): id to be assigned to the new connection road.
        """

        if angleBetweenRoads > 3.05: # when it's greater than 174 degrees, create a straight road
            return pyodrx.create_straight_road(connectionRoadId, length=self.straightRoadLen, junction=1)

        connectionRoad = self.roadBuilder.createRandomCurve(connectionRoadId, angleBetweenRoads, isJunction=True)
        return connectionRoad


    def link3RoadsWithMidAsJunction(self, roads):
        roads[0].add_successor(pyodrx.ElementType.junction,1, pyodrx.ContactPoint.start)
        self.linkInsideRoad(roads[1], 0, 2)
        roads[2].add_predecessor(pyodrx.ElementType.junction,1, pyodrx.ContactPoint.end)


    def linkInsideRoad(self, connectionRoad, predecessorId, successorId):
        connectionRoad.add_predecessor(pyodrx.ElementType.road, predecessorId, pyodrx.ContactPoint.end)
        connectionRoad.add_successor(pyodrx.ElementType.road, successorId, pyodrx.ContactPoint.start)

        pass

    def create2RoadJunction(self, roads):
        """[summary]

        Args:
            roads ([type]): 3 roads with mid as the junction type.
        """

        connection = self.connect2LaneRoads(0, 1)
        junction = pyodrx.Junction('test',1)
        junction.add_connection(connection)

        return junction

    
    def connect2LaneRoads(self, incomingRoadId, connectionRoadId,):
        """Assumes no center lane offset.

        Args:
            incomingRoadId ([type]): [description]
            connectionRoadId ([type]): [description]
        """
        connection = pyodrx.Connection(incomingRoadId, connectionRoadId, pyodrx.ContactPoint.start)
        connection.add_lanelink(-1,-1)
        return connection

        
    def harvest3WayJunctionsFrom2Ways(self, ingredientsFile, maxTries = 100, randomizeAngleSelection = True):
        """Merges 2 way junctions into 3 ways.

        Args:
            ingredientsFile ([type]): [description]
            maxTries (int, optional): [description]. Defaults to 100.
            randomizeAngleSelection (bool, optional): If True it will pick 2R roads randomly without any angle filtering. If false, it will only connect 2R roads which have different angles. Defaults to True.

        Raises:
            NotImplementedError: [description]
        """
        with(open(ingredientsFile, 'rb')) as f:
            odrDic = dill.load(f)

        selectedOdrs = None
        generatedOdrs = []
        if randomizeAngleSelection:
            odrList = []
            for angleOdrList in odrDic.values():
                odrList += angleOdrList

            numberOfOds = len(odrList)

            for _ in range(maxTries):
                try:
                    selectedOdrs = [odrList[np.random.choice(numberOfOds)], odrList[np.random.choice(numberOfOds)]]
                    newOdr = self.junctionMerger.merge2R2L(selectedOdrs)
                    generatedOdrs.append(newOdr)
                    self.lastId += 1

                except IncompatibleRoadsException:
                    continue
                
        else: 
            # TODO angle permutation for merging 2ways
            raise NotImplementedError("Angle permutation is not implemented yet")

    
        
        with(open(self.destinationPrefix + "harvested3R2LOrds.dill", "wb")) as f:
            dill.dump(generatedOdrs, f)
            print("Odr objects saved to " + self.destinationPrefix + "_harvested3R2LOrds.dill" )

        pass 


    def harvestByPainting2L(self, maxNumberOfRoadsPerJunction, triesPerRoadCount, show=False):
        """[summary]

        Args:
            maxNumberOfRoadsPerJunction ([type]): [description]
            triesPerRoadCount ([type]): number of junctions to be created for each set of roads. for 3 roads, we will try triesPerRoadCount, for 4 roads the same.
            save (bool, optional): [description]. Defaults to True.
        """

        odrs = []
        
        for numRoads in range(3, maxNumberOfRoadsPerJunction + 1):
            for _ in range(triesPerRoadCount):
                odr = self.sequentialJunctionBuilder.drawLikeAPainter2L(self.lastId, numRoads)
                self.lastId += 1

                if show:
                    extensions.view_road(odr, os.path.join('..', self.esminiPath))
                    
                xmlPath = self.getOutputPath(odr.name)
                odr.write_xml(xmlPath)
                # 2. save image
                if self.saveImage is True:
                    extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)
                
                odrs.append(odr)
        
        
        
        with(open(self.destinationPrefix + "harvestedByPainting2L.dill", "wb")) as f:
            dill.dump(odrs, f)
            print("Odr objects saved to " + self.destinationPrefix + "harvestedByPainting2L.dill" )

        pass 
Esempio n. 22
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")))
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)
Esempio n. 24
0
class test_NonOverlappingCurve(unittest.TestCase):
    def setUp(self):
        self.roadBuilder = RoadBuilder()
        self.junctionBuilder = JunctionBuilder()
        self.configuration = Configuration()
        self.angleCurvatureMap = AngleCurvatureMap()
        self.esminiPath = self.configuration.get("esminipath")

    def test_NonOverlappingCurve(self):
        numberofLanes = 10
        laneOffset = 3
        # angle = 120
        # curve, angle = AngleCurvatureMap.getCurvatureForNonOverlappingRoads(angle, numberofLanes, laneOffset)

        angle = np.pi * 0.75
        # curve, angle = AngleCurvatureMap.getCurvatureForNonOverlappingRoads(angle, numberofLanes, laneOffset)
        curve = AngleCurvatureMap.getMaxCurvatureAgainstMaxRoadWidth(
            angle, numberofLanes * laneOffset)
        roads = []
        roads.append(
            pyodrx.create_straight_road(0,
                                        50,
                                        n_lanes=numberofLanes,
                                        lane_offset=laneOffset))
        roads.append(
            self.roadBuilder.
            createSimpleCurveWithLongArcWithLaneNumberandOffset(
                1,
                angle,
                False,
                curvature=curve,
                _n_lanes=numberofLanes,
                _lane_offset=laneOffset))
        roads.append(
            pyodrx.create_straight_road(2,
                                        50,
                                        n_lanes=numberofLanes,
                                        lane_offset=laneOffset))

        roads[0].add_successor(pyodrx.ElementType.road, 1,
                               pyodrx.ContactPoint.start)

        roads[1].add_predecessor(pyodrx.ElementType.road, 0,
                                 pyodrx.ContactPoint.end)
        roads[1].add_successor(pyodrx.ElementType.road, 2,
                               pyodrx.ContactPoint.start)

        roads[2].add_predecessor(pyodrx.ElementType.road, 1,
                                 pyodrx.ContactPoint.end)

        odrName = "curve_test"
        odr = extensions.createOdr(odrName, roads, [])
        extensions.view_road(odr, self.esminiPath)

    def test_getCurvatureForAngleAndLength(self):
        numberofLanes = 10
        laneOffset = 3
        # angle = 120
        # curve, angle = AngleCurvatureMap.getCurvatureForNonOverlappingRoads(angle, numberofLanes, laneOffset)

        angle = np.pi * 1.2
        length = 20
        # curve, angle = AngleCurvatureMap.getCurvatureForNonOverlappingRoads(angle, numberofLanes, laneOffset)
        maxCurve = AngleCurvatureMap.getMaxCurvatureAgainstMaxRoadWidth(
            angle, numberofLanes * laneOffset)
        curve = AngleCurvatureMap.getCurvatureForAngleAndLength(angle, length)

        print(f"max curve {maxCurve}, current curve {curve}")
        roads = []
        roads.append(
            pyodrx.create_straight_road(0,
                                        50,
                                        n_lanes=numberofLanes,
                                        lane_offset=laneOffset))
        roads.append(
            self.roadBuilder.
            createSimpleCurveWithLongArcWithLaneNumberandOffset(
                1,
                angle,
                False,
                curvature=curve,
                _n_lanes=numberofLanes,
                _lane_offset=laneOffset))
        roads.append(
            pyodrx.create_straight_road(2,
                                        50,
                                        n_lanes=numberofLanes,
                                        lane_offset=laneOffset))

        roads[0].add_successor(pyodrx.ElementType.road, 1,
                               pyodrx.ContactPoint.start)

        roads[1].add_predecessor(pyodrx.ElementType.road, 0,
                                 pyodrx.ContactPoint.end)
        roads[1].add_successor(pyodrx.ElementType.road, 2,
                               pyodrx.ContactPoint.start)

        roads[2].add_predecessor(pyodrx.ElementType.road, 1,
                                 pyodrx.ContactPoint.end)

        odrName = "curve_test"
        odr = extensions.createOdr(odrName, roads, [])
        extensions.view_road(odr, self.esminiPath)
class test_RoadLiner(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        self.esminiPath = self.configuration.get("esminipath")
        self.roadBuilder = RoadBuilder()
        self.laneBuilder = LaneBuilder()
        self.laneLinker = LaneLinker()
        self.straightRoadBuilder = StraightRoadBuilder()
        self.curveBuilder = CurveRoadBuilder()
        self.roadLinker = RoadLinker()

    def test_getAngleBetweenStraightRoads(self):
        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))
        connectionRoad = self.curveBuilder.create(1,
                                                  np.pi / 4,
                                                  isJunction=True,
                                                  curvature=0.2,
                                                  n_lanes=1)
        roads.append(connectionRoad)
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=2))

        connectionRoad2 = self.curveBuilder.create(3,
                                                   np.pi / 2,
                                                   isJunction=True,
                                                   curvature=0.1,
                                                   n_lanes=1)
        roads.append(connectionRoad2)
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(4,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))

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

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

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

        roads[3].addExtendedPredecessor(roads[2], 0, pyodrx.ContactPoint.start)
        roads[3].addExtendedSuccessor(roads[4], 0, pyodrx.ContactPoint.start)

        roads[4].addExtendedPredecessor(roads[3], 0, pyodrx.ContactPoint.end)

        self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0],
                                                      roads[2])
        self.laneBuilder.createLanesForConnectionRoad(connectionRoad2,
                                                      roads[2], roads[4])

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

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

        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[0], roads[2])))
        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[0], roads[4])))
        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[2], roads[4])))

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

    def test_StartEnd(self):
        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))
        connectionRoad = self.curveBuilder.create(1,
                                                  np.pi / 4,
                                                  isJunction=True,
                                                  curvature=0.1,
                                                  n_lanes=1)
        roads.append(connectionRoad)
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))

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

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

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

        self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0],
                                                      roads[2])

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

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

        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[0], roads[2])))

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

    def test_fails(self):
        roads = []
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(0,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=1))
        connectionRoad = self.curveBuilder.create(1,
                                                  np.pi / 4,
                                                  isJunction=True,
                                                  curvature=0.2,
                                                  n_lanes=1)
        roads.append(connectionRoad)
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(2,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=2))

        connectionRoad2 = self.curveBuilder.create(3,
                                                   np.pi / 2,
                                                   isJunction=True,
                                                   curvature=0.1,
                                                   n_lanes=1)
        roads.append(connectionRoad2)
        roads.append(
            self.straightRoadBuilder.createWithDifferentLanes(4,
                                                              10,
                                                              n_lanes_left=1,
                                                              n_lanes_right=3))

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

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

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

        roads[3].addExtendedPredecessor(roads[2], 0, pyodrx.ContactPoint.start)
        roads[3].addExtendedSuccessor(roads[4], 0, pyodrx.ContactPoint.start)

        roads[4].addExtendedPredecessor(roads[3], 0, pyodrx.ContactPoint.end)

        self.laneBuilder.createLanesForConnectionRoad(connectionRoad, roads[0],
                                                      roads[2])
        self.laneBuilder.createLanesForConnectionRoad(connectionRoad2,
                                                      roads[2], roads[4])

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

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

        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[0], roads[2])))
        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[0], roads[4])))
        print(
            math.degrees(
                self.roadLinker.getAngleBetweenStraightRoads(
                    roads[2], roads[4])))
class test_AngleCurvatureMap(unittest.TestCase):
    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 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 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 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)
Esempio n. 27
0
class JunctionMerger:
    def __init__(self,
                 outputDir,
                 outputPrefix='R3_',
                 lastId=0,
                 esminiPath=None,
                 saveImage=True):
        """

        Args:
            outputDir ([type]): [description]
            outputPrefix ([type]): [description]
            lastId (int, optional): [description]. Defaults to 0.
        """

        self.destinationPrefix = os.path.join(outputDir, outputPrefix)
        self.lastId = lastId

        self.roadBuilder = RoadBuilder()

        self.configuration = Configuration()

        if esminiPath is None:
            self.esminiPath = self.configuration.get("esminipath")
        else:
            self.esminiPath = esminiPath

        self.saveImage = saveImage

        if os.path.isdir(self.esminiPath) is False:
            logging.warn(
                f"Esmini path not found {self.esminiPath}. Will break if you try to save images using merger."
            )

        pass

    def getOutputPath(self, fname):
        return self.destinationPrefix + fname + '.xodr'

    def canMerge(self, connectionRoadFirst, connectionRoadSecond):

        #1. if both straight, cannot merge
        if connectionRoadFirst.curveType is None and connectionRoadSecond.curveType is None:
            return False

        #1. if one straight, can merge
        if connectionRoadFirst.curveType is None or connectionRoadSecond.curveType is None:
            return True

        #1. if angles are same but curvatures are opposite. cannot merge because they overlap

        firstAngle = connectionRoadFirst.getArcAngle()
        # difference = abs(firstAngle - connectionRoadSecond.getArcAngle()) * 100 / firstAngle
        difference = abs(firstAngle - connectionRoadSecond.getArcAngle())

        dotSign = connectionRoadFirst.getFirstGeomCurvature(
        ) * connectionRoadSecond.getFirstGeomCurvature()

        if difference < (np.pi / 10) and dotSign < 0:
            return False
        return True

    def merge2R2L(self, odrs, save=True):

        # 1 find connectionRoad in the first, it's predecessor is first road, successor is the second road.

        connectionRoadsFirst = extensions.getConnectionRoads(
            odrs[0].roads, odrs[0].junctions[0])
        connectionRoadFirst = connectionRoadsFirst[0].shallowCopy()
        connectionRoadsSecond = extensions.getConnectionRoads(
            odrs[1].roads, odrs[1].junctions[0])
        connectionRoadSecond = connectionRoadsSecond[0].shallowCopy()

        if self.canMerge(connectionRoadFirst, connectionRoadSecond) is False:
            raise IncompatibleRoadsException(
                "incompatible junctions to merge.")

        roadFirstPred = extensions.getRoadFromRoadDic(
            odrs[0].roads,
            connectionRoadFirst.predecessor.element_id).shallowCopy()
        roadFirstSuc = extensions.getRoadFromRoadDic(
            odrs[0].roads,
            connectionRoadFirst.successor.element_id).shallowCopy()

        roadSecondPred = extensions.getRoadFromRoadDic(
            odrs[1].roads,
            connectionRoadSecond.predecessor.element_id).shallowCopy()
        roadSecondSuc = extensions.getRoadFromRoadDic(
            odrs[1].roads,
            connectionRoadSecond.successor.element_id).shallowCopy()

        # case 1: remove roadSecondPred & rebuild links for roads in the first odr

        roadFirstPred.updateSuccessor(pyodrx.ElementType.junction,
                                      connectionRoadFirst.id)

        connectionRoadFirst.updatePredecessor(
            pyodrx.ElementType.road, roadFirstPred.id, pyodrx.ContactPoint.end
        )  # interestingly, this becomes the start point after merging.
        connectionRoadFirst.updateSuccessor(pyodrx.ElementType.road,
                                            roadFirstSuc.id,
                                            pyodrx.ContactPoint.start)

        roadFirstSuc.updatePredecessor(pyodrx.ElementType.junction,
                                       connectionRoadFirst.id)

        roadSecondSuc.updatePredecessor(pyodrx.ElementType.junction,
                                        connectionRoadFirst.id)

        roads = []
        roads.append(roadFirstPred)
        roads.append(connectionRoadFirst)
        roads.append(roadFirstSuc)
        roads.append(connectionRoadSecond)
        roads.append(roadSecondSuc)

        # fix links for roadFirstSuc, connectionRoadSecond, roadSecondSuc

        self.regenAndMergeWithConnectionRoad(roadFirstSuc,
                                             connectionRoadSecond,
                                             roadSecondSuc)

        # create new junction

        junction = self.createJunctionFor2Connections(roadFirstPred,
                                                      connectionRoadFirst,
                                                      roadFirstSuc,
                                                      connectionRoadSecond)

        # newOdr = self.mergeByRoad(self, commonRoads, ords)

        self.lastId += 1

        # create the opendrive
        odr = pyodrx.OpenDrive("3R_2L_" + str(self.lastId))
        for r in roads:
            odr.add_road(r)

        odr.add_junction(junction)
        print(f"starting adjustment. May freeze!!!!!!!!!!!!!")
        odr.adjust_roads_and_lanes()

        xmlPath = self.getOutputPath(odr.name)
        if save:
            odr.write_xml(xmlPath)

        if self.saveImage:
            extensions.saveRoadImageFromFile(xmlPath, self.esminiPath)

        return odr

    def regenAndMergeWithConnectionRoad(self, lastRoad_odr_1,
                                        connectionRoad_odr_2, lastRoad_odr_2):
        """Clears all road and lane links for all roads except lastRoad_odr_1.
            

        Args:
            lastRoad_odr_1 ([type]): reassigns successor 
            connectionRoad_odr_2 ([type]): re-ids and reassigns successor and predecessors
            lastRoad_odr_2 ([type]): [description] re-ids and reassigns predecessor
        """

        # regenerate ids for connectionRoadSecond and roadSecondSuc
        connectionRoad_odr_2.id = lastRoad_odr_1.id + 100
        lastRoad_odr_2.id = connectionRoad_odr_2.id + 1

        # fix links for roadFirstSuc, connectionRoadSecond, roadSecondSuc
        lastRoad_odr_1.updateSuccessor(pyodrx.ElementType.junction,
                                       connectionRoad_odr_2.id)

        connectionRoad_odr_2.updatePredecessor(
            pyodrx.ElementType.road, lastRoad_odr_1.id,
            pyodrx.ContactPoint.start
        )  # interestingly, this becomes the start point after merging.

        connectionRoad_odr_2.updateSuccessor(
            pyodrx.ElementType.road, lastRoad_odr_2.id,
            pyodrx.ContactPoint.start
        )  # interestingly, this becomes the start point after merging.

        lastRoad_odr_2.updatePredecessor(pyodrx.ElementType.junction,
                                         connectionRoad_odr_2.id)

        pass

    def createJunctionFor2Connections(self, roadFirstPred, connectionRoadFirst,
                                      roadFirstSuc, connectionRoadSecond):

        # TODO experiment with connecting more lanes for a single connection road.

        con1 = pyodrx.Connection(roadFirstPred.id, connectionRoadFirst.id,
                                 pyodrx.ContactPoint.start)
        con1.add_lanelink(-1, -1)

        con2 = pyodrx.Connection(roadFirstSuc.id, connectionRoadSecond.id,
                                 pyodrx.ContactPoint.start)
        con2.add_lanelink(-1, -1)

        junction = pyodrx.Junction('junc', 1)

        junction.add_connection(con1)
        junction.add_connection(con2)

        return junction
Esempio n. 28
0
class test_ThreeWayJunction(unittest.TestCase):
    def setUp(self):

        self.configuration = Configuration()
        outputDir = os.path.join(os.getcwd(), 'output')
        lastId = 0
        self.seed = 2
        self.builder = ThreeWayJunctionBuilder(minAngle=np.pi / 9,
                                               maxAngle=np.pi * .25,
                                               straightRoadLen=20)

        self.randomState = self.configuration.get("random_state")

        pass

    def test_ThreeWayJunctionWithAngle(self):
        angleBetweenRoads = np.pi / 4
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.view_road_odrviewer(odr, os.path.join('..',self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)

    def test_ThreeWayJunctionWithRandomAngle(self):

        angleBetweenRoads = ((7 / 18) * np.random.random() + (1 / 9)) * np.pi
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        extensions.view_road_odrviewer(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)

        angleBetweenRoads = ((7 / 18) * np.random.random() + (1 / 9)) * np.pi
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.view_road_odrviewer(odr, os.path.join('..',self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)

        angleBetweenRoads = ((7 / 18) * np.random.random() + (1 / 9)) * np.pi
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.view_road_odrviewer(odr, os.path.join('..',self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)

        angleBetweenRoads = ((7 / 18) * np.random.random() + (1 / 9)) * np.pi
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.view_road_odrviewer(odr, os.path.join('..',self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)

        angleBetweenRoads = ((7 / 18) * np.random.random() + (1 / 9)) * np.pi
        odr = self.builder.ThreeWayJunctionWithAngle(
            odrId=1,
            angleBetweenRoads=angleBetweenRoads,
            maxLanePerSide=4,
            minLanePerSide=2,
            cp1=pyodrx.ContactPoint.end)
        extensions.printRoadPositions(odr)
        extensions.view_road(
            odr, os.path.join('..', self.configuration.get("esminipath")))
        # extensions.view_road_odrviewer(odr, os.path.join('..',self.configuration.get("esminipath")))
        xmlPath = f"output/test_ThreeWayJunctionWithAngle.xodr"
        odr.write_xml(xmlPath)
Esempio n. 29
0
 def test_Get(self):
     configuration = Configuration()
     testVal = configuration.get('test2.test22')
     assert testVal == 'this is something'