Cree una escena de RoadRunner con intersecciones y objetos estáticos usando el mapa HD de RoadRunner
Este ejemplo muestra cómo crear un mapa RoadRunner HD a partir de un archivo Keyhole Markup Language (KML) que contiene las coordenadas de latitud y longitud de una intersección de carreteras. Puede importar los datos del mapa HD de RoadRunner a RoadRunner y usarlos para crear una escena 3D que contenga la intersección de la carretera y los objetos estáticos circundantes, como árboles y edificios. Para importar los archivos de datos de la carretera, debe tener una licencia de Mapping Toolbox™ .
Importar archivos KML
En este ejemplo, utilizará archivos KML para importar formas puntuales para la intersección de carreteras y formas poligonales para los edificios y árboles. Este ejemplo utiliza datos de mapas (© 2022 de Google) para un área alrededor de Whitesville Road en Nueva Jersey, EE. UU.
Lea los datos de los archivos KML usando la función readgeotable
, que solo lee las formas, nombres y descripciones.
kmlRoadData = readgeotable("RoadIntersection.kml"); kmlTreeData = readgeotable("Trees.kml"); kmlBuildingData = readgeotable("Buildings.kml");
Traza las coordenadas de la carretera, muestra los edificios y renderiza polígonos para las ubicaciones de los árboles.
geoplot(kmlRoadData) hold on geoplot(kmlTreeData) geoplot(kmlBuildingData) geobasemap topographic
Convierta la tabla geoespacial en una tabla de centros de carreteras para obtener las coordenadas de latitud y longitud de dos carreteras que se encuentran en una intersección.
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
Convierta la tabla geoespacial en una tabla de vértices de polígonos para obtener las coordenadas de latitud y longitud de los árboles dentro de los polígonos y los edificios.
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
Crear mapa RoadRunner HD
Crea un mapa RoadRunner HD vacío.
rrMap = roadrunnerHDMap;
Calcule el origen de referencia geográfica como el centro del cuadrilátero delimitador.
[latlim,lonlim] = geoquadline([lat1; lat2],[lon1; lon2]); lat0 = mean(latlim); lon0 = mean(lonlim);
Establezca la referencia geográfica para la región de interés.
rrMap.GeoReference = [lat0 lon0];
Proyecto Coordenadas Latitud-Longitud a xy Coordenadas del Mapa
Lea el CRS transversal proyectado por Mercator en el mapa HD de RoadRunner .
p = readCRS(rrMap);
Proyecte las coordenadas de latitud y longitud en coordenadas 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);
Calcular geometrías para carriles y límites de carriles
Crea las ecuaciones lineales para los dos caminos de la intersección.
coefficients1 = polyfit([x1(1) x1(2)],[y1(1) y1(2)],1); coefficients2 = polyfit([x2(1) x2(2)],[y2(1) y2(2)],1);
Calcule las geometrías de los carriles usando las ecuaciones de líneas.
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
Crear intersección de carreteras
Cree la red de carreteras de RoadRunner HD Map utilizando los datos calculados y modifique las carreteras para que se parezcan a la carretera real, que consta de varios carriles y varios límites de carriles. Luego, aplique marcas de carril apropiadas a los límites de los carriles como en la escena real. Para mejorar el rendimiento, a medida que aumenta la cantidad de objetos en el mapa, inicialice las propiedades Lanes
y LaneBoundaries
del mapa HD.
rrMap.Lanes(12,1) = roadrunner.hdmap.Lane; rrMap.LaneBoundaries(14,1) = roadrunner.hdmap.LaneBoundary;
Asigne valores a la propiedad 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
Asigne ID y sus coordenadas correspondientes a los límites de los carriles.
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
Asocie los límites de los carriles con sus carriles utilizando los ID de los límites de los carriles.
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
Defina las rutas de los archivos a los recursos de señalización de carril de 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);
Especifique que las marcas abarquen toda la longitud de los límites de sus carriles. Luego, asigne marcas blancas sólidas a los límites de los carriles cerca de los bordes de la carretera, marcas de carril blancas con trazos a los límites de los carriles intermedios y marcas amarillas dobles al límite del carril central.
% 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);
Calcular geometrías de objetos estáticos
Calcule las coordenadas de los vértices de cada polígono de árboles utilizando la función auxiliar 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);
Crear objetos estáticos
Defina un objeto estático para los árboles y luego agregue los árboles al modelo y defina sus propiedades.
% 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
Defina un objeto estático para construir y luego agregue los edificios al modelo y defina sus propiedades.
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
Establecer límites geográficos y referencias
Configurar los límites geográficos y la referencia para el mapa RoadRunner HD centra la escena en la carretera importada y le permite insertar la carretera en la escena sin usar la herramienta Configuración mundial en RoadRunner.
Establezca los límites geográficos del mapa como los valores de coordenadas mínimo y máximo del límite central.
geometries = [x1 y1; x2 y2]; geoBounds = [min(geometries) 0; max(geometries) 0]; rrMap.GeographicBoundary = geoBounds;
Trazar los centros de los carriles y los límites de los carriles.
plot(rrMap,ShowStaticObjects=true) title("RoadRunner HD Map of Road Intersection Scene") xlabel("x (m)") ylabel("y (m)")
Guarde el mapa RoadRunner HD en un archivo.
write(rrMap,"RoadIntersection")
Importar archivo de mapa HD a RoadRunner y crear escena
Para abrir RoadRunner usando MATLAB, especifique la ruta a su proyecto. Este código muestra una carpeta de proyecto de muestra en Windows®. Abra RoadRunner usando la ruta especificada a su proyecto.
rrProjectPath = "C:\RR\MyProjects";
rrApp = roadrunner(rrProjectPath);
Importe los datos del mapa RoadRunner HD desde un archivo específico a la escena abierta actualmente y cree el mapa. Para crear la escena, debe tener una licencia activa de RoadRunner Scene Builder .
Copie el archivo de mapa RoadRunner HD al proyecto RoadRunner .
copyfile("RoadIntersection.rrhd","C:\RR\MyProjects\Assets")
Especifique opciones de importación para el mapa RoadRunner HD.
importOptions = roadrunnerHDMapImportOptions(ImportStep="Load");
Importe el mapa RoadRunner HD a RoadRunner.
importScene(rrApp,"RoadIntersection.rrhd","RoadRunner HD Map",importOptions)
El lienzo de edición de escena muestra el mapa RoadRunner HD de la escena. Para verificar los datos importados, puede seleccionar puntos de control, carriles, límites de carriles y objetos estáticos en el lienzo de edición de escena y ver sus propiedades desde el panel Atributos.
Especifique opciones para crear una escena a partir del mapa RoadRunner HD importado. Desactive los grupos de superposición para permitir que RoadRunner cree cruces automáticos en la superposición geométrica de las carreteras.
enableOverlapGroupsOptions = enableOverlapGroupsOptions(IsEnabled=0); buildOptions = roadrunnerHDMapBuildOptions(DetectAsphaltSurfaces=true,EnableOverlapGroupsOptions=enableOverlapGroupsOptions);
Cree y visualice una escena a partir de los datos importados del mapa RoadRunner HD. Para crear escenas, debe tener una licencia de RoadRunner Scene Builder .
buildScene(rrApp,"RoadRunner HD Map",buildOptions)
La escena de RoadRunner construido contiene carreteras que se cruzan, así como árboles y edificios. Modifique la intersección para que se parezca al cruce real ajustando el radio de la esquina del cruce usando la herramienta Esquina de cruce.
Consulte también
Temas relacionados
- Construya carreteras sencillas mediante programación utilizando RoadRunner HD Map
- Cree una escena 3D de pista de prueba en RoadRunner usando RoadRunner HD Map
- Build Pikes Peak RoadRunner 3D Scene Using RoadRunner HD Map (Automated Driving Toolbox)
- Cree escenas a partir de datos personalizados utilizando RoadRunner HD Map