Skip to content

Grand Unified Obstacle Treatment #7130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Unreleased
- Changes from 5.27.1
- Features
- ADDED: Add generic support for obstacles [#7130](https://github.com/Project-OSRM/osrm-backend/pull/7130)
- ADDED: Route pedestrians over highway=platform [#6993](https://github.com/Project-OSRM/osrm-backend/pull/6993)
- REMOVED: Remove all core-CH left-overs [#6920](https://github.com/Project-OSRM/osrm-backend/pull/6920)
- ADDED: Add support for a keepalive_timeout flag. [#6674](https://github.com/Project-OSRM/osrm-backend/pull/6674)
Expand Down
184 changes: 180 additions & 4 deletions docs/profiles.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# OSRM profiles
OSRM supports "profiles". Profiles representing routing behavior for different transport modes like car, bike and foot. You can also create profiles for variations like a fastest/shortest car profile or fastest/safest/greenest bicycles profile.

A profile describes whether or not it's possible to route along a particular type of way, whether we can pass a particular node, and how quickly we'll be traveling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
A profile describes whether or not it's possible to route along a particular type of way, whether we can pass a particular node, and how quickly we'll be traveling when we do. This feeds into the way the routing graph is created and thus influences the output routes.

## Available profiles
Out-of-the-box OSRM comes with profiles for car, bicycle and foot. You can easily modify these or create new ones if you like.
Expand Down Expand Up @@ -116,7 +116,7 @@ suffix_list | Set | List of name suffixes
relation_types | Sequence | Determines which relations should be cached for processing in this profile. It contains relations types

### process_node(profile, node, result, relations)
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
Process an OSM node to determine whether this node is an obstacle, if it can be passed at all and whether passing it incurs a delay.

Argument | Description
---------|-------------------------------------------------------
Expand All @@ -126,12 +126,177 @@ result | The output that you will modify.
relations| Storage of relations to access relations, where `node` is a member.

The following attributes can be set on `result`:
(Note: for new code use the `obstacle_map`.

Attribute | Type | Notes
----------------|---------|---------------------------------------------------------
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?

### Obstacle
A user type that represents an obstacle on the road or a place where you can turn
around.

This may be a completely impassable obstacle like a barrier, a temporary obstacle like a
traffic light or a stop sign, or an obstacle that just slows you down like a
traffic_calming. The obstacle may be present in both directions or in one direction
only.

This also represents a good turning point like a mini_roundabout, turning_loop, or
turning_circle.

An object of this type is immutable once constructed.

```lua
local obs = Obstacle.new(
obstacle_type.traffic_signals,
obstacle_direction.forward,
2.5,
0
)
assert(obs.duration == 2.5)
```

Member | Mode | Type | Notes
----------|-----------|--------------------|----------------------------------
type | read-only | obstacle_type | eg. `obstacle_type.barrier`
direction | read-only | obstacle_direction | eg. `obstacle_direction.forward`
duration | read-only | float | The expected delay in seconds
weight | read-only | float | The weight

#### obstacle_type
An enum with the following keys:

Keys |
----------------|
none |
barrier |
traffic_signals |
stop |
give_way |
crossing |
traffic_calming |
mini_roundabout |
turning_loop |
turning_circle |

#### obstacle_direction
An enum with the following keys:

Keys |
---------|
none |
forward |
backward |
both |

### obstacle_map
A global user type. It stores obstacles.

The canonical workflow is: to store obstacles in `process_node()` and retrieve them in
`process_turn()`.

Note: In the course of processing, between the `process_node()` stage and the
`process_turn()` stage, the extractor switches from using OSM nodes to using
internal nodes. Both types have different ids. You can only store OSM nodes and only
retrieve internal nodes. This implies that, in `process_node()`, you cannot retrieve an
obstacle you have just stored.

#### obstacle_map:add(node, obstacle)
Call this function inside `process_node()` to register an obstacle on a node. You can
register as many different obstacles as you wish on any given node. It is your
responsibility to register the same obstacle only once.

In a following step -- likely in `process_turn()` -- you can retrieve all obstacles
registered at any given node. This function works with OSM nodes.

Argument | Type | Notes
---------|----------|--------------------------------------------
node | OSMNode | The same node as passed to `process_node`.
obstacle | Obstacle | The obstacle

Usage example:

```lua
function process_node(profile, node, result, relations)
...
obstacle_map:add(node,
Obstacle.new(
obstacle_type.traffic_signal,
obstacle_direction.forward,
2, 0))
end
```

#### obstacle_map:any(from, to, type)
Return true if there are any obstacles at node `to` when coming from node
`from` and having the type `type`.

You will likely call this function inside `process_turn()`.
Note that this works only with internal nodes, not with OSM nodes.

```lua
bool obstacle_map:any(to)
bool obstacle_map:any(from, to)
bool obstacle_map:any(from, to, type)
```

Argument | Type | Notes
---------|---------------|-------------------------------------------------------------------------------------
from | Node | The leading node. Optional.
to | Node | The node with the obstacle.
type | obstacle_type | The obstacle type. Defaults to all types. May be a bitwise-or combination of types.
returns | bool | True if there are any obstacles satisfiying the given criteria.

Usage examples:

```lua
function process_turn(profile, turn)
if obstacle_map:any(turn.via) then
...
end
if obstacle_map:any(turn.from, turn.via, obstacle_type.traffic_signal) then
turn.duration = turn.duration + 2
end
end
```

#### obstacle_map:get(from, to, type)
This function retrieves all registered obstacles at node `to` when coming from the node
`from` and having the type `type`.

You will likely call this function inside `process_turn()`.
Note that this works only with internal nodes, not with OSM nodes.

```lua
obstacle_map:get(to)
obstacle_map:get(from, to)
obstacle_map:get(from, to, type)
```

Argument | Type | Notes
---------|---------------|-------------------------------------------------------------------------------------
from | Node | The leading node. Optional.
to | Node | The node with the obstacle.
type | obstacle_type | The obstacle type. Defaults to all types. May be a bitwise-or combination of types.
returns | table | A table of `Obstacle`s.

Usage examples:

```lua
function process_turn(profile, turn)
for _, obs in pairs(obstacle_map:get(turn.via)) do
if obs.type == obstacle_type.barrier then
turn.duration = turn.duration + obs.duration
end
end
for _, obs in pairs(obstacle_map:get(
turn.from, turn.via, obstacle_type.traffic_signal)) do
turn.duration = turn.duration + obs.duration
end
end
```

### process_way(profile, way, result, relations)
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash.

Expand Down Expand Up @@ -233,14 +398,24 @@ target_highway_turn_classification | Read | Integer |
target_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
target_speed | Read | Integer | Speed on this target road in km/h
target_priority_class | Read | Enum | The type of road priority class of the target. Defined in `include/extractor/road_classification.hpp`
from | Read | NodeID | The leading node
via | Read | NodeID | The intersection node
to | Read | NodeID | The trailing node
source_road | Read | ExtractionTurnLeg | The incoming road
target_road | Read | ExtractionTurnLeg | The outgoing road
roads_on_the_right | Read | Vector<ExtractionTurnLeg> | Vector with information about other roads on the right of the turn that are also connected at the intersection
roads_on_the_left | Read | Vector<ExtractionTurnLeg> | Vector with information about other roads on the left of the turn that are also connected at the intersection. If turn is a u turn, this is empty.
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)

#### `roads_on_the_right` and `roads_on_the_left`

The information of `roads_on_the_right` and `roads_on_the_left` that can be read are as follows:
#### `from`, `via`, and `to`
Use these node IDs to retrieve obstacles. See: `obstacle_map:get`.

#### `source_road`, `target_road`, `roads_on_the_right`, and `roads_on_the_left`

The information of `source_road`, `target_road`, `roads_on_the_right`, and
`roads_on_the_left` that can be read are as follows:

Attribute | Read/write? | Type | Notes
--------------------- | ------------- | --------- | ------------------------------------------------------
Expand All @@ -252,6 +427,7 @@ number_of_lanes | Read | Integer | How many lanes does th
highway_turn_classification | Read | Integer | Classification based on highway tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15)
access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15)
speed | Read | Integer | Speed on this road in km/h
distance | Read | Double | The length of the road edge
priority_class | Read | Enum | The type of road priority class of the leg. Defined in `include/extractor/road_classification.hpp`
is_incoming | Read | Boolean | Is the road an incoming road of the intersection
is_outgoing | Read | Boolean | Is the road an outgoing road of the intersection
Expand Down
4 changes: 1 addition & 3 deletions docs/src/content.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ var fs = require('fs');
*/
module.exports =
'# HTTP API\n' +
fs.readFileSync('./content/http.md', 'utf8') + '\n'+
'# libosrm C++ API\n' +
fs.readFileSync('./content/libosrm.md', 'utf8') + '\n';
fs.readFileSync('./content/http.md', 'utf8') + '\n';
Loading
Loading