Compare commits

..

2 Commits

Author SHA1 Message Date
Daniel Patterson 9912b26b32 Final release. 2017-09-11 09:25:24 -07:00
Daniel Patterson 838b2a750e Create release branch for 5.12 2017-09-05 12:44:25 -07:00
39 changed files with 318 additions and 1247 deletions
+10 -9
View File
@@ -15,6 +15,7 @@ branches:
- master
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
- 5.12
cache:
yarn: true
@@ -68,7 +69,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
after_success:
- bash <(curl -s https://codecov.io/bash)
@@ -78,7 +79,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux
@@ -86,7 +87,7 @@ matrix:
addons: &clang40
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux
@@ -111,7 +112,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: linux
@@ -125,7 +126,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
- os: linux
@@ -133,7 +134,7 @@ matrix:
addons: &gcc49
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'ccache']
packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
- os: osx
@@ -158,7 +159,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
# Shared Library
@@ -167,7 +168,7 @@ matrix:
addons: &gcc6
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Disabled because CI slowness
@@ -176,7 +177,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests.
+1 -10
View File
@@ -1,14 +1,5 @@
# UNRELEASED
- Profile:
- New function to support relations: `process_relation`. Read more in profiles documentation.
- Append cardinal directions from route relations to ref fields to improve instructions
- Support of `distance` weight in foot and bicycle profiles
- Infrastructure:
- Lua 5.1 support is removed due to lack of support in sol2 https://github.com/ThePhD/sol2/issues/302
- Node.js Bindings:
- Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool
# 5.12.0
- Changes from 5.11.0
- Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways)
- Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
+21 -4
View File
@@ -60,7 +60,7 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_MINOR 12)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
@@ -379,8 +379,8 @@ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
# Activate C++1y
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++14")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
endif()
# Configuring other platform dependencies
@@ -521,7 +521,24 @@ else()
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
MESSAGE(FATAL_ERROR "Lua 5.2 was not found.")
FIND_PACKAGE(Lua 5.1 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
# Now fall back to a lua verison without exact
# in case this cmake version also forces patch versions
FIND_PACKAGE(Lua 5.2)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
FIND_PACKAGE(Lua 5.1)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
MESSAGE(FATAL_ERROR "Lua 5.1 or 5.2 was not found.")
ENDIF()
ENDIF()
ENDIF()
ENDIF()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
+4 -7
View File
@@ -7,22 +7,19 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SET PROJECT_DIR=%CD%
ECHO PROJECT_DIR^: %PROJECT_DIR%
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
:: Check CMake version
SET CMAKE_VERSION=3.9.2
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
ECHO cmake^: && cmake --version
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
cmake --version | findstr /C:%CMAKE_VERSION% && GOTO CMAKE_OK
cmake --version | findstr /C:"3.7.1" && GOTO CMAKE_OK
:CMAKE_NOT_OK
SET CMAKE_VERSION=3.7.1
ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION%
powershell Invoke-WebRequest https://cmake.org/files/v3.9/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
IF NOT EXIST cm.zip powershell Invoke-WebRequest https://cmake.org/files/v3.7/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
IF NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
:CMAKE_OK
ECHO CMAKE_OK
+7 -59
View File
@@ -47,7 +47,7 @@ Profiles can also define a `process_segment` function to handle differences in s
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
## 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.
@@ -91,7 +91,7 @@ The `setup` function is called once when the profile is loaded and must return a
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:
The following global properties can be set under `properties` in the hash you return in the `setup` function:
Attribute | Type | Notes
-------------------------------------|----------|----------------------------------------------------------------------------
@@ -114,7 +114,7 @@ classes | Sequence | Determines the allowed
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
### process_node(profile, node, result, relations)
### 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.
Argument | Description
@@ -122,7 +122,6 @@ 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.
relations| The list of relation attributes passed from `process_relation` function for this node.
The following attributes can be set on `result`:
@@ -131,7 +130,7 @@ Attribute | Type | Notes
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
### process_way(profile, way, result, relations)
## 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
@@ -139,7 +138,6 @@ 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.
relations| The list of relation attributes passed from `process_relation` function for this way.
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.
@@ -179,60 +177,10 @@ road_classification.road_priority_class | Enum | Guidance: order in priority
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
### process_relation(profile, relation, result)
Supported since API **version 3**.
Given an OpenStreetMap relation, the `process_relation` function should setup values into result structure.
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input relation to process (read-only).
result | The output that you will modify.
Relation process work flow consist of next steps:
1. Calls `process_relation` function for each relation. It should fill a `result` structure
2. After that each data will be passed for each member of processed relation into `process_node` and `process_way` functions
The following attributes can be set on that result in `process_relation`:
Attribute | Type | Notes
----------------------------------------|----------|--------------------------------------------------------------------------
is_restriction | Boolean | Flag to determine if relation is a turn restriction
Example processing code:
```lua
function process_way(profile, way, result, relations)
for _, r in ipairs(relations) do
for k, v in pairs(r) do
print('data_' .. k .. '_value_' .. v)
end
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
if t == "route" then
for _, m in ipairs(relation:members()) do
if m:role == "north" then
result[m]['direction'] = 'north'
print('direction_north')
end
end
print('route_relation')
end
end
```
### 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 `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
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.
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.
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.
@@ -317,7 +265,7 @@ Example:
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
-35
View File
@@ -1,35 +0,0 @@
@routing @bicycle
Feature: Bike - Use distance weight
Background:
Given a grid size of 200 meters
Scenario: Bike - Check distance weight
Given the profile file
"""
local functions = require('bicycle')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.properties.weight_name = 'distance'
return profile
end
return functions
"""
Given the node map
"""
a-b-c
"""
And the ways
| nodes | highway |
| abc | residential |
When I route I should get
| from | to | route | weight | time | distance |
| a | b | abc,abc | 200 | 48s | 200m +-1 |
| a | c | abc,abc | 400 | 96s | 400m +-1 |
-68
View File
@@ -1,68 +0,0 @@
@routing @car @relations
Feature: Car - route relations
Background:
Given the profile "car"
@sliproads
Scenario: Cardinal direction assignment to refs
Given the node map
"""
a b
| |
c------+--+------d
e------+--+------f
| |
g h
i----------------j
k----------------l
x----------------y
z----------------w
"""
And the ways
| nodes | name | highway | ref |
| ag | southbound | motorway | I 80 |
| hb | northbound | motorway | I 80 |
| dc | westbound | motorway | I 85;CO 93 |
| ef | eastbound | motorway | I 85;US 12 |
| ij | westbound-2 | motorway | I 99 |
| ji | eastbound-2 | motorway | I 99 |
| kl | eastbound-2 | motorway | I 99 |
| lk | eastbound-2 | motorway | I 99 |
| xy | watermill | motorway | I 45M; US 3 |
And the relations
| type | way:south | route | ref |
| route | ag | road | 80 |
| route | ef | road | 12 |
And the relations
| type | way:north | route | ref |
| route | hb | road | 80 |
| route | cd | road | 93 |
And the relations
| type | way:west | route | ref |
| route | dc | road | 85 |
| route | ij | road | 99 |
| route | xy | road | I 45 |
And the relations
| type | way:east | route | ref |
| route | lk | road | I 99 |
And the relations
| type | way:east | route | ref |
| route | xy | road | US 3 |
When I route I should get
| waypoints | route | ref |
| a,g | southbound,southbound | I 80 $south,I 80 $south |
| h,b | northbound,northbound | I 80 $north,I 80 $north |
| d,c | westbound,westbound | I 85 $west; CO 93 $north,I 85 $west; CO 93 $north |
| e,f | eastbound,eastbound | I 85; US 12 $south,I 85; US 12 $south |
| i,j | westbound-2,westbound-2 | I 99 $west,I 99 $west |
| l,k | eastbound-2,eastbound-2 | I 99 $east,I 99 $east |
| x,y | watermill,watermill | I 45M $west; US 3 $east,I 45M $west; US 3 $east |
-35
View File
@@ -1,35 +0,0 @@
@routing @foot
Feature: Foot - Use distance weight
Background:
Given a grid size of 200 meters
Scenario: Foot - Check distance weight
Given the profile file
"""
local functions = require('foot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.properties.weight_name = 'distance'
return profile
end
return functions
"""
Given the node map
"""
a-b-c
"""
And the ways
| nodes | highway |
| abc | residential |
When I route I should get
| from | to | route | weight | time | distance |
| a | b | abc,abc | 200 | 144s | 200m +-1 |
| a | c | abc,abc | 400 | 288s | 400m +-1 |
-21
View File
@@ -1349,24 +1349,3 @@ Feature: Simple Turns
When I route I should get
| waypoints | route | turns |
| a,d | ab,dc,dc | depart,turn left,arrive |
# https://www.openstreetmap.org/node/1332083066
Scenario: Turns ordering must respect initial bearings
Given the node map
"""
a . be .
\ c.
d/ .f . g
"""
And the ways
| nodes | highway | oneway |
| ab | primary | yes |
| bcd | primary | yes |
| befg | primary | yes |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
| a,g | ab,befg,befg | depart,fork slight left,arrive |
@@ -1,32 +0,0 @@
@extract
Feature: osrm-extract must be silent with NONE
Background:
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been saved to disk
Scenario: osrm-extract - Passing base file with verbosity NONE
Given the profile file
"""
functions = require('testbot')
function way_function(profile, way, result)
result.forward_mode = mode.driving
result.forward_speed = 1
end
functions.process_way = way_function
return functions
"""
When I run "osrm-extract --profile {profile_file} {osm_file} --verbosity NONE"
Then it should exit successfully
And stdout should not contain "[info]"
And stdout should not contain "[error]"
And stdout should not contain "10%"
And stderr should be empty
@@ -24,7 +24,7 @@ Feature: Invalid profile API versions
Scenario: Profile API version too high
Given the profile file
"""
api_version = 4
api_version = 3
"""
And the node map
"""
-119
View File
@@ -1,119 +0,0 @@
Feature: Profile API version 3
Background:
Given a grid size of 100 meters
Scenario: Basic profile function calls and property values
Given the profile file
"""
api_version = 3
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, relations)
print ('process_node ' .. node:id())
end
function process_way(profile, way, result, relations)
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
for _, r in ipairs(relations) do
for k, v in pairs(r) do
print('data_' .. k .. '_value_' .. v)
end
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
if t == "route" then
for _, m in ipairs(relation:members()) do
if m:role() == "north" then
result[m]['direction'] = 'north'
print('direction_north')
end
end
print('route_relation')
end
print ('process_relation ' .. relation:id())
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_relation = process_relation,
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 relations
| type | way:north | route |
| route | ac | road |
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_relation"
And stdout should contain "route_relation"
And stdout should contain "direction_north"
And stdout should contain "data_direction_value_north"
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 |
+1 -5
View File
@@ -24,8 +24,6 @@
#include "util/fingerprint.hpp"
#include "util/json_container.hpp"
#include <tbb/task_scheduler_init.h>
#include <memory>
#include <string>
@@ -55,8 +53,7 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
public:
explicit Engine(const EngineConfig &config)
: task_scheduler(config.use_threads_number),
route_plugin(config.max_locations_viaroute, config.max_alternatives), //
: route_plugin(config.max_locations_viaroute, config.max_alternatives), //
table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), //
@@ -128,7 +125,6 @@ template <typename Algorithm> class Engine final : public EngineInterface
}
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
mutable SearchEngineData<Algorithm> heaps;
tbb::task_scheduler_init task_scheduler;
const plugins::ViaRoutePlugin route_plugin;
const plugins::TablePlugin table_plugin;
-2
View File
@@ -90,8 +90,6 @@ struct EngineConfig final
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH;
int use_threads_number = 1;
std::string verbosity;
};
}
}
@@ -20,8 +20,8 @@ template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
} // namespace routing_algorithms
} // namespace engine
-81
View File
@@ -1,81 +0,0 @@
#ifndef EXTRACTION_RELATION_HPP
#define EXTRACTION_RELATION_HPP
#include <osmium/osm/relation.hpp>
#include <boost/assert.hpp>
#include <string>
#include <unordered_map>
#include <vector>
namespace osrm
{
namespace extractor
{
struct ExtractionRelation
{
using AttributesMap = std::unordered_map<std::string, std::string>;
using OsmIDTyped = std::pair<osmium::object_id_type, osmium::item_type>;
struct OsmIDTypedHash
{
std::size_t operator()(const OsmIDTyped &id) const
{
return id.first ^ (static_cast<std::uint64_t>(id.second) << 56);
}
};
ExtractionRelation() : is_restriction(false) {}
void clear()
{
is_restriction = false;
values.clear();
}
bool IsRestriction() const { return is_restriction; }
AttributesMap &GetMember(const osmium::RelationMember &member)
{
return values[OsmIDTyped(member.ref(), member.type())];
}
bool is_restriction;
std::unordered_map<OsmIDTyped, AttributesMap, OsmIDTypedHash> values;
};
// It contains data of all parsed relations for each node/way element
class ExtractionRelationContainer
{
public:
using AttributesMap = ExtractionRelation::AttributesMap;
using OsmIDTyped = ExtractionRelation::OsmIDTyped;
using RelationList = std::vector<AttributesMap>;
void AddRelation(const ExtractionRelation &rel)
{
BOOST_ASSERT(!rel.is_restriction);
for (auto it : rel.values)
data[it.first].push_back(it.second);
}
const RelationList &Get(const OsmIDTyped &id) const
{
const auto it = data.find(id);
if (it != data.end())
return it->second;
static RelationList empty;
return empty;
}
private:
std::unordered_map<OsmIDTyped, RelationList, ExtractionRelation::OsmIDTypedHash> data;
};
} // namespace extractor
} // namespace osrm
#endif // EXTRACTION_RELATION_HPP
@@ -15,7 +15,6 @@ namespace osmium
{
class Node;
class Way;
class Relation;
}
namespace std
@@ -45,7 +44,6 @@ namespace extractor
class ExtractionContainers;
struct ExtractionNode;
struct ExtractionWay;
struct ExtractionRelation;
struct ProfileProperties;
struct InputConditionalTurnRestriction;
@@ -153,14 +153,6 @@ class CoordinateExtractor
const double length,
const double rate) const;
// find the coordinate at a specific distance in the vector
util::Coordinate
ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates) const;
util::Coordinate ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &length_cache) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const extractor::CompressedEdgeContainer &compressed_geometries;
@@ -249,6 +241,14 @@ class CoordinateExtractor
const double segment_length,
const std::vector<double> &segment_distances,
const std::uint8_t considered_lanes) const;
// find the coordinate at a specific location in the vector
util::Coordinate ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &length_cache) const;
util::Coordinate
ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates) const;
};
} // namespace guidance
+6 -11
View File
@@ -19,7 +19,6 @@ namespace osmium
{
class Node;
class Way;
class Relation;
}
namespace osrm
@@ -34,10 +33,8 @@ namespace extractor
{
class RestrictionParser;
class ExtractionRelationContainer;
struct ExtractionNode;
struct ExtractionWay;
struct ExtractionRelation;
struct ExtractionTurn;
struct ExtractionSegment;
@@ -62,14 +59,12 @@ class ScriptingEnvironment
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
virtual void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
virtual void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
};
}
}
@@ -1,7 +1,6 @@
#ifndef SCRIPTING_ENVIRONMENT_LUA_HPP
#define SCRIPTING_ENVIRONMENT_LUA_HPP
#include "extractor/extraction_relation.hpp"
#include "extractor/raster_source.hpp"
#include "extractor/scripting_environment.hpp"
@@ -20,13 +19,8 @@ namespace extractor
struct LuaScriptingContext final
{
void ProcessNode(const osmium::Node &,
ExtractionNode &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessWay(const osmium::Way &,
ExtractionWay &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
void ProcessNode(const osmium::Node &, ExtractionNode &result);
void ProcessWay(const osmium::Way &, ExtractionWay &result);
ProfileProperties properties;
RasterContainer raster_sources;
@@ -35,13 +29,11 @@ struct LuaScriptingContext final
bool has_turn_penalty_function;
bool has_node_function;
bool has_way_function;
bool has_relation_function;
bool has_segment_function;
sol::function turn_function;
sol::function way_function;
sol::function node_function;
sol::function relation_function;
sol::function segment_function;
int api_version;
@@ -59,7 +51,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
{
public:
static const constexpr int SUPPORTED_MIN_API_VERSION = 0;
static const constexpr int SUPPORTED_MAX_API_VERSION = 3;
static const constexpr int SUPPORTED_MAX_API_VERSION = 2;
explicit Sol2ScriptingEnvironment(const std::string &file_name);
~Sol2ScriptingEnvironment() override = default;
@@ -73,14 +65,12 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
void ProcessTurn(ExtractionTurn &turn) override;
void ProcessSegment(ExtractionSegment &segment) override;
void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
private:
LuaScriptingContext &GetSol2Context();
-8
View File
@@ -186,7 +186,6 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
params->Get(Nan::New("max_locations_map_matching").ToLocalChecked());
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked());
auto use_threads_number = params->Get(Nan::New("use_threads_number").ToLocalChecked());
if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
{
@@ -218,11 +217,6 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
Nan::ThrowError("max_alternatives must be an integral number");
return engine_config_ptr();
}
if (!use_threads_number->IsUndefined() && !use_threads_number->IsNumber())
{
Nan::ThrowError("use_threads_number must be an integral number");
return engine_config_ptr();
}
if (max_locations_trip->IsNumber())
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
@@ -239,8 +233,6 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
if (max_alternatives->IsNumber())
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue());
if (use_threads_number->IsNumber())
engine_config->use_threads_number = static_cast<int>(use_threads_number->NumberValue());
return engine_config;
}
+2 -32
View File
@@ -53,40 +53,10 @@ class Log
virtual ~Log();
std::mutex &get_mutex();
template <typename T> inline Log &operator<<(const T &data)
{
const auto &policy = LogPolicy::GetInstance();
if (!policy.IsMute() && level <= policy.GetLevel())
{
stream << data;
}
return *this;
}
template <typename T> inline Log &operator<<(const std::atomic<T> &data)
{
const auto &policy = LogPolicy::GetInstance();
if (!policy.IsMute() && level <= policy.GetLevel())
{
stream << T(data);
}
return *this;
}
typedef std::ostream &(manip)(std::ostream &);
inline Log &operator<<(manip &m)
{
const auto &policy = LogPolicy::GetInstance();
if (!policy.IsMute() && level <= policy.GetLevel())
{
stream << m;
}
return *this;
}
template <typename T> inline std::ostream &operator<<(const T &data) { return stream << data; }
protected:
const LogLevel level;
LogLevel level;
std::ostringstream buffer;
std::ostream &stream;
};
+1 -1
View File
@@ -83,7 +83,7 @@ class Percent
// When not on a TTY, print newlines after each progress indicator so
// so that progress is visible to line-buffered logging systems
if (!IsStdoutATTY())
log << std::endl;
log << "" << std::endl;
}
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.13.0-cardinal.1",
"version": "5.12.0",
"private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {
+2 -5
View File
@@ -536,7 +536,7 @@ function process_way(profile, way, result)
-- handle turn lanes and road classification, used for guidance
WayHandlers.classification,
-- handle allowed start/end modes
WayHandlers.startpoint,
@@ -544,10 +544,7 @@ function process_way(profile, way, result)
WayHandlers.roundabouts,
-- set name, ref and pronunciation
WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
WayHandlers.names
}
WayHandlers.run(profile,way,result,data,handlers)
+3 -75
View File
@@ -1,14 +1,12 @@
-- Car profile
api_version = 3
api_version = 2
Set = require('lib/set')
Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
function setup()
local use_left_hand_driving = false
@@ -256,7 +254,6 @@ function setup()
["ch:trunk"] = 100,
["ch:motorway"] = 120,
["de:living_street"] = 7,
["dk:rural"] = 80,
["ru:living_street"] = 20,
["ru:urban"] = 60,
["ua:urban"] = 60,
@@ -281,7 +278,7 @@ function setup()
}
end
function process_node(profile, node, result, relations)
function process_node(profile, node, result)
-- parse access and barrier tags
local access = find_access_tag(node, profile.access_tags_hierarchy)
if access then
@@ -308,7 +305,7 @@ function process_node(profile, node, result, relations)
end
end
function process_way(profile, way, result, relations)
function process_way(profile, way, result)
-- the intial filtering of ways based on presence of tags
-- affects processing times significantly, because all ways
-- have to be checked.
@@ -392,74 +389,6 @@ function process_way(profile, way, result, relations)
}
WayHandlers.run(profile,way,result,data,handlers)
-- now process relations data
local matched_refs = nil;
if result.ref then
local match_res = Relations.match_to_ref(relations, result.ref)
local ref = ''
for _, m in pairs(match_res) do
if ref ~= '' then
ref = ref .. '; '
end
if m.dir then
ref = ref .. m.ref .. ' $' .. m.dir
else
ref = ref .. m.ref
end
end
result.ref = ref
end
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
function add_extra_data(m)
local name = relation:get_value_by_key("name")
if name then
result[m]['route_name'] = name
end
local ref = relation:get_value_by_key("ref")
if ref then
result[m]['route_ref'] = ref
end
end
if t == 'route' then
local route = relation:get_value_by_key("route")
if route == 'road' then
for _, m in ipairs(relation:members()) do
-- process case, where directions set as role
local role = string.lower(m:role())
if role == 'north' or role == 'south' or role == 'west' or role == 'east' then
result[m]['route_direction'] = role
add_extra_data(m)
end
end
end
local direction = relation:get_value_by_key('direction')
if direction then
direction = string.lower(direction)
if direction == 'north' or direction == 'south' or direction == 'west' or direction == 'east' then
for _, m in ipairs(relation:members()) do
if m:role() == 'forward' then
result[m]['route_direction'] = direction
add_extra_data(m)
end
end
end
end
end
end
function process_turn(profile, turn)
@@ -504,6 +433,5 @@ return {
setup = setup,
process_way = process_way,
process_node = process_node,
process_relation = process_relation,
process_turn = process_turn
}
+1 -4
View File
@@ -237,10 +237,7 @@ function process_way(profile, way, result)
WayHandlers.startpoint,
-- set name, ref and pronunciation
WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
WayHandlers.names
}
WayHandlers.run(profile,way,result,data,handlers)
-94
View File
@@ -1,94 +0,0 @@
-- Profile functions dealing with various aspects of relation parsing
--
-- You can run a selection you find useful in your profile,
-- or do you own processing if/when required.
Utils = require('lib/utils')
Relations = {}
-- match ref values to relations data
function Relations.match_to_ref(relations, ref)
function calculate_scores(refs, tag_value)
local tag_tokens = Set(Utils.tokenize_common(tag_value))
local result = {}
for i, r in ipairs(refs) do
local ref_tokens = Utils.tokenize_common(r)
local score = 0
for _, t in ipairs(ref_tokens) do
if tag_tokens[t] then
if Utils.is_number(t) then
score = score + 2
else
score = score + 1
end
end
end
result[r] = score
end
return result
end
local references = Utils.string_list_tokens(ref)
local result_match = {}
local order = {}
for i, r in ipairs(references) do
result_match[r] = false
order[i] = r
end
for i, rel in ipairs(relations) do
local name_scores = nil
local name_tokens = {}
local route_name = rel["route_name"]
if route_name then
name_scores = calculate_scores(references, route_name)
end
local ref_scores = nil
local ref_tokens = {}
local route_ref = rel["route_ref"]
if route_ref then
ref_scores = calculate_scores(references, route_ref)
end
-- merge scores
local direction = rel["route_direction"]
if direction then
local best_score = -1
local best_ref = nil
function find_best(scores)
if scores then
for k ,v in pairs(scores) do
if v > best_score then
best_ref = k
best_score = v
end
end
end
end
find_best(name_scores)
find_best(ref_scores)
if best_ref then
result_match[best_ref] = direction
end
end
end
local result = {}
for i, r in ipairs(order) do
result[i] = { ref = r, dir = result_match[r] };
end
return result
end
return Relations
-43
View File
@@ -1,43 +0,0 @@
-- Profile functions to implement common algorithms of data processing
--
-- You can run a selection you find useful in your profile,
-- or do you own processing if/when required.
Utils = {}
-- split string 'a; b; c' to table with values ['a', 'b', 'c']
-- so it use just one separator ';'
function Utils.string_list_tokens(str)
result = {}
local idx = 0
for s in str.gmatch(str, "([^;]*)") do
if s ~= nil and s ~= '' then
idx = idx + 1
result[idx] = s:gsub("^%s*(.-)%s*$", "%1")
end
end
return result
end
-- same as Utils.StringListTokens, but with many possible separators:
-- ',' | ';' | ' '| '(' | ')'
function Utils.tokenize_common(str)
result = {}
local idx = 0
for s in str.gmatch(str, "%S+") do
if s ~= nil and s ~= '' then
idx = idx + 1
result[idx] = s:gsub("^%s*(.-)%s*$", "%1")
end
end
return result
end
-- returns true, if string contains a number
function Utils.is_number(str)
return (tonumber(str) ~= nil)
end
return Utils
+1 -1
View File
@@ -20,7 +20,7 @@ bool EngineConfig::IsValid() const
unlimited_or_more_than(max_locations_trip, 2) &&
unlimited_or_more_than(max_locations_viaroute, 2) &&
unlimited_or_more_than(max_results_nearest, 0) &&
max_alternatives >= 0 && use_threads_number >= 1;
max_alternatives >= 0;
return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid;
}
+129 -145
View File
@@ -2,7 +2,6 @@
#include "engine/routing_algorithms/routing_base_ch.hpp"
#include <boost/assert.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <limits>
#include <memory>
@@ -20,34 +19,18 @@ namespace
{
struct NodeBucket
{
NodeID middle_node;
unsigned column_index; // a column in the weight/duration matrix
unsigned target_id; // essentially a row in the weight matrix
EdgeWeight weight;
EdgeDuration duration;
NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
EdgeWeight duration;
NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration)
: target_id(target_id), weight(weight), duration(duration)
{
}
// partial order comparison
bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
// functor for equal_range
struct Compare
{
bool operator()(const NodeBucket &lhs, const NodeID &rhs) const
{
return lhs.middle_node < rhs;
}
bool operator()(const NodeID &lhs, const NodeBucket &rhs) const
{
return lhs < rhs.middle_node;
}
};
};
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
const NodeID node,
EdgeWeight &weight,
@@ -91,12 +74,12 @@ void relaxOutgoingEdges(const DataFacade<ch::Algorithm> &facade,
{
const NodeID to = facade.GetTarget(edge);
const auto edge_weight = data.weight;
const auto edge_duration = data.duration;
const EdgeWeight edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const auto to_weight = weight + edge_weight;
const auto to_duration = duration + edge_duration;
const EdgeWeight to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to))
@@ -218,12 +201,12 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
continue;
}
const auto edge_weight = data.weight;
const auto edge_duration = data.duration;
const EdgeWeight edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const auto to_weight = weight + edge_weight;
const auto to_duration = duration + edge_duration;
const EdgeWeight to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to))
@@ -246,46 +229,48 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned row_idx,
const unsigned number_of_targets,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
const std::vector<NodeBucket> &search_space_with_buckets,
const SearchSpaceWithBuckets &search_space_with_buckets,
std::vector<EdgeWeight> &weights_table,
std::vector<EdgeDuration> &durations_table,
std::vector<EdgeWeight> &durations_table,
const PhantomNode &phantom_node)
{
const auto node = query_heap.DeleteMin();
const auto source_weight = query_heap.GetKey(node);
const auto source_duration = query_heap.GetData(node).duration;
const NodeID node = query_heap.DeleteMin();
const EdgeWeight source_weight = query_heap.GetKey(node);
const EdgeWeight source_duration = query_heap.GetData(node).duration;
// check if each encountered node has an entry
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
search_space_with_buckets.end(),
node,
NodeBucket::Compare());
for (const auto &current_bucket : boost::make_iterator_range(bucket_list))
const auto bucket_iterator = search_space_with_buckets.find(node);
// iterate bucket if there exists one
if (bucket_iterator != search_space_with_buckets.end())
{
// get target id from bucket entry
const auto column_idx = current_bucket.column_index;
const auto target_weight = current_bucket.weight;
const auto target_duration = current_bucket.duration;
auto &current_weight = weights_table[row_idx * number_of_targets + column_idx];
auto &current_duration = durations_table[row_idx * number_of_targets + column_idx];
// check if new weight is better
auto new_weight = source_weight + target_weight;
auto new_duration = source_duration + target_duration;
if (new_weight < 0)
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
for (const NodeBucket &current_bucket : bucket_list)
{
if (addLoopWeight(facade, node, new_weight, new_duration))
// get target id from bucket entry
const unsigned column_idx = current_bucket.target_id;
const EdgeWeight target_weight = current_bucket.weight;
const EdgeWeight target_duration = current_bucket.duration;
auto &current_weight = weights_table[row_idx * number_of_targets + column_idx];
auto &current_duration = durations_table[row_idx * number_of_targets + column_idx];
// check if new weight is better
auto new_weight = source_weight + target_weight;
auto new_duration = source_duration + target_duration;
if (new_weight < 0)
{
current_weight = std::min(current_weight, new_weight);
current_duration = std::min(current_duration, new_duration);
if (addLoopWeight(facade, node, new_weight, new_duration))
{
current_weight = std::min(current_weight, new_weight);
current_duration = std::min(current_duration, new_duration);
}
}
else if (new_weight < current_weight)
{
current_weight = new_weight;
current_duration = new_duration;
}
}
else if (new_weight < current_weight)
{
current_weight = new_weight;
current_duration = new_duration;
}
}
@@ -297,15 +282,15 @@ template <typename Algorithm>
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned column_idx,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
std::vector<NodeBucket> &search_space_with_buckets,
SearchSpaceWithBuckets &search_space_with_buckets,
const PhantomNode &phantom_node)
{
const auto node = query_heap.DeleteMin();
const auto target_weight = query_heap.GetKey(node);
const auto target_duration = query_heap.GetData(node).duration;
const NodeID node = query_heap.DeleteMin();
const EdgeWeight target_weight = query_heap.GetKey(node);
const EdgeWeight target_duration = query_heap.GetData(node).duration;
// store settled nodes in search space bucket
search_space_with_buckets.emplace_back(node, column_idx, target_weight, target_duration);
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
relaxOutgoingEdges<REVERSE_DIRECTION>(
facade, node, target_weight, target_duration, query_heap, phantom_node);
@@ -316,92 +301,91 @@ template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices)
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices)
{
if (source_indices.empty())
{
source_indices.resize(phantom_nodes.size());
std::iota(source_indices.begin(), source_indices.end(), 0);
}
if (target_indices.empty())
{
target_indices.resize(phantom_nodes.size());
std::iota(target_indices.begin(), target_indices.end(), 0);
}
const auto number_of_sources = source_indices.size();
const auto number_of_targets = target_indices.size();
const auto number_of_sources =
source_indices.empty() ? phantom_nodes.size() : source_indices.size();
const auto number_of_targets =
target_indices.empty() ? phantom_nodes.size() : target_indices.size();
const auto number_of_entries = number_of_sources * number_of_targets;
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
std::vector<EdgeWeight> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
std::mutex lock;
std::vector<NodeBucket> search_space_with_buckets;
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
// Backward search for target phantoms
tbb::parallel_for(
tbb::blocked_range<std::size_t>{0, target_indices.size()},
[&](const tbb::blocked_range<std::size_t> &chunk) {
for (auto column_idx = chunk.begin(), end = chunk.end(); column_idx != end;
++column_idx)
{
const auto index = target_indices[column_idx];
const auto &phantom = phantom_nodes[index];
auto &query_heap = *(engine_working_data.many_to_many_heap);
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(
facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
insertTargetInHeap(query_heap, phantom);
SearchSpaceWithBuckets search_space_with_buckets;
// explore search space
std::vector<NodeBucket> local_buckets;
while (!query_heap.Empty())
{
backwardRoutingStep(facade, column_idx, query_heap, local_buckets, phantom);
}
unsigned column_idx = 0;
const auto search_target_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert target nodes
query_heap.Clear();
insertTargetInHeap(query_heap, phantom);
{ // Insert local buckets into the global search space
std::lock_guard<std::mutex> guard{lock};
search_space_with_buckets.insert(std::end(search_space_with_buckets),
std::begin(local_buckets),
std::end(local_buckets));
}
}
});
// explore search space
while (!query_heap.Empty())
{
backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets, phantom);
}
++column_idx;
};
tbb::parallel_sort(search_space_with_buckets.begin(), search_space_with_buckets.end());
// for each source do forward search
unsigned row_idx = 0;
const auto search_source_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert source nodes
query_heap.Clear();
insertSourceInHeap(query_heap, phantom);
// For each source do forward search
tbb::parallel_for(tbb::blocked_range<std::size_t>{0, source_indices.size()},
[&](const tbb::blocked_range<std::size_t> &chunk) {
for (auto row_idx = chunk.begin(), end = chunk.end(); row_idx != end;
++row_idx)
{
const auto index = source_indices[row_idx];
const auto &phantom = phantom_nodes[index];
// explore search space
while (!query_heap.Empty())
{
forwardRoutingStep(facade,
row_idx,
number_of_targets,
query_heap,
search_space_with_buckets,
weights_table,
durations_table,
phantom);
}
++row_idx;
};
// clear heap and insert source nodes
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(
facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
insertSourceInHeap(query_heap, phantom);
if (target_indices.empty())
{
for (const auto &phantom : phantom_nodes)
{
search_target_phantom(phantom);
}
}
else
{
for (const auto index : target_indices)
{
const auto &phantom = phantom_nodes[index];
search_target_phantom(phantom);
}
}
// explore search space
while (!query_heap.Empty())
{
forwardRoutingStep(facade,
row_idx,
number_of_targets,
query_heap,
search_space_with_buckets,
weights_table,
durations_table,
phantom);
}
}
});
if (source_indices.empty())
{
for (const auto &phantom : phantom_nodes)
{
search_source_phantom(phantom);
}
}
else
{
for (const auto index : source_indices)
{
const auto &phantom = phantom_nodes[index];
search_source_phantom(phantom);
}
}
return durations_table;
}
@@ -410,15 +394,15 @@ template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
const DataFacade<mld::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
} // namespace routing_algorithms
} // namespace engine
+8 -45
View File
@@ -3,7 +3,6 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/files.hpp"
@@ -289,13 +288,12 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const osmium::io::File input_file(config.input_path.string());
osmium::thread::Pool pool(number_of_threads);
std::unique_ptr<osmium::io::Reader> reader(new osmium::io::Reader(
osmium::io::Reader reader(
input_file,
osmium::osm_entity_bits::relation,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no)));
pool,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no));
osmium::io::Header header = reader->header();
const osmium::io::Header header = reader.header();
unsigned number_of_nodes = 0;
unsigned number_of_ways = 0;
@@ -333,7 +331,6 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length());
ExtractionRelationContainer relations;
std::vector<std::string> restrictions = scripting_environment.GetRestrictions();
// setup restriction parser
const RestrictionParser restriction_parser(
@@ -341,19 +338,20 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
config.parse_conditionals,
restrictions);
std::mutex process_mutex;
using SharedBuffer = std::shared_ptr<const osmium::memory::Buffer>;
struct ParsedBuffer
{
SharedBuffer buffer;
std::vector<std::pair<const osmium::Node &, ExtractionNode>> resulting_nodes;
std::vector<std::pair<const osmium::Way &, ExtractionWay>> resulting_ways;
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> resulting_relations;
std::vector<InputConditionalTurnRestriction> resulting_restrictions;
};
tbb::filter_t<void, SharedBuffer> buffer_reader(
tbb::filter::serial_in_order, [&](tbb::flow_control &fc) {
if (auto buffer = reader->read())
if (auto buffer = reader.read())
{
return std::make_shared<const osmium::memory::Buffer>(std::move(buffer));
}
@@ -372,10 +370,8 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
parsed_buffer->buffer = buffer;
scripting_environment.ProcessElements(*buffer,
restriction_parser,
relations,
parsed_buffer->resulting_nodes,
parsed_buffer->resulting_ways,
parsed_buffer->resulting_relations,
parsed_buffer->resulting_restrictions);
return parsed_buffer;
});
@@ -395,46 +391,13 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
{
extractor_callbacks->ProcessWay(result.first, result.second);
}
});
tbb::filter_t<std::shared_ptr<ParsedBuffer>, void> buffer_storage_relation(
tbb::filter::serial_in_order, [&](const std::shared_ptr<ParsedBuffer> parsed_buffer) {
if (!parsed_buffer)
return;
number_of_relations += parsed_buffer->resulting_relations.size();
for (const auto &result : parsed_buffer->resulting_relations)
{
/// TODO: add restriction processing
if (result.second.is_restriction)
continue;
relations.AddRelation(result.second);
}
number_of_relations += parsed_buffer->resulting_restrictions.size();
for (const auto &result : parsed_buffer->resulting_restrictions)
{
extractor_callbacks->ProcessRestriction(result);
}
});
/* Main trick that we can use the same pipeline. It just receive relation objects
* from osmium. So other containers would be empty and doesn't process anything
*/
util::Log() << "Parse relations ...";
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
buffer_reader & buffer_transform & buffer_storage_relation);
reader->close();
/* At this step we just filter ways and nodes from osmium, so any relation wouldn't be
* processed there.
*/
util::Log() << "Parse ways and nodes ...";
reader.reset(new osmium::io::Reader(
input_file,
osmium::osm_entity_bits::node | osmium::osm_entity_bits::way,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no)));
// Number of pipeline tokens that yielded the best speedup was about 1.5 * num_cores
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
buffer_reader & buffer_transform & buffer_storage);
@@ -54,18 +54,11 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
const boost::optional<NodeID> sorting_base,
const bool use_low_precision_angles) const
{
const auto intersection_degree = node_based_graph.GetOutDegree(node_at_center_of_intersection);
const util::Coordinate turn_coordinate = coordinates[node_at_center_of_intersection];
// compute bearings in a relatively small circle to prevent wrong roads order with true bearings
struct RoadWithInitialBearing
{
double bearing;
IntersectionShapeData road;
};
std::vector<RoadWithInitialBearing> initial_roads_ordering;
IntersectionShape intersection;
// reserve enough items (+ the possibly missing u-turn edge)
initial_roads_ordering.reserve(intersection_degree);
const auto intersection_degree = node_based_graph.GetOutDegree(node_at_center_of_intersection);
intersection.reserve(intersection_degree);
const util::Coordinate turn_coordinate = coordinates[node_at_center_of_intersection];
// number of lanes at the intersection changes how far we look down the road
const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection);
@@ -89,11 +82,6 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
auto coordinates = coordinate_extractor.GetCoordinatesAlongRoad(
node_at_center_of_intersection, edge_connected_to_intersection, !INVERT, to_node);
const auto close_coordinate =
coordinate_extractor.ExtractCoordinateAtLength(2. /*m*/, coordinates);
const auto initial_bearing =
util::coordinate_calculation::bearing(turn_coordinate, close_coordinate);
const auto segment_length = util::coordinate_calculation::getLength(
coordinates.begin(),
coordinates.end(),
@@ -135,79 +123,31 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
BOOST_ASSERT(std::abs(bearing) <= 0.1);
}
initial_roads_ordering.push_back(
{initial_bearing, {edge_connected_to_intersection, bearing, segment_length}});
intersection.push_back({edge_connected_to_intersection, bearing, segment_length});
}
if (!initial_roads_ordering.empty())
if (!intersection.empty())
{
const auto base_initial_bearing = [&]() {
const auto base_bearing = [&]() {
if (sorting_base)
{
const auto itr = std::find_if(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
[&](const auto &data) {
return node_based_graph.GetTarget(
data.road.eid) == *sorting_base;
});
if (itr != initial_roads_ordering.end())
const auto itr =
std::find_if(intersection.begin(),
intersection.end(),
[&](const IntersectionShapeData &data) {
return node_based_graph.GetTarget(data.eid) == *sorting_base;
});
if (itr != intersection.end())
return util::bearing::reverse(itr->bearing);
}
return util::bearing::reverse(initial_roads_ordering.begin()->bearing);
return util::bearing::reverse(intersection.begin()->bearing);
}();
// sort roads with respect to the initial bearings, a tie-breaker for equal initial bearings
// is to order roads via final bearings to have roads in clockwise order
//
// rhs <---. lhs <----.
// / /
// lhs / rhs /
//
// lhs road is before rhs one rhs road is before lhs one
// bearing::angleBetween < 180 bearing::angleBetween > 180
const auto initial_bearing_order = makeCompareShapeDataAngleToBearing(base_initial_bearing);
std::sort(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
[&initial_bearing_order](const auto &lhs, const auto &rhs) {
return initial_bearing_order(lhs, rhs) ||
(lhs.bearing == rhs.bearing &&
util::bearing::angleBetween(lhs.road.bearing, rhs.road.bearing) <
180);
});
// copy intersection data in the initial order
IntersectionShape intersection;
intersection.reserve(initial_roads_ordering.size());
std::transform(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
std::back_inserter(intersection),
[](const auto &entry) { return entry.road; });
if (intersection.size() > 2)
{ // Check bearings ordering with respect to true bearings
const auto base_bearing = intersection.front().bearing;
const auto bearings_order =
makeCompareShapeDataAngleToBearing(util::bearing::reverse(base_bearing));
for (auto curr = intersection.begin(), next = std::next(curr);
next != intersection.end();
++curr, ++next)
{
if (bearings_order(*next, *curr))
{ // If the true bearing is out of the initial order (next before current) then
// adjust the next bearing to keep the order. The adjustment angle is at most
// 0.5° or a half-angle between the current bearing and the base bearing.
// to prevent overlapping over base bearing + 360°.
const auto angle_adjustment = std::min(
.5, util::restrictAngleToValidRange(base_bearing - curr->bearing) / 2.);
next->bearing =
util::restrictAngleToValidRange(curr->bearing + angle_adjustment);
}
}
}
return intersection;
std::sort(intersection.begin(),
intersection.end(),
makeCompareShapeDataAngleToBearing(base_bearing));
}
return IntersectionShape{};
return intersection;
}
// a
+21 -125
View File
@@ -2,7 +2,6 @@
#include "extractor/extraction_helper_functions.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_segment.hpp"
#include "extractor/extraction_turn.hpp"
#include "extractor/extraction_way.hpp"
@@ -32,9 +31,6 @@ template <> struct is_container<osmium::Node> : std::false_type
template <> struct is_container<osmium::Way> : std::false_type
{
};
template <> struct is_container<osmium::Relation> : std::false_type
{
};
}
namespace osrm
@@ -220,14 +216,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"sharp_left",
extractor::guidance::DirectionModifier::SharpLeft);
context.state.new_enum("item_type",
"node",
osmium::item_type::node,
"way",
osmium::item_type::way,
"relation",
osmium::item_type::relation);
context.state.new_usertype<RasterContainer>("raster",
"load",
&RasterContainer::LoadRasterSource,
@@ -288,30 +276,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"version",
&osmium::Way::version);
context.state.new_usertype<osmium::RelationMember>(
"RelationMember",
"role",
&osmium::RelationMember::role,
"type",
&osmium::RelationMember::type,
"id",
[](const osmium::RelationMember &member) -> osmium::object_id_type {
return member.ref();
});
context.state.new_usertype<osmium::Relation>(
"Relation",
"get_value_by_key",
&get_value_by_key<osmium::Relation>,
"id",
&osmium::Relation::id,
"version",
&osmium::Relation::version,
"members",
[](const osmium::Relation &rel) -> const osmium::RelationMemberList & {
return rel.members();
});
context.state.new_usertype<osmium::Node>("Node",
"location",
&osmium::Node::location,
@@ -320,7 +284,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"id",
&osmium::Node::id,
"version",
&osmium::Node::version);
&osmium::Way::version);
context.state.new_usertype<ExtractionNode>("ResultNode",
"traffic_lights",
@@ -402,18 +366,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
sol::property([](const ExtractionWay &way) { return way.backward_restricted; },
[](ExtractionWay &way, bool flag) { way.backward_restricted = flag; }));
context.state.new_usertype<ExtractionRelation>(
"ExtractionRelation",
sol::meta_function::new_index,
[](ExtractionRelation &rel, const osmium::RelationMember &member)
-> ExtractionRelation::AttributesMap & { return rel.GetMember(member); },
sol::meta_function::index,
[](ExtractionRelation &rel, const osmium::RelationMember &member)
-> ExtractionRelation::AttributesMap & { return rel.GetMember(member); },
"restriction",
sol::property([](const ExtractionRelation &rel) { return rel.is_restriction; },
[](ExtractionRelation &rel, bool flag) { rel.is_restriction = flag; }));
context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
"source",
&ExtractionSegment::source,
@@ -505,7 +457,10 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
util::Log() << "Using profile api version " << context.api_version;
// version-dependent parts of the api
auto initV2Context = [&]() {
switch (context.api_version)
{
case 2:
{
// clear global not used in v2
context.state["properties"] = sol::nullopt;
@@ -588,22 +543,6 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
if (force_split_edges != sol::nullopt)
context.properties.force_split_edges = force_split_edges.value();
}
};
switch (context.api_version)
{
case 3:
{
initV2Context();
context.relation_function = function_table.value()["process_relation"];
context.has_relation_function = context.relation_function.valid();
break;
}
case 2:
{
initV2Context();
break;
}
case 1:
@@ -676,15 +615,12 @@ LuaScriptingContext &Sol2ScriptingEnvironment::GetSol2Context()
void Sol2ScriptingEnvironment::ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions)
{
ExtractionNode result_node;
ExtractionWay result_way;
ExtractionRelation result_relation;
auto &local_context = this->GetSol2Context();
for (auto entity = buffer.cbegin(), end = buffer.cend(); entity != end; ++entity)
@@ -692,47 +628,33 @@ void Sol2ScriptingEnvironment::ProcessElements(
switch (entity->type())
{
case osmium::item_type::node:
{
const auto &node = static_cast<const osmium::Node &>(*entity);
result_node.clear();
if (local_context.has_node_function &&
(!node.tags().empty() || local_context.properties.call_tagless_node_function))
(!static_cast<const osmium::Node &>(*entity).tags().empty() ||
local_context.properties.call_tagless_node_function))
{
const auto &id = ExtractionRelation::OsmIDTyped(node.id(), osmium::item_type::node);
local_context.ProcessNode(node, result_node, relations.Get(id));
local_context.ProcessNode(static_cast<const osmium::Node &>(*entity), result_node);
}
resulting_nodes.push_back({node, std::move(result_node)});
}
break;
resulting_nodes.push_back(std::pair<const osmium::Node &, ExtractionNode>(
static_cast<const osmium::Node &>(*entity), std::move(result_node)));
break;
case osmium::item_type::way:
{
const osmium::Way &way = static_cast<const osmium::Way &>(*entity);
result_way.clear();
if (local_context.has_way_function)
{
const auto &id = ExtractionRelation::OsmIDTyped(way.id(), osmium::item_type::way);
local_context.ProcessWay(way, result_way, relations.Get(id));
local_context.ProcessWay(static_cast<const osmium::Way &>(*entity), result_way);
}
resulting_ways.push_back({way, std::move(result_way)});
}
break;
resulting_ways.push_back(std::pair<const osmium::Way &, ExtractionWay>(
static_cast<const osmium::Way &>(*entity), std::move(result_way)));
break;
case osmium::item_type::relation:
{
const auto &relation = static_cast<const osmium::Relation &>(*entity);
if (auto result_res = restriction_parser.TryParse(relation))
auto result_res =
restriction_parser.TryParse(static_cast<const osmium::Relation &>(*entity));
if (result_res)
{
resulting_restrictions.push_back(*result_res);
}
if (local_context.api_version > 2)
{
result_relation.clear();
if (local_context.has_relation_function)
{
local_context.ProcessRelation(relation, result_relation);
}
resulting_relations.push_back({relation, std::move(result_relation)});
}
}
break;
default:
@@ -810,7 +732,6 @@ std::vector<std::vector<std::string>> Sol2ScriptingEnvironment::GetExcludableCla
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListsFromTable("excludable");
default:
@@ -823,7 +744,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetClassNames()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("classes");
default:
@@ -836,7 +756,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list");
case 1:
@@ -851,7 +770,6 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions");
case 1:
@@ -867,7 +785,6 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
switch (context.api_version)
{
case 3:
case 2:
if (context.has_turn_penalty_function)
{
@@ -934,7 +851,6 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
{
switch (context.api_version)
{
case 3:
case 2:
context.segment_function(context.profile_table, segment);
break;
@@ -950,17 +866,12 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
}
}
void LuaScriptingContext::ProcessNode(const osmium::Node &node,
ExtractionNode &result,
const ExtractionRelationContainer::RelationList &relations)
void LuaScriptingContext::ProcessNode(const osmium::Node &node, ExtractionNode &result)
{
BOOST_ASSERT(state.lua_state() != nullptr);
switch (api_version)
{
case 3:
node_function(profile_table, node, result, relations);
break;
case 2:
node_function(profile_table, node, result);
break;
@@ -971,17 +882,12 @@ void LuaScriptingContext::ProcessNode(const osmium::Node &node,
}
}
void LuaScriptingContext::ProcessWay(const osmium::Way &way,
ExtractionWay &result,
const ExtractionRelationContainer::RelationList &relations)
void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &result)
{
BOOST_ASSERT(state.lua_state() != nullptr);
switch (api_version)
{
case 3:
way_function(profile_table, way, result, relations);
break;
case 2:
way_function(profile_table, way, result);
break;
@@ -991,15 +897,5 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way,
break;
}
}
void LuaScriptingContext::ProcessRelation(const osmium::Relation &relation,
ExtractionRelation &result)
{
BOOST_ASSERT(state.lua_state() != nullptr);
BOOST_ASSERT(api_version > 2);
relation_function(profile_table, relation, result);
}
} // namespace extractor
} // namespace osrm
}
+53 -48
View File
@@ -52,49 +52,46 @@ const static unsigned INIT_OK_START_ENGINE = 0;
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
const static unsigned INIT_FAILED = -1;
namespace osrm
static EngineConfig::Algorithm stringToAlgorithm(std::string algorithm)
{
namespace engine
{
std::istream &operator>>(std::istream &in, EngineConfig::Algorithm &algorithm)
{
std::string token;
in >> token;
boost::to_lower(token);
boost::to_lower(algorithm);
if (token == "ch")
algorithm = EngineConfig::Algorithm::CH;
else if (token == "corech")
algorithm = EngineConfig::Algorithm::CoreCH;
else if (token == "mld")
algorithm = EngineConfig::Algorithm::MLD;
else
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
return in;
}
}
if (algorithm == "ch")
return EngineConfig::Algorithm::CH;
if (algorithm == "corech")
return EngineConfig::Algorithm::CoreCH;
if (algorithm == "mld")
return EngineConfig::Algorithm::MLD;
throw util::RuntimeError(algorithm, ErrorCode::UnknownAlgorithm, SOURCE_REF);
}
// generate boost::program_options object for the routing part
inline unsigned generateServerProgramOptions(const int argc,
const char *argv[],
std::string verbosity,
boost::filesystem::path &base_path,
std::string &ip_address,
int &ip_port,
int &requested_num_threads,
bool &use_shared_memory,
std::string &algorithm,
bool &trial,
EngineConfig &config)
int &max_locations_trip,
int &max_locations_viaroute,
int &max_locations_distance_table,
int &max_locations_map_matching,
int &max_results_nearest,
int &max_alternatives)
{
using boost::program_options::value;
using boost::filesystem::path;
const auto hardware_threads = std::max<int>(1, std::thread::hardware_concurrency());
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options() //
("version,v", "Show version")("help,h", "Show this help message")(
"verbosity,l",
boost::program_options::value<std::string>(&config.verbosity)->default_value("INFO"),
boost::program_options::value<std::string>(&verbosity)->default_value("INFO"),
std::string("Log verbosity level: " + util::LogPolicy::GetLevels()).c_str())(
"trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
@@ -108,32 +105,31 @@ inline unsigned generateServerProgramOptions(const int argc,
value<int>(&ip_port)->default_value(5000),
"TCP/IP port") //
("threads,t",
value<int>(&config.use_threads_number)->default_value(hardware_threads),
value<int>(&requested_num_threads)->default_value(8),
"Number of threads to use") //
("shared-memory,s",
value<bool>(&config.use_shared_memory)->implicit_value(true)->default_value(false),
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false),
"Load data from shared memory") //
("algorithm,a",
value<EngineConfig::Algorithm>(&config.algorithm)
->default_value(EngineConfig::Algorithm::CH, "CH"),
value<std::string>(&algorithm)->default_value("CH"),
"Algorithm to use for the data. Can be CH, CoreCH, MLD.") //
("max-viaroute-size",
value<int>(&config.max_locations_viaroute)->default_value(500),
value<int>(&max_locations_viaroute)->default_value(500),
"Max. locations supported in viaroute query") //
("max-trip-size",
value<int>(&config.max_locations_trip)->default_value(100),
value<int>(&max_locations_trip)->default_value(100),
"Max. locations supported in trip query") //
("max-table-size",
value<int>(&config.max_locations_distance_table)->default_value(100),
value<int>(&max_locations_distance_table)->default_value(100),
"Max. locations supported in distance table query") //
("max-matching-size",
value<int>(&config.max_locations_map_matching)->default_value(100),
value<int>(&max_locations_map_matching)->default_value(100),
"Max. locations supported in map matching query") //
("max-nearest-size",
value<int>(&config.max_results_nearest)->default_value(100),
value<int>(&max_results_nearest)->default_value(100),
"Max. results supported in nearest query") //
("max-alternatives",
value<int>(&config.max_alternatives)->default_value(3),
value<int>(&max_alternatives)->default_value(3),
"Max. number of alternatives supported in the MLD route query");
// hidden options, will be allowed on command line, but will not be shown to the user
@@ -184,22 +180,19 @@ inline unsigned generateServerProgramOptions(const int argc,
boost::program_options::notify(option_variables);
if (!config.use_shared_memory && option_variables.count("base"))
if (!use_shared_memory && option_variables.count("base"))
{
return INIT_OK_START_ENGINE;
}
else if (config.use_shared_memory && !option_variables.count("base"))
else if (use_shared_memory && !option_variables.count("base"))
{
return INIT_OK_START_ENGINE;
}
else if (config.use_shared_memory && option_variables.count("base"))
else if (use_shared_memory && option_variables.count("base"))
{
util::Log(logWARNING) << "Shared memory settings conflict with path settings.";
}
// Adjust number of threads to hardware concurrency
config.use_threads_number = std::min(hardware_threads, config.use_threads_number);
std::cout << visible_options;
return INIT_OK_DO_NOT_START_ENGINE;
}
@@ -210,13 +203,28 @@ int main(int argc, const char *argv[]) try
bool trial_run = false;
std::string ip_address;
int ip_port;
int ip_port, requested_thread_num;
EngineConfig config;
std::string verbosity;
boost::filesystem::path base_path;
const unsigned init_result =
generateServerProgramOptions(argc, argv, base_path, ip_address, ip_port, trial_run, config);
std::string algorithm;
const unsigned init_result = generateServerProgramOptions(argc,
argv,
verbosity,
base_path,
ip_address,
ip_port,
requested_thread_num,
config.use_shared_memory,
algorithm,
trial_run,
config.max_locations_trip,
config.max_locations_viaroute,
config.max_locations_distance_table,
config.max_locations_map_matching,
config.max_results_nearest,
config.max_alternatives);
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
{
return EXIT_SUCCESS;
@@ -226,7 +234,7 @@ int main(int argc, const char *argv[]) try
return EXIT_FAILURE;
}
util::LogPolicy::GetInstance().SetLevel(config.verbosity);
util::LogPolicy::GetInstance().SetLevel(verbosity);
if (!base_path.empty())
{
@@ -245,6 +253,7 @@ int main(int argc, const char *argv[]) try
}
return EXIT_FAILURE;
}
config.algorithm = stringToAlgorithm(algorithm);
util::Log() << "starting up engines, " << OSRM_VERSION;
@@ -253,10 +262,6 @@ int main(int argc, const char *argv[]) try
util::Log() << "Loading from shared memory";
}
// Use the same number of threads for Server and TBB threads pools
// It doubles number of used threads
auto requested_thread_num = config.use_threads_number;
util::Log() << "Threads: " << requested_thread_num;
util::Log() << "IP address: " << ip_address;
util::Log() << "IP port: " << ip_port;
+1 -1
View File
@@ -48,7 +48,7 @@ void LogPolicy::SetLevel(std::string const &level)
else if (boost::iequals(level, "DEBUG"))
m_level = logDEBUG;
else
m_level = logINFO;
;
}
LogPolicy &LogPolicy::GetInstance()
-1
View File
@@ -153,7 +153,6 @@
{"key": "maxspeed", "value": "ua:urban"},
{"key": "maxspeed", "value": "at:rural"},
{"key": "maxspeed", "value": "de:rural"},
{"key": "maxspeed", "value": "dk:rural"},
{"key": "maxspeed", "value": "at:trunk"},
{"key": "maxspeed", "value": "cz:trunk"},
{"key": "maxspeed", "value": "ro:trunk"},
+1 -1
View File
@@ -1 +1 @@
n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02
n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02
@@ -34,14 +34,11 @@ class MockScriptingEnvironment : public extractor::ScriptingEnvironment
void ProcessTurn(extractor::ExtractionTurn &) override final {}
void ProcessSegment(extractor::ExtractionSegment &) override final {}
void ProcessElements(
const osmium::memory::Buffer &,
const extractor::RestrictionParser &,
const extractor::ExtractionRelationContainer &,
std::vector<std::pair<const osmium::Node &, extractor::ExtractionNode>> &,
std::vector<std::pair<const osmium::Way &, extractor::ExtractionWay>> &,
std::vector<std::pair<const osmium::Relation &, extractor::ExtractionRelation>> &,
std::vector<extractor::InputConditionalTurnRestriction> &) override final
void ProcessElements(const osmium::memory::Buffer &,
const extractor::RestrictionParser &,
std::vector<std::pair<const osmium::Node &, extractor::ExtractionNode>> &,
std::vector<std::pair<const osmium::Way &, extractor::ExtractionWay>> &,
std::vector<extractor::InputConditionalTurnRestriction> &) override final
{
}
};