Skip to content

Crosswalk elements

road_on_crosswalk

The road_on_crosswalk route element represents a driving route across a crosswalk. Crosswalks are provided to Foretify from the source map by the MSP as quadrilaterals.

They have a crosswalk_mark_type attribute that can be one of the following:

  • solid
  • transverse
  • ladder
  • diagonal_ladder
  • bars
  • spaced_bars
  • bar_pairs
  • none
  • other

The also have a crosswalk_mark_color attribute that can be:

  • white
  • yellow
  • green
  • rainbow
  • none
  • other

The number of road_on_crosswalk occurrences corresponding to a single crosswalk can vary as follows:

  • One occurrence per crosswalk if it is on a one-way road.
  • One occurrence per crosswalk
  • Two occurrences per crosswalk if it is on a two-way road.
    Two occurrences per crosswalk
  • More than two occurrences per crosswalk if it is part of a junction.
    Six occurrences per crosswalk {straight, left, right} * {entering-junction, exiting-junction}

In a junction, a road_on_crosswalk occurrence can be reached either when entering or exiting the junction. The road_on_crosswalk_type enum classifies these occurrences based on their relationship to the road:

  • on_one_way - represents a single road_on_crosswalk occurrence for a given crosswalk on a one-way road.
  • on_two_way - indicates one of two road_on_crosswalk occurrences for a given crosswalk on a two-way road.
  • junction_entry - indicates that the road_on_crosswalk is in an entry to a junction.
  • junction_exit- indicates that the road_on_crosswalk is in an exit from a junction.

OSC definition of road_on_crosswalk

# A crosswalk may be over a one-way-road, over a two-way-road or over multiple internal-roads 
# at a junction. When inside a junction a vehicle may arrive at the crosswalk on its way
# into the junction or on its way out of the junction.
#
enum road_on_crosswalk_type: [other, on_one_way, on_two_way, junction_entry, junction_exit]

enum crosswalk_mark_type: [solid, transverse, ladder, diagonal_ladder, bars, spaced_bars, bar_pairs, none, other]

enum crosswalk_mark_color: [white, yellow, green, rainbow, none, other]

# road_on_crosswalk route element is a drive_route over a crosswalk. 
# Start offset and end offset are the polygon borders of the crosswalk
#
struct road_on_crosswalk inherits road_element:
    # ID (internal) of the crosswalk crossed by this element.
    #
    crosswalk_id: uint

    # type of crosswalk crossed by this element
    #
    kind: road_on_crosswalk_type

    # road marking type and color
    #
    mark_type: crosswalk_mark_type
    mark_color: crosswalk_mark_color

road_to_crosswalk

The road_to_crosswalk route element represents a route that begins at the start of the overlapping or preceding one_way_road and ends precisely at the start of a road_on_crosswalk.

An exceptional case occurs when a crosswalk is located immediately after a junction, and the start of the nearest one_way_road is less than config.map.road_to_crosswalk_min_length (default of 10 meters) behind it. In this situation, the route is extended back to include the start of the one_way_road before the junction, resulting in multiple road_to_crosswalk occurrences for a single road_on_crosswalk.

In the exceptional case illustrated below, the road_on_crosswalk outlined in red is positioned just after exiting the junction, leading to three road_to_crosswalk occurrences connecting to it, one from each internal_road leading to it.

General case of road_to_crosswalk

In this image, road_on_crosswalk occurrences are highlighted in purple, and road_to_crosswalk occurrences are highlighted in green.

The road_to_crosswalk starts at the beginning of a one_way_road, leading to a road_on_crosswalk on the one_way_road.

There are two road_on_crosswalk occurences for a single crosswalk that covers two internal_roads. The two corresponding road_to_crosswalk occurences start at the beginning of the the previous one_way_road and overlap.

OSC definition of road_to_crosswalk

# road_to_crosswalk - a piece of road before a road_on_crosswalk. The element ends at the beginning of the 
# road_on_crosswalk. It starts at the beginning of the containing or preceding one_way_road.
#
struct road_to_crosswalk inherits road_element:
    road_on_crosswalk_id: uint
    road_on_crosswalk: road_on_crosswalk with:
        keep(it.id == self.road_on_crosswalk_id)
    one_way_road_id: int
    one_way_road: one_way_road with:
        keep((self.one_way_road_id == -1 and it == null) or (self.one_way_road_id >=0 and it.id == self.one_way_road_id))

road_from_crosswalk

The road_from_crosswalk route element represents a route that starts precisely at the end of a road_on_crosswalk and ends at the end of the overlapping or following one_way_road.

The following image illustrates examples of road_from_crosswalk elements that follow road_on_crosswalk placements in different locations: at a junction entry, a junction exit and in the middle of a road (not in a junction).

When a crosswalk is located "very close" to a junction entry, but not classified as a junction_entry we may still want to mark road_from_crosswalk elements along the possible junction routes that follow it. In this context, "very close" is defined by the configuration variable config.map.road_to_crosswalk_min_length which specifies a threshold distance. If the forward distance from the crosswalk to the junction is less than this threshold, the system generates road_from_crosswalk elements for all junction routes, just as it would be for a road_on_crosswalk of kind junction_entry.

This case is illustrated in the following image where three road_from_crosswalk elements (highlighted in purple) follow a single road_on_crosswalk element (outlined in red), due to its close proximity to the junction.

OSC definition of road_from_crosswalk

# road_from_crosswalk - a piece of road after a road_on_crosswalk. The element starts at the end of the 
# road_on_crosswalk. It ends at the end of the containing or following one_way_road.
#
struct road_from_crosswalk inherits road_element:
    road_on_crosswalk_id: uint
    road_on_crosswalk: road_on_crosswalk with:
        keep(it.id == self.road_on_crosswalk_id)
    one_way_road_id: int
    one_way_road: one_way_road with:
        keep((self.one_way_road_id == -1 and it == null) or (self.one_way_road_id >=0 and it.id == self.one_way_road_id))

get_roadside_position_by_crosswalk modifier

The purpose of the get_roadside_position_by_crosswalk modifier is to provide the start or end positions for a pedestrian crossing a specified road_on_crosswalk element, which is typically along the path of the Ego.

Modifier get_roadside_position_by_crosswalk has a single output parameter, position, which is an msp_position specifying a position by a crosswalk.

The input parameters of get_roadside_position_by_crosswalk are as follows.

Parameter Description
road_on_crosswalk The specific road_on_crosswalk element for which you want to determine the position.
side Indicates which side of the road_on_crosswalk (left or right relative to the driving direction) you want to get the position for.
lon_offset A longitudinal offset specified in road coordinates from the start of the road_on_crosswalk element.
path_fraction An alternative to lon_offset, this parameter specifies the longitudinal offset as a percentage of the length of the road_on_crosswalk element. The value is an integer in the range [0..100].
lat_offset A lateral offset relative to the outermost edge of the driving lane, such as the boundary between the driving lanes and the curb. Following the Foretify convention, lat_offset is directional according to the right-hand rule: positive values indicate a leftward direction, and negative values indicate a rightward direction, based on the orientation of the road_on_crosswalk parameter.

OSC definition of get_roadside_position_by_crosswalk

