Define Road Layouts Programmatically
This example shows how to programmatically create a variety of road junctions with Automated Driving Toolbox™ functions. You can combine these junctions with other junctions to create complicated road networks. You can view the code for each plot and use it in your own project.
Alternatively, you can create road junctions interactively by using the Driving Scenario Designer app.
Straight Roads
Roads of a fixed width can be defined by a series of points that define the locations of the center of the road. A straight road is very simple to describe by specifying its starting and stopping location. Here is an example of a road which starts at (0,0) and ends at (50,0) and has a width of 6 (meters).
scenario = drivingScenario; roadCenters = [0 0; 50 0]; roadWidth = 6; road(scenario, roadCenters, roadWidth); plot(scenario,'RoadCenters','on','Centerline','on');
Laned Roads
As an alternative to specifying road widths, you can specify lanes by providing a lane specification. Here is an example of specifying a road with one lane on the left and two on the right.
scenario = drivingScenario; roadCenters = [0 0; 50 0]; road(scenario, roadCenters, 'lanes', lanespec([1 2])); plot(scenario,'RoadCenters','on');
Intersections
Intersections are automatically generated wherever two roads meet. In this example, we add another 50 m section of road.
roadCenters = [25 -25; 25 25];
road(scenario, roadCenters, 'lanes', lanespec([1 1]));
Multiple Lane Specifications
You can also create roads with multiple road segments that have different lane specifications. This example creates a composite lane specification for a road to simulate lane drop.
scenario = drivingScenario; roadCenters = [0 0; 50 0]; % Define an array of lane specifications for two one-way road segments. % Notice that one lane drops in the second road segment. lsArray = [lanespec(3) lanespec(2)]; % Define a road segment connector object. Specify position to drop a lane % and taper length. lc = laneSpecConnector('Position','Left','TaperLength',30); % Combine lane specifications of road segments. clspec = compositeLaneSpec(lsArray,'Connector',lc); road(scenario,roadCenters,'lanes',clspec); plot(scenario,'RoadCenters','on');
Curved Roads
Curved roads can be described by using three or more points. The more points you use, the more complex the curve you can create. In this example, we have a curve passing through three points:
scenario = drivingScenario; roadCenters = [0 0; 10 0; 53 -20]; roadWidth = 6; road(scenario, roadCenters, roadWidth,'lanes',lanespec(2)); plot(scenario,'RoadCenters','on');
Roundabouts
When you specify the road centers, a piecewise clothoid curve is fit in between each segment, where curvature is preserved in between points. Clothoid curves are used extensively when designing roads, because they have a curvature that varies linearly with distance traveled along the road, which is very simple for drivers to navigate.
By default, roads built by the scenario will have no curvature at the endpoints. To make a road loop, repeat the first and last point.
In this example, we show a 4m wide circular road segment circumscribed about a 30 m square area. Adding roads that feed into the roundabout is a matter of specifying other straight or curved road segments:
scenario = drivingScenario; roadCenters = [-15 -15 15 -15 15 15 -15 15 -15 -15]; road(scenario, roadCenters, 'lanes', lanespec(1)); % Define roundabout exits with two lanes each road(scenario, [-35 0; -20 0],'lanes', lanespec([1 1])); road(scenario, [ 20 0; 35 0],'lanes', lanespec([1 1])); road(scenario, [ 0 35; 0 20],'lanes', lanespec([1 1])); road(scenario, [ 0 -20; 0 -35],'lanes', lanespec([1 1])); plot(scenario,'RoadCenters','on');
Exit Lane
This example simulates a simple exit lane. We start with a simple straight road and then overlay a few points of another road so that it overlaps the original straight road:
scenario = drivingScenario; ls = lanespec(2); laneWidth = ls.Width(1); % add straight road segment road(scenario, [0 0 0; 50 0 0], 'lanes', lanespec(2)); % define waypoints of lane exit roadCenters = [3.0 -laneWidth/2 3.1 -laneWidth/2 15.0 -laneWidth 45.0 -20]; % add the exit lane road(scenario, roadCenters, laneWidth); plot(scenario,'RoadCenters','on')
Adding Elevation
Roads can optionally have elevation information. This can be accomplished by including a third column in the waypoints.
scenario = drivingScenario; roadCenters = [ 0 0 0 25 0 3 50 0 0]; road(scenario, roadCenters, 'lanes', lanespec(2)); plot(scenario,'RoadCenters','on'); view(30,24);
Overpasses
Roads can cross each other without intersecting if they have differing elevation. The road surface of an overpass is typically 6 to 8 meters above the road.
scenario = drivingScenario; roadCenters = [ 0 0 0 20 -20 0 20 20 8 -20 -20 8 -20 20 0 0 0 0]; road(scenario, roadCenters, 'lanes',lanespec([1 2])); plot(scenario,'RoadCenters','on'); view(30,24)
Road Banking
Roads can be banked, where bank angles can be defined for each waypoint. The following is an oval racetrack with 9 degree banked curves.
scenario = drivingScenario; % transpose waypoints so they visually align with bank angles below roadCenters = ... [ 0 40 49 50 100 50 49 40 -40 -49 -50 -100 -50 -49 -40 0 -50 -50 -50 -50 0 50 50 50 50 50 50 0 -50 -50 -50 -50 0 0 .45 .45 .45 .45 .45 0 0 .45 .45 .45 .45 .45 0 0]'; bankAngles = ... [ 0 0 9 9 9 9 9 0 0 9 9 9 9 9 0 0]; road(scenario, roadCenters, bankAngles, 'lanes', lanespec(2)); plot(scenario,'RoadCenters','on'); view(-60,20)
Road Heading
Roads can have headings, where heading angles can be defined for each road center. The following is a long loop road with two parallel tracks.
scenario = drivingScenario; % Add a long loop road segment roadCenters = [2023 2362; -2504 -2141; -2036 -2634; 2444 1870; 2023 2362]; % Specify the heading angles as a constraint to the road center points slope = roadCenters(2,:) - roadCenters(1,:); hdAngl = atand(slope(2)/slope(1)); roadHeadings = [hdAngl+180; hdAngl+180; hdAngl; hdAngl; hdAngl+180]; % Add the heading angles into the driving scenario road(scenario,roadCenters,'Heading',roadHeadings); plot(scenario,'RoadCenters','on')
Diamond Interchange
Highways and expressways typically are comprised of two parallel roads, each going in the opposing direction. An economical interchange between a highway and a local road is a diamond interchange, which typically consists of a local road overpass and four ramps.
scenario = drivingScenario; % Highways road(scenario, [-200 -8 0; 200 -8 0], 'lanes',lanespec(3)); % north road(scenario, [ 200 8 0;-200 8 0], 'lanes',lanespec(3)); % south % Local Road road(scenario, [-0 -200 8; 0 200 8], 'lanes',lanespec([1 1])); % Access ramps rampNE = [ 3 -20 8; 10 -20 7.8; 126 -20 .2; 130 -20 0; 200 -13.5 0]; road(scenario, [ 1 1 1] .* rampNE, 'lanes',lanespec(1)); road(scenario, [ 1 -1 1] .* flipud(rampNE), 'lanes',lanespec(1)); road(scenario, [-1 -1 1] .* rampNE, 'lanes',lanespec(1)); road(scenario, [-1 1 1] .* flipud(rampNE), 'lanes',lanespec(1)); plot(scenario); view(-60,30)
Cloverleaf Interchange
A popular interchange between two highways is the cloverleaf interchange. The cloverleaf interchange consists of four inner and four outer ramps.
A limitation of the driving scenario is that road information is removed in the vicinity of a road junction.
scenario = drivingScenario; % Highways road(scenario, [-300 -8 0; 300 -8 0], 15); % north road(scenario, [-300 8 0; 300 8 0], 15); % south road(scenario, [-8 -300 8; -8 300 8], 15); % east road(scenario, [ 8 -300 8; 8 300 8], 15); % west % Inner ramps rampNE = [0 -18 0; 20 -18 0; 120 -120 4; 18 -20 8; 18 0 8]; rampNW = [ 1 -1 1] .* rampNE(end:-1:1,:); rampSW = [-1 -1 1] .* rampNE; rampSE = [ 1 -1 1] .* rampSW(end:-1:1,:); innerRamps = [rampNE(1:end-1,:) rampNW(1:end-1,:) rampSW(1:end-1,:) rampSE]; road(scenario, innerRamps, 5.4); % Outer ramps roadCenters = [13.5 -300 8; 15 -260 8; 125 -125 4; 260 -15 0; 300 -13.5 0]; road(scenario, [ 1 1 1] .* roadCenters, 5.4); road(scenario, [ 1 -1 1] .* roadCenters, 5.4); road(scenario, [-1 -1 1] .* roadCenters, 5.4); road(scenario, [-1 1 1] .* roadCenters, 5.4); plot(scenario,'RoadCenters','on'); view(-60,30);
Next Steps
This example showed how to create a variety of road junctions using a drivingScenario
object. To add actors and trajectories to these roads using Automated Driving Toolbox functions, see Create Actor and Vehicle Trajectories Programmatically. Alternatively, you can add actors and trajectories interactively by loading the drivingScenario
object into the Driving Scenario Designer app:
drivingScenarioDesigner(scenario)