Drake
Builder Class Reference

A class to ease the construction of a RoadGeometry from Connection and DirectedWaypoint objects. More...

#include <drake/automotive/maliput/rndf/builder.h>

Public Member Functions

 Builder (double linear_tolerance, double angular_tolerance)
 Constructs a Builder which can be used to specify and assemble an RNDF implementation of an api::RoadGeometry. More...
 
void SetBoundingBox (const std::pair< ignition::math::Vector3d, ignition::math::Vector3d > &bounding_box)
 Sets the bounding box of the RNDF map. More...
 
void CreateSegmentConnections (int segment_id, std::vector< Connection > *connections)
 Populates the Builder's inner connection map with the given connections representing an RNDF segment. More...
 
void CreateConnectionsForZones (double width, std::vector< DirectedWaypoint > *perimeter_waypoints)
 Creates a collection of Connection objects between every pair of entry and exit waypoints in perimeter_waypoints. More...
 
void CreateConnection (double width, const ignition::rndf::UniqueId &exit_id, const ignition::rndf::UniqueId &entry_id)
 Creates a connection between two RNDF lanes based on a pair of exit and entry ids that map to specific, existing waypoints. More...
 
std::unique_ptr< const api::RoadGeometryBuild (const api::RoadGeometryId &id)
 Builds an api::RoadGeometry. More...
 
Does not allow copy, move, or assignment
 Builder (const Builder &)=delete
 
Builderoperator= (const Builder &)=delete
 
 Builder (Builder &&)=delete
 
Builderoperator= (Builder &&)=delete
 

Detailed Description

A class to ease the construction of a RoadGeometry from Connection and DirectedWaypoint objects.

RNDF segments and lanes are mapped to Maliput's Segment and Lane entities, respectively. This mapping is not straightforward as Maliput is based on analytical curve parameterizations while RNDF provides a sampled geometry based on waypoints. RNDF waypoints are thus used as control points in a cubic spline interpolation that results in SplineLanes. RNDF lanes' direction is implied by RNDF waypoint IDs (segment_num.lane_num.waypoint_num) which is captured by the interpolation and reflected in DirectedWaypoints. These DirectedWaypoints are grouped in Connections, which describe not only RNDF lanes but also the connections between pairs of exit and entry RNDF waypoints. During the build process, interpolated waypoints are added to these Connections so as to keep their distribution akin to a grid (and thus enable index-based operations).

Since lanes in an RNDF segment may flow in different directions, segment connections are also grouped by their directions relative to the first connection found in the collection. An arbitrary point outside the bounding box of the road geometry is selected to be a "center of rotation" and the sum of all the DirectedWaypoints "momentums" (with normalized tangents) is computed. It must be said that the "momentum" equation is used to derive connection direction, but it bears no physical meaning. Since all the waypoints lay in the \( z = 0 \) plane, the "momentum" vector will only contain a non-zero z coordinate value. The sign of the "momentum"'s z coordinate will be taken as a reference to define the sense of flow. For all other connections, the "momentum" is computed and compared against the sign of the reference.

RNDF zones also do not have a direct representation in Maliput either. To model zones, fake connections are added between every pair of entry and exit waypoints in a zone. The directions of these waypoints are set to head towards the centroid of all the zone perimeter waypoints. There's currently no support for RNDF zones' parking spots.

The resulting RoadGeometry presents the following naming for its composed entities:

  • Lane naming: "l:$1-$2", where
    1. RNDF exit waypoint ID.
    2. RNDF entry waypoint ID.
  • Segment naming: "s:$1-$2-$3", where
    1. RNDF segment ID.
    2. Direction-based grouping index.
    3. RNDF segment piece index (in between every 2 waypoints).
  • Junction naming: "j:$1-$2-$3", where
    1. RNDF segment ID.
    2. Direction-based grouping index.
    3. RNDF segment piece index (in between every 2 waypoints).
  • BranchPoint naming: "bp:$1", where
    1. Index in RoadGeometry's inner collection.

An example of how this is achieved is depicted in the following example. Note that '+' denotes RNDF waypoints, 'x' denotes invalid waypoints and 'o' denotes interpolated waypoints. Also '|' denotes Segment boundaries.

         1.1.1                   1.1.2
         +-----------------------+            <---- Connection: 1.1.1-1.1.2
1.2.1                                       1.2.2
+-------------------------------------------+ <---- Connection: 1.2.1-1.2.2
         1.3.1                   1.3.2
         +-----------------------+            <---- Connection: 1.3.1-1.3.2

Mapping the above waypoints to SplineLane and Segment objects will be done by the Builder. In the end, we end up with something like:

