Contenuto principale

Questa pagina è stata tradotta con la traduzione automatica. Fai clic qui per vedere l'ultima versione in inglese.

Costruisci una scena RoadRunner con incroci e oggetti statici utilizzando la mappa RoadRunner HD

Questo esempio mostra come creare una mappa RoadRunner HD da un file KML (Keyhole Markup Language) contenente le coordinate di latitudine e longitudine di un'intersezione stradale. È possibile importare i dati della mappa RoadRunner HD in RoadRunner e utilizzarli per creare una scena 3D contenente l'intersezione stradale e gli oggetti statici circostanti, come alberi ed edifici. Per importare i file di dati per la strada, è necessario disporre di una licenza Mapping Toolbox™ .

Importa file KML

In questo esempio, utilizzerai file KML per importare forme puntiformi per l'intersezione stradale e forme poligonali per edifici e alberi. Questo esempio utilizza i dati della mappa (© 2022 di Google) per un'area intorno a Whitesville Road nel New Jersey, USA.

Leggi i dati dai file KML utilizzando la funzione readgeotable , che legge solo forme, nomi e descrizioni.

kmlRoadData = readgeotable("RoadIntersection.kml");
kmlTreeData = readgeotable("Trees.kml");
kmlBuildingData = readgeotable("Buildings.kml");

Traccia le coordinate della strada, visualizza gli edifici ed esegui il rendering dei poligoni per le posizioni degli alberi.

geoplot(kmlRoadData)
hold on
geoplot(kmlTreeData)
geoplot(kmlBuildingData)
geobasemap topographic

Convertire la tabella geospaziale in una tabella dei centri delle strade per ottenere le coordinate di latitudine e longitudine di due strade che si incontrano in un'intersezione.

T1 = geotable2table(kmlRoadData,["Latitude","Longitude"]);
[lat1,lon1] = polyjoin(T1.Latitude(1),T1.Longitude(1)); % Road centers of the first road meeting at the intersection
[lat2,lon2] = polyjoin(T1.Latitude(2),T1.Longitude(2)); % Road centers of the second road meeting at the intersection

Convertire la tabella geospaziale in una tabella dei vertici dei poligoni per ottenere le coordinate di latitudine e longitudine degli alberi all'interno dei poligoni e degli edifici.

T2 = geotable2table(kmlTreeData,["Latitude","Longitude"]);
[lat3,lon3] = polyjoin(T2.Latitude(1),T2.Longitude(1)); % Polygon geometry to form trees inside of polygon
[lat4,lon4] = polyjoin(T2.Latitude(2),T2.Longitude(2)); % Polygon geometry to form trees inside of polygon
[lat5,lon5] = polyjoin(T2.Latitude(3),T2.Longitude(3)); % Polygon geometry to form trees inside of polygon

T3 = geotable2table(kmlBuildingData,["Latitude","Longitude"]);
lat6 = T3.Latitude; % Geometry for buildings
lon6 = T3.Longitude; % Geometry for buildings

Crea mappa RoadRunner HD

Crea una mappa RoadRunner HD vuota.

rrMap = roadrunnerHDMap;

Calcolare l'origine geografica di riferimento come centro del quadrilatero di delimitazione.

[latlim,lonlim] = geoquadline([lat1; lat2],[lon1; lon2]);
lat0 = mean(latlim);
lon0 = mean(lonlim);

Imposta il riferimento geografico per la regione di interesse.

rrMap.GeoReference = [lat0 lon0];

Proietta le coordinate di latitudine e longitudine su xy Coordinate della mappa

Leggi il CRS trasversale proiettato da Mercatore dalla mappa RoadRunner HD.

p = readCRS(rrMap);

Proiettare le coordinate di latitudine e longitudine sulle coordinate xy.

% Road geometry data
[x1,y1] = projfwd(p,lat1,lon1);
[x2,y2] = projfwd(p,lat2,lon2);
% Trees geometry data
[x3,y3] = projfwd(p,lat3,lon3);
[x4,y4] = projfwd(p,lat4,lon4);
[x5,y5] = projfwd(p,lat5,lon5);
% Buildings geometry data
[x6,y6] = projfwd(p,lat6,lon6);

Calcolare le geometrie per le corsie e i confini delle corsie

Crea le equazioni delle linee per le due strade dell'intersezione.

coefficients1 = polyfit([x1(1) x1(2)],[y1(1) y1(2)],1);
coefficients2 = polyfit([x2(1) x2(2)],[y2(1) y2(2)],1);

Calcolare le geometrie delle corsie utilizzando le equazioni delle linee.

m1 = coefficients1(1);
c1 = coefficients1(2);
% Specify lane widths, estimated using the measurement tool of Google Earth
leftLanesWidth = [0 -3.659 -3.686 -3.643 -2.988];
rightLanesWidth = [2.820 3.764 3.698];
% Find cumulative width of all lanes to compute the geometries of parallel lanes
leftLanesWidth = cumsum(leftLanesWidth);
rightLanesWidth = cumsum(rightLanesWidth);
rightLanesWidth = flip(rightLanesWidth);
d1 = [rightLanesWidth leftLanesWidth];

m2 = coefficients2(1);
c2 = coefficients2(2);
% Specify lane widths, estimated using the measurement tool of Google Earth
leftLanesWidth2 = [0 -3.614 -3.610 -3.661];
rightLanesWidth2 = [3.621 3.685];
% Find cumulative width of all lanes to compute the geometries of parallel lanes
leftLanesWidth2 = cumsum(leftLanesWidth2);
rightLanesWidth2 = cumsum(rightLanesWidth2);
rightLanesWidth2 = flip(rightLanesWidth2);
d2 = [rightLanesWidth2 leftLanesWidth2];

d = [d1 d2];
numLanes = size(d,2);
x = cell(numLanes,1);
[x{1:8}] = deal(x1);
[x{9:14}] = deal(x2);
m(1:8) = deal(m1);
m(9:14) = deal(m2);
c(1:8) = deal(c1);
c(9:14) = deal(c2);
y = cell(numLanes,1);
for i = 1:numLanes
   y{i} =  m(i)*x{i} + c(i) + d(i)*sqrt(1+m(i)^2);
end

Crea incrocio stradale

Crea la rete stradale RoadRunner HD Map utilizzando i dati calcolati e modifica le strade in modo che assomiglino alla strada reale, che consiste di più corsie e confini di più corsie. Quindi, applica la segnaletica orizzontale appropriata ai confini della corsia come nella scena reale. Per migliorare le prestazioni, all'aumentare del numero di oggetti nella mappa, inizializzare le proprietà Lanes e LaneBoundaries della mappa HD.

rrMap.Lanes(12,1) = roadrunner.hdmap.Lane;
rrMap.LaneBoundaries(14,1) = roadrunner.hdmap.LaneBoundary;

Assegnare valori alla proprietà Lanes .

laneIds = ["Lane1","Lane2","Lane3","Lane4","Lane5","Lane6","Lane7","Lane8","Lane9","Lane10","Lane11","Lane12"];
travelDirection = ["Undirected","Forward","Forward","Backward","Backward","Backward","Undirected","Backward","Backward","Backward","Forward","Forward"];
for i = 1:size(rrMap.Lanes,1)
    rrMap.Lanes(i).ID = laneIds(i);
    rrMap.Lanes(i).TravelDirection = travelDirection(i);
    rrMap.Lanes(i).LaneType = "Driving";
    if (i<8) % Assign coordinates to the Geometry properties of the lanes of the first road meeting at intersection
        rrMap.Lanes(i).Geometry = ([x{i} y{i}] + [x{i} y{i+1}])/2;
    elseif (i>8) % Assign coordinates to the Geometry properties of the lanes of the second road meeting at intersection
       rrMap.Lanes(i).Geometry = ([x{i} y{i+1}] + [x{i} y{i+2}])/2;
    end
end

Assegnare gli ID e le relative coordinate corrispondenti ai confini della corsia.

laneBoundaries = ["LB1","LB2","LB3","LB4","LB5","LB6","LB7","LB8","LB9","LB10","LB11","LB12","LB13","LB14"];
for i = 1:size(rrMap.LaneBoundaries,1) 
    rrMap.LaneBoundaries(i).ID = laneBoundaries(i);
    rrMap.LaneBoundaries(i).Geometry = [x{i} y{i}];
end

Associare i confini della corsia alle rispettive corsie utilizzando gli ID dei confini della corsia.

for i = 1:size(rrMap.Lanes,1)
    if (i<8) % Associate lane boundaries of the first road meeting at intersection
        leftBoundary(rrMap.Lanes(i),"LB"+i,Alignment="Forward");
        rightBoundary(rrMap.Lanes(i),"LB"+(i+1),Alignment="Forward");
    else % Associate lane boundaries of the second road meeting at intersection
        leftBoundary(rrMap.Lanes(i),"LB"+(i+1),Alignment="Backward");
        rightBoundary(rrMap.Lanes(i),"LB"+(i+2),Alignment="Backward");
    end
end

Definire i percorsi dei file per le risorse di segnaletica stradale RoadRunner .