# Get a position on the road-side (e.g., curb or shoulder) along some crosswalk
#
modifier top.get_roadside_position_by_crosswalk:

    # Output properties

    # The resulting position generated from defined input properties
    #
    position: msp_position with:
        properties(it, required: true)

    # Input properties

    # Input 'road_on_crosswalk', used for defining the reference route
    #
    road_on_crosswalk: road_on_crosswalk with:
        properties(it, required: true)

    # 'side', on which side of the road is the requested position
    #
    side: av_side with:
        properties(it, required: true)

    # Sets a longitudinal offset from the start of the crosswalk. 
    # Offset must be positive and less than or equal to road_on_crosswalk.length.
    #
    lon_offset: length with:
        properties(it, exclusive_sets: ["lon_pos"])
        keep(lon_offset >= 0m and lon_offset <= road_on_crosswalk.length)

    # Sets a longitudinal reference by defining a fraction of the total crosswalk length.
    # Value must be in [0..100], otherwise 'lon_offset' parameter is used. 
    #
    path_fraction: int with:
        properties(it, exclusive_sets: ["lon_pos"])
        keep(default path_fraction == -1)

    # Lateral offset from the edge of the crosswalk
    #
    lat_offset: length with:
        properties(it)
        keep(default it == 0m)

Example using get_roadside_position_by_crosswalk modifier

In this scenario, the SUT’s route crosses a crosswalk while exiting a junction in a left turn. A pedestrian is crossing in parallel with the SUT drive. A possible result is illustrated in the following image. The SUT and its planned path are green, the pedestrian is highlighted yellow, and the road_on_crosswalk occurrences are marked in purple.

Example scenario using get_roadside_position_by_crosswalk modifier

OSC2 code: route elements get_roadside_position_by_crosswalk
import "$FTX/env/basic/exe_platforms/model_ssp/config/model_dummy_config.osc"
import "$FTX/env/basic/msp/open_drive.osc"

extend test_config:
    set map = "$FTX/packages/maps/M499_FTX_suburban.xodr"

scenario sut.turn_left_to_crosswalk_with_pedestrian_from_left:
    p: person
    start_pos: msp_position
    mid_pos: msp_position
    end_pos: msp_position

    # road_on_crosswalk - a road route congruent with a crosswalk arrived at when departing a junction.
    # 
    road_on_crosswalk: road_on_crosswalk with:
        keep(it.kind == junction_exit)

    # road_to_crosswalk - a road route reaching 'road_on_crosswalk'.
    #
    road_to_crosswalk: road_to_crosswalk with:
        keep(it.road_on_crosswalk == self.road_on_crosswalk)

    # left_turn - a left-turn internal_road.
    #
    left_turn: internal_road with:
        keep(it.direction in [slight_left, left, sharp_left])

    road_from_crosswalk: road_from_crosswalk with:
        keep(it.road_on_crosswalk == self.road_on_crosswalk)

    position_along_road(end_pos, 
                        road_from_crosswalk, 
                        lon_offset: 20m, 
                        outermost_lane: true, 
                        lat_offset: -1m, 
                        lat_reference: right)

    # set 'start_pos' on the left side of the crosswalk, 1 meter away from the road's edge
    # (could be on sidewalk or on shoulder or in a position that is not on the road-network).
    #
    get_roadside_position_by_crosswalk(start_pos, road_on_crosswalk, left, lon_offset: 1m, lat_offset: 1m)

    # set 'mid_pos' on the right side of the crosswalk, 1 meter away from the road's edge
    # (could be on sidewalk or on shoulder or in a position that is not on the road-network).
    #
    get_roadside_position_by_crosswalk(mid_pos, road_on_crosswalk, right, lon_offset: 2m, lat_offset: -1m)

    do parallel(overlap: start):
        serial:
            m1: p.move(mid_pos, start_position: start_pos, duration: 10s)
            m2: p.move(end_pos, duration: 10s)
        serial:
            a: sut.car.drive(duration: 10s) with:
                a1: along(road_to_crosswalk, at: start)
                a2: along(left_turn, at: end, run_mode: best_effort)
            b: sut.car.drive(duration: 10s) with:
                b1: along(road_on_crosswalk, at: start, run_mode: best_effort)
                b2: along(road_from_crosswalk, at: end, run_mode: best_effort)
                b3: speed(20kph, at: end, run_mode: best_effort)

extend top.main:
    do sut.turn_left_to_crosswalk_with_pedestrian_from_left()