1# OSRM profiles 2OSRM 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. 3 4 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. 5 6## Available profiles 7Out-of-the-box OSRM comes with profiles for car, bicycle and foot. You can easily modify these or create new ones if you like. 8 9Profiles have a 'lua' extension, and are placed in 'profiles' directory. 10 11When running OSRM preprocessing commands you specify the profile with the --profile (or the shorthand -p) option, for example: 12 13`osrm-extract --profile ../profiles/car.lua planet-latest.osm.pbf` 14 15## Processing flow 16It's important to understand that profiles are used when preprocessing the OSM data, NOT at query time when routes are computed. 17 18This means that after modifying a profile **you will need to extract, contract and reload the data again** and to see changes in the routing results. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow) for more. 19 20## Profiles are written in Lua 21Profiles are not just configuration files. They are scripts written in the [Lua scripting language](http://www.lua.org). The reason for this is that OpenStreetMap data is complex, and it's not possible to simply define tag mappings. Lua scripting offers a powerful way to handle all the possible tag combinations found in OpenStreetMap nodes and ways. 22 23## Basic structure of profiles 24A profile will process every node and way in the OSM input data to determine what ways are routable in which direction, at what speed, etc. 25 26A profile will typically: 27 28- Define api version (required) 29- Require library files (optional) 30- Define setup function (required) 31- Define process functions (some are required) 32- Return functions table (required) 33 34A profile can also define various local functions it needs. 35 36Looking at [car.lua](../profiles/car.lua) as an example, at the top of the file the api version is defined and then required library files are included. 37 38Then follows the `setup` function, which is called once when the profile is loaded. It returns a big hash table of configurations, specifying things like what speed to use for different way types. The configurations are used later in the various processing functions. Many adjustments can be done just by modifying this configuration table. 39 40The setup function is also where you can do other setup, like loading an elevation data source if you want to consider that when processing ways. 41 42Then come the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`. 43 44The `process_turn` function processes every possible turn in the network, and sets a penalty depending on the angle and turn of the movement. 45 46Profiles can also define a `process_segment` function to handle differences in speed along an OSM way, for example to handle elevation. As you can see, this is not currently used in the car profile. 47 48At the end of the file, a table is returned with references to the setup and processing functions the profile has defined. 49 50## Understanding speed, weight and rate 51When computing a route from A to B there can be different measures of what is the best route. That's why there's a need for different profiles. 52 53Because speeds vary on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer. 54 55To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concepts of `weight` and `rate`. The rate is an abstract measure that you can assign to ways as you like to make some ways preferable to others. Routing will prefer ways with high rate. 56 57The weight of a way is normally computed as length / rate. The weight can be thought of as the resistance or cost when passing the way. Routing will prefer ways with low weight. 58 59You can also set the weight of a way to a fixed value. In this case it's not calculated based on the length or rate, and the rate is ignored. 60 61You should set the speed to your best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times. 62 63If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time estimation will be skewed. 64 65If you set the same rate on all ways, the result will be shortest path routing. 66If you set rate = speed on all ways, the result will be fastest path routing. 67If you want to prioritize certain streets, increase the rate on these. 68 69## Elements 70### api_version 71A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 4. 72 73### Library files 74The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks. 75 76File | Notes 77------------------|------------------------------ 78way_handlers.lua | Functions for processing way tags 79tags.lua | Functions for general parsing of OSM tags 80set.lua | Defines the Set helper for handling sets of values 81sequence.lua | Defines the Sequence helper for handling sequences of values 82access.lua | Function for finding relevant access tags 83destination.lua | Function for finding relevant destination tags 84maxspeed.lua | Function for determining maximum speed 85guidance.lua | Function for processing guidance attributes 86 87They all return a table of functions when you use `require` to load them. You can either store this table and reference its functions later, or if you need only a single function you can store that directly. 88 89### setup() 90The `setup` function is called once when the profile is loaded and must return a table of configurations. It's also where you can do other global setup, like loading data sources that are used during processing. 91 92Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA interpreter will have its own set of globals. 93 94The following global properties can be set under `properties` in the hash you return in the `setup` function: 95 96Attribute | Type | Notes 97-------------------------------------|----------|---------------------------------------------------------------------------- 98weight_name | String | Name used in output for the routing weight property (default `'duration'`) 99weight_precision | Unsigned | Decimal precision of edge weights (default `1`) 100left_hand_driving | Boolean | Are vehicles assumed to drive on the left? (used in guidance, default `false`) 101use_turn_restrictions | Boolean | Are turn restrictions followed? (default `false`) 102continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`) 103max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s) 104max_turn_weight | Float | Maximum turn penalty weight 105force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `process_segment` will be called for all segments (default `false`) 106 107 108The following additional global properties can be set in the hash you return in the `setup` function: 109 110Attribute | Type | Notes 111-------------------------------------|------------------|---------------------------------------------------------------------------- 112excludable | Sequence of Sets | Determines which class-combinations are supported by the `exclude` option at query time. E.g. `Sequence{Set{"ferry", "motorway"}, Set{"motorway"}}` will allow you to exclude ferries and motorways, or only motorways. 113classes | Sequence | Determines the allowed classes that can be referenced using `{forward,backward}_classes` on the way in the `process_way` function. 114restrictions | Sequence | Determines which turn restrictions will be used for this profile. 115suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES". 116relation_types | Sequence | Determines wich relations should be cached for processing in this profile. It contains relations types 117 118### process_node(profile, node, result, relations) 119Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay. 120 121Argument | Description 122---------|------------------------------------------------------- 123profile | The configuration table you returned in `setup`. 124node | The input node to process (read-only). 125result | The output that you will modify. 126relations| Storage of relations to access relations, where `node` is a member. 127 128The following attributes can be set on `result`: 129 130Attribute | Type | Notes 131----------------|---------|--------------------------------------------------------- 132barrier | Boolean | Is it an impassable barrier? 133traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)? 134 135### process_way(profile, way, result, relations) 136Given 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. 137 138Argument | Description 139---------|------------------------------------------------------- 140profile | The configuration table you returned in `setup`. 141way | The input way to process (read-only). 142result | The output that you will modify. 143relations| Storage of relations to access relations, where `way` is a member. 144 145Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way. 146 147It will also set a number of other attributes on `result`. 148 149Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `process_way` function. Instead `process_way` will examine the tag set on the way, process this information in various ways, calling other local functions and referencing the configuration in `profile`, etc., before arriving at the result. 150 151The following attributes can be set on the result in `process_way`: 152 153Attribute | Type | Notes 154----------------------------------------|----------|-------------------------------------------------------------------------- 155forward_speed | Float | Speed on this way in km/h. Mandatory. 156backward_speed | Float | "" 157forward_rate | Float | Routing weight, expressed as meters/*weight* (e.g. for a fastest-route weighting, you would want this to be meters/second, so set it to forward_speed/3.6) 158backward_rate | Float | "" 159forward_mode | Enum | Mode of travel (e.g. `car`, `ferry`). Mandatory. Defined in `include/extractor/travel_mode.hpp`. 160backward_mode | Enum | "" 161forward_classes | Table | Mark this way as being of a specific class, e.g. `result.classes["toll"] = true`. This will be exposed in the API as `classes` on each `RouteStep`. 162backward_classes | Table | "" 163duration | Float | Alternative setter for duration of the whole way in both directions 164weight | Float | Alternative setter for weight of the whole way in both directions 165turn_lanes_forward | String | Directions for individual lanes (normalized OSM `turn:lanes` value) 166turn_lanes_backward | String | "" 167forward_restricted | Boolean | Is this a restricted access road? (e.g. private, or deliveries only; used to enable high turn penalty, so that way is only chosen for start/end of route) 168backward_restricted | Boolean | "" 169is_startpoint | Boolean | Can a journey start on this way? (e.g. ferry; if `false`, prevents snapping the start point to this way) 170roundabout | Boolean | Is this part of a roundabout? 171circular | Boolean | Is this part of a non-roundabout circular junction? 172name | String | Name of the way 173ref | String | Road number (equal to set `forward_ref` and `backward_ref` with one value) 174forward_ref | String | Road number in forward way direction 175backward_ref | String | Road number in backward way direction 176destinations | String | The road's destinations 177exits | String | The ramp's exit numbers or names 178pronunciation | String | Name pronunciation 179road_classification.motorway_class | Boolean | Guidance: way is a motorway 180road_classification.link_class | Boolean | Guidance: way is a slip/link road 181road_classification.road_priority_class | Enum | Guidance: order in priority list. Defined in `include/extractor/road_classification.hpp` 182road_classification.may_be_ignored | Boolean | Guidance: way is non-highway 183road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way 184 185### process_segment(profile, segment) 186The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes. 187 188On OpenStreetMap way cannot have different tags on different parts of a way. Instead you would split the way into several smaller ways. However many ways are long. For example, many ways pass hills without any change in tags. 189 190Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment accordingly. 191 192In the `process_segment` function you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to look up information from another data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example. 193 194The following attributes can be read and set on the result in `process_segment`: 195 196Attribute | Read/write? | Type | Notes 197-------------------|-------------|---------|---------------------------------------- 198source.lon | Read | Float | Co-ordinates of segment start 199source.lat | Read | Float | "" 200target.lon | Read | Float | Co-ordinates of segment end 201target.lat | Read | Float | "" 202distance | Read | Float | Length of segment 203weight | Read/write | Float | Routing weight for this segment 204duration | Read/write | Float | Duration for this segment 205 206### process_turn(profile, turn) 207The `process_turn` function is called for every possible turn in the network. Based on the angle and type of turn you assign the weight and duration of the movement. 208 209The following attributes can be read and set on the result in `process_turn`: 210 211Attribute | Read/write? | Type | Notes 212--------------------- | ------------- | --------- | ------------------------------------------------------ 213angle | Read | Float | Angle of turn in degrees (`[-179, 180]`: `0`=straight, `180`=u turn, `+x`=x degrees to the right, `-x`= x degrees to the left) 214number_of_roads | Read | Integer | Number of ways at the intersection of the turn 215is_u_turn | Read | Boolean | Is the turn a u-turn? 216has_traffic_light | Read | Boolean | Is a traffic light present at this turn? 217is_left_hand_driving | Read | Boolean | Is left-hand traffic? 218source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`) 219source_mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp` 220source_is_motorway | Read | Boolean | Is the source road a motorway? 221source_is_link | Read | Boolean | Is the source road a link? 222source_number_of_lanes | Read | Integer | How many lanes does the source road have? (default when not tagged: 0) 223source_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)) 224source_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)) 225source_speed | Read | Integer | Speed on this source road in km/h 226source_priority_class | Read | Enum | The type of road priority class of the source. Defined in `include/extractor/road_classification.hpp` 227target_restricted | Read | Boolean | Is the target a restricted access road? (See definition in `process_way`) 228target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp` 229target_is_motorway | Read | Boolean | Is the target road a motorway? 230target_is_link | Read | Boolean | Is the target road a link? 231target_number_of_lanes | Read | Integer | How many lanes does the target road have? (default when not tagged: 0) 232target_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)) 233target_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)) 234target_speed | Read | Integer | Speed on this target road in km/h 235target_priority_class | Read | Enum | The type of road priority class of the target. Defined in `include/extractor/road_classification.hpp` 236roads_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 237roads_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. 238weight | Read/write | Float | Penalty to be applied for this turn (routing weight) 239duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds) 240 241#### `roads_on_the_right` and `roads_on_the_left` 242 243The information of `roads_on_the_right` and `roads_on_the_left` that can be read are as follows: 244 245Attribute | Read/write? | Type | Notes 246--------------------- | ------------- | --------- | ------------------------------------------------------ 247is_restricted | Read | Boolean | Is it a restricted access road? (See definition in `process_way`) 248mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp` 249is_motorway | Read | Boolean | Is the road a motorway? 250is_link | Read | Boolean | Is the road a link? 251number_of_lanes | Read | Integer | How many lanes does the road have? (default when not tagged: 0) 252highway_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) 253access_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) 254speed | Read | Integer | Speed on this road in km/h 255priority_class | Read | Enum | The type of road priority class of the leg. Defined in `include/extractor/road_classification.hpp` 256is_incoming | Read | Boolean | Is the road an incoming road of the intersection 257is_outgoing | Read | Boolean | Is the road an outgoing road of the intersection 258 259The order of the roads in `roads_on_the_right` and `roads_on_the_left` are *counter clockwise*. If the turn is a u turn, all other connected roads will be in `roads_on_the_right`. 260 261**Example** 262 263``` 264 c e 265 | / 266 | / 267 a ---- x ---- b 268 /| 269 / | 270 f d 271 272 273``` 274When turning from `a` to `b` via `x`, 275* `roads_on_the_right[1]` is the road `xf` 276* `roads_on_the_right[2]` is the road `xd` 277* `roads_on_the_left[1]` is the road `xe` 278* `roads_on_the_left[2]` is the road `xc` 279 280Note that indices of arrays in lua are 1-based. 281 282#### `highway_turn_classification` and `access_turn_classification` 283When setting appropriate turn weights and duration, information about the highway and access tags of roads that are involved in the turn are necessary. The lua turn function `process_turn` does not have access to the original osrm tags anymore. However, `highway_turn_classification` and `access_turn_classification` can be set during setup. The classification set during setup can be later used in `process_turn`. 284 285**Example** 286 287In the following example we use `highway_turn_classification` to set the turn weight to `10` if the turn is on a highway and to `5` if the turn is on a primary. 288 289``` 290function setup() 291 return { 292 highway_turn_classification = { 293 ['motorway'] = 2, 294 ['primary'] = 1 295 } 296 } 297end 298 299function process_turn(profile, turn) { 300 if turn.source_highway_turn_classification == 2 and turn.target_highway_turn_classification == 2 then 301 turn.weight = 10 302 end 303 if turn.source_highway_turn_classification == 1 and turn.target_highway_turn_classification == 1 then 304 turn.weight = 5 305 end 306} 307``` 308 309## Guidance 310The guidance parameters in profiles are currently a work in progress. They can and will change. 311Please be aware of this when using guidance configuration possibilities. 312 313Guidance uses road classes to decide on when/if to emit specific instructions and to discover which road is obvious when following a route. 314Classification uses three flags and a priority-category. 315The flags indicate whether a road is a motorway (required for on/off ramps), a link type (the ramps itself, if also a motorway) and whether a road may be omitted in considerations (is considered purely for connectivity). 316The priority-category influences the decision which road is considered the obvious choice and which roads can be seen as fork. 317Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large. 318 319### Using raster data 320OSRM has built-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes. 321 322Use `raster:load()` in your `setup` function to load data and store the source in your configuration hash: 323 324```lua 325function setup() 326 return { 327 raster_source = raster:load( 328 "rastersource.asc", -- file to load 329 0, -- longitude min 330 0.1, -- longitude max 331 0, -- latitude min 332 0.1, -- latitude max 333 5, -- number of rows 334 4 -- number of columns 335 ) 336 } 337end 338``` 339 340The input data must an ASCII file with rows of integers. e.g.: 341 342``` 3430 0 0 0 3440 0 0 250 3450 0 250 500 3460 0 0 250 3470 0 0 0 348``` 349 350In your `segment_function` you can then access the raster source and use `raster:query()` to query to find the nearest data point, or `raster:interpolate()` to interpolate a value based on nearby data points. 351 352You must check whether the result is valid before use it. 353 354Example: 355 356```lua 357function process_segment (profile, segment) 358 local sourceData = raster:query(profile.raster_source, segment.source.lon, segment.source.lat) 359 local targetData = raster:query(profile.raster_source, segment.target.lon, segment.target.lat) 360 361 local invalid = sourceData.invalid_data() 362 if sourceData.datum ~= invalid and targetData.datum ~= invalid then 363 -- use values to adjust weight and duration 364 [...] 365end 366``` 367 368See [rasterbot.lua](../profiles/rasterbot.lua) and [rasterbotinterp.lua](../profiles/rasterbotinterp.lua) for examples. 369 370### Helper functions 371There are a few helper functions defined in the global scope that profiles can use: 372 373- `durationIsValid` 374- `parseDuration` 375- `trimLaneString` 376- `applyAccessTokens` 377- `canonicalizeStringList` 378