% Define path to a dashed single white lane marking asset
dashedSingleWhiteAsset = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Markings/DashedSingleWhite.rrlms");
% Define path to a solid white lane marking asset
solidWhiteAsset = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Markings/SolidSingleWhite.rrlms");
% Define path to a solid double yellow lane marking asset
doubleYellowAsset = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Markings/SolidDoubleYellow.rrlms");
rrMap.LaneMarkings(3,1) = roadrunner.hdmap.LaneMarking;
[rrMap.LaneMarkings.ID] = deal("DashedSingleWhite","SolidWhite","DoubleYellow");
[rrMap.LaneMarkings.AssetPath] = deal(dashedSingleWhiteAsset,solidWhiteAsset,doubleYellowAsset);

Specificare che la segnaletica orizzontale si estenda per l'intera lunghezza dei confini della corsia. Quindi, assegnare la segnaletica bianca continua ai confini della corsia vicino ai bordi della strada, la segnaletica bianca tratteggiata ai confini della corsia intermedia e la doppia segnaletica gialla al confine della corsia centrale.

% Specify the span for markings as the entire lengths of their lane boundaries
markingSpan = [0 1];

markingRefDSW = roadrunner.hdmap.MarkingReference(MarkingID=roadrunner.hdmap.Reference(ID="DashedSingleWhite"));
markingAttribDSW = roadrunner.hdmap.ParametricAttribution(MarkingReference=markingRefDSW,Span=markingSpan);

markingRefSY = roadrunner.hdmap.MarkingReference(MarkingID=roadrunner.hdmap.Reference(ID="DoubleYellow"));
markingAttribSY = roadrunner.hdmap.ParametricAttribution(MarkingReference=markingRefSY,Span=markingSpan);

markingRefSW = roadrunner.hdmap.MarkingReference(MarkingID=roadrunner.hdmap.Reference(ID="SolidWhite"));
markingAttribSW = roadrunner.hdmap.ParametricAttribution(MarkingReference=markingRefSW,Span=markingSpan);

% Assign the markings to lane boundaries
[rrMap.LaneBoundaries.ParametricAttributes] = deal(markingAttribSW,markingAttribSW,markingAttribDSW,markingAttribSY,markingAttribDSW,markingAttribDSW,markingAttribSW,markingAttribSW, ...
    markingAttribSW,markingAttribDSW,markingAttribDSW,markingAttribSY,markingAttribDSW,markingAttribSW);

Calcolare geometrie di oggetti statici

Calcola le coordinate dei vertici di ciascun poligono di alberi utilizzando la funzione helper helperInsidePolygon .

