Exemplo n.º 1
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)
Exemplo n.º 2
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