profiles api v2
This commit is contained in:
parent
5ece65cade
commit
e413b25cd9
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,5 +1,19 @@
|
|||||||
# 5.10.0
|
# 5.10.0
|
||||||
- Changes from 5.9:
|
- Changes from 5.9:
|
||||||
|
- Profiles:
|
||||||
|
- New version 2 profile API which cleans up a number of things and makes it easier to for profiles to include each other. Profiles using the old version 0 and 1 APIs are still supported.
|
||||||
|
- New required `setup()` function that must return a configuration hash. Storing configuration in globals is deprecated.
|
||||||
|
- Passes the config hash returned in `setup()` as an argument to `process_node/way/segment/turn`.
|
||||||
|
- Properties are now set in `.properties` in the config hash returend by setup().
|
||||||
|
- initialize raster sources in `setup()` instead of in a separate callback.
|
||||||
|
- Renames the `sources` helper to `raster`.
|
||||||
|
- Renames `way_functions` to `process_way` (same for node, segment and turn).
|
||||||
|
- Removes `get_restrictions()`. Instead set `.restrictions` in the config hash in `setup()`.
|
||||||
|
- Removes `get_name_suffix_list()`. Instead set `.suffix_list` in the config hash in `setup()`.
|
||||||
|
- Renames `Handlers` to `WayHandlers`.
|
||||||
|
- Pass functions instead of strings to `WayHandlers.run()`, so it's possible to mix in your own functions.
|
||||||
|
- Reorders arguments to `WayHandlers` functions to match `process_way()`.
|
||||||
|
- Profiles must return a hash of profile functions. This makes it easier for profiles to include each other.
|
||||||
|
|
||||||
# 5.9.0
|
# 5.9.0
|
||||||
- Changes from 5.8:
|
- Changes from 5.8:
|
||||||
|
237
docs/profiles.md
237
docs/profiles.md
@ -1,31 +1,97 @@
|
|||||||
OSRM supports "profiles". Configurations representing different routing behaviours for (typically) different transport modes. A profile describes whether or not we route along a particular type of way, or over a particular node in the OpenStreetMap data, and also how quickly we'll be travelling when we do. This feeds into the way the routing graph is created and thus influences the output routes.
|
# 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.
|
||||||
|
|
||||||
## Available profiles
|
## 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.
|
||||||
|
|
||||||
Out-of-the-box OSRM comes with several different profiles, including car, bicycle and foot.
|
Profiles have a 'lua' extension, and are places in 'profiles' directory.
|
||||||
|
|
||||||
Profile configuration files have a 'lua' extension, and are found under the 'profiles' subdirectory.
|
When running OSRM preprocessing commands you specify the profile with the --profile (or the shorthand -p) option, for example:
|
||||||
Alternatively commands will take a lua profile specified with an explicit -p param, for example:
|
|
||||||
|
|
||||||
`osrm-extract -p ../profiles/car.lua planet-latest.osm.pbf`
|
`osrm-extract --profile ../profiles/car.lua planet-latest.osm.pbf`
|
||||||
|
|
||||||
And then **you will need to extract and contract again** (A change to the profile will typically affect the extract step as well as the contract step. See [Processing Flow](https://github.com/Project-OSRM/osrm-backend/wiki/Processing-Flow))
|
## Processing flow
|
||||||
|
It's important to understand that profiles are used when preprocessing the OSM data, NOT at query time when routes are computed.
|
||||||
|
|
||||||
## lua scripts?
|
This 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.
|
||||||
|
|
||||||
Profiles 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 not sufficiently straightforward, to simply define tag mappings. Lua scripting offers a powerful way of coping with the complexity of different node,way,relation,tag combinations found within OpenStreetMap data.
|
## Profiles are written in LUA
|
||||||
|
Profiles 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.
|
||||||
|
|
||||||
## Basic structure of a profile
|
## Basic structure of profiles
|
||||||
|
A 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.
|
||||||
|
|
||||||
You can understand these lua scripts enough to make interesting modifications, without needing to get to grips with how they work completely.
|
A profile will typically:
|
||||||
|
|
||||||
Towards the top of the file, a profile (such as [car.lua](../profiles/car.lua)) will typically define various configurations as global variables. A lot of these are look-up hashes of one sort or another.
|
- Define api version (required)
|
||||||
|
- Require library files (optional)
|
||||||
|
- Define setup function (required)
|
||||||
|
- Define process functions (some are required)
|
||||||
|
- Return functions table (required)
|
||||||
|
|
||||||
As you scroll down the file you'll see local variables, and then local functions, and finally...
|
A profile can also define various local functions it needs.
|
||||||
|
|
||||||
`way_function` and `node_function` are the important functions which are called when extracting OpenStreetMap data with `osrm-extract`.
|
Looking 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.
|
||||||
|
|
||||||
The following global properties can be set in your profile:
|
Then follows the `setup` functions, 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 be modifying this configuration table.
|
||||||
|
|
||||||
|
The setup function is also where you can do other setup, like loading elevation data source if you want to consider that when processing ways.
|
||||||
|
|
||||||
|
Then comes the `process_node` and `process_way` functions, which are called for each OSM node and way when extracting OpenStreetMap data with `osrm-extract`.
|
||||||
|
|
||||||
|
The `process_turn` function processes every possible turn in the network, and sets a penalty depending on the angle and turn of the movement.
|
||||||
|
|
||||||
|
Profiles 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.
|
||||||
|
|
||||||
|
At the end of the file, a table if returned with references to the setup and processing functions the profile has defined.
|
||||||
|
|
||||||
|
## Understanding speed, weight and rate
|
||||||
|
When computing a route from A to B there can be different measure of what is the best route. That's why there's a need for different profiles.
|
||||||
|
|
||||||
|
Because speeds very 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.
|
||||||
|
|
||||||
|
To handle this, OSRM doesn't simply choose the ways with the highest speed. Instead it uses the concept 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.
|
||||||
|
|
||||||
|
The weight of a way 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.
|
||||||
|
|
||||||
|
You 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.
|
||||||
|
|
||||||
|
You should set the speed to you best estimate of the actual speed that will be used on a particular way. This will result in the best estimated travel times.
|
||||||
|
|
||||||
|
If you want to prefer certain ways due to other factors than the speed, adjust the rate accordingly. If you adjust the speed, the time time estimation will be skewed.
|
||||||
|
|
||||||
|
If you set the same rate on all ways, the result will be shortest path routing.
|
||||||
|
If you set rate = speed on all ways, the result will be fastest path routing.
|
||||||
|
If you want to prioritize certain street, increase the rate on these.
|
||||||
|
|
||||||
|
## Elements
|
||||||
|
### api_version
|
||||||
|
A 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 2.
|
||||||
|
|
||||||
|
### Library files
|
||||||
|
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
|
||||||
|
|
||||||
|
File | Notes
|
||||||
|
------------------|------------------------------
|
||||||
|
way_handlers.lua | Functions for processing way tags
|
||||||
|
tags.lua | Functions for general parsing of OSM tags
|
||||||
|
set.lua | Defines the Set helper for handling sets of values
|
||||||
|
sequence.lua | Defines the Sequence helper for handling sequences of values
|
||||||
|
access.lua | Function for finding relevant access tags
|
||||||
|
destination.lua | Function for finding relevant destination tags
|
||||||
|
destination.lua | Function for determining maximum speed
|
||||||
|
guidance.lua | Function for processing guidance attributes
|
||||||
|
|
||||||
|
They all return a table of functions when you use `require` to load them. You can either store this table and reference it's functions later, of if you need only a single you can store that directly.
|
||||||
|
|
||||||
|
### setup()
|
||||||
|
The `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.
|
||||||
|
|
||||||
|
Note 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 iinterpreter will have it's own set of globals.
|
||||||
|
|
||||||
|
The following global properties can be set under `properties` in the hash you return in the `setup` function:
|
||||||
|
|
||||||
Attribute | Type | Notes
|
Attribute | Type | Notes
|
||||||
-------------------------------------|----------|----------------------------------------------------------------------------
|
-------------------------------------|----------|----------------------------------------------------------------------------
|
||||||
@ -36,17 +102,40 @@ use_turn_restrictions | Boolean | Are turn instructions followed
|
|||||||
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
|
continue_straight_at_waypoint | Boolean | Must the route continue straight on at a via point, or are U-turns allowed? (default `true`)
|
||||||
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
|
max_speed_for_map_matching | Float | Maximum vehicle speed to be assumed in matching (in m/s)
|
||||||
max_turn_weight | Float | Maximum turn penalty weight
|
max_turn_weight | Float | Maximum turn penalty weight
|
||||||
force_split_edges | Boolean | True value forces a split of forward and backward edges of extracted ways and guarantees that `segment_function` will be called for all segments (default `false`)
|
force_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`)
|
||||||
|
|
||||||
## way_function
|
### process_node(profile, node, result)
|
||||||
|
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
|
||||||
|
|
||||||
Given an OpenStreetMap way, the `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 to be returned. The most important thing it will do is set the value of `result.forward_speed` and `result.backward_speed` as a suitable integer value representing the speed for traversing the way.
|
Argument | Description
|
||||||
|
---------|-------------------------------------------------------
|
||||||
|
profile | The configuration table you returned in `setup`.
|
||||||
|
node | The input node to process (read-only).
|
||||||
|
result | The output that you will modify.
|
||||||
|
|
||||||
All other calculations stem from that, including the returned timings in driving directions, but also, less directly, it feeds into the actual routing decisions the engine will take (a way with a slow traversal speed, may be less favoured than a way with fast traversal speed, but it depends how long it is, and... what it connects to in the rest of the network graph)
|
The following attributes can be set on `result`:
|
||||||
|
|
||||||
Using the power of the scripting language you wouldn't typically see something as simple as a `result.forward_speed = 20` line within the `way_function`. Instead a `way_function` will examine the tagging (e.g. `way:get_value_by_key("highway")` and many others), process this information in various ways, calling other local functions, referencing the global variables and look-up hashes, before arriving at the result.
|
Attribute | Type | Notes
|
||||||
|
----------------|---------|---------------------------------------------------------
|
||||||
|
barrier | Boolean | Is it an impassable barrier?
|
||||||
|
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
|
||||||
|
|
||||||
The following attributes can be set on the result in `way_function`:
|
## process_way(profile, way, result)
|
||||||
|
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.
|
||||||
|
|
||||||
|
Argument | Description
|
||||||
|
---------|-------------------------------------------------------
|
||||||
|
profile | The configuration table you returned in `setup`.
|
||||||
|
node | The input way to process (read-only).
|
||||||
|
result | The output that you will modify.
|
||||||
|
|
||||||
|
Importantly 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.
|
||||||
|
|
||||||
|
It will also set a number of other attributes on `result`.
|
||||||
|
|
||||||
|
Using 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.
|
||||||
|
|
||||||
|
The following attributes can be set on the result in `process_way`:
|
||||||
|
|
||||||
Attribute | Type | Notes
|
Attribute | Type | Notes
|
||||||
----------------------------------------|----------|--------------------------------------------------------------------------
|
----------------------------------------|----------|--------------------------------------------------------------------------
|
||||||
@ -60,7 +149,7 @@ forward_classes | Table | Mark this way as being of a
|
|||||||
backward_classes | Table | " "
|
backward_classes | Table | " "
|
||||||
duration | Float | Alternative setter for duration of the whole way in both directions
|
duration | Float | Alternative setter for duration of the whole way in both directions
|
||||||
weight | Float | Alternative setter for weight of the whole way in both directions
|
weight | Float | Alternative setter for weight of the whole way in both directions
|
||||||
turn_lanes_forward | String | Directions for individual lanes (normalised OSM `turn:lanes` value)
|
turn_lanes_forward | String | Directions for individual lanes (normalized OSM `turn:lanes` value)
|
||||||
turn_lanes_backward | String | " "
|
turn_lanes_backward | String | " "
|
||||||
forward_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)
|
forward_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)
|
||||||
backward_restricted | Boolean | " "
|
backward_restricted | Boolean | " "
|
||||||
@ -78,32 +167,19 @@ road_classification.road_priority_class | Enum | Guidance: order in priority
|
|||||||
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
|
||||||
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
|
||||||
|
|
||||||
### Guidance
|
### process_segment(profile, segment)
|
||||||
|
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
|
||||||
|
|
||||||
The guidance parameters in profiles are currently a work in progress. They can and will change.
|
On 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.
|
||||||
Please be aware of this when using guidance configuration possibilities.
|
|
||||||
|
|
||||||
Guidance uses road classes to decide on when/if to emit specific instructions and to discover which road is obvious when following a route.
|
Processing 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.
|
||||||
Classification uses three flags and a priority-category.
|
|
||||||
The 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 omittted in considerations (is considered purely for connectivity).
|
|
||||||
The priority-category influences the decision which road is considered the obvious choice and which roads can be seen as fork.
|
|
||||||
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
|
|
||||||
|
|
||||||
## node_function
|
In the `process_segment` you don't have access to OSM tags. Instead you use the geographical location of the start and end point of the way to lookup other data source, like elevation data. See [rasterbot.lua](../profiles/rasterbot.lua) for an example.
|
||||||
|
|
||||||
The following attributes can be set on the result in `node_function`:
|
The following attributes can be read and set on the result in `process_segment`:
|
||||||
|
|
||||||
Attribute | Type | Notes
|
|
||||||
----------------|---------|-------------------------------------------------------
|
|
||||||
barrier | Boolean | Is it an impassable barrier?
|
|
||||||
traffic_lights | Boolean | Is it a traffic light (incurs delay in `turn_function`)?
|
|
||||||
|
|
||||||
## segment_function
|
|
||||||
|
|
||||||
The following attributes can be read and set on the result in `segment_function`:
|
|
||||||
|
|
||||||
Attribute | Read/write? | Type | Notes
|
Attribute | Read/write? | Type | Notes
|
||||||
-------------------|-------------|---------|------------------------------------------------------
|
-------------------|-------------|---------|----------------------------------------
|
||||||
source.lon | Read | Float | Co-ordinates of segment start
|
source.lon | Read | Float | Co-ordinates of segment start
|
||||||
source.lat | Read | Float | " "
|
source.lat | Read | Float | " "
|
||||||
target.lon | Read | Float | Co-ordinates of segment end
|
target.lon | Read | Float | Co-ordinates of segment end
|
||||||
@ -112,17 +188,88 @@ target.distance | Read | Float | Length of segment
|
|||||||
weight | Read/write | Float | Routing weight for this segment
|
weight | Read/write | Float | Routing weight for this segment
|
||||||
duration | Read/write | Float | Duration for this segment
|
duration | Read/write | Float | Duration for this segment
|
||||||
|
|
||||||
## turn_function
|
### process_turn(profile, turn)
|
||||||
|
The `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.
|
||||||
|
|
||||||
The following attributes can be read and set on the result in `turn_function`:
|
The following attributes can be read and set on the result in `process_turn`:
|
||||||
|
|
||||||
Attribute | Read/write? | Type | Notes
|
Attribute | Read/write? | Type | Notes
|
||||||
-------------------|-------------|---------|------------------------------------------------------
|
-------------------|-------------|---------|------------------------------------------------------
|
||||||
direction_modifier | Read | Enum | Geometry of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
direction_modifier | Read | Enum | Geometry of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||||
turn_type | Read | Enum | Priority of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
turn_type | Read | Enum | Priority of turn. Defined in `include/extractor/guidance/turn_instruction.hpp`
|
||||||
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
has_traffic_light | Read | Boolean | Is a traffic light present at this turn?
|
||||||
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `way_function`)
|
source_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
|
||||||
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `way_function`)
|
target_restricted | Read | Boolean | Is it to a restricted access road? (See definition in `process_way`)
|
||||||
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
|
angle | Read | Float | Angle of turn in degrees (`0-360`: `0`=u-turn, `180`=straight on)
|
||||||
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
duration | Read/write | Float | Penalty to be applied for this turn (duration in deciseconds)
|
||||||
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
weight | Read/write | Float | Penalty to be applied for this turn (routing weight)
|
||||||
|
|
||||||
|
## Guidance
|
||||||
|
The guidance parameters in profiles are currently a work in progress. They can and will change.
|
||||||
|
Please be aware of this when using guidance configuration possibilities.
|
||||||
|
|
||||||
|
Guidance uses road classes to decide on when/if to emit specific instructions and to discover which road is obvious when following a route.
|
||||||
|
Classification uses three flags and a priority-category.
|
||||||
|
The 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).
|
||||||
|
The priority-category influences the decision which road is considered the obvious choice and which roads can be seen as fork.
|
||||||
|
Forks can be emitted between roads of similar priority category only. Obvious choices follow a major priority road, if the priority difference is large.
|
||||||
|
|
||||||
|
### Using raster data
|
||||||
|
OSRM has build-in support for loading an interpolating raster data in ASCII format. This can be used e.g. for factoring in elevation when computing routes.
|
||||||
|
|
||||||
|
Use `raster:load()` in your `setup` function to load data and store the source in your configuration hash:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function setup()
|
||||||
|
return {
|
||||||
|
raster_source = raster:load(
|
||||||
|
"rastersource.asc", -- file to load
|
||||||
|
0, -- longitude min
|
||||||
|
0.1, -- longitude max
|
||||||
|
0, -- latitude min
|
||||||
|
0.1, -- latitude max
|
||||||
|
5, -- number of rows
|
||||||
|
4 -- number of columns
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The input data must an ASCII file with rows of integers. e.g.:
|
||||||
|
|
||||||
|
```
|
||||||
|
0 0 0 0
|
||||||
|
0 0 0 250
|
||||||
|
0 0 250 500
|
||||||
|
0 0 0 250
|
||||||
|
0 0 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
In 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.
|
||||||
|
|
||||||
|
You must check whether the result is valid before use it.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function process_segment (profile, segment)
|
||||||
|
local sourceData = raster:query(profile.raster_source, segment.source.lon, segment.source.lat)
|
||||||
|
local targetData = raster:query(profile.raster_source, segment.target.lon, segment.target.lat)
|
||||||
|
|
||||||
|
local invalid = sourceData.invalid_data()
|
||||||
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
|
-- use values to adjust weight and duration
|
||||||
|
[...]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
See [rasterbot.lua](../profiles/rasterbot.lua) and [rasterbotinterp.lua](../profiles/rasterbotinterp.lua) for examples.
|
||||||
|
|
||||||
|
### Helper functions
|
||||||
|
There are a few helper functions defined in the global scope that profiles can use:
|
||||||
|
|
||||||
|
durationIsValid
|
||||||
|
parseDuration
|
||||||
|
trimLaneString
|
||||||
|
applyAccessTokens
|
||||||
|
canonicalizeStringList
|
@ -2,10 +2,9 @@
|
|||||||
Feature: Bicycle - Route around alleys
|
Feature: Bicycle - Route around alleys
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile file
|
Given the profile file "bicycle" initialized with
|
||||||
"""
|
"""
|
||||||
require 'bicycle'
|
profile.properties.weight_name = 'cyclability'
|
||||||
properties.weight_name = 'cyclability'
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Bicycle - Avoid taking alleys
|
Scenario: Bicycle - Avoid taking alleys
|
||||||
|
@ -4,7 +4,7 @@ Feature: Bicycle - Handle cycling
|
|||||||
Background:
|
Background:
|
||||||
Given the profile "bicycle"
|
Given the profile "bicycle"
|
||||||
|
|
||||||
Scenario: Bicycle - Use a ferry route
|
Scenario: Bicycle - Use a movable bridge
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
a b c
|
a b c
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
Feature: Bicycle - Adds penalties to unsafe roads
|
Feature: Bicycle - Adds penalties to unsafe roads
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile file
|
Given the profile file "bicycle" initialized with
|
||||||
"""
|
"""
|
||||||
require 'bicycle'
|
profile.properties.weight_name = 'cyclability'
|
||||||
properties.weight_name = 'cyclability'
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Bike - Apply penalties to ways without cycleways
|
Scenario: Bike - Apply penalties to ways without cycleways
|
||||||
|
@ -7,10 +7,9 @@ Feature: Turn Penalties
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Bicycle - Turn penalties on cyclability
|
Scenario: Bicycle - Turn penalties on cyclability
|
||||||
Given the profile file
|
Given the profile file "bicycle" initialized with
|
||||||
"""
|
"""
|
||||||
require 'bicycle'
|
profile.properties.weight_name = 'cyclability'
|
||||||
properties.weight_name = 'cyclability'
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -1,18 +1,11 @@
|
|||||||
@routing @testbot @sidebias
|
@routing @testbot @sidebias
|
||||||
Feature: Testbot - side bias
|
Feature: Testbot - side bias
|
||||||
|
|
||||||
Background:
|
Scenario: Left-hand bias
|
||||||
Given the profile file
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
require 'testbot'
|
profile.left_hand_driving = true
|
||||||
properties.left_hand_driving = true
|
profile.turn_bias = 1/1.075
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Left hand bias
|
|
||||||
Given the profile file "car" extended with
|
|
||||||
"""
|
|
||||||
properties.left_hand_driving = true
|
|
||||||
profile.turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
|
||||||
"""
|
"""
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
@ -31,11 +24,11 @@ Feature: Testbot - side bias
|
|||||||
| d | a | bd,ab,ab | 24s +-1 |
|
| d | a | bd,ab,ab | 24s +-1 |
|
||||||
| d | c | bd,bc,bc | 27s +-1 |
|
| d | c | bd,bc,bc | 27s +-1 |
|
||||||
|
|
||||||
Scenario: Right hand bias
|
Scenario: Right-hand bias
|
||||||
Given the profile file "car" extended with
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
properties.left_hand_driving = false
|
profile.left_hand_driving = true
|
||||||
profile.turn_bias = properties.left_hand_driving and 1/1.075 or 1.075
|
profile.turn_bias = 1.075
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
@ -56,6 +49,11 @@ Feature: Testbot - side bias
|
|||||||
| d | c | bd,bc,bc | 24s +-1 |
|
| d | c | bd,bc,bc | 24s +-1 |
|
||||||
|
|
||||||
Scenario: Roundabout exit counting for left sided driving
|
Scenario: Roundabout exit counting for left sided driving
|
||||||
|
Given the profile file "testbot" initialized with
|
||||||
|
"""
|
||||||
|
profile.left_hand_driving = true
|
||||||
|
profile.turn_bias = 1/1.075
|
||||||
|
"""
|
||||||
And a grid size of 10 meters
|
And a grid size of 10 meters
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
@routing @car @weight
|
@routing @car @weight
|
||||||
Feature: Car - weights
|
Feature: Car - weights
|
||||||
|
|
||||||
Background: Use specific speeds
|
|
||||||
Given the profile "car"
|
|
||||||
|
|
||||||
Scenario: Only routes down service road when that's the destination
|
Scenario: Only routes down service road when that's the destination
|
||||||
Given the node map
|
Given the profile "car"
|
||||||
|
And the node map
|
||||||
"""
|
"""
|
||||||
a--b--c
|
a--b--c
|
||||||
|
|
|
|
||||||
@ -25,7 +23,8 @@ Feature: Car - weights
|
|||||||
| a | d | abc,bdf,bdf | 18 km/h | 71.7 |
|
| a | d | abc,bdf,bdf | 18 km/h | 71.7 |
|
||||||
|
|
||||||
Scenario: Does not jump off the highway to go down service road
|
Scenario: Does not jump off the highway to go down service road
|
||||||
Given the node map
|
Given the profile "car"
|
||||||
|
And the node map
|
||||||
"""
|
"""
|
||||||
a
|
a
|
||||||
|
|
|
|
||||||
@ -63,10 +62,9 @@ Feature: Car - weights
|
|||||||
| a | e | ab,be,be | 14 km/h | 112 |
|
| a | e | ab,be,be | 14 km/h | 112 |
|
||||||
|
|
||||||
Scenario: Distance weights
|
Scenario: Distance weights
|
||||||
Given the profile file "car" extended with
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
profile.properties.weight_name = 'distance'
|
||||||
properties.weight_name = 'distance'
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -582,9 +582,9 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
Scenario: No Lanes for Roundabouts, see #2626
|
Scenario: No Lanes for Roundabouts, see #2626
|
||||||
Given the profile file "car" extended with
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
properties.left_hand_driving = true
|
profile.left_hand_driving = true
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
|
@ -3,11 +3,10 @@ Feature: Basic Roundabout
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the profile file
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
require 'car'
|
profile.properties.left_hand_driving = true
|
||||||
properties.left_hand_driving = true
|
"""
|
||||||
"""
|
|
||||||
|
|
||||||
Scenario: Roundabout exit counting for left sided driving
|
Scenario: Roundabout exit counting for left sided driving
|
||||||
And a grid size of 10 meters
|
And a grid size of 10 meters
|
||||||
|
@ -33,15 +33,25 @@ Feature: osrm-contract command line option: edge-weight-updates-over-factor
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Logging using weigts as durations for non-duration profile
|
Scenario: Logging using weigts as durations for non-duration profile
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
properties.weight_name = 'steps'
|
local functions = require('testbot')
|
||||||
function way_function(way, result)
|
functions.setup_testbot = functions.setup
|
||||||
|
|
||||||
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.weight = 1
|
result.weight = 1
|
||||||
result.duration = 1
|
result.duration = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
@ -12,15 +12,20 @@ Feature: osrm-extract lua ways:get_nodes()
|
|||||||
And the data has been saved to disk
|
And the data has been saved to disk
|
||||||
|
|
||||||
Scenario: osrm-extract - Passing base file
|
Scenario: osrm-extract - Passing base file
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
function way_function(way, result)
|
functions = require('testbot')
|
||||||
|
|
||||||
|
function way_function(profile, way, result)
|
||||||
for _, node in ipairs(way:get_nodes()) do
|
for _, node in ipairs(way:get_nodes()) do
|
||||||
print('node id ' .. node:id())
|
print('node id ' .. node:id())
|
||||||
end
|
end
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.forward_speed = 1
|
result.forward_speed = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
functions.process_way = way_function
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
Then it should exit successfully
|
Then it should exit successfully
|
||||||
|
40
features/options/profiles/invalid_version.feature
Normal file
40
features/options/profiles/invalid_version.feature
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
Feature: Invalid profile API versions
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
|
Scenario: Profile API version too low
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = -1
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
ab
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I try to run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit with an error
|
||||||
|
And stderr should contain "Invalid profile API version"
|
||||||
|
|
||||||
|
Scenario: Profile API version too high
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 3
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
ab
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ab |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I try to run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit with an error
|
||||||
|
And stderr should contain "Invalid profile API version"
|
@ -1,84 +1,36 @@
|
|||||||
Feature: Profile API version 0
|
Feature: Profile API version 0
|
||||||
|
|
||||||
Background:
|
Scenario: Profile api version 0
|
||||||
Given a grid size of 100 meters
|
|
||||||
|
|
||||||
Scenario: Not-defined API version
|
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
function way_function(way, result)
|
api_version = 0
|
||||||
result.forward_mode = mode.driving
|
-- set profile properties
|
||||||
result.forward_speed = 1
|
properties.u_turn_penalty = 20
|
||||||
end
|
properties.traffic_signal_penalty = 2
|
||||||
"""
|
properties.max_speed_for_map_matching = 180/3.6
|
||||||
And the node map
|
properties.use_turn_restrictions = true
|
||||||
"""
|
properties.continue_straight_at_waypoint = true
|
||||||
ab
|
properties.left_hand_driving = false
|
||||||
"""
|
properties.weight_name = 'duration'
|
||||||
And the ways
|
function node_function (node, result)
|
||||||
| nodes |
|
print ('node_function ' .. node:id())
|
||||||
| ab |
|
end
|
||||||
And the data has been saved to disk
|
function way_function(way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
When I try to run "osrm-extract --profile {profile_file} {osm_file}"
|
result.forward_mode = mode.driving
|
||||||
Then it should exit successfully
|
result.backward_mode = mode.driving
|
||||||
And stderr should not contain "Invalid profile API version"
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
Scenario: Out-bound API version
|
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
||||||
Given the profile file
|
end
|
||||||
"""
|
function turn_function (angle)
|
||||||
api_version = 2
|
print('turn_function ' .. angle)
|
||||||
"""
|
return angle == 0 and 0 or 42
|
||||||
And the node map
|
end
|
||||||
"""
|
function segment_function (source, target, distance, weight)
|
||||||
ab
|
print ('segment_function ' .. source.lon .. ' ' .. source.lat)
|
||||||
"""
|
end
|
||||||
And the ways
|
"""
|
||||||
| nodes |
|
|
||||||
| ab |
|
|
||||||
And the data has been saved to disk
|
|
||||||
|
|
||||||
When I try to run "osrm-extract --profile {profile_file} {osm_file}"
|
|
||||||
Then it should exit with an error
|
|
||||||
And stderr should contain "Invalid profile API version"
|
|
||||||
|
|
||||||
|
|
||||||
Scenario: Basic profile function calls and property values
|
|
||||||
Given the profile file
|
|
||||||
"""
|
|
||||||
api_version = 0
|
|
||||||
|
|
||||||
-- set profile properties
|
|
||||||
properties.u_turn_penalty = 20
|
|
||||||
properties.traffic_signal_penalty = 2
|
|
||||||
properties.max_speed_for_map_matching = 180/3.6
|
|
||||||
properties.use_turn_restrictions = true
|
|
||||||
properties.continue_straight_at_waypoint = true
|
|
||||||
properties.left_hand_driving = false
|
|
||||||
properties.weight_name = 'duration'
|
|
||||||
|
|
||||||
function node_function (node, result)
|
|
||||||
print ('node_function ' .. node:id())
|
|
||||||
end
|
|
||||||
|
|
||||||
function way_function(way, result)
|
|
||||||
result.name = way:get_value_by_key('name')
|
|
||||||
result.forward_mode = mode.driving
|
|
||||||
result.backward_mode = mode.driving
|
|
||||||
result.forward_speed = 36
|
|
||||||
result.backward_speed = 36
|
|
||||||
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
function turn_function (angle)
|
|
||||||
print('turn_function ' .. angle)
|
|
||||||
return angle == 0 and 0 or 42
|
|
||||||
end
|
|
||||||
|
|
||||||
function segment_function (source, target, distance, weight)
|
|
||||||
print ('segment_function ' .. source.lon .. ' ' .. source.lat)
|
|
||||||
end
|
|
||||||
"""
|
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
a
|
a
|
||||||
@ -105,3 +57,60 @@ end
|
|||||||
| a | b | ac,cb,cb | 24.2s |
|
| a | b | ac,cb,cb | 24.2s |
|
||||||
| a | d | ac,cd,cd | 24.2s |
|
| a | d | ac,cd,cd | 24.2s |
|
||||||
| a | e | ac,ce | 20s |
|
| a | e | ac,ce | 20s |
|
||||||
|
|
||||||
|
Scenario: Profile version undefined, assume version 0
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
-- set profile properties
|
||||||
|
properties.u_turn_penalty = 20
|
||||||
|
properties.traffic_signal_penalty = 2
|
||||||
|
properties.max_speed_for_map_matching = 180/3.6
|
||||||
|
properties.use_turn_restrictions = true
|
||||||
|
properties.continue_straight_at_waypoint = true
|
||||||
|
properties.left_hand_driving = false
|
||||||
|
properties.weight_name = 'duration'
|
||||||
|
function node_function (node, result)
|
||||||
|
print ('node_function ' .. node:id())
|
||||||
|
end
|
||||||
|
function way_function(way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
|
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
function turn_function (angle)
|
||||||
|
print('turn_function ' .. angle)
|
||||||
|
return angle == 0 and 0 or 42
|
||||||
|
end
|
||||||
|
function segment_function (source, target, distance, weight)
|
||||||
|
print ('segment_function ' .. source.lon .. ' ' .. source.lat)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
b c d
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| cb |
|
||||||
|
| cd |
|
||||||
|
| ce |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "node_function"
|
||||||
|
And stdout should contain "way_function"
|
||||||
|
And stdout should contain "turn_function"
|
||||||
|
And stdout should contain "segment_function"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time |
|
||||||
|
| a | b | ac,cb,cb | 24.2s |
|
||||||
|
| a | d | ac,cd,cd | 24.2s |
|
||||||
|
| a | e | ac,ce | 20s |
|
@ -6,41 +6,42 @@ Feature: Profile API version 1
|
|||||||
Scenario: Basic profile function calls and property values
|
Scenario: Basic profile function calls and property values
|
||||||
Given the profile file
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
api_version = 1
|
||||||
|
|
||||||
-- set profile properties
|
-- set profile properties
|
||||||
properties.max_speed_for_map_matching = 180/3.6
|
properties.max_speed_for_map_matching = 180/3.6
|
||||||
properties.use_turn_restrictions = true
|
properties.use_turn_restrictions = true
|
||||||
properties.continue_straight_at_waypoint = true
|
properties.continue_straight_at_waypoint = true
|
||||||
properties.weight_name = 'test_version1'
|
properties.weight_name = 'test_version1'
|
||||||
properties.weight_precision = 2
|
properties.weight_precision = 2
|
||||||
|
|
||||||
assert(properties.max_turn_weight == 327.67)
|
assert(properties.max_turn_weight == 327.67)
|
||||||
|
|
||||||
function node_function (node, result)
|
function node_function (node, result)
|
||||||
print ('node_function ' .. node:id())
|
print(node, result)
|
||||||
end
|
print ('node_function ' .. node:id())
|
||||||
|
end
|
||||||
|
|
||||||
function way_function(way, result)
|
function way_function(way, result)
|
||||||
result.name = way:get_value_by_key('name')
|
result.name = way:get_value_by_key('name')
|
||||||
result.weight = 10
|
result.weight = 10
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.forward_speed = 36
|
result.forward_speed = 36
|
||||||
result.backward_speed = 36
|
result.backward_speed = 36
|
||||||
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function (turn)
|
function turn_function (turn)
|
||||||
print('turn_function', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
print('turn_function', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
||||||
turn.weight = turn.angle == 0 and 0 or 4.2
|
turn.weight = turn.angle == 0 and 0 or 4.2
|
||||||
turn.duration = turn.weight
|
turn.duration = turn.weight
|
||||||
end
|
end
|
||||||
|
|
||||||
function segment_function (segment)
|
function segment_function (segment)
|
||||||
print ('segment_function ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
print ('segment_function ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
||||||
end
|
end
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
a
|
a
|
||||||
@ -67,3 +68,165 @@ end
|
|||||||
| a | b | ac,cb,cb | 19.2s |
|
| a | b | ac,cb,cb | 19.2s |
|
||||||
| a | d | ac,cd,cd | 19.2s |
|
| a | d | ac,cd,cd | 19.2s |
|
||||||
| a | e | ac,ce | 20s |
|
| a | e | ac,ce | 20s |
|
||||||
|
|
||||||
|
Scenario: Basic profile function calls and property values
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
|
||||||
|
-- set profile properties
|
||||||
|
properties.max_speed_for_map_matching = 180/3.6
|
||||||
|
properties.use_turn_restrictions = true
|
||||||
|
properties.continue_straight_at_waypoint = true
|
||||||
|
properties.weight_name = 'test_version1'
|
||||||
|
properties.weight_precision = 2
|
||||||
|
|
||||||
|
assert(properties.max_turn_weight == 327.67)
|
||||||
|
|
||||||
|
function node_function (node, result)
|
||||||
|
print(node, result)
|
||||||
|
print ('node_function ' .. node:id())
|
||||||
|
end
|
||||||
|
|
||||||
|
function way_function(way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.weight = 10
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
|
print ('way_function ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function turn_function (turn)
|
||||||
|
print('turn_function', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
||||||
|
turn.weight = turn.angle == 0 and 0 or 4.2
|
||||||
|
turn.duration = turn.weight
|
||||||
|
end
|
||||||
|
|
||||||
|
function segment_function (segment)
|
||||||
|
print ('segment_function ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
bcd
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| cb |
|
||||||
|
| cd |
|
||||||
|
| ce |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "node_function"
|
||||||
|
And stdout should contain "way_function"
|
||||||
|
And stdout should contain "turn_function"
|
||||||
|
And stdout should contain "segment_function"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time |
|
||||||
|
| a | b | ac,cb,cb | 19.2s |
|
||||||
|
| a | d | ac,cd,cd | 19.2s |
|
||||||
|
| a | e | ac,ce | 20s |
|
||||||
|
|
||||||
|
Scenario: Weighting based on raster sources
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 1
|
||||||
|
|
||||||
|
properties.force_split_edges = true
|
||||||
|
|
||||||
|
function source_function()
|
||||||
|
local path = os.getenv('OSRM_RASTER_SOURCE')
|
||||||
|
if not path then
|
||||||
|
path = 'rastersource.asc'
|
||||||
|
end
|
||||||
|
raster_source = sources:load(
|
||||||
|
path,
|
||||||
|
0, -- lon_min
|
||||||
|
0.1, -- lon_max
|
||||||
|
0, -- lat_min
|
||||||
|
0.1, -- lat_max
|
||||||
|
5, -- nrows
|
||||||
|
4 -- ncols
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
function way_function (way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.forward_mode = mode.cycling
|
||||||
|
result.backward_mode = mode.cycling
|
||||||
|
result.forward_speed = 15
|
||||||
|
result.backward_speed = 15
|
||||||
|
end
|
||||||
|
|
||||||
|
function segment_function (segment)
|
||||||
|
local sourceData = sources:query(raster_source, segment.source.lon, segment.source.lat)
|
||||||
|
local targetData = sources:query(raster_source, segment.target.lon, segment.target.lat)
|
||||||
|
io.write('evaluating segment: ' .. sourceData.datum .. ' ' .. targetData.datum .. '\n')
|
||||||
|
local invalid = sourceData.invalid_data()
|
||||||
|
local scaled_weight = segment.weight
|
||||||
|
local scaled_duration = segment.duration
|
||||||
|
|
||||||
|
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
|
||||||
|
local slope = (targetData.datum - sourceData.datum) / segment.distance
|
||||||
|
scaled_weight = scaled_weight / (1.0 - (slope * 5.0))
|
||||||
|
scaled_duration = scaled_duration / (1.0 - (slope * 5.0))
|
||||||
|
io.write(' slope: ' .. slope .. '\n')
|
||||||
|
io.write(' was weight: ' .. segment.weight .. '\n')
|
||||||
|
io.write(' new weight: ' .. scaled_weight .. '\n')
|
||||||
|
io.write(' was duration: ' .. segment.duration .. '\n')
|
||||||
|
io.write(' new duration: ' .. scaled_duration .. '\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
segment.weight = scaled_weight
|
||||||
|
segment.duration = scaled_duration
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the node locations
|
||||||
|
| node | lat | lon |
|
||||||
|
| a | 0.1 | 0.1 |
|
||||||
|
| b | 0.05 | 0.1 |
|
||||||
|
| c | 0.0 | 0.1 |
|
||||||
|
| d | 0.05 | 0.03 |
|
||||||
|
| e | 0.05 | 0.066 |
|
||||||
|
| f | 0.075 | 0.066 |
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| ad | primary |
|
||||||
|
| bc | primary |
|
||||||
|
| dc | primary |
|
||||||
|
| de | primary |
|
||||||
|
| eb | primary |
|
||||||
|
| df | primary |
|
||||||
|
| fb | primary |
|
||||||
|
And the raster source
|
||||||
|
"""
|
||||||
|
0 0 0 0
|
||||||
|
0 0 0 250
|
||||||
|
0 0 250 500
|
||||||
|
0 0 0 250
|
||||||
|
0 0 0 0
|
||||||
|
"""
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | speed |
|
||||||
|
| a | b | ab,ab | 8 km/h |
|
||||||
|
| b | a | ab,ab | 22 km/h |
|
||||||
|
| a | c | ab,bc,bc | 12 km/h |
|
||||||
|
| b | c | bc,bc | 22 km/h |
|
||||||
|
| a | d | ad,ad | 15 km/h |
|
||||||
|
| d | c | dc,dc | 15 km/h |
|
||||||
|
| d | e | de,de | 10 km/h |
|
||||||
|
| e | b | eb,eb | 10 km/h |
|
||||||
|
| d | f | df,df | 15 km/h |
|
||||||
|
| f | b | fb,fb | 7 km/h |
|
||||||
|
| d | b | de,eb,eb | 10 km/h |
|
||||||
|
87
features/options/profiles/version2.feature
Normal file
87
features/options/profiles/version2.feature
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
Feature: Profile API version 2
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given a grid size of 100 meters
|
||||||
|
|
||||||
|
Scenario: Basic profile function calls and property values
|
||||||
|
Given the profile file
|
||||||
|
"""
|
||||||
|
api_version = 2
|
||||||
|
|
||||||
|
Set = require('lib/set')
|
||||||
|
Sequence = require('lib/sequence')
|
||||||
|
Handlers = require("lib/way_handlers")
|
||||||
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
|
limit = require("lib/maxspeed").limit
|
||||||
|
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
return {
|
||||||
|
properties = {
|
||||||
|
max_speed_for_map_matching = 180/3.6,
|
||||||
|
use_turn_restrictions = true,
|
||||||
|
continue_straight_at_waypoint = true,
|
||||||
|
weight_name = 'test_version2',
|
||||||
|
weight_precision = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_node(profile, node, result)
|
||||||
|
print ('process_node ' .. node:id())
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_way(profile, way, result)
|
||||||
|
result.name = way:get_value_by_key('name')
|
||||||
|
result.weight = 10
|
||||||
|
result.forward_mode = mode.driving
|
||||||
|
result.backward_mode = mode.driving
|
||||||
|
result.forward_speed = 36
|
||||||
|
result.backward_speed = 36
|
||||||
|
print ('process_way ' .. way:id() .. ' ' .. result.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_turn (profile, turn)
|
||||||
|
print('process_turn', turn.angle, turn.turn_type, turn.direction_modifier, turn.has_traffic_light)
|
||||||
|
turn.weight = turn.angle == 0 and 0 or 4.2
|
||||||
|
turn.duration = turn.weight
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_segment (profile, segment)
|
||||||
|
print ('process_segment ' .. segment.source.lon .. ' ' .. segment.source.lat)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_node = process_node,
|
||||||
|
process_way = process_way,
|
||||||
|
process_segment = process_segment,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
And the node map
|
||||||
|
"""
|
||||||
|
a
|
||||||
|
bcd
|
||||||
|
e
|
||||||
|
"""
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| cb |
|
||||||
|
| cd |
|
||||||
|
| ce |
|
||||||
|
And the data has been saved to disk
|
||||||
|
|
||||||
|
When I run "osrm-extract --profile {profile_file} {osm_file}"
|
||||||
|
Then it should exit successfully
|
||||||
|
And stdout should contain "process_node"
|
||||||
|
And stdout should contain "process_way"
|
||||||
|
And stdout should contain "process_turn"
|
||||||
|
And stdout should contain "process_segment"
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | time |
|
||||||
|
| a | b | ac,cb,cb | 19.2s |
|
||||||
|
| a | d | ac,cd,cd | 19.2s |
|
||||||
|
| a | e | ac,ce | 20s |
|
@ -248,17 +248,20 @@ module.exports = function () {
|
|||||||
fs.writeFile(this.penaltiesCacheFile, data, callback);
|
fs.writeFile(this.penaltiesCacheFile, data, callback);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Given(/^the profile file(?: "([^"]*)" extended with)?$/, (profile, data, callback) => {
|
this.Given(/^the profile file(?: "([^"]*)" initialized with)?$/, (profile, data, callback) => {
|
||||||
const lua_profiles_path = this.PROFILES_PATH.split(path.sep).join('/');
|
const lua_profiles_path = this.PROFILES_PATH.split(path.sep).join('/');
|
||||||
let text = 'package.path = "' + lua_profiles_path + '/?.lua;" .. package.path\n';
|
let text = 'package.path = "' + lua_profiles_path + '/?.lua;" .. package.path\n';
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
text += data + '\n';
|
text += data + '\n';
|
||||||
} else {
|
} else {
|
||||||
text += 'local f = assert(io.open("' + lua_profiles_path + '/' + profile + '.lua", "r"))\n';
|
text += 'local functions = require("' + profile + '")\n';
|
||||||
text += 'local s = f:read("*all") .. [[\n' + data + '\n]]\n';
|
text += 'functions.setup_parent = functions.setup\n';
|
||||||
text += 'f:close()\n';
|
text += 'functions.setup = function()\n';
|
||||||
text += 'local m = assert(loadstring and loadstring(s) or load(s))\n';
|
text += 'local profile = functions.setup_parent()\n';
|
||||||
text += 'm()\n';
|
text += data + '\n';
|
||||||
|
text += 'return profile\n';
|
||||||
|
text += 'end\n';
|
||||||
|
text += 'return functions\n';
|
||||||
}
|
}
|
||||||
this.profileFile = this.profileCacheFile;
|
this.profileFile = this.profileCacheFile;
|
||||||
// TODO: Don't overwrite if it exists
|
// TODO: Don't overwrite if it exists
|
||||||
|
@ -221,15 +221,24 @@ Feature: Basic Distance Matrix
|
|||||||
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
|
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix based on segment durations
|
Scenario: Testbot - Travel time matrix based on segment durations
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
function segment_function (segment)
|
functions.setup = function()
|
||||||
|
local profile = functions.setup_testbot()
|
||||||
|
profile.traffic_signal_penalty = 0
|
||||||
|
profile.u_turn_penalty = 0
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
segment.weight = 2
|
segment.weight = 2
|
||||||
segment.duration = 11
|
segment.duration = 11
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the node map
|
And the node map
|
||||||
@ -254,16 +263,25 @@ Feature: Basic Distance Matrix
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Testbot - Travel time matrix for alternative loop paths
|
Scenario: Testbot - Travel time matrix for alternative loop paths
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_precision = 3
|
functions.setup = function()
|
||||||
function segment_function (segment)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.traffic_signal_penalty = 0
|
||||||
|
profile.u_turn_penalty = 0
|
||||||
|
profile.weight_precision = 3
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
segment.weight = 777
|
segment.weight = 777
|
||||||
segment.duration = 3
|
segment.duration = 3
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
|
@ -1,29 +1,27 @@
|
|||||||
@routing @testbot @nil
|
@routing @testbot @nil
|
||||||
Feature: Testbot - Check assigning nil values
|
Feature: Testbot - Check assigning nil values
|
||||||
Scenario: Assign nil values to all way strings
|
Scenario: Assign nil values to all way strings
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
function way_function (way, result)
|
functions = require('testbot')
|
||||||
result.name = "name"
|
|
||||||
result.ref = "ref"
|
|
||||||
result.destinations = "destinations"
|
|
||||||
result.pronunciation = "pronunciation"
|
|
||||||
result.turn_lanes_forward = "turn_lanes_forward"
|
|
||||||
result.turn_lanes_backward = "turn_lanes_backward"
|
|
||||||
|
|
||||||
result.name = nil
|
function way_function(profile, way, result)
|
||||||
result.ref = nil
|
result.name = nil
|
||||||
result.destinations = nil
|
result.ref = nil
|
||||||
result.exits = nil
|
result.destinations = nil
|
||||||
result.pronunciation = nil
|
result.exits = nil
|
||||||
result.turn_lanes_forward = nil
|
result.pronunciation = nil
|
||||||
result.turn_lanes_backward = nil
|
result.turn_lanes_forward = nil
|
||||||
|
result.turn_lanes_backward = nil
|
||||||
|
|
||||||
result.forward_speed = 10
|
result.forward_speed = 10
|
||||||
result.backward_speed = 10
|
result.backward_speed = 10
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
end
|
end
|
||||||
|
|
||||||
|
functions.process_way = way_function
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
|
@ -39,13 +39,17 @@ Feature: Projection to nearest point on road
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Projection results negative duration
|
Scenario: Projection results negative duration
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
functions = require('testbot')
|
||||||
function segment_function (segment)
|
|
||||||
|
function segment_function(profile, segment)
|
||||||
segment.weight = 5.5
|
segment.weight = 5.5
|
||||||
segment.duration = 2.8
|
segment.duration = 2.8
|
||||||
end
|
end
|
||||||
|
|
||||||
|
functions.process_segment = segment_function
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node locations
|
Given the node locations
|
||||||
|
@ -84,12 +84,11 @@ Feature: Traffic - speeds
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Weighting based on speed file weights, ETA based on file durations
|
Scenario: Weighting based on speed file weights, ETA based on file durations
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file "testbot" initialized with
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
profile.properties.traffic_signal_penalty = 0
|
||||||
properties.traffic_signal_penalty = 0
|
profile.properties.u_turn_penalty = 0
|
||||||
properties.u_turn_penalty = 0
|
profile.properties.weight_precision = 2
|
||||||
properties.weight_precision = 2
|
|
||||||
"""
|
"""
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
@ -8,12 +8,11 @@ Feature: Traffic - speeds edge cases
|
|||||||
And the ways
|
And the ways
|
||||||
| nodes | highway |
|
| nodes | highway |
|
||||||
| ab | primary |
|
| ab | primary |
|
||||||
And the profile file "testbot" extended with
|
And the profile file "testbot" initialized with
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
profile.properties.traffic_signal_penalty = 0
|
||||||
properties.traffic_signal_penalty = 0
|
profile.properties.u_turn_penalty = 0
|
||||||
properties.u_turn_penalty = 0
|
profile.properties.weight_precision = 2
|
||||||
properties.weight_precision = 2
|
|
||||||
"""
|
"""
|
||||||
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
And the contract extra arguments "--segment-speed-file {speeds_file}"
|
||||||
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
And the customize extra arguments "--segment-speed-file {speeds_file}"
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
@routing @testbot @turn_penalty
|
@routing @testbot @turn_penalty
|
||||||
Feature: Turn Penalties
|
Feature: Turn Penalties
|
||||||
|
|
||||||
Background:
|
Scenario: Turns should incur a delay that depend on the angle
|
||||||
Given the profile "turnbot"
|
Given the profile "turnbot"
|
||||||
Given a grid size of 200 meters
|
Given a grid size of 200 meters
|
||||||
|
|
||||||
|
|
||||||
Scenario: Turns should incur a delay that depend on the angle
|
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
c d e
|
c d e
|
||||||
|
@ -60,18 +60,27 @@ Feature: Weight tests
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property
|
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
function way_function(way, result)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.forward_speed = 42
|
result.forward_speed = 42
|
||||||
result.backward_speed = 42
|
result.backward_speed = 42
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
"""
|
"""
|
||||||
@ -87,18 +96,27 @@ Feature: Weight tests
|
|||||||
And it should exit with an error
|
And it should exit with an error
|
||||||
|
|
||||||
Scenario: Step weights -- way_function: second way wins
|
Scenario: Step weights -- way_function: second way wins
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
function way_function(way, result)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.duration = 42
|
result.duration = 42
|
||||||
result.weight = 35
|
result.weight = 35
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -119,19 +137,28 @@ Feature: Weight tests
|
|||||||
| h,a | , | 140m +-1 | 35,0 | 42s,0s |
|
| h,a | , | 140m +-1 | 35,0 | 42s,0s |
|
||||||
|
|
||||||
Scenario: Step weights -- way_function: higher weight_per_meter is preferred
|
Scenario: Step weights -- way_function: higher weight_per_meter is preferred
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
function way_function(way, result)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.duration = 42
|
result.duration = 42
|
||||||
result.forward_rate = 1
|
result.forward_rate = 1
|
||||||
result.backward_rate = 0.5
|
result.backward_rate = 0.5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -155,22 +182,32 @@ Feature: Weight tests
|
|||||||
| h,f | , | 40m | 80,0 | 12s,0s |
|
| h,f | , | 40m | 80,0 | 12s,0s |
|
||||||
|
|
||||||
Scenario: Step weights -- segment_function
|
Scenario: Step weights -- segment_function
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
function way_function(way, result)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.weight = 42
|
result.weight = 42
|
||||||
result.duration = 3
|
result.duration = 3
|
||||||
end
|
end
|
||||||
function segment_function (segment)
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
segment.weight = 1
|
segment.weight = 1
|
||||||
segment.duration = 11
|
segment.duration = 11
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -195,28 +232,39 @@ Feature: Weight tests
|
|||||||
|
|
||||||
|
|
||||||
Scenario: Step weights -- segment_function and turn_function with weight precision
|
Scenario: Step weights -- segment_function and turn_function with weight precision
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
properties.weight_precision = 3
|
local profile = functions.setup_testbot()
|
||||||
function way_function(way, result)
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
profile.properties.weight_precision = 3
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.weight = 42
|
result.weight = 42
|
||||||
result.duration = 3
|
result.duration = 3
|
||||||
end
|
end
|
||||||
function segment_function (segment)
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
segment.weight = 1.11
|
segment.weight = 1.11
|
||||||
segment.duration = 100
|
segment.duration = 100
|
||||||
end
|
end
|
||||||
function turn_function (turn)
|
|
||||||
|
functions.process_turn = function(profile, turn)
|
||||||
print (turn.angle)
|
print (turn.angle)
|
||||||
turn.weight = 2 + turn.angle / 100
|
turn.weight = 2 + turn.angle / 100
|
||||||
turn.duration = turn.angle
|
turn.duration = turn.angle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -241,22 +289,32 @@ Feature: Weight tests
|
|||||||
|
|
||||||
@traffic @speed
|
@traffic @speed
|
||||||
Scenario: Step weights -- segment_function with speed and turn updates
|
Scenario: Step weights -- segment_function with speed and turn updates
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
local functions = require('testbot')
|
||||||
properties.traffic_signal_penalty = 0
|
functions.setup_testbot = functions.setup
|
||||||
properties.u_turn_penalty = 0
|
|
||||||
properties.weight_name = 'steps'
|
functions.setup = function()
|
||||||
function way_function(way, result)
|
local profile = functions.setup_testbot()
|
||||||
|
profile.properties.traffic_signal_penalty = 0
|
||||||
|
profile.properties.u_turn_penalty = 0
|
||||||
|
profile.properties.weight_name = 'steps'
|
||||||
|
return profile
|
||||||
|
end
|
||||||
|
|
||||||
|
functions.process_way = function(profile, way, result)
|
||||||
result.forward_mode = mode.driving
|
result.forward_mode = mode.driving
|
||||||
result.backward_mode = mode.driving
|
result.backward_mode = mode.driving
|
||||||
result.weight = 42
|
result.weight = 42
|
||||||
result.duration = 3
|
result.duration = 3
|
||||||
end
|
end
|
||||||
function segment_function (segment)
|
|
||||||
|
functions.process_segment = function(profile, segment)
|
||||||
segment.weight = 10
|
segment.weight = 10
|
||||||
segment.duration = 11
|
segment.duration = 11
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the node map
|
And the node map
|
||||||
@ -289,10 +347,9 @@ Feature: Weight tests
|
|||||||
|
|
||||||
@traffic @speed
|
@traffic @speed
|
||||||
Scenario: Step weights -- segment_function with speed and turn updates with fallback to durations
|
Scenario: Step weights -- segment_function with speed and turn updates with fallback to durations
|
||||||
Given the profile file "testbot" extended with
|
Given the profile file "testbot" initialized with
|
||||||
"""
|
"""
|
||||||
api_version = 1
|
profile.properties.weight_precision = 3
|
||||||
properties.weight_precision = 3
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
And the node map
|
And the node map
|
||||||
|
@ -125,10 +125,10 @@ class RasterSource
|
|||||||
int _ymax);
|
int _ymax);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SourceContainer
|
class RasterContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SourceContainer() = default;
|
RasterContainer() = default;
|
||||||
|
|
||||||
int LoadRasterSource(const std::string &path_string,
|
int LoadRasterSource(const std::string &path_string,
|
||||||
double xmin,
|
double xmin,
|
||||||
|
@ -54,7 +54,6 @@ class ScriptingEnvironment
|
|||||||
|
|
||||||
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
virtual std::vector<std::string> GetNameSuffixList() = 0;
|
||||||
virtual std::vector<std::string> GetRestrictions() = 0;
|
virtual std::vector<std::string> GetRestrictions() = 0;
|
||||||
virtual void SetupSources() = 0;
|
|
||||||
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
|
||||||
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ struct LuaScriptingContext final
|
|||||||
void ProcessWay(const osmium::Way &, ExtractionWay &result);
|
void ProcessWay(const osmium::Way &, ExtractionWay &result);
|
||||||
|
|
||||||
ProfileProperties properties;
|
ProfileProperties properties;
|
||||||
SourceContainer sources;
|
RasterContainer raster_sources;
|
||||||
sol::state state;
|
sol::state state;
|
||||||
|
|
||||||
bool has_turn_penalty_function;
|
bool has_turn_penalty_function;
|
||||||
@ -37,6 +37,7 @@ struct LuaScriptingContext final
|
|||||||
sol::function segment_function;
|
sol::function segment_function;
|
||||||
|
|
||||||
int api_version;
|
int api_version;
|
||||||
|
sol::table profile_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +51,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
|
||||||
static const constexpr int SUPPORTED_MAX_API_VERSION = 1;
|
static const constexpr int SUPPORTED_MAX_API_VERSION = 2;
|
||||||
|
|
||||||
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
explicit Sol2ScriptingEnvironment(const std::string &file_name);
|
||||||
~Sol2ScriptingEnvironment() override = default;
|
~Sol2ScriptingEnvironment() override = default;
|
||||||
@ -59,9 +60,10 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
|||||||
|
|
||||||
LuaScriptingContext &GetSol2Context();
|
LuaScriptingContext &GetSol2Context();
|
||||||
|
|
||||||
|
std::vector<std::string> GetStringListFromTable(const std::string &table_name);
|
||||||
|
std::vector<std::string> GetStringListFromFunction(const std::string &function_name);
|
||||||
std::vector<std::string> GetNameSuffixList() override;
|
std::vector<std::string> GetNameSuffixList() override;
|
||||||
std::vector<std::string> GetRestrictions() override;
|
std::vector<std::string> GetRestrictions() override;
|
||||||
void SetupSources() override;
|
|
||||||
void ProcessTurn(ExtractionTurn &turn) override;
|
void ProcessTurn(ExtractionTurn &turn) override;
|
||||||
void ProcessSegment(ExtractionSegment &segment) override;
|
void ProcessSegment(ExtractionSegment &segment) override;
|
||||||
|
|
||||||
|
@ -1,199 +1,196 @@
|
|||||||
api_version = 1
|
|
||||||
|
|
||||||
-- Bicycle profile
|
-- Bicycle profile
|
||||||
local find_access_tag = require("lib/access").find_access_tag
|
|
||||||
local Set = require('lib/set')
|
|
||||||
local Sequence = require('lib/sequence')
|
|
||||||
local Handlers = require("lib/handlers")
|
|
||||||
local next = next -- bind to local for speed
|
|
||||||
local limit = require("lib/maxspeed").limit
|
|
||||||
|
|
||||||
-- these need to be global because they are accesed externaly
|
api_version = 2
|
||||||
properties.max_speed_for_map_matching = 110/3.6 -- kmph -> m/s
|
|
||||||
properties.use_turn_restrictions = false
|
|
||||||
properties.continue_straight_at_waypoint = false
|
|
||||||
properties.weight_name = 'duration'
|
|
||||||
--properties.weight_name = 'cyclability'
|
|
||||||
|
|
||||||
-- Set to true if you need to call the node_function for every node.
|
Set = require('lib/set')
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
Sequence = require('lib/sequence')
|
||||||
-- (which slow down pre-processing).
|
Handlers = require("lib/way_handlers")
|
||||||
properties.call_tagless_node_function = false
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
|
limit = require("lib/maxspeed").limit
|
||||||
|
|
||||||
|
function setup()
|
||||||
|
local default_speed = 15
|
||||||
|
local walking_speed = 6
|
||||||
|
|
||||||
local default_speed = 15
|
return {
|
||||||
local walking_speed = 6
|
properties = {
|
||||||
|
u_turn_penalty = 20,
|
||||||
|
traffic_light_penalty = 2,
|
||||||
|
--weight_name = 'cyclability',
|
||||||
|
weight_name = 'duration',
|
||||||
|
process_call_tagless_node = false,
|
||||||
|
max_speed_for_map_matching = 110/3.6, -- kmph -> m/s
|
||||||
|
use_turn_restrictions = false,
|
||||||
|
continue_straight_at_waypoint = false
|
||||||
|
},
|
||||||
|
|
||||||
local profile = {
|
default_mode = mode.cycling,
|
||||||
default_mode = mode.cycling,
|
default_speed = default_speed,
|
||||||
default_speed = 15,
|
walking_speed = walking_speed,
|
||||||
oneway_handling = true,
|
oneway_handling = true,
|
||||||
traffic_light_penalty = 2,
|
turn_penalty = 6,
|
||||||
u_turn_penalty = 20,
|
turn_bias = 1.4,
|
||||||
turn_penalty = 6,
|
use_public_transport = true,
|
||||||
turn_bias = 1.4,
|
|
||||||
use_public_transport = true,
|
|
||||||
|
|
||||||
allowed_start_modes = Set {
|
allowed_start_modes = Set {
|
||||||
mode.cycling,
|
mode.cycling,
|
||||||
mode.pushing_bike
|
mode.pushing_bike
|
||||||
},
|
},
|
||||||
|
|
||||||
barrier_whitelist = Set {
|
barrier_whitelist = Set {
|
||||||
'sump_buster',
|
'sump_buster',
|
||||||
'bus_trap',
|
'bus_trap',
|
||||||
'cycle_barrier',
|
'cycle_barrier',
|
||||||
'bollard',
|
'bollard',
|
||||||
'entrance',
|
'entrance',
|
||||||
'cattle_grid',
|
'cattle_grid',
|
||||||
'border_control',
|
'border_control',
|
||||||
'toll_booth',
|
'toll_booth',
|
||||||
'sally_port',
|
'sally_port',
|
||||||
'gate',
|
'gate',
|
||||||
'no',
|
'no',
|
||||||
'block'
|
'block'
|
||||||
},
|
},
|
||||||
|
|
||||||
access_tag_whitelist = Set {
|
access_tag_whitelist = Set {
|
||||||
'yes',
|
'yes',
|
||||||
'permissive',
|
'permissive',
|
||||||
'designated'
|
'designated'
|
||||||
},
|
},
|
||||||
|
|
||||||
access_tag_blacklist = Set {
|
access_tag_blacklist = Set {
|
||||||
'no',
|
'no',
|
||||||
'private',
|
'private',
|
||||||
'agricultural',
|
'agricultural',
|
||||||
'forestry',
|
'forestry',
|
||||||
'delivery'
|
'delivery'
|
||||||
},
|
},
|
||||||
|
|
||||||
restricted_access_tag_list = Set { },
|
restricted_access_tag_list = Set { },
|
||||||
|
|
||||||
restricted_highway_whitelist = Set { },
|
restricted_highway_whitelist = Set { },
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
access_tags_hierarchy = Sequence {
|
||||||
'bicycle',
|
'bicycle',
|
||||||
'vehicle',
|
'vehicle',
|
||||||
'access'
|
'access'
|
||||||
},
|
},
|
||||||
|
|
||||||
restrictions = Set {
|
restrictions = Set {
|
||||||
'bicycle'
|
'bicycle'
|
||||||
},
|
},
|
||||||
|
|
||||||
cycleway_tags = Set {
|
cycleway_tags = Set {
|
||||||
'track',
|
'track',
|
||||||
'lane',
|
'lane',
|
||||||
'opposite',
|
'opposite',
|
||||||
'opposite_lane',
|
'opposite_lane',
|
||||||
'opposite_track',
|
'opposite_track',
|
||||||
'share_busway',
|
'share_busway',
|
||||||
'sharrow',
|
'sharrow',
|
||||||
'shared',
|
'shared',
|
||||||
'shared_lane'
|
'shared_lane'
|
||||||
},
|
},
|
||||||
|
|
||||||
-- reduce the driving speed by 30% for unsafe roads
|
-- reduce the driving speed by 30% for unsafe roads
|
||||||
-- only used for cyclability metric
|
-- only used for cyclability metric
|
||||||
unsafe_highway_list = {
|
unsafe_highway_list = {
|
||||||
primary = 0.7,
|
primary = 0.7,
|
||||||
secondary = 0.75,
|
secondary = 0.75,
|
||||||
tertiary = 0.8,
|
tertiary = 0.8,
|
||||||
primary_link = 0.7,
|
primary_link = 0.7,
|
||||||
secondary_link = 0.75,
|
secondary_link = 0.75,
|
||||||
tertiary_link = 0.8,
|
tertiary_link = 0.8,
|
||||||
},
|
},
|
||||||
|
|
||||||
service_penalties = {
|
service_penalties = {
|
||||||
alley = 0.5,
|
alley = 0.5,
|
||||||
},
|
},
|
||||||
|
|
||||||
bicycle_speeds = {
|
bicycle_speeds = {
|
||||||
cycleway = default_speed,
|
cycleway = default_speed,
|
||||||
primary = default_speed,
|
primary = default_speed,
|
||||||
primary_link = default_speed,
|
primary_link = default_speed,
|
||||||
secondary = default_speed,
|
secondary = default_speed,
|
||||||
secondary_link = default_speed,
|
secondary_link = default_speed,
|
||||||
tertiary = default_speed,
|
tertiary = default_speed,
|
||||||
tertiary_link = default_speed,
|
tertiary_link = default_speed,
|
||||||
residential = default_speed,
|
residential = default_speed,
|
||||||
unclassified = default_speed,
|
unclassified = default_speed,
|
||||||
living_street = default_speed,
|
living_street = default_speed,
|
||||||
road = default_speed,
|
road = default_speed,
|
||||||
service = default_speed,
|
service = default_speed,
|
||||||
track = 12,
|
track = 12,
|
||||||
path = 12
|
path = 12
|
||||||
},
|
},
|
||||||
|
|
||||||
pedestrian_speeds = {
|
pedestrian_speeds = {
|
||||||
footway = walking_speed,
|
footway = walking_speed,
|
||||||
pedestrian = walking_speed,
|
pedestrian = walking_speed,
|
||||||
steps = 2
|
steps = 2
|
||||||
},
|
},
|
||||||
|
|
||||||
railway_speeds = {
|
railway_speeds = {
|
||||||
train = 10,
|
train = 10,
|
||||||
railway = 10,
|
railway = 10,
|
||||||
subway = 10,
|
subway = 10,
|
||||||
light_rail = 10,
|
light_rail = 10,
|
||||||
monorail = 10,
|
monorail = 10,
|
||||||
tram = 10
|
tram = 10
|
||||||
},
|
},
|
||||||
|
|
||||||
platform_speeds = {
|
platform_speeds = {
|
||||||
platform = walking_speed
|
platform = walking_speed
|
||||||
},
|
},
|
||||||
|
|
||||||
amenity_speeds = {
|
amenity_speeds = {
|
||||||
parking = 10,
|
parking = 10,
|
||||||
parking_entrance = 10
|
parking_entrance = 10
|
||||||
},
|
},
|
||||||
|
|
||||||
man_made_speeds = {
|
man_made_speeds = {
|
||||||
pier = walking_speed
|
pier = walking_speed
|
||||||
},
|
},
|
||||||
|
|
||||||
route_speeds = {
|
route_speeds = {
|
||||||
ferry = 5
|
ferry = 5
|
||||||
},
|
},
|
||||||
|
|
||||||
bridge_speeds = {
|
bridge_speeds = {
|
||||||
movable = 5
|
movable = 5
|
||||||
},
|
},
|
||||||
|
|
||||||
surface_speeds = {
|
surface_speeds = {
|
||||||
asphalt = default_speed,
|
asphalt = default_speed,
|
||||||
["cobblestone:flattened"] = 10,
|
["cobblestone:flattened"] = 10,
|
||||||
paving_stones = 10,
|
paving_stones = 10,
|
||||||
compacted = 10,
|
compacted = 10,
|
||||||
cobblestone = 6,
|
cobblestone = 6,
|
||||||
unpaved = 6,
|
unpaved = 6,
|
||||||
fine_gravel = 6,
|
fine_gravel = 6,
|
||||||
gravel = 6,
|
gravel = 6,
|
||||||
pebblestone = 6,
|
pebblestone = 6,
|
||||||
ground = 6,
|
ground = 6,
|
||||||
dirt = 6,
|
dirt = 6,
|
||||||
earth = 6,
|
earth = 6,
|
||||||
grass = 6,
|
grass = 6,
|
||||||
mud = 3,
|
mud = 3,
|
||||||
sand = 3,
|
sand = 3,
|
||||||
sett = 10
|
sett = 10
|
||||||
},
|
},
|
||||||
|
|
||||||
tracktype_speeds = {
|
tracktype_speeds = {
|
||||||
},
|
},
|
||||||
|
|
||||||
smoothness_speeds = {
|
smoothness_speeds = {
|
||||||
},
|
},
|
||||||
|
|
||||||
avoid = Set {
|
avoid = Set {
|
||||||
'impassable',
|
'impassable',
|
||||||
'construction',
|
'construction'
|
||||||
'proposed'
|
}
|
||||||
}
|
}
|
||||||
}
|
end
|
||||||
|
|
||||||
|
|
||||||
local function parse_maxspeed(source)
|
local function parse_maxspeed(source)
|
||||||
if not source then
|
if not source then
|
||||||
@ -209,13 +206,7 @@ local function parse_maxspeed(source)
|
|||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
|
||||||
function get_restrictions(vector)
|
function process_node (profile, node, result)
|
||||||
for i,v in ipairs(profile.restrictions) do
|
|
||||||
vector:Add(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function node_function (node, result)
|
|
||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
local highway = node:get_value_by_key("highway")
|
local highway = node:get_value_by_key("highway")
|
||||||
local is_crossing = highway and highway == "crossing"
|
local is_crossing = highway and highway == "crossing"
|
||||||
@ -243,41 +234,8 @@ function node_function (node, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function way_function (way, result)
|
function handle_bicycle_tags(profile,way,result,data)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- initial routability check, filters out buildings, boundaries, etc
|
||||||
-- affects processing times significantly, because all ways
|
|
||||||
-- have to be checked.
|
|
||||||
-- to increase performance, prefetching and intial tag check
|
|
||||||
-- is done in directly instead of via a handler.
|
|
||||||
|
|
||||||
-- in general we should try to abort as soon as
|
|
||||||
-- possible if the way is not routable, to avoid doing
|
|
||||||
-- unnecessary work. this implies we should check things that
|
|
||||||
-- commonly forbids access early, and handle edge cases later.
|
|
||||||
|
|
||||||
-- data table for storing intermediate values during processing
|
|
||||||
|
|
||||||
local data = {
|
|
||||||
-- prefetch tags
|
|
||||||
highway = way:get_value_by_key('highway'),
|
|
||||||
}
|
|
||||||
|
|
||||||
local handlers = Sequence {
|
|
||||||
-- set the default mode for this profile. if can be changed later
|
|
||||||
-- in case it turns we're e.g. on a ferry
|
|
||||||
'handle_default_mode',
|
|
||||||
|
|
||||||
-- check various tags that could indicate that the way is not
|
|
||||||
-- routable. this includes things like status=impassable,
|
|
||||||
-- toll=yes and oneway=reversible
|
|
||||||
'handle_blocked_ways',
|
|
||||||
}
|
|
||||||
|
|
||||||
if Handlers.run(handlers,way,result,data,profile) == false then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- initial routability check, filters out buildings, boundaries, etc
|
|
||||||
local route = way:get_value_by_key("route")
|
local route = way:get_value_by_key("route")
|
||||||
local man_made = way:get_value_by_key("man_made")
|
local man_made = way:get_value_by_key("man_made")
|
||||||
local railway = way:get_value_by_key("railway")
|
local railway = way:get_value_by_key("railway")
|
||||||
@ -293,13 +251,13 @@ function way_function (way, result)
|
|||||||
(not public_transport or public_transport=='') and
|
(not public_transport or public_transport=='') and
|
||||||
(not bridge or bridge=='')
|
(not bridge or bridge=='')
|
||||||
then
|
then
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- access
|
-- access
|
||||||
local access = find_access_tag(way, profile.access_tags_hierarchy)
|
local access = find_access_tag(way, profile.access_tags_hierarchy)
|
||||||
if access and profile.access_tag_blacklist[access] then
|
if access and profile.access_tag_blacklist[access] then
|
||||||
return
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- other tags
|
-- other tags
|
||||||
@ -371,8 +329,8 @@ function way_function (way, result)
|
|||||||
way_type_allows_pushing = true
|
way_type_allows_pushing = true
|
||||||
elseif access and profile.access_tag_whitelist[access] then
|
elseif access and profile.access_tag_whitelist[access] then
|
||||||
-- unknown way, but valid access tag
|
-- unknown way, but valid access tag
|
||||||
result.forward_speed = default_speed
|
result.forward_speed = profile.default_speed
|
||||||
result.backward_speed = default_speed
|
result.backward_speed = profile.default_speed
|
||||||
way_type_allows_pushing = true
|
way_type_allows_pushing = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -447,18 +405,18 @@ function way_function (way, result)
|
|||||||
push_backward_speed = profile.man_made_speeds[man_made]
|
push_backward_speed = profile.man_made_speeds[man_made]
|
||||||
else
|
else
|
||||||
if foot == 'yes' then
|
if foot == 'yes' then
|
||||||
push_forward_speed = walking_speed
|
push_forward_speed = profile.walking_speed
|
||||||
if not implied_oneway then
|
if not implied_oneway then
|
||||||
push_backward_speed = walking_speed
|
push_backward_speed = profile.walking_speed
|
||||||
end
|
end
|
||||||
elseif foot_forward == 'yes' then
|
elseif foot_forward == 'yes' then
|
||||||
push_forward_speed = walking_speed
|
push_forward_speed = profile.walking_speed
|
||||||
elseif foot_backward == 'yes' then
|
elseif foot_backward == 'yes' then
|
||||||
push_backward_speed = walking_speed
|
push_backward_speed = profile.walking_speed
|
||||||
elseif way_type_allows_pushing then
|
elseif way_type_allows_pushing then
|
||||||
push_forward_speed = walking_speed
|
push_forward_speed = profile.walking_speed
|
||||||
if not implied_oneway then
|
if not implied_oneway then
|
||||||
push_backward_speed = walking_speed
|
push_backward_speed = profile.walking_speed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -481,8 +439,8 @@ function way_function (way, result)
|
|||||||
if bicycle == "dismount" then
|
if bicycle == "dismount" then
|
||||||
result.forward_mode = mode.pushing_bike
|
result.forward_mode = mode.pushing_bike
|
||||||
result.backward_mode = mode.pushing_bike
|
result.backward_mode = mode.pushing_bike
|
||||||
result.forward_speed = walking_speed
|
result.forward_speed = profile.walking_speed
|
||||||
result.backward_speed = walking_speed
|
result.backward_speed = profile.walking_speed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -502,7 +460,7 @@ function way_function (way, result)
|
|||||||
|
|
||||||
|
|
||||||
-- convert duration into cyclability
|
-- convert duration into cyclability
|
||||||
if properties.weight_name == 'cyclability' then
|
if profile.properties.weight_name == 'cyclability' then
|
||||||
local safety_penalty = profile.unsafe_highway_list[data.highway] or 1.
|
local safety_penalty = profile.unsafe_highway_list[data.highway] or 1.
|
||||||
local is_unsafe = safety_penalty < 1
|
local is_unsafe = safety_penalty < 1
|
||||||
local forward_is_unsafe = is_unsafe and not has_cycleway_right
|
local forward_is_unsafe = is_unsafe and not has_cycleway_right
|
||||||
@ -534,29 +492,59 @@ function way_function (way, result)
|
|||||||
result.weight = result.duration / forward_penalty
|
result.weight = result.duration / forward_penalty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
function process_way (profile, way, result)
|
||||||
|
-- the initial filtering of ways based on presence of tags
|
||||||
|
-- affects processing times significantly, because all ways
|
||||||
|
-- have to be checked.
|
||||||
|
-- to increase performance, prefetching and initial tag check
|
||||||
|
-- is done directly instead of via a handler.
|
||||||
|
|
||||||
local handlers = Sequence {
|
-- in general we should try to abort as soon as
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- possible if the way is not routable, to avoid doing
|
||||||
'handle_surface',
|
-- unnecessary work. this implies we should check things that
|
||||||
|
-- commonly forbids access early, and handle edge cases later.
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- data table for storing intermediate values during processing
|
||||||
'handle_classification',
|
|
||||||
|
|
||||||
-- handle various other flags
|
local data = {
|
||||||
'handle_roundabouts',
|
-- prefetch tags
|
||||||
|
highway = way:get_value_by_key('highway'),
|
||||||
-- handle allowed start/end modes
|
|
||||||
'handle_startpoint',
|
|
||||||
|
|
||||||
-- set name, ref and pronunciation
|
|
||||||
'handle_names'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Handlers.run(handlers,way,result,data,profile)
|
local handlers = Sequence {
|
||||||
|
-- set the default mode for this profile. if can be changed later
|
||||||
|
-- in case it turns we're e.g. on a ferry
|
||||||
|
WayHandlers.default_mode,
|
||||||
|
|
||||||
|
-- check various tags that could indicate that the way is not
|
||||||
|
-- routable. this includes things like status=impassable,
|
||||||
|
-- toll=yes and oneway=reversible
|
||||||
|
WayHandlers.blocked_ways,
|
||||||
|
|
||||||
|
-- our main handler
|
||||||
|
handle_bicycle_tags,
|
||||||
|
|
||||||
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
|
WayHandlers.surface,
|
||||||
|
|
||||||
|
-- handle turn lanes and road classification, used for guidance
|
||||||
|
WayHandlers.classification,
|
||||||
|
|
||||||
|
-- handle allowed start/end modes
|
||||||
|
WayHandlers.startpoint,
|
||||||
|
|
||||||
|
-- handle roundabouts
|
||||||
|
WayHandlers.roundabouts,
|
||||||
|
|
||||||
|
-- set name, ref and pronunciation
|
||||||
|
WayHandlers.names
|
||||||
|
}
|
||||||
|
|
||||||
|
WayHandlers.run(profile,way,result,data,handlers)
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function(turn)
|
function process_turn(profile, turn)
|
||||||
-- compute turn penalty as angle^2, with a left/right bias
|
-- compute turn penalty as angle^2, with a left/right bias
|
||||||
local normalized_angle = turn.angle / 90.0
|
local normalized_angle = turn.angle / 90.0
|
||||||
if normalized_angle >= 0.0 then
|
if normalized_angle >= 0.0 then
|
||||||
@ -566,17 +554,20 @@ function turn_function(turn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.uturn then
|
if turn.direction_modifier == direction_modifier.uturn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = turn.duration + profile.traffic_light_penalty
|
turn.duration = turn.duration + profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
if properties.weight_name == 'cyclability' then
|
if profile.properties.weight_name == 'cyclability' then
|
||||||
turn.weight = turn.duration
|
turn.weight = turn.duration
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
|
||||||
turn.weight = turn.weight + 3000
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_way = process_way,
|
||||||
|
process_node = process_node,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
563
profiles/car.lua
563
profiles/car.lua
@ -1,282 +1,268 @@
|
|||||||
-- Car profile
|
-- Car profile
|
||||||
|
|
||||||
api_version = 1
|
api_version = 2
|
||||||
|
|
||||||
local find_access_tag = require("lib/access").find_access_tag
|
Set = require('lib/set')
|
||||||
local Set = require('lib/set')
|
Sequence = require('lib/sequence')
|
||||||
local Sequence = require('lib/sequence')
|
Handlers = require("lib/way_handlers")
|
||||||
local Handlers = require("lib/handlers")
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
local next = next -- bind to local for speed
|
limit = require("lib/maxspeed").limit
|
||||||
|
|
||||||
-- set profile properties
|
function setup()
|
||||||
properties.max_speed_for_map_matching = 180/3.6 -- 180kmph -> m/s
|
local use_left_hand_driving = false
|
||||||
properties.use_turn_restrictions = true
|
return {
|
||||||
properties.continue_straight_at_waypoint = true
|
properties = {
|
||||||
properties.left_hand_driving = false
|
max_speed_for_map_matching = 180/3.6, -- 180kmph -> m/s
|
||||||
-- For routing based on duration, but weighted for preferring certain roads
|
left_hand_driving = use_left_hand_driving,
|
||||||
properties.weight_name = 'routability'
|
-- For routing based on duration, but weighted for preferring certain roads
|
||||||
-- For shortest duration without penalties for accessibility
|
weight_name = 'routability',
|
||||||
--properties.weight_name = 'duration'
|
-- For shortest duration without penalties for accessibility
|
||||||
-- For shortest distance without penalties for accessibility
|
-- weight_name = 'duration',
|
||||||
--properties.weight_name = 'distance'
|
-- For shortest distance without penalties for accessibility
|
||||||
|
-- weight_name = 'distance',
|
||||||
|
process_call_tagless_node = false,
|
||||||
|
u_turn_penalty = 20,
|
||||||
|
continue_straight_at_waypoint = true,
|
||||||
|
use_turn_restrictions = true,
|
||||||
|
traffic_light_penalty = 2,
|
||||||
|
},
|
||||||
|
|
||||||
|
default_mode = mode.driving,
|
||||||
|
default_speed = 10,
|
||||||
|
oneway_handling = true,
|
||||||
|
side_road_multiplier = 0.8,
|
||||||
|
turn_penalty = 7.5,
|
||||||
|
speed_reduction = 0.8,
|
||||||
|
|
||||||
-- Set to true if you need to call the node_function for every node.
|
-- Note: this biases right-side driving.
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
-- Should be inverted for left-driving countries.
|
||||||
-- (which slow down pre-processing).
|
turn_bias = use_left_hand_driving and 1/1.075 or 1.075,
|
||||||
properties.call_tagless_node_function = false
|
|
||||||
|
|
||||||
|
-- a list of suffixes to suppress in name change instructions
|
||||||
|
suffix_list = {
|
||||||
|
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
||||||
|
},
|
||||||
|
|
||||||
local profile = {
|
barrier_whitelist = Set {
|
||||||
default_mode = mode.driving,
|
'cattle_grid',
|
||||||
default_speed = 10,
|
'border_control',
|
||||||
oneway_handling = true,
|
'checkpoint',
|
||||||
|
'toll_booth',
|
||||||
|
'sally_port',
|
||||||
|
'gate',
|
||||||
|
'lift_gate',
|
||||||
|
'no',
|
||||||
|
'entrance'
|
||||||
|
},
|
||||||
|
|
||||||
side_road_multiplier = 0.8,
|
access_tag_whitelist = Set {
|
||||||
turn_penalty = 7.5,
|
'yes',
|
||||||
speed_reduction = 0.8,
|
'motorcar',
|
||||||
traffic_light_penalty = 2,
|
'motor_vehicle',
|
||||||
u_turn_penalty = 20,
|
'vehicle',
|
||||||
|
'permissive',
|
||||||
|
'designated',
|
||||||
|
'hov'
|
||||||
|
},
|
||||||
|
|
||||||
-- Note: this biases right-side driving.
|
access_tag_blacklist = Set {
|
||||||
-- Should be inverted for left-driving countries.
|
'no',
|
||||||
turn_bias = properties.left_hand_driving and 1/1.075 or 1.075,
|
'agricultural',
|
||||||
|
'forestry',
|
||||||
|
'emergency',
|
||||||
|
'psv',
|
||||||
|
'customers',
|
||||||
|
'private',
|
||||||
|
'delivery',
|
||||||
|
'destination'
|
||||||
|
},
|
||||||
|
|
||||||
-- a list of suffixes to suppress in name change instructions
|
restricted_access_tag_list = Set {
|
||||||
suffix_list = {
|
'private',
|
||||||
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
'delivery',
|
||||||
},
|
'destination',
|
||||||
|
'customers',
|
||||||
|
},
|
||||||
|
|
||||||
barrier_whitelist = Set {
|
access_tags_hierarchy = Sequence {
|
||||||
'cattle_grid',
|
'motorcar',
|
||||||
'border_control',
|
'motor_vehicle',
|
||||||
'checkpoint',
|
'vehicle',
|
||||||
'toll_booth',
|
'access'
|
||||||
'sally_port',
|
},
|
||||||
'gate',
|
|
||||||
'lift_gate',
|
|
||||||
'no',
|
|
||||||
'entrance'
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tag_whitelist = Set {
|
service_tag_forbidden = Set {
|
||||||
'yes',
|
'emergency_access'
|
||||||
'motorcar',
|
},
|
||||||
'motor_vehicle',
|
|
||||||
'vehicle',
|
|
||||||
'permissive',
|
|
||||||
'designated',
|
|
||||||
'hov'
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tag_blacklist = Set {
|
restrictions = Sequence {
|
||||||
'no',
|
'motorcar',
|
||||||
'agricultural',
|
'motor_vehicle',
|
||||||
'forestry',
|
'vehicle'
|
||||||
'emergency',
|
},
|
||||||
'psv',
|
|
||||||
'customers',
|
|
||||||
'private',
|
|
||||||
'delivery',
|
|
||||||
'destination'
|
|
||||||
},
|
|
||||||
|
|
||||||
restricted_access_tag_list = Set {
|
avoid = Set {
|
||||||
'private',
|
'area',
|
||||||
'delivery',
|
-- 'toll', -- uncomment this to avoid tolls
|
||||||
'destination',
|
'reversible',
|
||||||
'customers',
|
'impassable',
|
||||||
},
|
'hov_lanes',
|
||||||
|
'steps',
|
||||||
|
'construction',
|
||||||
|
'proposed'
|
||||||
|
},
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
speeds = Sequence {
|
||||||
'motorcar',
|
highway = {
|
||||||
'motor_vehicle',
|
motorway = 90,
|
||||||
'vehicle',
|
motorway_link = 45,
|
||||||
'access'
|
trunk = 85,
|
||||||
},
|
trunk_link = 40,
|
||||||
|
primary = 65,
|
||||||
|
primary_link = 30,
|
||||||
|
secondary = 55,
|
||||||
|
secondary_link = 25,
|
||||||
|
tertiary = 40,
|
||||||
|
tertiary_link = 20,
|
||||||
|
unclassified = 25,
|
||||||
|
residential = 25,
|
||||||
|
living_street = 10,
|
||||||
|
service = 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
service_tag_forbidden = Set {
|
service_penalties = {
|
||||||
'emergency_access'
|
alley = 0.5,
|
||||||
},
|
parking = 0.5,
|
||||||
|
parking_aisle = 0.5,
|
||||||
|
driveway = 0.5,
|
||||||
|
["drive-through"] = 0.5,
|
||||||
|
["drive-thru"] = 0.5
|
||||||
|
},
|
||||||
|
|
||||||
restrictions = Sequence {
|
restricted_highway_whitelist = Set {
|
||||||
'motorcar',
|
'motorway',
|
||||||
'motor_vehicle',
|
'motorway_link',
|
||||||
'vehicle'
|
'trunk',
|
||||||
},
|
'trunk_link',
|
||||||
|
'primary',
|
||||||
|
'primary_link',
|
||||||
|
'secondary',
|
||||||
|
'secondary_link',
|
||||||
|
'tertiary',
|
||||||
|
'tertiary_link',
|
||||||
|
'residential',
|
||||||
|
'living_street',
|
||||||
|
},
|
||||||
|
|
||||||
avoid = Set {
|
route_speeds = {
|
||||||
'area',
|
ferry = 5,
|
||||||
-- 'toll', -- uncomment this to avoid tolls
|
shuttle_train = 10
|
||||||
'reversible',
|
},
|
||||||
'impassable',
|
|
||||||
'hov_lanes',
|
|
||||||
'steps',
|
|
||||||
'construction',
|
|
||||||
'proposed'
|
|
||||||
},
|
|
||||||
|
|
||||||
speeds = Sequence {
|
bridge_speeds = {
|
||||||
highway = {
|
movable = 5
|
||||||
motorway = 90,
|
},
|
||||||
motorway_link = 45,
|
|
||||||
trunk = 85,
|
-- surface/trackype/smoothness
|
||||||
trunk_link = 40,
|
-- values were estimated from looking at the photos at the relevant wiki pages
|
||||||
primary = 65,
|
|
||||||
primary_link = 30,
|
-- max speed for surfaces
|
||||||
secondary = 55,
|
surface_speeds = {
|
||||||
secondary_link = 25,
|
asphalt = nil, -- nil mean no limit. removing the line has the same effect
|
||||||
tertiary = 40,
|
concrete = nil,
|
||||||
tertiary_link = 20,
|
["concrete:plates"] = nil,
|
||||||
unclassified = 25,
|
["concrete:lanes"] = nil,
|
||||||
residential = 25,
|
paved = nil,
|
||||||
living_street = 10,
|
|
||||||
service = 15
|
cement = 80,
|
||||||
|
compacted = 80,
|
||||||
|
fine_gravel = 80,
|
||||||
|
|
||||||
|
paving_stones = 60,
|
||||||
|
metal = 60,
|
||||||
|
bricks = 60,
|
||||||
|
|
||||||
|
grass = 40,
|
||||||
|
wood = 40,
|
||||||
|
sett = 40,
|
||||||
|
grass_paver = 40,
|
||||||
|
gravel = 40,
|
||||||
|
unpaved = 40,
|
||||||
|
ground = 40,
|
||||||
|
dirt = 40,
|
||||||
|
pebblestone = 40,
|
||||||
|
tartan = 40,
|
||||||
|
|
||||||
|
cobblestone = 30,
|
||||||
|
clay = 30,
|
||||||
|
|
||||||
|
earth = 20,
|
||||||
|
stone = 20,
|
||||||
|
rocky = 20,
|
||||||
|
sand = 20,
|
||||||
|
|
||||||
|
mud = 10
|
||||||
|
},
|
||||||
|
|
||||||
|
-- max speed for tracktypes
|
||||||
|
tracktype_speeds = {
|
||||||
|
grade1 = 60,
|
||||||
|
grade2 = 40,
|
||||||
|
grade3 = 30,
|
||||||
|
grade4 = 25,
|
||||||
|
grade5 = 20
|
||||||
|
},
|
||||||
|
|
||||||
|
-- max speed for smoothnesses
|
||||||
|
smoothness_speeds = {
|
||||||
|
intermediate = 80,
|
||||||
|
bad = 40,
|
||||||
|
very_bad = 20,
|
||||||
|
horrible = 10,
|
||||||
|
very_horrible = 5,
|
||||||
|
impassable = 0
|
||||||
|
},
|
||||||
|
|
||||||
|
-- http://wiki.openstreetmap.org/wiki/Speed_limits
|
||||||
|
maxspeed_table_default = {
|
||||||
|
urban = 50,
|
||||||
|
rural = 90,
|
||||||
|
trunk = 110,
|
||||||
|
motorway = 130
|
||||||
|
},
|
||||||
|
|
||||||
|
-- List only exceptions
|
||||||
|
maxspeed_table = {
|
||||||
|
["ch:rural"] = 80,
|
||||||
|
["ch:trunk"] = 100,
|
||||||
|
["ch:motorway"] = 120,
|
||||||
|
["de:living_street"] = 7,
|
||||||
|
["ru:living_street"] = 20,
|
||||||
|
["ru:urban"] = 60,
|
||||||
|
["ua:urban"] = 60,
|
||||||
|
["at:rural"] = 100,
|
||||||
|
["de:rural"] = 100,
|
||||||
|
["at:trunk"] = 100,
|
||||||
|
["cz:trunk"] = 0,
|
||||||
|
["ro:trunk"] = 100,
|
||||||
|
["cz:motorway"] = 0,
|
||||||
|
["de:motorway"] = 0,
|
||||||
|
["ru:motorway"] = 110,
|
||||||
|
["gb:nsl_single"] = (60*1609)/1000,
|
||||||
|
["gb:nsl_dual"] = (70*1609)/1000,
|
||||||
|
["gb:motorway"] = (70*1609)/1000,
|
||||||
|
["uk:nsl_single"] = (60*1609)/1000,
|
||||||
|
["uk:nsl_dual"] = (70*1609)/1000,
|
||||||
|
["uk:motorway"] = (70*1609)/1000,
|
||||||
|
["nl:rural"] = 80,
|
||||||
|
["nl:trunk"] = 100,
|
||||||
|
["none"] = 140
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
service_penalties = {
|
|
||||||
alley = 0.5,
|
|
||||||
parking = 0.5,
|
|
||||||
parking_aisle = 0.5,
|
|
||||||
driveway = 0.5,
|
|
||||||
["drive-through"] = 0.5,
|
|
||||||
["drive-thru"] = 0.5
|
|
||||||
},
|
|
||||||
|
|
||||||
restricted_highway_whitelist = Set {
|
|
||||||
'motorway',
|
|
||||||
'motorway_link',
|
|
||||||
'trunk',
|
|
||||||
'trunk_link',
|
|
||||||
'primary',
|
|
||||||
'primary_link',
|
|
||||||
'secondary',
|
|
||||||
'secondary_link',
|
|
||||||
'tertiary',
|
|
||||||
'tertiary_link',
|
|
||||||
'residential',
|
|
||||||
'living_street',
|
|
||||||
},
|
|
||||||
|
|
||||||
route_speeds = {
|
|
||||||
ferry = 5,
|
|
||||||
shuttle_train = 10
|
|
||||||
},
|
|
||||||
|
|
||||||
bridge_speeds = {
|
|
||||||
movable = 5
|
|
||||||
},
|
|
||||||
|
|
||||||
-- surface/trackype/smoothness
|
|
||||||
-- values were estimated from looking at the photos at the relevant wiki pages
|
|
||||||
|
|
||||||
-- max speed for surfaces
|
|
||||||
surface_speeds = {
|
|
||||||
asphalt = nil, -- nil mean no limit. removing the line has the same effect
|
|
||||||
concrete = nil,
|
|
||||||
["concrete:plates"] = nil,
|
|
||||||
["concrete:lanes"] = nil,
|
|
||||||
paved = nil,
|
|
||||||
|
|
||||||
cement = 80,
|
|
||||||
compacted = 80,
|
|
||||||
fine_gravel = 80,
|
|
||||||
|
|
||||||
paving_stones = 60,
|
|
||||||
metal = 60,
|
|
||||||
bricks = 60,
|
|
||||||
|
|
||||||
grass = 40,
|
|
||||||
wood = 40,
|
|
||||||
sett = 40,
|
|
||||||
grass_paver = 40,
|
|
||||||
gravel = 40,
|
|
||||||
unpaved = 40,
|
|
||||||
ground = 40,
|
|
||||||
dirt = 40,
|
|
||||||
pebblestone = 40,
|
|
||||||
tartan = 40,
|
|
||||||
|
|
||||||
cobblestone = 30,
|
|
||||||
clay = 30,
|
|
||||||
|
|
||||||
earth = 20,
|
|
||||||
stone = 20,
|
|
||||||
rocky = 20,
|
|
||||||
sand = 20,
|
|
||||||
|
|
||||||
mud = 10
|
|
||||||
},
|
|
||||||
|
|
||||||
-- max speed for tracktypes
|
|
||||||
tracktype_speeds = {
|
|
||||||
grade1 = 60,
|
|
||||||
grade2 = 40,
|
|
||||||
grade3 = 30,
|
|
||||||
grade4 = 25,
|
|
||||||
grade5 = 20
|
|
||||||
},
|
|
||||||
|
|
||||||
-- max speed for smoothnesses
|
|
||||||
smoothness_speeds = {
|
|
||||||
intermediate = 80,
|
|
||||||
bad = 40,
|
|
||||||
very_bad = 20,
|
|
||||||
horrible = 10,
|
|
||||||
very_horrible = 5,
|
|
||||||
impassable = 0
|
|
||||||
},
|
|
||||||
|
|
||||||
-- http://wiki.openstreetmap.org/wiki/Speed_limits
|
|
||||||
maxspeed_table_default = {
|
|
||||||
urban = 50,
|
|
||||||
rural = 90,
|
|
||||||
trunk = 110,
|
|
||||||
motorway = 130
|
|
||||||
},
|
|
||||||
|
|
||||||
-- List only exceptions
|
|
||||||
maxspeed_table = {
|
|
||||||
["ch:rural"] = 80,
|
|
||||||
["ch:trunk"] = 100,
|
|
||||||
["ch:motorway"] = 120,
|
|
||||||
["de:living_street"] = 7,
|
|
||||||
["ru:living_street"] = 20,
|
|
||||||
["ru:urban"] = 60,
|
|
||||||
["ua:urban"] = 60,
|
|
||||||
["at:rural"] = 100,
|
|
||||||
["de:rural"] = 100,
|
|
||||||
["at:trunk"] = 100,
|
|
||||||
["cz:trunk"] = 0,
|
|
||||||
["ro:trunk"] = 100,
|
|
||||||
["cz:motorway"] = 0,
|
|
||||||
["de:motorway"] = 0,
|
|
||||||
["ru:motorway"] = 110,
|
|
||||||
["gb:nsl_single"] = (60*1609)/1000,
|
|
||||||
["gb:nsl_dual"] = (70*1609)/1000,
|
|
||||||
["gb:motorway"] = (70*1609)/1000,
|
|
||||||
["uk:nsl_single"] = (60*1609)/1000,
|
|
||||||
["uk:nsl_dual"] = (70*1609)/1000,
|
|
||||||
["uk:motorway"] = (70*1609)/1000,
|
|
||||||
["nl:rural"] = 80,
|
|
||||||
["nl:trunk"] = 100,
|
|
||||||
["none"] = 140
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function get_name_suffix_list(vector)
|
|
||||||
for index,suffix in ipairs(profile.suffix_list) do
|
|
||||||
vector:Add(suffix)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function get_restrictions(vector)
|
function process_node (profile, node, result)
|
||||||
for i,v in ipairs(profile.restrictions) do
|
|
||||||
vector:Add(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function node_function (node, result)
|
|
||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
@ -303,7 +289,7 @@ function node_function (node, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function way_function(way, result)
|
function process_way(profile, way, result)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
-- affects processing times significantly, because all ways
|
-- affects processing times significantly, because all ways
|
||||||
-- have to be checked.
|
-- have to be checked.
|
||||||
@ -335,61 +321,61 @@ function way_function(way, result)
|
|||||||
handlers = Sequence {
|
handlers = Sequence {
|
||||||
-- set the default mode for this profile. if can be changed later
|
-- set the default mode for this profile. if can be changed later
|
||||||
-- in case it turns we're e.g. on a ferry
|
-- in case it turns we're e.g. on a ferry
|
||||||
'handle_default_mode',
|
WayHandlers.default_mode,
|
||||||
|
|
||||||
-- check various tags that could indicate that the way is not
|
-- check various tags that could indicate that the way is not
|
||||||
-- routable. this includes things like status=impassable,
|
-- routable. this includes things like status=impassable,
|
||||||
-- toll=yes and oneway=reversible
|
-- toll=yes and oneway=reversible
|
||||||
'handle_blocked_ways',
|
WayHandlers.blocked_ways,
|
||||||
|
|
||||||
-- determine access status by checking our hierarchy of
|
-- determine access status by checking our hierarchy of
|
||||||
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
||||||
'handle_access',
|
WayHandlers.access,
|
||||||
|
|
||||||
-- check whether forward/backward directions are routable
|
-- check whether forward/backward directions are routable
|
||||||
'handle_oneway',
|
WayHandlers.oneway,
|
||||||
|
|
||||||
-- check a road's destination
|
-- check a road's destination
|
||||||
'handle_destinations',
|
WayHandlers.destinations,
|
||||||
|
|
||||||
-- check whether we're using a special transport mode
|
-- check whether we're using a special transport mode
|
||||||
'handle_ferries',
|
WayHandlers.ferries,
|
||||||
'handle_movables',
|
WayHandlers.movables,
|
||||||
|
|
||||||
-- handle service road restrictions
|
-- handle service road restrictions
|
||||||
'handle_service',
|
WayHandlers.service,
|
||||||
|
|
||||||
-- handle hov
|
-- handle hov
|
||||||
'handle_hov',
|
WayHandlers.hov,
|
||||||
|
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
'handle_speed',
|
WayHandlers.speed,
|
||||||
'handle_surface',
|
WayHandlers.surface,
|
||||||
'handle_maxspeed',
|
WayHandlers.maxspeed,
|
||||||
'handle_penalties',
|
WayHandlers.penalties,
|
||||||
|
|
||||||
-- compute class labels
|
-- compute class labels
|
||||||
'handle_classes',
|
WayHandlers.classes,
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- handle turn lanes and road classification, used for guidance
|
||||||
'handle_turn_lanes',
|
WayHandlers.turn_lanes,
|
||||||
'handle_classification',
|
WayHandlers.classification,
|
||||||
|
|
||||||
-- handle various other flags
|
-- handle various other flags
|
||||||
'handle_roundabouts',
|
WayHandlers.roundabouts,
|
||||||
'handle_startpoint',
|
WayHandlers.startpoint,
|
||||||
|
|
||||||
-- set name, ref and pronunciation
|
-- set name, ref and pronunciation
|
||||||
'handle_names',
|
WayHandlers.names,
|
||||||
|
|
||||||
-- set weight properties of the way
|
-- set weight properties of the way
|
||||||
'handle_weights'
|
WayHandlers.weights
|
||||||
}
|
}
|
||||||
|
|
||||||
Handlers.run(handlers,way,result,data,profile)
|
WayHandlers.run(profile,way,result,data,handlers)
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function (turn)
|
function process_turn (profile, turn)
|
||||||
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty
|
-- Use a sigmoid function to return a penalty that maxes out at turn_penalty
|
||||||
-- over the space of 0-180 degrees. Values here were chosen by fitting
|
-- over the space of 0-180 degrees. Values here were chosen by fitting
|
||||||
-- the function to some turn penalty samples from real driving.
|
-- the function to some turn penalty samples from real driving.
|
||||||
@ -397,7 +383,7 @@ function turn_function (turn)
|
|||||||
local turn_bias = profile.turn_bias
|
local turn_bias = profile.turn_bias
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = profile.traffic_light_penalty
|
turn.duration = profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.turn_type ~= turn_type.no_turn then
|
if turn.turn_type ~= turn_type.no_turn then
|
||||||
@ -408,21 +394,28 @@ function turn_function (turn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- for distance based routing we don't want to have penalties based on turn angle
|
-- for distance based routing we don't want to have penalties based on turn angle
|
||||||
if properties.weight_name == 'distance' then
|
if profile.properties.weight_name == 'distance' then
|
||||||
turn.weight = 0
|
turn.weight = 0
|
||||||
else
|
else
|
||||||
turn.weight = turn.duration
|
turn.weight = turn.duration
|
||||||
end
|
end
|
||||||
|
|
||||||
if properties.weight_name == 'routability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = properties.max_turn_weight;
|
turn.weight = constants.max_turn_weight
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_way = process_way,
|
||||||
|
process_node = process_node,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
@ -1,149 +1,143 @@
|
|||||||
-- Foot profile
|
-- Foot profile
|
||||||
|
|
||||||
api_version = 1
|
api_version = 2
|
||||||
|
|
||||||
local find_access_tag = require("lib/access").find_access_tag
|
Set = require('lib/set')
|
||||||
local Set = require('lib/set')
|
Sequence = require('lib/sequence')
|
||||||
local Sequence = require('lib/sequence')
|
Handlers = require("lib/way_handlers")
|
||||||
local Handlers = require("lib/handlers")
|
find_access_tag = require("lib/access").find_access_tag
|
||||||
local next = next -- bind to local for speed
|
|
||||||
|
|
||||||
properties.max_speed_for_map_matching = 40/3.6 -- kmph -> m/s
|
function setup()
|
||||||
properties.use_turn_restrictions = false
|
local walking_speed = 5
|
||||||
properties.continue_straight_at_waypoint = false
|
return {
|
||||||
properties.weight_name = 'duration'
|
properties = {
|
||||||
--properties.weight_name = 'routability'
|
weight_name = 'duration',
|
||||||
|
max_speed_for_map_matching = 40/3.6, -- kmph -> m/s
|
||||||
-- Set to true if you need to call the node_function for every node.
|
call_tagless_node_function = false,
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
traffic_light_penalty = 2,
|
||||||
-- (which slow down pre-processing).
|
u_turn_penalty = 2,
|
||||||
properties.call_tagless_node_function = false
|
continue_straight_at_waypoint = false,
|
||||||
|
use_turn_restrictions = false,
|
||||||
local walking_speed = 5
|
|
||||||
|
|
||||||
local profile = {
|
|
||||||
default_mode = mode.walking,
|
|
||||||
default_speed = walking_speed,
|
|
||||||
oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway'
|
|
||||||
traffic_light_penalty = 2,
|
|
||||||
u_turn_penalty = 2,
|
|
||||||
|
|
||||||
barrier_whitelist = Set {
|
|
||||||
'cycle_barrier',
|
|
||||||
'bollard',
|
|
||||||
'entrance',
|
|
||||||
'cattle_grid',
|
|
||||||
'border_control',
|
|
||||||
'toll_booth',
|
|
||||||
'sally_port',
|
|
||||||
'gate',
|
|
||||||
'no',
|
|
||||||
'kerb',
|
|
||||||
'block'
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tag_whitelist = Set {
|
|
||||||
'yes',
|
|
||||||
'foot',
|
|
||||||
'permissive',
|
|
||||||
'designated'
|
|
||||||
},
|
|
||||||
|
|
||||||
access_tag_blacklist = Set {
|
|
||||||
'no',
|
|
||||||
'agricultural',
|
|
||||||
'forestry',
|
|
||||||
'private',
|
|
||||||
'delivery',
|
|
||||||
},
|
|
||||||
|
|
||||||
restricted_access_tag_list = Set { },
|
|
||||||
|
|
||||||
restricted_highway_whitelist = Set { },
|
|
||||||
|
|
||||||
access_tags_hierarchy = Sequence {
|
|
||||||
'foot',
|
|
||||||
'access'
|
|
||||||
},
|
|
||||||
|
|
||||||
restrictions = Sequence {
|
|
||||||
'foot'
|
|
||||||
},
|
|
||||||
|
|
||||||
-- list of suffixes to suppress in name change instructions
|
|
||||||
suffix_list = Set {
|
|
||||||
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
|
||||||
},
|
|
||||||
|
|
||||||
avoid = Set {
|
|
||||||
'impassable',
|
|
||||||
'construction',
|
|
||||||
'proposed'
|
|
||||||
},
|
|
||||||
|
|
||||||
speeds = Sequence {
|
|
||||||
highway = {
|
|
||||||
primary = walking_speed,
|
|
||||||
primary_link = walking_speed,
|
|
||||||
secondary = walking_speed,
|
|
||||||
secondary_link = walking_speed,
|
|
||||||
tertiary = walking_speed,
|
|
||||||
tertiary_link = walking_speed,
|
|
||||||
unclassified = walking_speed,
|
|
||||||
residential = walking_speed,
|
|
||||||
road = walking_speed,
|
|
||||||
living_street = walking_speed,
|
|
||||||
service = walking_speed,
|
|
||||||
track = walking_speed,
|
|
||||||
path = walking_speed,
|
|
||||||
steps = walking_speed,
|
|
||||||
pedestrian = walking_speed,
|
|
||||||
footway = walking_speed,
|
|
||||||
pier = walking_speed,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
railway = {
|
default_mode = mode.walking,
|
||||||
platform = walking_speed
|
default_speed = walking_speed,
|
||||||
|
oneway_handling = 'specific', -- respect 'oneway:foot' but not 'oneway'
|
||||||
|
|
||||||
|
barrier_whitelist = Set {
|
||||||
|
'cycle_barrier',
|
||||||
|
'bollard',
|
||||||
|
'entrance',
|
||||||
|
'cattle_grid',
|
||||||
|
'border_control',
|
||||||
|
'toll_booth',
|
||||||
|
'sally_port',
|
||||||
|
'gate',
|
||||||
|
'no',
|
||||||
|
'kerb',
|
||||||
|
'block'
|
||||||
},
|
},
|
||||||
|
|
||||||
amenity = {
|
access_tag_whitelist = Set {
|
||||||
parking = walking_speed,
|
'yes',
|
||||||
parking_entrance= walking_speed
|
'foot',
|
||||||
|
'permissive',
|
||||||
|
'designated'
|
||||||
},
|
},
|
||||||
|
|
||||||
man_made = {
|
access_tag_blacklist = Set {
|
||||||
pier = walking_speed
|
'no',
|
||||||
|
'agricultural',
|
||||||
|
'forestry',
|
||||||
|
'private',
|
||||||
|
'delivery',
|
||||||
},
|
},
|
||||||
|
|
||||||
leisure = {
|
restricted_access_tag_list = Set { },
|
||||||
track = walking_speed
|
|
||||||
|
restricted_highway_whitelist = Set { },
|
||||||
|
|
||||||
|
access_tags_hierarchy = Sequence {
|
||||||
|
'foot',
|
||||||
|
'access'
|
||||||
|
},
|
||||||
|
|
||||||
|
restrictions = Sequence {
|
||||||
|
'foot'
|
||||||
|
},
|
||||||
|
|
||||||
|
-- list of suffixes to suppress in name change instructions
|
||||||
|
suffix_list = Set {
|
||||||
|
'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'North', 'South', 'West', 'East'
|
||||||
|
},
|
||||||
|
|
||||||
|
avoid = Set {
|
||||||
|
'impassable'
|
||||||
|
},
|
||||||
|
|
||||||
|
speeds = Sequence {
|
||||||
|
highway = {
|
||||||
|
primary = walking_speed,
|
||||||
|
primary_link = walking_speed,
|
||||||
|
secondary = walking_speed,
|
||||||
|
secondary_link = walking_speed,
|
||||||
|
tertiary = walking_speed,
|
||||||
|
tertiary_link = walking_speed,
|
||||||
|
unclassified = walking_speed,
|
||||||
|
residential = walking_speed,
|
||||||
|
road = walking_speed,
|
||||||
|
living_street = walking_speed,
|
||||||
|
service = walking_speed,
|
||||||
|
track = walking_speed,
|
||||||
|
path = walking_speed,
|
||||||
|
steps = walking_speed,
|
||||||
|
pedestrian = walking_speed,
|
||||||
|
footway = walking_speed,
|
||||||
|
pier = walking_speed,
|
||||||
|
},
|
||||||
|
|
||||||
|
railway = {
|
||||||
|
platform = walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
amenity = {
|
||||||
|
parking = walking_speed,
|
||||||
|
parking_entrance= walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
man_made = {
|
||||||
|
pier = walking_speed
|
||||||
|
},
|
||||||
|
|
||||||
|
leisure = {
|
||||||
|
track = walking_speed
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
route_speeds = {
|
||||||
|
ferry = 5
|
||||||
|
},
|
||||||
|
|
||||||
|
bridge_speeds = {
|
||||||
|
},
|
||||||
|
|
||||||
|
surface_speeds = {
|
||||||
|
fine_gravel = walking_speed*0.75,
|
||||||
|
gravel = walking_speed*0.75,
|
||||||
|
pebblestone = walking_speed*0.75,
|
||||||
|
mud = walking_speed*0.5,
|
||||||
|
sand = walking_speed*0.5
|
||||||
|
},
|
||||||
|
|
||||||
|
tracktype_speeds = {
|
||||||
|
},
|
||||||
|
|
||||||
|
smoothness_speeds = {
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
route_speeds = {
|
|
||||||
ferry = 5
|
|
||||||
},
|
|
||||||
|
|
||||||
bridge_speeds = {
|
|
||||||
},
|
|
||||||
|
|
||||||
surface_speeds = {
|
|
||||||
fine_gravel = walking_speed*0.75,
|
|
||||||
gravel = walking_speed*0.75,
|
|
||||||
pebblestone = walking_speed*0.75,
|
|
||||||
mud = walking_speed*0.5,
|
|
||||||
sand = walking_speed*0.5
|
|
||||||
},
|
|
||||||
|
|
||||||
tracktype_speeds = {
|
|
||||||
},
|
|
||||||
|
|
||||||
smoothness_speeds = {
|
|
||||||
}
|
}
|
||||||
}
|
end
|
||||||
|
|
||||||
|
function process_node (profile, node, result)
|
||||||
function node_function (node, result)
|
|
||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
local access = find_access_tag(node, profile.access_tags_hierarchy)
|
||||||
if access then
|
if access then
|
||||||
@ -171,7 +165,7 @@ function node_function (node, result)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- main entry point for processsing a way
|
-- main entry point for processsing a way
|
||||||
function way_function(way, result)
|
function process_way(profile, way, result)
|
||||||
-- the intial filtering of ways based on presence of tags
|
-- the intial filtering of ways based on presence of tags
|
||||||
-- affects processing times significantly, because all ways
|
-- affects processing times significantly, because all ways
|
||||||
-- have to be checked.
|
-- have to be checked.
|
||||||
@ -208,59 +202,66 @@ function way_function(way, result)
|
|||||||
local handlers = Sequence {
|
local handlers = Sequence {
|
||||||
-- set the default mode for this profile. if can be changed later
|
-- set the default mode for this profile. if can be changed later
|
||||||
-- in case it turns we're e.g. on a ferry
|
-- in case it turns we're e.g. on a ferry
|
||||||
'handle_default_mode',
|
WayHandlers.default_mode,
|
||||||
|
|
||||||
-- check various tags that could indicate that the way is not
|
-- check various tags that could indicate that the way is not
|
||||||
-- routable. this includes things like status=impassable,
|
-- routable. this includes things like status=impassable,
|
||||||
-- toll=yes and oneway=reversible
|
-- toll=yes and oneway=reversible
|
||||||
'handle_blocked_ways',
|
WayHandlers.blocked_ways,
|
||||||
|
|
||||||
-- determine access status by checking our hierarchy of
|
-- determine access status by checking our hierarchy of
|
||||||
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
-- access tags, e.g: motorcar, motor_vehicle, vehicle
|
||||||
'handle_access',
|
WayHandlers.access,
|
||||||
|
|
||||||
-- check whether forward/backward directons are routable
|
-- check whether forward/backward directons are routable
|
||||||
'handle_oneway',
|
WayHandlers.oneway,
|
||||||
|
|
||||||
-- check whether forward/backward directons are routable
|
-- check whether forward/backward directons are routable
|
||||||
'handle_destinations',
|
WayHandlers.destinations,
|
||||||
|
|
||||||
-- check whether we're using a special transport mode
|
-- check whether we're using a special transport mode
|
||||||
'handle_ferries',
|
WayHandlers.ferries,
|
||||||
'handle_movables',
|
WayHandlers.movables,
|
||||||
|
|
||||||
-- compute speed taking into account way type, maxspeed tags, etc.
|
-- compute speed taking into account way type, maxspeed tags, etc.
|
||||||
'handle_speed',
|
WayHandlers.speed,
|
||||||
'handle_surface',
|
WayHandlers.surface,
|
||||||
|
|
||||||
-- handle turn lanes and road classification, used for guidance
|
-- handle turn lanes and road classification, used for guidance
|
||||||
'handle_classification',
|
WayHandlers.classification,
|
||||||
|
|
||||||
-- handle various other flags
|
-- handle various other flags
|
||||||
'handle_roundabouts',
|
WayHandlers.roundabouts,
|
||||||
'handle_startpoint',
|
WayHandlers.startpoint,
|
||||||
|
|
||||||
-- set name, ref and pronunciation
|
-- set name, ref and pronunciation
|
||||||
'handle_names'
|
WayHandlers.names
|
||||||
}
|
}
|
||||||
|
|
||||||
Handlers.run(handlers,way,result,data,profile)
|
WayHandlers.run(profile,way,result,data,handlers)
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function (turn)
|
function process_turn (profile, turn)
|
||||||
turn.duration = 0.
|
turn.duration = 0.
|
||||||
|
|
||||||
if turn.direction_modifier == direction_modifier.u_turn then
|
if turn.direction_modifier == direction_modifier.u_turn then
|
||||||
turn.duration = turn.duration + profile.u_turn_penalty
|
turn.duration = turn.duration + profile.properties.u_turn_penalty
|
||||||
end
|
end
|
||||||
|
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = profile.traffic_light_penalty
|
turn.duration = profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
if properties.weight_name == 'routability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
-- penalize turns from non-local access only segments onto local access only tags
|
-- penalize turns from non-local access only segments onto local access only tags
|
||||||
if not turn.source_restricted and turn.target_restricted then
|
if not turn.source_restricted and turn.target_restricted then
|
||||||
turn.weight = turn.weight + 3000
|
turn.weight = turn.weight + 3000
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_way = process_way,
|
||||||
|
process_node = process_node,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
@ -90,7 +90,8 @@ function Debug.report_tag_fetches()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Debug.load_profile(profile)
|
function Debug.load_profile(profile)
|
||||||
require(profile)
|
Debug.functions = require(profile)
|
||||||
|
Debug.profile = Debug.functions.setup()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Debug.reset_tag_fetch_counts()
|
function Debug.reset_tag_fetch_counts()
|
||||||
@ -115,7 +116,7 @@ function Debug.register_tag_fetch(k)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Debug.way_function(way,result)
|
function Debug.process_way(way,result)
|
||||||
|
|
||||||
-- setup result table
|
-- setup result table
|
||||||
result.road_classification = {}
|
result.road_classification = {}
|
||||||
@ -132,8 +133,8 @@ function Debug.way_function(way,result)
|
|||||||
-- reset tag counts
|
-- reset tag counts
|
||||||
Debug:reset_tag_fetch_counts()
|
Debug:reset_tag_fetch_counts()
|
||||||
|
|
||||||
-- call the global method defined in the profile file
|
-- call the way processsing function
|
||||||
way_function(way,result)
|
Debug.functions.process_way(Debug.profile,way,result)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Debug
|
return Debug
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-- Sequence of items
|
-- Sequence of items
|
||||||
-- Ordered, but have to loop through items to check for inclusion.
|
-- Ordered, but have to loop through items to check for inclusion.
|
||||||
-- Currently the same as a table.
|
-- Currently the same as a table.
|
||||||
|
-- Adds the convenience function append() to append to the sequnce.
|
||||||
|
|
||||||
function Sequence(source)
|
function Sequence(source)
|
||||||
return source
|
return source
|
||||||
|
@ -9,25 +9,26 @@ local set_classification = require("lib/guidance").set_classification
|
|||||||
local get_destination = require("lib/destination").get_destination
|
local get_destination = require("lib/destination").get_destination
|
||||||
local Tags = require('lib/tags')
|
local Tags = require('lib/tags')
|
||||||
|
|
||||||
Handlers = {}
|
WayHandlers = {}
|
||||||
|
|
||||||
-- check that way has at least one tag that could imply routability-
|
-- check that way has at least one tag that could imply routability-
|
||||||
-- we store the checked tags in data, to avoid fetching again later
|
-- we store the checked tags in data, to avoid fetching again later
|
||||||
function Handlers.handle_tag_prefetch(way,result,data,profile)
|
function WayHandlers.tag_prefetch(profile,way,result,data)
|
||||||
for key,v in pairs(profile.prefetch) do
|
for key,v in pairs(profile.prefetch) do
|
||||||
data[key] = way:get_value_by_key( key )
|
data[key] = way:get_value_by_key( key )
|
||||||
end
|
end
|
||||||
|
|
||||||
return next(data) ~= nil
|
return next(data) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- set default mode
|
-- set default mode
|
||||||
function Handlers.handle_default_mode(way,result,data,profile)
|
function WayHandlers.default_mode(profile,way,result,data)
|
||||||
result.forward_mode = profile.default_mode
|
result.forward_mode = profile.default_mode
|
||||||
result.backward_mode = profile.default_mode
|
result.backward_mode = profile.default_mode
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handles name, including ref and pronunciation
|
-- handles name, including ref and pronunciation
|
||||||
function Handlers.handle_names(way,result,data,profile)
|
function WayHandlers.names(profile,way,result,data)
|
||||||
-- parse the remaining tags
|
-- parse the remaining tags
|
||||||
local name = way:get_value_by_key("name")
|
local name = way:get_value_by_key("name")
|
||||||
local pronunciation = way:get_value_by_key("name:pronunciation")
|
local pronunciation = way:get_value_by_key("name:pronunciation")
|
||||||
@ -53,7 +54,7 @@ function Handlers.handle_names(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- junctions
|
-- junctions
|
||||||
function Handlers.handle_roundabouts(way,result,data,profile)
|
function WayHandlers.roundabouts(profile,way,result,data)
|
||||||
local junction = way:get_value_by_key("junction");
|
local junction = way:get_value_by_key("junction");
|
||||||
|
|
||||||
if junction == "roundabout" then
|
if junction == "roundabout" then
|
||||||
@ -69,7 +70,7 @@ function Handlers.handle_roundabouts(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- determine if this way can be used as a start/end point for routing
|
-- determine if this way can be used as a start/end point for routing
|
||||||
function Handlers.handle_startpoint(way,result,data,profile)
|
function WayHandlers.startpoint(profile,way,result,data)
|
||||||
-- if profile specifies set of allowed start modes, then check for that
|
-- if profile specifies set of allowed start modes, then check for that
|
||||||
-- otherwise require default mode
|
-- otherwise require default mode
|
||||||
if profile.allowed_start_modes then
|
if profile.allowed_start_modes then
|
||||||
@ -82,7 +83,7 @@ function Handlers.handle_startpoint(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle turn lanes
|
-- handle turn lanes
|
||||||
function Handlers.handle_turn_lanes(way,result,data,profile)
|
function WayHandlers.turn_lanes(profile,way,result,data)
|
||||||
local forward, backward = get_turn_lanes(way,data)
|
local forward, backward = get_turn_lanes(way,data)
|
||||||
|
|
||||||
if forward then
|
if forward then
|
||||||
@ -95,12 +96,12 @@ function Handlers.handle_turn_lanes(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- set the road classification based on guidance globals configuration
|
-- set the road classification based on guidance globals configuration
|
||||||
function Handlers.handle_classification(way,result,data,profile)
|
function WayHandlers.classification(profile,way,result,data)
|
||||||
set_classification(data.highway,result,way)
|
set_classification(data.highway,result,way)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- handle destination tags
|
-- handle destination tags
|
||||||
function Handlers.handle_destinations(way,result,data,profile)
|
function WayHandlers.destinations(profile,way,result,data)
|
||||||
if data.is_forward_oneway or data.is_reverse_oneway then
|
if data.is_forward_oneway or data.is_reverse_oneway then
|
||||||
local destination = get_destination(way, data.is_forward_oneway)
|
local destination = get_destination(way, data.is_forward_oneway)
|
||||||
result.destinations = canonicalizeStringList(destination, ",")
|
result.destinations = canonicalizeStringList(destination, ",")
|
||||||
@ -108,7 +109,7 @@ function Handlers.handle_destinations(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handling ferries and piers
|
-- handling ferries and piers
|
||||||
function Handlers.handle_ferries(way,result,data,profile)
|
function WayHandlers.ferries(profile,way,result,data)
|
||||||
local route = data.route
|
local route = data.route
|
||||||
if route then
|
if route then
|
||||||
local route_speed = profile.route_speeds[route]
|
local route_speed = profile.route_speeds[route]
|
||||||
@ -126,7 +127,7 @@ function Handlers.handle_ferries(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handling movable bridges
|
-- handling movable bridges
|
||||||
function Handlers.handle_movables(way,result,data,profile)
|
function WayHandlers.movables(profile,way,result,data)
|
||||||
local bridge = data.bridge
|
local bridge = data.bridge
|
||||||
if bridge then
|
if bridge then
|
||||||
local bridge_speed = profile.bridge_speeds[bridge]
|
local bridge_speed = profile.bridge_speeds[bridge]
|
||||||
@ -148,7 +149,7 @@ function Handlers.handle_movables(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- service roads
|
-- service roads
|
||||||
function Handlers.handle_service(way,result,data,profile)
|
function WayHandlers.service(profile,way,result,data)
|
||||||
local service = way:get_value_by_key("service")
|
local service = way:get_value_by_key("service")
|
||||||
if service then
|
if service then
|
||||||
-- Set don't allow access to certain service roads
|
-- Set don't allow access to certain service roads
|
||||||
@ -161,7 +162,7 @@ function Handlers.handle_service(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- all lanes restricted to hov vehicles?
|
-- all lanes restricted to hov vehicles?
|
||||||
function Handlers.has_all_designated_hov_lanes(lanes)
|
function WayHandlers.has_all_designated_hov_lanes(lanes)
|
||||||
if not lanes then
|
if not lanes then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -176,7 +177,7 @@ function Handlers.has_all_designated_hov_lanes(lanes)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle high occupancy vehicle tags
|
-- handle high occupancy vehicle tags
|
||||||
function Handlers.handle_hov(way,result,data,profile)
|
function WayHandlers.hov(profile,way,result,data)
|
||||||
-- respect user-preference for HOV
|
-- respect user-preference for HOV
|
||||||
if not profile.avoid.hov_lanes then
|
if not profile.avoid.hov_lanes then
|
||||||
return
|
return
|
||||||
@ -189,11 +190,11 @@ function Handlers.handle_hov(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes')
|
data.hov_lanes_forward, data.hov_lanes_backward = Tags.get_forward_backward_by_key(way,data,'hov:lanes')
|
||||||
local all_hov_forward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_forward)
|
local all_hov_forward = WayHandlers.has_all_designated_hov_lanes(data.hov_lanes_forward)
|
||||||
local all_hov_backward = Handlers.has_all_designated_hov_lanes(data.hov_lanes_backward)
|
local all_hov_backward = WayHandlers.has_all_designated_hov_lanes(data.hov_lanes_backward)
|
||||||
|
|
||||||
-- in this case we will use turn penalties instead of filtering out
|
-- in this case we will use turn penalties instead of filtering out
|
||||||
if properties.weight_name == 'routability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
if (all_hov_forward) then
|
if (all_hov_forward) then
|
||||||
result.forward_restricted = true
|
result.forward_restricted = true
|
||||||
end
|
end
|
||||||
@ -213,7 +214,7 @@ function Handlers.handle_hov(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check accessibility by traversing our access tag hierarchy
|
-- check accessibility by traversing our access tag hierarchy
|
||||||
function Handlers.handle_access(way,result,data,profile)
|
function WayHandlers.access(profile,way,result,data)
|
||||||
data.forward_access, data.backward_access =
|
data.forward_access, data.backward_access =
|
||||||
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
|
Tags.get_forward_backward_by_set(way,data,profile.access_tags_hierarchy)
|
||||||
|
|
||||||
@ -242,7 +243,7 @@ function Handlers.handle_access(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle speed (excluding maxspeed)
|
-- handle speed (excluding maxspeed)
|
||||||
function Handlers.handle_speed(way,result,data,profile)
|
function WayHandlers.speed(profile,way,result,data)
|
||||||
if result.forward_speed ~= -1 then
|
if result.forward_speed ~= -1 then
|
||||||
return -- abort if already set, eg. by a route
|
return -- abort if already set, eg. by a route
|
||||||
end
|
end
|
||||||
@ -278,7 +279,7 @@ function Handlers.handle_speed(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- add class information
|
-- add class information
|
||||||
function Handlers.handle_classes(way,result,data,profile)
|
function WayHandlers.classes(profile,way,result,data)
|
||||||
local forward_toll, backward_toll = Tags.get_forward_backward_by_key(way, data, "toll")
|
local forward_toll, backward_toll = Tags.get_forward_backward_by_key(way, data, "toll")
|
||||||
local forward_route, backward_route = Tags.get_forward_backward_by_key(way, data, "route")
|
local forward_route, backward_route = Tags.get_forward_backward_by_key(way, data, "route")
|
||||||
|
|
||||||
@ -310,7 +311,7 @@ function Handlers.handle_classes(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- reduce speed on bad surfaces
|
-- reduce speed on bad surfaces
|
||||||
function Handlers.handle_surface(way,result,data,profile)
|
function WayHandlers.surface(profile,way,result,data)
|
||||||
local surface = way:get_value_by_key("surface")
|
local surface = way:get_value_by_key("surface")
|
||||||
local tracktype = way:get_value_by_key("tracktype")
|
local tracktype = way:get_value_by_key("tracktype")
|
||||||
local smoothness = way:get_value_by_key("smoothness")
|
local smoothness = way:get_value_by_key("smoothness")
|
||||||
@ -330,7 +331,7 @@ function Handlers.handle_surface(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- scale speeds to get better average driving times
|
-- scale speeds to get better average driving times
|
||||||
function Handlers.handle_penalties(way,result,data,profile)
|
function WayHandlers.penalties(profile,way,result,data)
|
||||||
-- heavily penalize a way tagged with all HOV lanes
|
-- heavily penalize a way tagged with all HOV lanes
|
||||||
-- in order to only route over them if there is no other option
|
-- in order to only route over them if there is no other option
|
||||||
local service_penalty = 1.0
|
local service_penalty = 1.0
|
||||||
@ -375,7 +376,7 @@ function Handlers.handle_penalties(way,result,data,profile)
|
|||||||
local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
||||||
local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
local backward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty)
|
||||||
|
|
||||||
if properties.weight_name == 'routability' then
|
if profile.properties.weight_name == 'routability' then
|
||||||
if result.forward_speed > 0 then
|
if result.forward_speed > 0 then
|
||||||
result.forward_rate = (result.forward_speed * forward_penalty) / 3.6
|
result.forward_rate = (result.forward_speed * forward_penalty) / 3.6
|
||||||
end
|
end
|
||||||
@ -389,11 +390,11 @@ function Handlers.handle_penalties(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- maxspeed and advisory maxspeed
|
-- maxspeed and advisory maxspeed
|
||||||
function Handlers.handle_maxspeed(way,result,data,profile)
|
function WayHandlers.maxspeed(profile,way,result,data)
|
||||||
local keys = Sequence { 'maxspeed:advisory', 'maxspeed' }
|
local keys = Sequence { 'maxspeed:advisory', 'maxspeed' }
|
||||||
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
|
local forward, backward = Tags.get_forward_backward_by_set(way,data,keys)
|
||||||
forward = Handlers.parse_maxspeed(forward,profile)
|
forward = WayHandlers.parse_maxspeed(forward,profile)
|
||||||
backward = Handlers.parse_maxspeed(backward,profile)
|
backward = WayHandlers.parse_maxspeed(backward,profile)
|
||||||
|
|
||||||
if forward and forward > 0 then
|
if forward and forward > 0 then
|
||||||
result.forward_speed = forward * profile.speed_reduction
|
result.forward_speed = forward * profile.speed_reduction
|
||||||
@ -404,7 +405,7 @@ function Handlers.handle_maxspeed(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Handlers.parse_maxspeed(source,profile)
|
function WayHandlers.parse_maxspeed(source,profile)
|
||||||
if not source then
|
if not source then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
@ -429,7 +430,7 @@ function Handlers.parse_maxspeed(source,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle oneways tags
|
-- handle oneways tags
|
||||||
function Handlers.handle_oneway(way,result,data,profile)
|
function WayHandlers.oneway(profile,way,result,data)
|
||||||
if not profile.oneway_handling then
|
if not profile.oneway_handling then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -476,8 +477,8 @@ function Handlers.handle_oneway(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Handlers.handle_weights(way,result,data,profile)
|
function WayHandlers.weights(profile,way,result,data)
|
||||||
if properties.weight_name == 'distance' then
|
if profile.properties.weight_name == 'distance' then
|
||||||
result.weight = -1
|
result.weight = -1
|
||||||
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
-- set weight rates to 1 for the distance weight, edge weights are distance / rate
|
||||||
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
if (result.forward_mode ~= mode.inaccessible and result.forward_speed > 0) then
|
||||||
@ -490,7 +491,7 @@ function Handlers.handle_weights(way,result,data,profile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- handle various that can block access
|
-- handle various that can block access
|
||||||
function Handlers.handle_blocked_ways(way,result,data,profile)
|
function WayHandlers.blocked_ways(profile,way,result,data)
|
||||||
|
|
||||||
-- areas
|
-- areas
|
||||||
if profile.avoid.area and way:get_value_by_key("area") == "yes" then
|
if profile.avoid.area and way:get_value_by_key("area") == "yes" then
|
||||||
@ -554,27 +555,27 @@ end
|
|||||||
-- Call a sequence of handlers, aborting in case a handler returns false. Example:
|
-- Call a sequence of handlers, aborting in case a handler returns false. Example:
|
||||||
--
|
--
|
||||||
-- handlers = Sequence {
|
-- handlers = Sequence {
|
||||||
-- 'handle_tag_prefetch',
|
-- WayHandlers.tag_prefetch,
|
||||||
-- 'handle_default_mode',
|
-- WayHandlers.default_mode,
|
||||||
-- 'handle_blocked_ways',
|
-- WayHandlers.blocked_ways,
|
||||||
-- 'handle_access',
|
-- WayHandlers.access,
|
||||||
-- 'handle_speed',
|
-- WayHandlers.speed,
|
||||||
-- 'handle_names'
|
-- WayHandlers.names
|
||||||
-- }
|
-- }
|
||||||
--
|
--
|
||||||
-- Handlers.run(handlers,way,result,data,profile)
|
-- WayHandlers.run(handlers,way,result,data,profile)
|
||||||
--
|
--
|
||||||
-- Each method in the list will be called on the Handlers object.
|
-- Each method in the list will be called on the WayHandlers object.
|
||||||
-- All handlers must accept the parameteres (way,result,data,profile) and return false
|
-- All handlers must accept the parameteres (profile,way,result,data) and return false
|
||||||
-- if the handler chain should be aborted.
|
-- if the handler chain should be aborted.
|
||||||
-- To ensure the correct order of method calls, use a Sequence of handler names.
|
-- To ensure the correct order of method calls, use a Sequence of handler names.
|
||||||
|
|
||||||
function Handlers.run(handlers,way,result,data,profile)
|
function WayHandlers.run(profile,way,result,data,handlers)
|
||||||
for i,handler in ipairs(handlers) do
|
for i,handler in ipairs(handlers) do
|
||||||
if Handlers[handler](way,result,data,profile) == false then
|
if handler(profile,way,result,data) == false then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Handlers
|
return WayHandlers
|
@ -1,19 +1,30 @@
|
|||||||
api_version = 1
|
|
||||||
-- Rasterbot profile
|
-- Rasterbot profile
|
||||||
|
|
||||||
properties.force_split_edges = true
|
api_version = 2
|
||||||
|
|
||||||
-- Set to true if you need to call the node_function for every node.
|
function setup()
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
local raster_path = os.getenv('OSRM_RASTER_SOURCE') or "rastersource.asc"
|
||||||
-- (which slow down pre-processing).
|
|
||||||
properties.call_tagless_node_function = false
|
|
||||||
|
|
||||||
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
return {
|
||||||
|
properties = {
|
||||||
function node_function (node, result)
|
force_split_edges = true,
|
||||||
|
process_call_tagless_node = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
raster_source = raster:load(
|
||||||
|
raster_path,
|
||||||
|
0, -- lon_min
|
||||||
|
0.1, -- lon_max
|
||||||
|
0, -- lat_min
|
||||||
|
0.1, -- lat_max
|
||||||
|
5, -- nrows
|
||||||
|
4 -- ncols
|
||||||
|
)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function way_function (way, result)
|
-- Minimalist process_ways in order to test source_ and process_segments
|
||||||
|
function process_way (profile, way, result)
|
||||||
local highway = way:get_value_by_key("highway")
|
local highway = way:get_value_by_key("highway")
|
||||||
local name = way:get_value_by_key("name")
|
local name = way:get_value_by_key("name")
|
||||||
|
|
||||||
@ -28,25 +39,9 @@ function way_function (way, result)
|
|||||||
result.backward_speed = 15
|
result.backward_speed = 15
|
||||||
end
|
end
|
||||||
|
|
||||||
function source_function ()
|
function process_segment (profile, segment)
|
||||||
local path = os.getenv('OSRM_RASTER_SOURCE')
|
local sourceData = raster:query(profile.raster_source, segment.source.lon, segment.source.lat)
|
||||||
if not path then
|
local targetData = raster:query(profile.raster_source, segment.target.lon, segment.target.lat)
|
||||||
path = "rastersource.asc"
|
|
||||||
end
|
|
||||||
raster_source = sources:load(
|
|
||||||
path,
|
|
||||||
0, -- lon_min
|
|
||||||
0.1, -- lon_max
|
|
||||||
0, -- lat_min
|
|
||||||
0.1, -- lat_max
|
|
||||||
5, -- nrows
|
|
||||||
4 -- ncols
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
function segment_function (segment)
|
|
||||||
local sourceData = sources:query(raster_source, segment.source.lon, segment.source.lat)
|
|
||||||
local targetData = sources:query(raster_source, segment.target.lon, segment.target.lat)
|
|
||||||
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
local scaled_weight = segment.weight
|
local scaled_weight = segment.weight
|
||||||
@ -66,3 +61,9 @@ function segment_function (segment)
|
|||||||
segment.weight = scaled_weight
|
segment.weight = scaled_weight
|
||||||
segment.duration = scaled_duration
|
segment.duration = scaled_duration
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_way = process_way,
|
||||||
|
process_segment = process_segment
|
||||||
|
}
|
||||||
|
@ -1,50 +1,10 @@
|
|||||||
api_version = 1
|
-- Rasterbot with interpolation profile
|
||||||
-- Rasterbot profile
|
|
||||||
|
|
||||||
-- Set to true if you need to call the node_function for every node.
|
functions = require('rasterbot')
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
|
||||||
-- (which slow down pre-processing).
|
|
||||||
properties.call_tagless_node_function = false
|
|
||||||
|
|
||||||
-- Minimalist node_ and way_functions in order to test source_ and segment_functions
|
functions.process_segment = function(profile, segment)
|
||||||
|
local sourceData = raster:interpolate(profile.raster_source, segment.source.lon, segment.source.lat)
|
||||||
function node_function (node, result)
|
local targetData = raster:interpolate(profile.raster_source, segment.target.lon, segment.target.lat)
|
||||||
end
|
|
||||||
|
|
||||||
function way_function (way, result)
|
|
||||||
local highway = way:get_value_by_key("highway")
|
|
||||||
local name = way:get_value_by_key("name")
|
|
||||||
|
|
||||||
if name then
|
|
||||||
result.name = name
|
|
||||||
end
|
|
||||||
|
|
||||||
result.forward_mode = mode.cycling
|
|
||||||
result.backward_mode = mode.cycling
|
|
||||||
|
|
||||||
result.forward_speed = 15
|
|
||||||
result.backward_speed = 15
|
|
||||||
end
|
|
||||||
|
|
||||||
function source_function ()
|
|
||||||
local path = os.getenv('OSRM_RASTER_SOURCE')
|
|
||||||
if not path then
|
|
||||||
path = "rastersource.asc"
|
|
||||||
end
|
|
||||||
raster_source = sources:load(
|
|
||||||
path,
|
|
||||||
0, -- lon_min
|
|
||||||
0.1, -- lon_max
|
|
||||||
0, -- lat_min
|
|
||||||
0.1, -- lat_max
|
|
||||||
5, -- nrows
|
|
||||||
4 -- ncols
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
function segment_function (segment)
|
|
||||||
local sourceData = sources:interpolate(raster_source, segment.source.lon, segment.source.lat)
|
|
||||||
local targetData = sources:interpolate(raster_source, segment.target.lon, segment.target.lat)
|
|
||||||
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
io.write("evaluating segment: " .. sourceData.datum .. " " .. targetData.datum .. "\n")
|
||||||
local invalid = sourceData.invalid_data()
|
local invalid = sourceData.invalid_data()
|
||||||
local scaled_weight = segment.weight
|
local scaled_weight = segment.weight
|
||||||
@ -64,3 +24,5 @@ function segment_function (segment)
|
|||||||
segment.weight = scaled_weight
|
segment.weight = scaled_weight
|
||||||
segment.duration = scaled_duration
|
segment.duration = scaled_duration
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
@ -1,49 +1,35 @@
|
|||||||
api_version = 1
|
|
||||||
-- Testbot profile
|
-- Testbot profile
|
||||||
|
|
||||||
-- Moves at fixed, well-known speeds, practical for testing speed and travel times:
|
-- Moves at fixed, well-known speeds, practical for testing speed and travel times:
|
||||||
|
|
||||||
-- Primary road: 36km/h = 36000m/3600s = 100m/10s
|
-- Primary road: 36km/h = 36000m/3600s = 100m/10s
|
||||||
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s
|
-- Secondary road: 18km/h = 18000m/3600s = 100m/20s
|
||||||
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
|
-- Tertiary road: 12km/h = 12000m/3600s = 100m/30s
|
||||||
|
|
||||||
speed_profile = {
|
api_version = 2
|
||||||
["primary"] = 36,
|
|
||||||
["secondary"] = 18,
|
|
||||||
["tertiary"] = 12,
|
|
||||||
["steps"] = 6,
|
|
||||||
["default"] = 24
|
|
||||||
}
|
|
||||||
|
|
||||||
-- these settings are read directly by osrm
|
function setup()
|
||||||
|
return {
|
||||||
|
properties = {
|
||||||
|
continue_straight_at_waypoint = true,
|
||||||
|
max_speed_for_map_matching = 30/3.6, --km -> m/s
|
||||||
|
weight_name = 'duration',
|
||||||
|
process_call_tagless_node = false,
|
||||||
|
uturn_penalty = 20,
|
||||||
|
traffic_light_penalty = 7, -- seconds
|
||||||
|
use_turn_restrictions = true
|
||||||
|
},
|
||||||
|
|
||||||
properties.continue_straight_at_waypoint = true
|
default_speed = 24,
|
||||||
properties.use_turn_restrictions = true
|
speeds = {
|
||||||
properties.max_speed_for_map_matching = 30/3.6 --km -> m/s
|
primary = 36,
|
||||||
properties.weight_name = 'duration'
|
secondary = 18,
|
||||||
|
tertiary = 12,
|
||||||
-- Set to true if you need to call the node_function for every node.
|
steps = 6,
|
||||||
-- Generally can be left as false to avoid unnecessary Lua calls
|
}
|
||||||
-- (which slow down pre-processing).
|
}
|
||||||
properties.call_tagless_node_function = false
|
|
||||||
|
|
||||||
local uturn_penalty = 20
|
|
||||||
local traffic_light_penalty = 7 -- seconds
|
|
||||||
|
|
||||||
function limit_speed(speed, limits)
|
|
||||||
-- don't use ipairs(), since it stops at the first nil value
|
|
||||||
for i=1, #limits do
|
|
||||||
limit = limits[i]
|
|
||||||
if limit ~= nil and limit > 0 then
|
|
||||||
if limit < speed then
|
|
||||||
return limit -- stop at first speedlimit that's smaller than speed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return speed
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function node_function (node, result)
|
function process_node (profile, node, result)
|
||||||
local traffic_signal = node:get_value_by_key("highway")
|
local traffic_signal = node:get_value_by_key("highway")
|
||||||
|
|
||||||
if traffic_signal and traffic_signal == "traffic_signals" then
|
if traffic_signal and traffic_signal == "traffic_signals" then
|
||||||
@ -52,7 +38,7 @@ function node_function (node, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function way_function (way, result)
|
function process_way (profile, way, result)
|
||||||
local highway = way:get_value_by_key("highway")
|
local highway = way:get_value_by_key("highway")
|
||||||
local name = way:get_value_by_key("name")
|
local name = way:get_value_by_key("name")
|
||||||
local oneway = way:get_value_by_key("oneway")
|
local oneway = way:get_value_by_key("oneway")
|
||||||
@ -75,7 +61,7 @@ function way_function (way, result)
|
|||||||
result.forward_mode = mode.route
|
result.forward_mode = mode.route
|
||||||
result.backward_mode = mode.route
|
result.backward_mode = mode.route
|
||||||
else
|
else
|
||||||
local speed_forw = speed_profile[highway] or speed_profile['default']
|
local speed_forw = profile.speeds[highway] or profile.default_speed
|
||||||
local speed_back = speed_forw
|
local speed_back = speed_forw
|
||||||
|
|
||||||
if highway == "river" then
|
if highway == "river" then
|
||||||
@ -122,12 +108,19 @@ function way_function (way, result)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function turn_function (turn)
|
function process_turn (profile, turn)
|
||||||
if turn.direction_modifier == direction_modifier.uturn then
|
if turn.direction_modifier == direction_modifier.uturn then
|
||||||
turn.duration = uturn_penalty
|
turn.duration = profile.properties.uturn_penalty
|
||||||
turn.weight = uturn_penalty
|
turn.weight = profile.properties.uturn_penalty
|
||||||
end
|
end
|
||||||
if turn.has_traffic_light then
|
if turn.has_traffic_light then
|
||||||
turn.duration = turn.duration + traffic_light_penalty
|
turn.duration = turn.duration + profile.properties.traffic_light_penalty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
setup = setup,
|
||||||
|
process_way = process_way,
|
||||||
|
process_node = process_node,
|
||||||
|
process_turn = process_turn
|
||||||
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
api_version = 1
|
|
||||||
|
|
||||||
-- Testbot, with turn penalty
|
-- Testbot, with turn penalty
|
||||||
-- Used for testing turn penalties
|
-- Used for testing turn penalties
|
||||||
|
|
||||||
require 'testbot'
|
functions = require 'testbot'
|
||||||
|
|
||||||
function turn_function (turn)
|
functions.process_turn = function(profile, turn)
|
||||||
turn.duration = 20 * math.abs(turn.angle) / 180
|
turn.duration = 20 * math.abs(turn.angle) / 180
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return functions
|
@ -224,9 +224,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
|
|||||||
turn_lane_map,
|
turn_lane_map,
|
||||||
scripting_environment.GetProfileProperties());
|
scripting_environment.GetProfileProperties());
|
||||||
|
|
||||||
// setup raster sources
|
|
||||||
scripting_environment.SetupSources();
|
|
||||||
|
|
||||||
std::string generator = header.get("generator");
|
std::string generator = header.get("generator");
|
||||||
if (generator.empty())
|
if (generator.empty())
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ RasterDatum RasterSource::GetRasterInterpolate(const int lon, const int lat) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load raster source into memory
|
// Load raster source into memory
|
||||||
int SourceContainer::LoadRasterSource(const std::string &path_string,
|
int RasterContainer::LoadRasterSource(const std::string &path_string,
|
||||||
double xmin,
|
double xmin,
|
||||||
double xmax,
|
double xmax,
|
||||||
double ymin,
|
double ymin,
|
||||||
@ -125,7 +125,7 @@ int SourceContainer::LoadRasterSource(const std::string &path_string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// External function for looking up nearest data point from a specified source
|
// External function for looking up nearest data point from a specified source
|
||||||
RasterDatum SourceContainer::GetRasterDataFromSource(unsigned int source_id, double lon, double lat)
|
RasterDatum RasterContainer::GetRasterDataFromSource(unsigned int source_id, double lon, double lat)
|
||||||
{
|
{
|
||||||
if (LoadedSources.size() < source_id + 1)
|
if (LoadedSources.size() < source_id + 1)
|
||||||
{
|
{
|
||||||
@ -146,7 +146,7 @@ RasterDatum SourceContainer::GetRasterDataFromSource(unsigned int source_id, dou
|
|||||||
|
|
||||||
// External function for looking up interpolated data from a specified source
|
// External function for looking up interpolated data from a specified source
|
||||||
RasterDatum
|
RasterDatum
|
||||||
SourceContainer::GetRasterInterpolateFromSource(unsigned int source_id, double lon, double lat)
|
RasterContainer::GetRasterInterpolateFromSource(unsigned int source_id, double lon, double lat)
|
||||||
{
|
{
|
||||||
if (LoadedSources.size() < source_id + 1)
|
if (LoadedSources.size() < source_id + 1)
|
||||||
{
|
{
|
||||||
|
@ -216,15 +216,13 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
"sharp_left",
|
"sharp_left",
|
||||||
extractor::guidance::DirectionModifier::SharpLeft);
|
extractor::guidance::DirectionModifier::SharpLeft);
|
||||||
|
|
||||||
context.state.new_usertype<SourceContainer>("sources",
|
context.state.new_usertype<RasterContainer>("raster",
|
||||||
"load",
|
"load",
|
||||||
&SourceContainer::LoadRasterSource,
|
&RasterContainer::LoadRasterSource,
|
||||||
"query",
|
"query",
|
||||||
&SourceContainer::GetRasterDataFromSource,
|
&RasterContainer::GetRasterDataFromSource,
|
||||||
"interpolate",
|
"interpolate",
|
||||||
&SourceContainer::GetRasterInterpolateFromSource);
|
&RasterContainer::GetRasterInterpolateFromSource);
|
||||||
|
|
||||||
context.state.new_enum("constants", "precision", COORDINATE_PRECISION);
|
|
||||||
|
|
||||||
context.state.new_usertype<ProfileProperties>(
|
context.state.new_usertype<ProfileProperties>(
|
||||||
"ProfileProperties",
|
"ProfileProperties",
|
||||||
@ -421,8 +419,10 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
context.state.new_usertype<RasterDatum>(
|
context.state.new_usertype<RasterDatum>(
|
||||||
"RasterDatum", "datum", &RasterDatum::datum, "invalid_data", &RasterDatum::get_invalid);
|
"RasterDatum", "datum", &RasterDatum::datum, "invalid_data", &RasterDatum::get_invalid);
|
||||||
|
|
||||||
|
// the "properties" global is only used in v1 of the api, but we don't know
|
||||||
|
// the version until we have read the file. so we have to declare it in any case.
|
||||||
|
// we will then clear it for v2 profiles after reading the file
|
||||||
context.state["properties"] = &context.properties;
|
context.state["properties"] = &context.properties;
|
||||||
context.state["sources"] = &context.sources;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// end of register block
|
// end of register block
|
||||||
@ -430,24 +430,15 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
|
|
||||||
util::luaAddScriptFolderToLoadPath(context.state.lua_state(), file_name.c_str());
|
util::luaAddScriptFolderToLoadPath(context.state.lua_state(), file_name.c_str());
|
||||||
|
|
||||||
context.state.script_file(file_name);
|
sol::optional<sol::table> function_table = context.state.script_file(file_name);
|
||||||
|
|
||||||
// cache references to functions for faster execution
|
|
||||||
context.turn_function = context.state["turn_function"];
|
|
||||||
context.node_function = context.state["node_function"];
|
|
||||||
context.way_function = context.state["way_function"];
|
|
||||||
context.segment_function = context.state["segment_function"];
|
|
||||||
|
|
||||||
context.has_turn_penalty_function = context.turn_function.valid();
|
|
||||||
context.has_node_function = context.node_function.valid();
|
|
||||||
context.has_way_function = context.way_function.valid();
|
|
||||||
context.has_segment_function = context.segment_function.valid();
|
|
||||||
|
|
||||||
// Check profile API version
|
// Check profile API version
|
||||||
auto maybe_version = context.state.get<sol::optional<int>>("api_version");
|
auto maybe_version = context.state.get<sol::optional<int>>("api_version");
|
||||||
if (maybe_version)
|
if (maybe_version)
|
||||||
{
|
|
||||||
context.api_version = *maybe_version;
|
context.api_version = *maybe_version;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.api_version = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.api_version < SUPPORTED_MIN_API_VERSION ||
|
if (context.api_version < SUPPORTED_MIN_API_VERSION ||
|
||||||
@ -459,14 +450,140 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
|
|||||||
" are supported." + SOURCE_REF);
|
" are supported." + SOURCE_REF);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that version-dependent properties were not changed by profile
|
util::Log() << "Using profile api version " << context.api_version;
|
||||||
|
|
||||||
|
// version-dependent parts of the api
|
||||||
switch (context.api_version)
|
switch (context.api_version)
|
||||||
{
|
{
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// clear global not used in v2
|
||||||
|
context.state["properties"] = sol::nullopt;
|
||||||
|
|
||||||
|
// check function table
|
||||||
|
if (function_table == sol::nullopt)
|
||||||
|
throw util::exception("Profile must return a function table.");
|
||||||
|
|
||||||
|
// setup helpers
|
||||||
|
context.state["raster"] = &context.raster_sources;
|
||||||
|
|
||||||
|
// set constants
|
||||||
|
context.state.new_enum("constants",
|
||||||
|
"precision",
|
||||||
|
COORDINATE_PRECISION,
|
||||||
|
"max_turn_weight",
|
||||||
|
std::numeric_limits<TurnPenalty>::max());
|
||||||
|
|
||||||
|
// call initialize function
|
||||||
|
sol::function setup_function = function_table.value()["setup"];
|
||||||
|
if (!setup_function.valid())
|
||||||
|
throw util::exception("Profile must have an setup() function.");
|
||||||
|
sol::optional<sol::table> profile_table = setup_function();
|
||||||
|
if (profile_table == sol::nullopt)
|
||||||
|
throw util::exception("Profile setup() must return a table.");
|
||||||
|
else
|
||||||
|
context.profile_table = profile_table.value();
|
||||||
|
|
||||||
|
// store functions
|
||||||
|
context.turn_function = function_table.value()["process_turn"];
|
||||||
|
context.node_function = function_table.value()["process_node"];
|
||||||
|
context.way_function = function_table.value()["process_way"];
|
||||||
|
context.segment_function = function_table.value()["process_segment"];
|
||||||
|
|
||||||
|
context.has_turn_penalty_function = context.turn_function.valid();
|
||||||
|
context.has_node_function = context.node_function.valid();
|
||||||
|
context.has_way_function = context.way_function.valid();
|
||||||
|
context.has_segment_function = context.segment_function.valid();
|
||||||
|
|
||||||
|
// read properties from 'profile.properties' table
|
||||||
|
sol::table properties = context.profile_table["properties"];
|
||||||
|
if (properties.valid())
|
||||||
|
{
|
||||||
|
sol::optional<std::string> weight_name = properties["weight_name"];
|
||||||
|
if (weight_name != sol::nullopt)
|
||||||
|
context.properties.SetWeightName(weight_name.value());
|
||||||
|
|
||||||
|
sol::optional<std::int32_t> traffic_signal_penalty =
|
||||||
|
properties["traffic_signal_penalty"];
|
||||||
|
if (traffic_signal_penalty != sol::nullopt)
|
||||||
|
context.properties.SetTrafficSignalPenalty(traffic_signal_penalty.value());
|
||||||
|
|
||||||
|
sol::optional<std::int32_t> u_turn_penalty = properties["u_turn_penalty"];
|
||||||
|
if (u_turn_penalty != sol::nullopt)
|
||||||
|
context.properties.SetUturnPenalty(u_turn_penalty.value());
|
||||||
|
|
||||||
|
sol::optional<double> max_speed_for_map_matching =
|
||||||
|
properties["max_speed_for_map_matching"];
|
||||||
|
if (max_speed_for_map_matching != sol::nullopt)
|
||||||
|
context.properties.SetMaxSpeedForMapMatching(max_speed_for_map_matching.value());
|
||||||
|
|
||||||
|
sol::optional<bool> continue_straight_at_waypoint =
|
||||||
|
properties["continue_straight_at_waypoint"];
|
||||||
|
if (continue_straight_at_waypoint != sol::nullopt)
|
||||||
|
context.properties.continue_straight_at_waypoint =
|
||||||
|
continue_straight_at_waypoint.value();
|
||||||
|
|
||||||
|
sol::optional<bool> use_turn_restrictions = properties["use_turn_restrictions"];
|
||||||
|
if (use_turn_restrictions != sol::nullopt)
|
||||||
|
context.properties.use_turn_restrictions = use_turn_restrictions.value();
|
||||||
|
|
||||||
|
sol::optional<bool> left_hand_driving = properties["left_hand_driving"];
|
||||||
|
if (left_hand_driving != sol::nullopt)
|
||||||
|
context.properties.left_hand_driving = left_hand_driving.value();
|
||||||
|
|
||||||
|
sol::optional<unsigned> weight_precision = properties["weight_precision"];
|
||||||
|
if (weight_precision != sol::nullopt)
|
||||||
|
context.properties.weight_precision = weight_precision.value();
|
||||||
|
|
||||||
|
sol::optional<bool> force_split_edges = properties["force_split_edges"];
|
||||||
|
if (force_split_edges != sol::nullopt)
|
||||||
|
context.properties.force_split_edges = force_split_edges.value();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
|
{
|
||||||
|
// cache references to functions for faster execution
|
||||||
|
context.turn_function = context.state["turn_function"];
|
||||||
|
context.node_function = context.state["node_function"];
|
||||||
|
context.way_function = context.state["way_function"];
|
||||||
|
context.segment_function = context.state["segment_function"];
|
||||||
|
|
||||||
|
context.has_turn_penalty_function = context.turn_function.valid();
|
||||||
|
context.has_node_function = context.node_function.valid();
|
||||||
|
context.has_way_function = context.way_function.valid();
|
||||||
|
context.has_segment_function = context.segment_function.valid();
|
||||||
|
|
||||||
|
// setup helpers
|
||||||
|
context.state["sources"] = &context.raster_sources;
|
||||||
|
|
||||||
|
// set constants
|
||||||
|
context.state.new_enum("constants", "precision", COORDINATE_PRECISION);
|
||||||
|
|
||||||
BOOST_ASSERT(context.properties.GetUturnPenalty() == 0);
|
BOOST_ASSERT(context.properties.GetUturnPenalty() == 0);
|
||||||
BOOST_ASSERT(context.properties.GetTrafficSignalPenalty() == 0);
|
BOOST_ASSERT(context.properties.GetTrafficSignalPenalty() == 0);
|
||||||
|
|
||||||
|
// call source_function if present
|
||||||
|
sol::function source_function = context.state["source_function"];
|
||||||
|
if (source_function.valid())
|
||||||
|
{
|
||||||
|
source_function();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0:
|
case 0:
|
||||||
|
// cache references to functions for faster execution
|
||||||
|
context.turn_function = context.state["turn_function"];
|
||||||
|
context.node_function = context.state["node_function"];
|
||||||
|
context.way_function = context.state["way_function"];
|
||||||
|
context.segment_function = context.state["segment_function"];
|
||||||
|
|
||||||
|
context.has_turn_penalty_function = context.turn_function.valid();
|
||||||
|
context.has_node_function = context.node_function.valid();
|
||||||
|
context.has_way_function = context.way_function.valid();
|
||||||
|
context.has_segment_function = context.segment_function.valid();
|
||||||
|
|
||||||
BOOST_ASSERT(context.properties.GetWeightName() == "duration");
|
BOOST_ASSERT(context.properties.GetWeightName() == "duration");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -542,48 +659,62 @@ void Sol2ScriptingEnvironment::ProcessElements(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
|
std::vector<std::string>
|
||||||
|
Sol2ScriptingEnvironment::GetStringListFromFunction(const std::string &function_name)
|
||||||
{
|
{
|
||||||
auto &context = GetSol2Context();
|
auto &context = GetSol2Context();
|
||||||
BOOST_ASSERT(context.state.lua_state() != nullptr);
|
BOOST_ASSERT(context.state.lua_state() != nullptr);
|
||||||
std::vector<std::string> suffixes_vector;
|
std::vector<std::string> strings;
|
||||||
|
sol::function function = context.state[function_name];
|
||||||
sol::function get_name_suffix_list = context.state["get_name_suffix_list"];
|
if (function.valid())
|
||||||
|
|
||||||
if (get_name_suffix_list.valid())
|
|
||||||
{
|
{
|
||||||
get_name_suffix_list(suffixes_vector);
|
function(strings);
|
||||||
}
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
return suffixes_vector;
|
std::vector<std::string>
|
||||||
|
Sol2ScriptingEnvironment::GetStringListFromTable(const std::string &table_name)
|
||||||
|
{
|
||||||
|
auto &context = GetSol2Context();
|
||||||
|
BOOST_ASSERT(context.state.lua_state() != nullptr);
|
||||||
|
std::vector<std::string> strings;
|
||||||
|
sol::table table = context.profile_table[table_name];
|
||||||
|
if (table.valid())
|
||||||
|
{
|
||||||
|
for (auto &&pair : table)
|
||||||
|
{
|
||||||
|
strings.push_back(pair.second.as<std::string>());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
|
||||||
|
{
|
||||||
|
auto &context = GetSol2Context();
|
||||||
|
switch (context.api_version)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list");
|
||||||
|
case 1:
|
||||||
|
return Sol2ScriptingEnvironment::GetStringListFromFunction("get_name_suffix_list");
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
|
std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
|
||||||
{
|
{
|
||||||
auto &context = GetSol2Context();
|
auto &context = GetSol2Context();
|
||||||
BOOST_ASSERT(context.state.lua_state() != nullptr);
|
switch (context.api_version)
|
||||||
std::vector<std::string> restrictions;
|
|
||||||
|
|
||||||
sol::function get_restrictions = context.state["get_restrictions"];
|
|
||||||
|
|
||||||
if (get_restrictions.valid())
|
|
||||||
{
|
{
|
||||||
get_restrictions(restrictions);
|
case 2:
|
||||||
}
|
return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions");
|
||||||
|
case 1:
|
||||||
return restrictions;
|
return Sol2ScriptingEnvironment::GetStringListFromFunction("get_restrictions");
|
||||||
}
|
default:
|
||||||
|
return {};
|
||||||
void Sol2ScriptingEnvironment::SetupSources()
|
|
||||||
{
|
|
||||||
auto &context = GetSol2Context();
|
|
||||||
BOOST_ASSERT(context.state.lua_state() != nullptr);
|
|
||||||
|
|
||||||
sol::function source_function = context.state["source_function"];
|
|
||||||
|
|
||||||
if (source_function.valid())
|
|
||||||
{
|
|
||||||
source_function();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,6 +724,21 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
|
|||||||
|
|
||||||
switch (context.api_version)
|
switch (context.api_version)
|
||||||
{
|
{
|
||||||
|
case 2:
|
||||||
|
if (context.has_turn_penalty_function)
|
||||||
|
{
|
||||||
|
context.turn_function(context.profile_table, turn);
|
||||||
|
|
||||||
|
// Turn weight falls back to the duration value in deciseconds
|
||||||
|
// or uses the extracted unit-less weight value
|
||||||
|
if (context.properties.fallback_to_duration)
|
||||||
|
turn.weight = turn.duration;
|
||||||
|
else
|
||||||
|
// cap turn weight to max turn weight, which depend on weight precision
|
||||||
|
turn.weight = std::min(turn.weight, context.properties.GetMaxTurnWeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (context.has_turn_penalty_function)
|
if (context.has_turn_penalty_function)
|
||||||
{
|
{
|
||||||
@ -644,6 +790,9 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
|
|||||||
{
|
{
|
||||||
switch (context.api_version)
|
switch (context.api_version)
|
||||||
{
|
{
|
||||||
|
case 2:
|
||||||
|
context.segment_function(context.profile_table, segment);
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
context.segment_function(segment);
|
context.segment_function(segment);
|
||||||
break;
|
break;
|
||||||
@ -660,14 +809,32 @@ void LuaScriptingContext::ProcessNode(const osmium::Node &node, ExtractionNode &
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(state.lua_state() != nullptr);
|
BOOST_ASSERT(state.lua_state() != nullptr);
|
||||||
|
|
||||||
node_function(node, result);
|
switch (api_version)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
node_function(profile_table, node, result);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 0:
|
||||||
|
node_function(node, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &result)
|
void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &result)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(state.lua_state() != nullptr);
|
BOOST_ASSERT(state.lua_state() != nullptr);
|
||||||
|
|
||||||
way_function(way, result);
|
switch (api_version)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
way_function(profile_table, way, result);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 0:
|
||||||
|
way_function(way, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ int normalize(double coord) { return static_cast<int>(coord * COORDINATE_PRECISI
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(raster_test)
|
BOOST_AUTO_TEST_CASE(raster_test)
|
||||||
{
|
{
|
||||||
SourceContainer sources;
|
RasterContainer sources;
|
||||||
int source_id =
|
int source_id =
|
||||||
sources.LoadRasterSource(OSRM_FIXTURES_DIR "/raster_data.asc", 1, 1.09, 1, 1.09, 10, 10);
|
sources.LoadRasterSource(OSRM_FIXTURES_DIR "/raster_data.asc", 1, 1.09, 1, 1.09, 10, 10);
|
||||||
BOOST_CHECK_EQUAL(source_id, 0);
|
BOOST_CHECK_EQUAL(source_id, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user