[X3,Y3] = helperInsidePolygon(x3,y3);
[X4,Y4] = helperInsidePolygon(x4,y4);
[X5,Y5] = helperInsidePolygon(x5,y5);
X = [X3'; X4'; X5'];
Y = [Y3'; Y4'; Y5']; 
numOfTrees = size(X);

Crea oggetti statici

Definire un oggetto statico per gli alberi, quindi aggiungere gli alberi al modello e definirne le proprietà.

% Define tree static object type
path = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Props/Trees/Eucalyptus_Sm01.fbx");
rrMap.StaticObjectTypes(1) = roadrunner.hdmap.StaticObjectType(ID="StaticObjectType1",AssetPath=path);

rrMap.StaticObjects(numOfTrees,1) = roadrunner.hdmap.StaticObject;
objectRef1 = roadrunner.hdmap.Reference(ID="StaticObjectType1");

% Specify the length, width, and height values of the trees, estimated using Google Earth.
length = 9;
width = 9;
height = 23;

for i = 1:numOfTrees
    x = X(i);
    y = Y(i);
    aGeoOrientedBoundingBox = roadrunner.hdmap.GeoOrientedBoundingBox;
    aGeoOrientedBoundingBox.Center = [x y 0];
    aGeoOrientedBoundingBox.Dimension = [length width height/2];
    geoAngle3 = mathworks.scenario.common.GeoAngle3;
    geoAngle3.roll = -2;
    geoAngle3.pitch = -2;
    geoAngle3.heading = 90;
    geoOrientation3 = mathworks.scenario.common.GeoOrientation3;
    geoOrientation3.geo_angle = geoAngle3;
    aGeoOrientedBoundingBox.GeoOrientation = [deg2rad(-2) deg2rad(-2) deg2rad(90)];

    treeID = "Tree" + string(i);
    rrMap.StaticObjects(i) = roadrunner.hdmap.StaticObject(ID=treeID, ...
        Geometry=aGeoOrientedBoundingBox, ...
        ObjectTypeReference=objectRef1);
end

Definire un oggetto statico per la costruzione, quindi aggiungere gli edifici al modello e definirne le proprietà.

numberOfBuildings = size(x6);
% Add static object type info
path = roadrunner.hdmap.RelativeAssetPath(AssetPath="Assets/Buildings/Downtown_30mX30m_6storey.fbx");
% Define static object type
rrMap.StaticObjectTypes(2) = roadrunner.hdmap.StaticObjectType(ID="StaticObjectType2",AssetPath=path);

% Initialize elements in the StaticObjects property of the HD map object, for better performance as the number of objects in the map increases
rrMap.StaticObjects(numberOfBuildings,1) = roadrunner.hdmap.StaticObject;
objectRef2 = roadrunner.hdmap.Reference(ID="StaticObjectType2");

% Specify the length, width, and height values of the buildings, estimated using Google Earth.
length = [26 26];
width = [26 46];
height = 28;
ID = ["Building1","Building2"];
for i= 1:numberOfBuildings
    x = x6(i);
    y = y6(i);
    aGeoOrientedBoundingBox = roadrunner.hdmap.GeoOrientedBoundingBox;
    aGeoOrientedBoundingBox.Center = [x y 0];
    aGeoOrientedBoundingBox.Dimension = [length(i) width(i) height/2];
    geoAngle3 = mathworks.scenario.common.GeoAngle3;
    geoAngle3.roll = 0;
    geoAngle3.pitch = 0;
    geoAngle3.heading = 0.4697;
    geoOrientation3 = mathworks.scenario.common.GeoOrientation3;
    geoOrientation3.geo_angle = geoAngle3;
    aGeoOrientedBoundingBox.GeoOrientation = [deg2rad(-2) deg2rad(-2) deg2rad(90)];

    rrMap.StaticObjects(i) = roadrunner.hdmap.StaticObject(ID=ID(i), ...
        Geometry=aGeoOrientedBoundingBox, ...
        ObjectTypeReference = objectRef2);
end

Imposta confini geografici e riferimenti

L'impostazione dei confini geografici e del riferimento per la mappa RoadRunner HD centra la scena sulla strada importata e consente di inserire la strada nella scena senza utilizzare lo strumento Impostazioni mondiali in RoadRunner.

Imposta i limiti geografici della mappa come valori delle coordinate minimo e massimo del confine centrale.

geometries = [x1 y1; x2 y2];
geoBounds = [min(geometries) 0; max(geometries) 0];
rrMap.GeographicBoundary = geoBounds;

Traccia i centri delle corsie e i confini delle corsie.

plot(rrMap,ShowStaticObjects=true)
title("RoadRunner HD Map of Road Intersection Scene")
xlabel("x (m)")
ylabel("y (m)")

Salva la mappa RoadRunner HD in un file.

write(rrMap,"RoadIntersection")

Importa file mappa HD in RoadRunner e crea scena

Per aprire RoadRunner utilizzando MATLAB, specifica il percorso del tuo progetto. Questo codice mostra una cartella di progetto di esempio in Windows®. Apri RoadRunner utilizzando il percorso specificato per il tuo progetto.

rrProjectPath = "C:\RR\MyProjects";
rrApp = roadrunner(rrProjectPath);

Importa i dati della mappa RoadRunner HD da un file specificato nella scena attualmente aperta e crea la mappa. Per creare la scena, è necessario disporre di una licenza attiva RoadRunner Scene Builder .

Copia il file RoadRunner HD Map nel progetto RoadRunner .

copyfile("RoadIntersection.rrhd","C:\RR\MyProjects\Assets")

Specifica le opzioni di importazione per la mappa RoadRunner HD.

importOptions = roadrunnerHDMapImportOptions(ImportStep="Load");

Importa la mappa RoadRunner HD in RoadRunner.

importScene(rrApp,"RoadIntersection.rrhd","RoadRunner HD Map",importOptions)

L'area di modifica della scena mostra la mappa RoadRunner HD della scena. Per verificare i dati importati, puoi selezionare punti di controllo, corsie, confini di corsia e oggetti statici nell'area di modifica della scena e visualizzare le loro proprietà dal riquadro Attributi.

Preview of the imported RoadRunner HD Map data.

Specificare le opzioni per creare una scena dalla mappa RoadRunner HD importata. Disattiva i gruppi di sovrapposizione per consentire a RoadRunner di creare incroci automatici in corrispondenza della sovrapposizione geometrica delle strade.

enableOverlapGroupsOptions = enableOverlapGroupsOptions(IsEnabled=0);
buildOptions = roadrunnerHDMapBuildOptions(DetectAsphaltSurfaces=true,EnableOverlapGroupsOptions=enableOverlapGroupsOptions);

Costruisci e visualizza una scena dai dati importati della mappa RoadRunner HD. Per creare scene, è necessario disporre di una licenza RoadRunner Scene Builder .

buildScene(rrApp,"RoadRunner HD Map",buildOptions)

La scena RoadRunner costruita contiene strade che si intersecano, nonché alberi ed edifici. Modificare l'intersezione in modo che assomigli alla giunzione reale regolando il raggio dell'angolo di giunzione utilizzando lo strumento Angolo di giunzione.

Built RoadRunner scene.

Vedi anche

|

Argomenti