|        |1.1.1                  |1.1.2     |
x--------+-----------------------+----------x <---- Connection: 1.1.1-1.1.2
|1.2.1   |1.2.3                  |1.2.4     |1.2.2
+--------o-----------------------o----------+ <---- Connection: 1.2.1-1.2.2
|        |1.3.1                  |1.3.2     |
x--------+-----------------------+----------x <---- Connection: 1.3.1-1.3.2

Those new waypoints that appear make possible the concept of Maliput Segment as a surface that holds all the trajectories (represented by Maliput Lanes). At the building stage, we can now match waypoints across lanes using an index-based algorithm, a pair of valid consecutive waypoints in a Connection are used to create a SplineLane. At the same time, we should create those Lanes inside the same segment, which is not difficult to do using the index approach. To sum up, Builder will create the following:

General workflow with this class should be:

  1. Create a Builder.
  2. Call SetBoundingBox().
  3. Call CreateSegmentConnections() for each RNDF segment.
  4. Call CreateConnectionsForZones() for each RNDF zone.
  5. Call CreateConnection() for each pair of entry-exit waypoints between RNDF lanes and zone perimeters (actually connecting their fake inner lanes to the outer real ones).
  6. Call Build() to get the built api::RoadGeometry.

Constructor & Destructor Documentation

Builder ( const Builder )
delete
Builder ( Builder &&  )
delete
Builder ( double  linear_tolerance,
double  angular_tolerance 
)
inline

Constructs a Builder which can be used to specify and assemble an RNDF implementation of an api::RoadGeometry.

Parameters
linear_toleranceLinear tolerance for RoadGeometry construction.
angular_toleranceAngular tolerance for RoadGeometry construction.

Member Function Documentation

std::unique_ptr< const api::RoadGeometry > Build ( const api::RoadGeometryId id)

Builds an api::RoadGeometry.

All the groups of connections are traversed. A Junction with a single Segment is created per group, and for each connection in that group, a Lane is added to the Segment. BranchPoints are updated as needed.

Parameters
idID of the api::RoadGeometry to be built.
Returns
The built api::RoadGeometry.
Exceptions
std::runtime_errorWhen the built RoadGeometry does not satisfy Maliput roads' constraints (see api::RoadGeometry::CheckInvariants()).

Here is the call graph for this function:

Here is the caller graph for this function:

void CreateConnection ( double  width,
const ignition::rndf::UniqueId &  exit_id,
const ignition::rndf::UniqueId &  entry_id 
)

Creates a connection between two RNDF lanes based on a pair of exit and entry ids that map to specific, existing waypoints.

This is helpful when building intersections.

Parameters
widthThe connection's width.
exit_idThe start waypoint ID of the connection.
entry_idThe end waypoint ID of the connection.
Exceptions
std::runtime_errorWhen neither exit_id nor entry_id are found.

Here is the caller graph for this function:

void CreateConnectionsForZones ( double  width,
std::vector< DirectedWaypoint > *  perimeter_waypoints 
)

Creates a collection of Connection objects between every pair of entry and exit waypoints in perimeter_waypoints.

RNDF defines zones as areas where free-path driving is allowed. Since Maliput does not cover this concept, and to avoid having dead-end lanes, every pair of entry and exit waypoints is connected. These waypoints' directions are set to head towards the centroid of all perimeter_waypoints.

Parameters
widthThe width of this zone's inner connections (and thus the fake inner lanes' lane bounds).
perimeter_waypointsA collection of DirectedWaypoint objects describing the zone's perimeter.
Exceptions
std::runtime_errorWhen perimeter_waypoints is a nullptr.
std::runtime_errorWhen perimeter_waypoints is an empty collection.

Here is the caller graph for this function:

void CreateSegmentConnections ( int  segment_id,
std::vector< Connection > *  connections 
)

Populates the Builder's inner connection map with the given connections representing an RNDF segment.

To do this, the connections' waypoints are first used to derive a geometry. Then, these connections are grouped based on relative direction using the first connection found as a reference. Once grouped, extra waypoints are added to each of them on a per group basis as necessary to ensure a grid-like distribution of waypoints.

Parameters
segment_idThe RNDF segment ID.
connectionsA collection of Connections representing each RNDF lane in the segment.
Exceptions
std::runtime_errorWhen connections is a nullptr.
std::runtime_errorWhen connections is an empty collection.

Here is the call graph for this function:

Here is the caller graph for this function:

Builder& operator= ( Builder &&  )
delete
Builder& operator= ( const Builder )
delete
void SetBoundingBox ( const std::pair< ignition::math::Vector3d, ignition::math::Vector3d > &  bounding_box)
inline

Sets the bounding box of the RNDF map.

Parameters
bounding_boxThe lower left and upper right corners' position pair for the bounding box.
Remarks
Bounding box definition is kept in 3D space for the sake of generality, even though there's currently no support for nonplanar RNDF geometries and, most of the time, the z-component of the given corners will be zero.

Here is the call graph for this function:


The documentation for this class was generated from the following files: