Main Content

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)

See Also

Apps

Objects

Functions

Related Topics