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.
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.
Vedi anche
Argomenti
- Costruisci strade semplici in modo programmatico utilizzando RoadRunner HD Map
- Costruisci una scena 3D della pista di prova in RoadRunner utilizzando la mappa RoadRunner HD
- Build Pikes Peak RoadRunner 3D Scene Using RoadRunner HD Map (Automated Driving Toolbox)
- Costruisci scene da dati personalizzati utilizzando RoadRunner HD Map