Compare commits

...

40 Commits

Author SHA1 Message Date
Daniel Patterson 078624a54c Bump versions preparing for merge. 2017-09-19 14:12:24 -07:00
Daniel Patterson bb5530646a Update changelog. 2017-09-19 14:12:13 -07:00
Denis Koronchik 4d3e35982b Some improvements in code 2017-09-19 14:09:30 -07:00
Denis Koronchik 6227242c85 Add test for route relation process in car.lua. Some fixes 2017-09-19 14:09:30 -07:00
Denis Koronchik b3e6b59528 Fix bug with simple refs support (not lists) 2017-09-19 14:09:30 -07:00
Denis Koronchik 40398a1856 Add route relation support for multi ref's 2017-09-19 14:09:29 -07:00
Denis Koronchik 7078ebd2cb Implement route relation parse in car.lua 2017-09-19 14:09:29 -07:00
Michael Krasnyk fa1a4e8bf6 Relax strict bearings ordering condition to non-strict one, #4331 2017-09-18 21:33:00 +02:00
Michael Krasnyk 2532d56b85 Turn angle calculation needs to respect initial road order, #4331 2017-09-18 21:33:00 +02:00
Michael Krasnyk 00fd869224 Test for turn angle calculation the initial road order breaking, #4331 2017-09-18 21:33:00 +02:00
Michael Krasnyk 5661726e2e Add feature tests for distance weights in foot and bicycle profiles 2017-09-18 16:40:51 +02:00
Michael Krasnyk cfa5d7e172 Add support of distance in foot and bicycle profiles 2017-09-18 16:40:51 +02:00
Michael Krasnyk fd7791a0e2 Fix gcc5 compilation
Ref: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77786
2017-09-15 16:29:40 +02:00
Michael Krasnyk e32b8bae00 Make unbuffered log verbosity aware 2017-09-15 15:01:17 +02:00
Michael Krasnyk 966139cde9 Adjust number of threads in osrm-routed 2017-09-15 10:55:13 +02:00
Michael Krasnyk ee19383f4d Link TBB task_scheduler lifetime with Engine scope 2017-09-15 10:55:13 +02:00
Michael Krasnyk 172a8bdcdb Parallelize ManyToMany plugin 2017-09-15 10:55:13 +02:00
Michael Krasnyk 543048efcc Remove std::unordered_map<NodeID, std::vector<NodeBucket>> 2017-09-15 10:55:13 +02:00
Michael Krasnyk 67c85ffa4c Restructure manyToManySearch for parallelization 2017-09-15 10:55:13 +02:00
Michael Krasnyk c065335882 [skip ci] Moved support relations entry in change log 2017-09-14 20:00:05 +02:00
Michael Krasnyk f6313fcbfb Bump CMake version to 3.9.2 2017-09-14 20:00:05 +02:00
Michael Krasnyk 6a3ea876b5 Fix EOL value in libosmium opl script 2017-09-14 20:00:05 +02:00
Michael Krasnyk 64ad308e9d Small ProcessElements refactoring 2017-09-14 20:00:05 +02:00
Michael Krasnyk 94169a20de Remove RelationsContainerWrap 2017-09-14 20:00:05 +02:00
Michael Krasnyk 5ca38eee3a Remove RelationMemberWrap and avoid data copying 2017-09-14 20:00:05 +02:00
Michael Krasnyk f4f65f62ee Remove Lua 5.1 support 2017-09-14 20:00:05 +02:00
Michael Krasnyk f89ada7f61 Remove ExtractionRelationData wraper 2017-09-14 20:00:05 +02:00
Denis Koronchik ff3b398e23 Review fixes 2017-09-14 20:00:05 +02:00
Denis Koronchik 84cb7865ab Fix different compilers support 2017-09-14 20:00:05 +02:00
Denis Koronchik 75bdf114be Review fixes 2017-09-14 20:00:05 +02:00
Denis Koronchik c2fd64d3cc Apply clang format 2017-09-14 20:00:05 +02:00
Denis Koronchik 580c5e39ae Fix some tests and add new ones 2017-09-14 20:00:05 +02:00
Denis Koronchik 8da6281dcd Update LUA profiles documentation 2017-09-14 20:00:05 +02:00
Denis Koronchik f79bcc6b8d Pass relation data to way and node functions 2017-09-14 20:00:05 +02:00
Denis Koronchik f2b63ba0aa LUA binding for a relation processing 2017-09-14 20:00:05 +02:00
Denis Koronchik a253111cbe Add ExtractionRelation class 2017-09-14 20:00:05 +02:00
Michael Krasnyk a5776288f6 Add dk:rural to taginfo.json 2017-09-14 08:03:18 +02:00
Mateusz Loskot dbcf4cab16 Replace GCC/clang option -std=C++1y with -std=C++14 2017-09-13 13:01:23 +02:00
Frédéric Rodrigo 4ea3f33376 Add to car profile missing DK:rural maxspeed_table exceptions osm-fr/osmose-backend#174 (#4488) 2017-09-08 11:36:06 -07:00
Daniel Patterson e4cdfb50cd Reset changelog for new release cycle. 2017-09-07 22:16:10 -07:00
39 changed files with 1248 additions and 317 deletions
+9 -9
View File
@@ -68,7 +68,7 @@ matrix:
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000 env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' ENABLE_COVERAGE=ON CUCUMBER_TIMEOUT=20000
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)
@@ -78,7 +78,7 @@ matrix:
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-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 env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
- os: linux - os: linux
@@ -86,7 +86,7 @@ matrix:
addons: &clang40 addons: &clang40
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['libstdc++-5-dev', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000 env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' CUCUMBER_TIMEOUT=60000
- os: linux - os: linux
@@ -111,7 +111,7 @@ matrix:
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: linux - os: linux
@@ -125,7 +125,7 @@ matrix:
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['g++-6', 'libbz2-dev', 'libstxxl-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' ENABLE_STXXL=On
- os: linux - os: linux
@@ -133,7 +133,7 @@ matrix:
addons: &gcc49 addons: &gcc49
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
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'] packages: ['g++-4.9', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release' env: CCOMPILER='gcc-4.9' CXXCOMPILER='g++-4.9' BUILD_TYPE='Release'
- os: osx - os: osx
@@ -158,7 +158,7 @@ matrix:
#- addons: &clang40 #- addons: &clang40
#- apt: #- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test'] #- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] #- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' #- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release'
# Shared Library # Shared Library
@@ -167,7 +167,7 @@ matrix:
addons: &gcc6 addons: &gcc6
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Disabled because CI slowness # Disabled because CI slowness
@@ -176,7 +176,7 @@ matrix:
#- addons: &clang40 #- addons: &clang40
#- apt: #- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test'] #- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev'] #- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libgdal-dev', 'libboost-all-dev']
#- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON #- env: CCOMPILER='clang-4.0' CXXCOMPILER='clang++-4.0' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
# Node build jobs. These skip running the tests. # Node build jobs. These skip running the tests.
+10
View File
@@ -1,4 +1,14 @@
# UNRELEASED # 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
- Guidance - Guidance
- now announcing turning onto oneways at the end of a road (e.g. onto dual carriageways) - 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`. - Adds new instruction types at the exit of roundabouts and rotaries `exit roundabout` and `exit rotary`.
+4 -21
View File
@@ -60,7 +60,7 @@ if (POLICY CMP0048)
endif() endif()
project(OSRM C CXX) project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5) set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 12) set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_PATCH 0) set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}") 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 # Activate C++1y
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y") set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++14")
endif() endif()
# Configuring other platform dependencies # Configuring other platform dependencies
@@ -521,24 +521,7 @@ else()
IF (LUA_FOUND) IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}") MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE() ELSE()
FIND_PACKAGE(Lua 5.1 EXACT) MESSAGE(FATAL_ERROR "Lua 5.2 was not found.")
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() ENDIF()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES}) set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
+7 -4
View File
@@ -7,19 +7,22 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SET PROJECT_DIR=%CD% SET PROJECT_DIR=%CD%
ECHO PROJECT_DIR^: %PROJECT_DIR% ECHO PROJECT_DIR^: %PROJECT_DIR%
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS% 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 ECHO cmake^: && cmake --version
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
cmake --version | findstr /C:"3.7.1" && GOTO CMAKE_OK cmake --version | findstr /C:%CMAKE_VERSION% && GOTO CMAKE_OK
:CMAKE_NOT_OK :CMAKE_NOT_OK
SET CMAKE_VERSION=3.7.1
ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION% ECHO CMAKE NOT OK - downloading new CMake %CMAKE_VERSION%
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 powershell Invoke-WebRequest https://cmake.org/files/v3.9/cmake-%CMAKE_VERSION%-win32-x86.zip -OutFile $env:PROJECT_DIR\cm.zip
IF %ERRORLEVEL% NEQ 0 GOTO ERROR 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 NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
IF %ERRORLEVEL% NEQ 0 GOTO ERROR IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
:CMAKE_OK :CMAKE_OK
ECHO CMAKE_OK ECHO CMAKE_OK
+54 -2
View File
@@ -114,7 +114,7 @@ classes | Sequence | Determines the allowed
restrictions | Sequence | Determines which turn restrictions will be used for this profile. 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". 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) ### process_node(profile, node, result, relations)
Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay. Process an OSM node to determine whether this node is a barrier or can be passed and whether passing it incurs a delay.
Argument | Description Argument | Description
@@ -122,6 +122,7 @@ Argument | Description
profile | The configuration table you returned in `setup`. profile | The configuration table you returned in `setup`.
node | The input node to process (read-only). node | The input node to process (read-only).
result | The output that you will modify. 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`: The following attributes can be set on `result`:
@@ -130,7 +131,7 @@ Attribute | Type | Notes
barrier | Boolean | Is it an impassable barrier? barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)? traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
## process_way(profile, way, result) ### process_way(profile, way, result, relations)
Given an OpenStreetMap way, the `process_way` function will either return nothing (meaning we are not going to route over this way at all), or it will set up a result hash. 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 Argument | Description
@@ -138,6 +139,7 @@ Argument | Description
profile | The configuration table you returned in `setup`. profile | The configuration table you returned in `setup`.
node | The input way to process (read-only). node | The input way to process (read-only).
result | The output that you will modify. 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. 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.
@@ -177,6 +179,56 @@ 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
### 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) ### 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.
+35
View File
@@ -0,0 +1,35 @@
@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
@@ -0,0 +1,68 @@
@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
@@ -0,0 +1,35 @@
@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,3 +1349,24 @@ Feature: Simple Turns
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,d | ab,dc,dc | depart,turn left,arrive | | 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 |
@@ -0,0 +1,32 @@
@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 Scenario: Profile API version too high
Given the profile file Given the profile file
""" """
api_version = 3 api_version = 4
""" """
And the node map And the node map
""" """
+119
View File
@@ -0,0 +1,119 @@
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 |
+5 -1
View File
@@ -24,6 +24,8 @@
#include "util/fingerprint.hpp" #include "util/fingerprint.hpp"
#include "util/json_container.hpp" #include "util/json_container.hpp"
#include <tbb/task_scheduler_init.h>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -53,7 +55,8 @@ template <typename Algorithm> class Engine final : public EngineInterface
{ {
public: public:
explicit Engine(const EngineConfig &config) explicit Engine(const EngineConfig &config)
: route_plugin(config.max_locations_viaroute, config.max_alternatives), // : task_scheduler(config.use_threads_number),
route_plugin(config.max_locations_viaroute, config.max_alternatives), //
table_plugin(config.max_locations_distance_table), // table_plugin(config.max_locations_distance_table), //
nearest_plugin(config.max_results_nearest), // nearest_plugin(config.max_results_nearest), //
trip_plugin(config.max_locations_trip), // trip_plugin(config.max_locations_trip), //
@@ -125,6 +128,7 @@ template <typename Algorithm> class Engine final : public EngineInterface
} }
std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider; std::unique_ptr<DataFacadeProvider<Algorithm>> facade_provider;
mutable SearchEngineData<Algorithm> heaps; mutable SearchEngineData<Algorithm> heaps;
tbb::task_scheduler_init task_scheduler;
const plugins::ViaRoutePlugin route_plugin; const plugins::ViaRoutePlugin route_plugin;
const plugins::TablePlugin table_plugin; const plugins::TablePlugin table_plugin;
+2
View File
@@ -90,6 +90,8 @@ struct EngineConfig final
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true; bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH; 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, std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade, const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes, const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, std::vector<std::size_t> source_indices,
const std::vector<std::size_t> &target_indices); std::vector<std::size_t> target_indices);
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
+81
View File
@@ -0,0 +1,81 @@
#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,6 +15,7 @@ namespace osmium
{ {
class Node; class Node;
class Way; class Way;
class Relation;
} }
namespace std namespace std
@@ -44,6 +45,7 @@ namespace extractor
class ExtractionContainers; class ExtractionContainers;
struct ExtractionNode; struct ExtractionNode;
struct ExtractionWay; struct ExtractionWay;
struct ExtractionRelation;
struct ProfileProperties; struct ProfileProperties;
struct InputConditionalTurnRestriction; struct InputConditionalTurnRestriction;
@@ -153,6 +153,14 @@ class CoordinateExtractor
const double length, const double length,
const double rate) const; 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: private:
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const extractor::CompressedEdgeContainer &compressed_geometries; const extractor::CompressedEdgeContainer &compressed_geometries;
@@ -241,14 +249,6 @@ class CoordinateExtractor
const double segment_length, const double segment_length,
const std::vector<double> &segment_distances, const std::vector<double> &segment_distances,
const std::uint8_t considered_lanes) const; 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 } // namespace guidance
+11 -6
View File
@@ -19,6 +19,7 @@ namespace osmium
{ {
class Node; class Node;
class Way; class Way;
class Relation;
} }
namespace osrm namespace osrm
@@ -33,8 +34,10 @@ namespace extractor
{ {
class RestrictionParser; class RestrictionParser;
class ExtractionRelationContainer;
struct ExtractionNode; struct ExtractionNode;
struct ExtractionWay; struct ExtractionWay;
struct ExtractionRelation;
struct ExtractionTurn; struct ExtractionTurn;
struct ExtractionSegment; struct ExtractionSegment;
@@ -59,12 +62,14 @@ class ScriptingEnvironment
virtual void ProcessTurn(ExtractionTurn &turn) = 0; virtual void ProcessTurn(ExtractionTurn &turn) = 0;
virtual void ProcessSegment(ExtractionSegment &segment) = 0; virtual void ProcessSegment(ExtractionSegment &segment) = 0;
virtual void virtual void ProcessElements(
ProcessElements(const osmium::memory::Buffer &buffer, const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser, const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes, const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways, std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0; 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;
}; };
} }
} }
@@ -1,6 +1,7 @@
#ifndef SCRIPTING_ENVIRONMENT_LUA_HPP #ifndef SCRIPTING_ENVIRONMENT_LUA_HPP
#define SCRIPTING_ENVIRONMENT_LUA_HPP #define SCRIPTING_ENVIRONMENT_LUA_HPP
#include "extractor/extraction_relation.hpp"
#include "extractor/raster_source.hpp" #include "extractor/raster_source.hpp"
#include "extractor/scripting_environment.hpp" #include "extractor/scripting_environment.hpp"
@@ -19,8 +20,13 @@ namespace extractor
struct LuaScriptingContext final struct LuaScriptingContext final
{ {
void ProcessNode(const osmium::Node &, ExtractionNode &result); void ProcessNode(const osmium::Node &,
void ProcessWay(const osmium::Way &, ExtractionWay &result); ExtractionNode &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessWay(const osmium::Way &,
ExtractionWay &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
ProfileProperties properties; ProfileProperties properties;
RasterContainer raster_sources; RasterContainer raster_sources;
@@ -29,11 +35,13 @@ struct LuaScriptingContext final
bool has_turn_penalty_function; bool has_turn_penalty_function;
bool has_node_function; bool has_node_function;
bool has_way_function; bool has_way_function;
bool has_relation_function;
bool has_segment_function; bool has_segment_function;
sol::function turn_function; sol::function turn_function;
sol::function way_function; sol::function way_function;
sol::function node_function; sol::function node_function;
sol::function relation_function;
sol::function segment_function; sol::function segment_function;
int api_version; int api_version;
@@ -51,7 +59,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 = 2; static const constexpr int SUPPORTED_MAX_API_VERSION = 3;
explicit Sol2ScriptingEnvironment(const std::string &file_name); explicit Sol2ScriptingEnvironment(const std::string &file_name);
~Sol2ScriptingEnvironment() override = default; ~Sol2ScriptingEnvironment() override = default;
@@ -65,12 +73,14 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
void ProcessTurn(ExtractionTurn &turn) override; void ProcessTurn(ExtractionTurn &turn) override;
void ProcessSegment(ExtractionSegment &segment) override; void ProcessSegment(ExtractionSegment &segment) override;
void void ProcessElements(
ProcessElements(const osmium::memory::Buffer &buffer, const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser, const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes, const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways, std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override; 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;
private: private:
LuaScriptingContext &GetSol2Context(); LuaScriptingContext &GetSol2Context();
+8
View File
@@ -186,6 +186,7 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
params->Get(Nan::New("max_locations_map_matching").ToLocalChecked()); params->Get(Nan::New("max_locations_map_matching").ToLocalChecked());
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked()); auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
auto max_alternatives = params->Get(Nan::New("max_alternatives").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()) if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
{ {
@@ -217,6 +218,11 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
Nan::ThrowError("max_alternatives must be an integral number"); Nan::ThrowError("max_alternatives must be an integral number");
return engine_config_ptr(); 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()) if (max_locations_trip->IsNumber())
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue()); engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
@@ -233,6 +239,8 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue()); engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
if (max_alternatives->IsNumber()) if (max_alternatives->IsNumber())
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue()); 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; return engine_config;
} }
+32 -2
View File
@@ -53,10 +53,40 @@ class Log
virtual ~Log(); virtual ~Log();
std::mutex &get_mutex(); std::mutex &get_mutex();
template <typename T> inline std::ostream &operator<<(const T &data) { return stream << data; } 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;
}
protected: protected:
LogLevel level; const LogLevel level;
std::ostringstream buffer; std::ostringstream buffer;
std::ostream &stream; 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 // When not on a TTY, print newlines after each progress indicator so
// so that progress is visible to line-buffered logging systems // so that progress is visible to line-buffered logging systems
if (!IsStdoutATTY()) if (!IsStdoutATTY())
log << "" << std::endl; log << std::endl;
} }
} }
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "osrm", "name": "osrm",
"version": "5.12.0-roundaboutexits.1", "version": "5.13.0-cardinal.1",
"private": false, "private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
+4 -1
View File
@@ -544,7 +544,10 @@ function process_way(profile, way, result)
WayHandlers.roundabouts, WayHandlers.roundabouts,
-- set name, ref and pronunciation -- set name, ref and pronunciation
WayHandlers.names WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
} }
WayHandlers.run(profile,way,result,data,handlers) WayHandlers.run(profile,way,result,data,handlers)
+75 -3
View File
@@ -1,12 +1,14 @@
-- Car profile -- Car profile
api_version = 2 api_version = 3
Set = require('lib/set') Set = require('lib/set')
Sequence = require('lib/sequence') Sequence = require('lib/sequence')
Handlers = require("lib/way_handlers") Handlers = require("lib/way_handlers")
Relations = require("lib/relations")
find_access_tag = require("lib/access").find_access_tag find_access_tag = require("lib/access").find_access_tag
limit = require("lib/maxspeed").limit limit = require("lib/maxspeed").limit
Utils = require("lib/utils")
function setup() function setup()
local use_left_hand_driving = false local use_left_hand_driving = false
@@ -254,6 +256,7 @@ function setup()
["ch:trunk"] = 100, ["ch:trunk"] = 100,
["ch:motorway"] = 120, ["ch:motorway"] = 120,
["de:living_street"] = 7, ["de:living_street"] = 7,
["dk:rural"] = 80,
["ru:living_street"] = 20, ["ru:living_street"] = 20,
["ru:urban"] = 60, ["ru:urban"] = 60,
["ua:urban"] = 60, ["ua:urban"] = 60,
@@ -278,7 +281,7 @@ function setup()
} }
end end
function process_node(profile, node, result) function process_node(profile, node, result, relations)
-- 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
@@ -305,7 +308,7 @@ function process_node(profile, node, result)
end end
end end
function process_way(profile, way, result) function process_way(profile, way, result, relations)
-- 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.
@@ -389,6 +392,74 @@ function process_way(profile, way, result)
} }
WayHandlers.run(profile,way,result,data,handlers) 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 end
function process_turn(profile, turn) function process_turn(profile, turn)
@@ -433,5 +504,6 @@ return {
setup = setup, setup = setup,
process_way = process_way, process_way = process_way,
process_node = process_node, process_node = process_node,
process_relation = process_relation,
process_turn = process_turn process_turn = process_turn
} }
+4 -1
View File
@@ -237,7 +237,10 @@ function process_way(profile, way, result)
WayHandlers.startpoint, WayHandlers.startpoint,
-- set name, ref and pronunciation -- set name, ref and pronunciation
WayHandlers.names WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
} }
WayHandlers.run(profile,way,result,data,handlers) WayHandlers.run(profile,way,result,data,handlers)
+94
View File
@@ -0,0 +1,94 @@
-- 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
@@ -0,0 +1,43 @@
-- 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_trip, 2) &&
unlimited_or_more_than(max_locations_viaroute, 2) && unlimited_or_more_than(max_locations_viaroute, 2) &&
unlimited_or_more_than(max_results_nearest, 0) && unlimited_or_more_than(max_results_nearest, 0) &&
max_alternatives >= 0; max_alternatives >= 0 && use_threads_number >= 1;
return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid; return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid;
} }
+145 -129
View File
@@ -2,6 +2,7 @@
#include "engine/routing_algorithms/routing_base_ch.hpp" #include "engine/routing_algorithms/routing_base_ch.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <limits> #include <limits>
#include <memory> #include <memory>
@@ -19,17 +20,33 @@ namespace
{ {
struct NodeBucket struct NodeBucket
{ {
unsigned target_id; // essentially a row in the weight matrix NodeID middle_node;
unsigned column_index; // a column in the weight/duration matrix
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeDuration duration;
NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration)
: target_id(target_id), weight(weight), duration(duration) NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
{ {
} }
};
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking // partial order comparison
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>; 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;
}
};
};
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade, inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
const NodeID node, const NodeID node,
@@ -74,12 +91,12 @@ void relaxOutgoingEdges(const DataFacade<ch::Algorithm> &facade,
{ {
const NodeID to = facade.GetTarget(edge); const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight; const auto edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration; const auto edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_weight; const auto to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration; const auto to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage // New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
@@ -201,12 +218,12 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
continue; continue;
} }
const EdgeWeight edge_weight = data.weight; const auto edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration; const auto edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_weight; const auto to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration; const auto to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage // New Node discovered -> Add to Heap + Node Info Storage
if (!query_heap.WasInserted(to)) if (!query_heap.WasInserted(to))
@@ -229,49 +246,47 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned row_idx, const unsigned row_idx,
const unsigned number_of_targets, const unsigned number_of_targets,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap, typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
const SearchSpaceWithBuckets &search_space_with_buckets, const std::vector<NodeBucket> &search_space_with_buckets,
std::vector<EdgeWeight> &weights_table, std::vector<EdgeWeight> &weights_table,
std::vector<EdgeWeight> &durations_table, std::vector<EdgeDuration> &durations_table,
const PhantomNode &phantom_node) const PhantomNode &phantom_node)
{ {
const NodeID node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const EdgeWeight source_weight = query_heap.GetKey(node); const auto source_weight = query_heap.GetKey(node);
const EdgeWeight source_duration = query_heap.GetData(node).duration; const auto source_duration = query_heap.GetData(node).duration;
// check if each encountered node has an entry // check if each encountered node has an entry
const auto bucket_iterator = search_space_with_buckets.find(node); const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
// iterate bucket if there exists one search_space_with_buckets.end(),
if (bucket_iterator != search_space_with_buckets.end()) node,
NodeBucket::Compare());
for (const auto &current_bucket : boost::make_iterator_range(bucket_list))
{ {
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second; // get target id from bucket entry
for (const NodeBucket &current_bucket : bucket_list) 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)
{ {
// get target id from bucket entry if (addLoopWeight(facade, node, new_weight, new_duration))
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)
{ {
if (addLoopWeight(facade, node, new_weight, new_duration)) current_weight = std::min(current_weight, new_weight);
{ current_duration = std::min(current_duration, 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;
}
} }
relaxOutgoingEdges<FORWARD_DIRECTION>( relaxOutgoingEdges<FORWARD_DIRECTION>(
@@ -282,15 +297,15 @@ template <typename Algorithm>
void backwardRoutingStep(const DataFacade<Algorithm> &facade, void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned column_idx, const unsigned column_idx,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap, typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
SearchSpaceWithBuckets &search_space_with_buckets, std::vector<NodeBucket> &search_space_with_buckets,
const PhantomNode &phantom_node) const PhantomNode &phantom_node)
{ {
const NodeID node = query_heap.DeleteMin(); const auto node = query_heap.DeleteMin();
const EdgeWeight target_weight = query_heap.GetKey(node); const auto target_weight = query_heap.GetKey(node);
const EdgeWeight target_duration = query_heap.GetData(node).duration; const auto target_duration = query_heap.GetData(node).duration;
// store settled nodes in search space bucket // store settled nodes in search space bucket
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration); search_space_with_buckets.emplace_back(node, column_idx, target_weight, target_duration);
relaxOutgoingEdges<REVERSE_DIRECTION>( relaxOutgoingEdges<REVERSE_DIRECTION>(
facade, node, target_weight, target_duration, query_heap, phantom_node); facade, node, target_weight, target_duration, query_heap, phantom_node);
@@ -301,91 +316,92 @@ template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data, std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade, const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes, const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, std::vector<std::size_t> source_indices,
const std::vector<std::size_t> &target_indices) std::vector<std::size_t> target_indices)
{ {
const auto number_of_sources = if (source_indices.empty())
source_indices.empty() ? phantom_nodes.size() : source_indices.size(); {
const auto number_of_targets = source_indices.resize(phantom_nodes.size());
target_indices.empty() ? phantom_nodes.size() : target_indices.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_entries = number_of_sources * number_of_targets; const auto number_of_entries = number_of_sources * number_of_targets;
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT); std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
std::vector<EdgeWeight> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION); std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes()); std::mutex lock;
std::vector<NodeBucket> search_space_with_buckets;
auto &query_heap = *(engine_working_data.many_to_many_heap); // 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];
SearchSpaceWithBuckets search_space_with_buckets; engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(
facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
insertTargetInHeap(query_heap, phantom);
unsigned column_idx = 0; // explore search space
const auto search_target_phantom = [&](const PhantomNode &phantom) { std::vector<NodeBucket> local_buckets;
// clear heap and insert target nodes while (!query_heap.Empty())
query_heap.Clear(); {
insertTargetInHeap(query_heap, phantom); backwardRoutingStep(facade, column_idx, query_heap, local_buckets, phantom);
}
// explore search space { // Insert local buckets into the global search space
while (!query_heap.Empty()) std::lock_guard<std::mutex> guard{lock};
{ search_space_with_buckets.insert(std::end(search_space_with_buckets),
backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets, phantom); std::begin(local_buckets),
} std::end(local_buckets));
++column_idx; }
}; }
});
// for each source do forward search tbb::parallel_sort(search_space_with_buckets.begin(), search_space_with_buckets.end());
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);
// explore search space // For each source do forward search
while (!query_heap.Empty()) tbb::parallel_for(tbb::blocked_range<std::size_t>{0, source_indices.size()},
{ [&](const tbb::blocked_range<std::size_t> &chunk) {
forwardRoutingStep(facade, for (auto row_idx = chunk.begin(), end = chunk.end(); row_idx != end;
row_idx, ++row_idx)
number_of_targets, {
query_heap, const auto index = source_indices[row_idx];
search_space_with_buckets, const auto &phantom = phantom_nodes[index];
weights_table,
durations_table,
phantom);
}
++row_idx;
};
if (target_indices.empty()) // clear heap and insert source nodes
{ engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(
for (const auto &phantom : phantom_nodes) facade.GetNumberOfNodes());
{ auto &query_heap = *(engine_working_data.many_to_many_heap);
search_target_phantom(phantom); insertSourceInHeap(query_heap, phantom);
}
}
else
{
for (const auto index : target_indices)
{
const auto &phantom = phantom_nodes[index];
search_target_phantom(phantom);
}
}
if (source_indices.empty()) // explore search space
{ while (!query_heap.Empty())
for (const auto &phantom : phantom_nodes) {
{ forwardRoutingStep(facade,
search_source_phantom(phantom); row_idx,
} number_of_targets,
} query_heap,
else search_space_with_buckets,
{ weights_table,
for (const auto index : source_indices) durations_table,
{ phantom);
const auto &phantom = phantom_nodes[index]; }
search_source_phantom(phantom); }
} });
}
return durations_table; return durations_table;
} }
@@ -394,15 +410,15 @@ template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data, manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade, const DataFacade<ch::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes, const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, std::vector<std::size_t> source_indices,
const std::vector<std::size_t> &target_indices); std::vector<std::size_t> target_indices);
template std::vector<EdgeWeight> template std::vector<EdgeWeight>
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data, manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
const DataFacade<mld::Algorithm> &facade, const DataFacade<mld::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes, const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, std::vector<std::size_t> source_indices,
const std::vector<std::size_t> &target_indices); std::vector<std::size_t> target_indices);
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
+46 -9
View File
@@ -3,6 +3,7 @@
#include "extractor/edge_based_edge.hpp" #include "extractor/edge_based_edge.hpp"
#include "extractor/extraction_containers.hpp" #include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp" #include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_way.hpp" #include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp" #include "extractor/extractor_callbacks.hpp"
#include "extractor/files.hpp" #include "extractor/files.hpp"
@@ -288,12 +289,13 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const osmium::io::File input_file(config.input_path.string()); const osmium::io::File input_file(config.input_path.string());
osmium::thread::Pool pool(number_of_threads); osmium::thread::Pool pool(number_of_threads);
osmium::io::Reader reader(
input_file,
pool,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no));
const osmium::io::Header header = reader.header(); std::unique_ptr<osmium::io::Reader> reader(new osmium::io::Reader(
input_file,
osmium::osm_entity_bits::relation,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no)));
osmium::io::Header header = reader->header();
unsigned number_of_nodes = 0; unsigned number_of_nodes = 0;
unsigned number_of_ways = 0; unsigned number_of_ways = 0;
@@ -331,6 +333,7 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length()); timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length());
ExtractionRelationContainer relations;
std::vector<std::string> restrictions = scripting_environment.GetRestrictions(); std::vector<std::string> restrictions = scripting_environment.GetRestrictions();
// setup restriction parser // setup restriction parser
const RestrictionParser restriction_parser( const RestrictionParser restriction_parser(
@@ -338,20 +341,19 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
config.parse_conditionals, config.parse_conditionals,
restrictions); restrictions);
std::mutex process_mutex;
using SharedBuffer = std::shared_ptr<const osmium::memory::Buffer>; using SharedBuffer = std::shared_ptr<const osmium::memory::Buffer>;
struct ParsedBuffer struct ParsedBuffer
{ {
SharedBuffer buffer; SharedBuffer buffer;
std::vector<std::pair<const osmium::Node &, ExtractionNode>> resulting_nodes; 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::Way &, ExtractionWay>> resulting_ways;
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> resulting_relations;
std::vector<InputConditionalTurnRestriction> resulting_restrictions; std::vector<InputConditionalTurnRestriction> resulting_restrictions;
}; };
tbb::filter_t<void, SharedBuffer> buffer_reader( tbb::filter_t<void, SharedBuffer> buffer_reader(
tbb::filter::serial_in_order, [&](tbb::flow_control &fc) { 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)); return std::make_shared<const osmium::memory::Buffer>(std::move(buffer));
} }
@@ -370,8 +372,10 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
parsed_buffer->buffer = buffer; parsed_buffer->buffer = buffer;
scripting_environment.ProcessElements(*buffer, scripting_environment.ProcessElements(*buffer,
restriction_parser, restriction_parser,
relations,
parsed_buffer->resulting_nodes, parsed_buffer->resulting_nodes,
parsed_buffer->resulting_ways, parsed_buffer->resulting_ways,
parsed_buffer->resulting_relations,
parsed_buffer->resulting_restrictions); parsed_buffer->resulting_restrictions);
return parsed_buffer; return parsed_buffer;
}); });
@@ -391,13 +395,46 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
{ {
extractor_callbacks->ProcessWay(result.first, result.second); extractor_callbacks->ProcessWay(result.first, result.second);
} }
number_of_relations += parsed_buffer->resulting_restrictions.size(); });
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);
}
for (const auto &result : parsed_buffer->resulting_restrictions) for (const auto &result : parsed_buffer->resulting_restrictions)
{ {
extractor_callbacks->ProcessRestriction(result); 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 // 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, tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
buffer_reader & buffer_transform & buffer_storage); buffer_reader & buffer_transform & buffer_storage);
@@ -54,12 +54,19 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
const boost::optional<NodeID> sorting_base, const boost::optional<NodeID> sorting_base,
const bool use_low_precision_angles) const const bool use_low_precision_angles) const
{ {
IntersectionShape intersection;
// reserve enough items (+ the possibly missing u-turn edge)
const auto intersection_degree = node_based_graph.GetOutDegree(node_at_center_of_intersection); 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]; 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;
// reserve enough items (+ the possibly missing u-turn edge)
initial_roads_ordering.reserve(intersection_degree);
// number of lanes at the intersection changes how far we look down the road // 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); const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection);
const auto max_lanes_intersection = std::accumulate( const auto max_lanes_intersection = std::accumulate(
@@ -82,6 +89,11 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
auto coordinates = coordinate_extractor.GetCoordinatesAlongRoad( auto coordinates = coordinate_extractor.GetCoordinatesAlongRoad(
node_at_center_of_intersection, edge_connected_to_intersection, !INVERT, to_node); 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( const auto segment_length = util::coordinate_calculation::getLength(
coordinates.begin(), coordinates.begin(),
coordinates.end(), coordinates.end(),
@@ -123,31 +135,79 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
BOOST_ASSERT(std::abs(bearing) <= 0.1); BOOST_ASSERT(std::abs(bearing) <= 0.1);
} }
intersection.push_back({edge_connected_to_intersection, bearing, segment_length}); initial_roads_ordering.push_back(
{initial_bearing, {edge_connected_to_intersection, bearing, segment_length}});
} }
if (!intersection.empty()) if (!initial_roads_ordering.empty())
{ {
const auto base_bearing = [&]() { const auto base_initial_bearing = [&]() {
if (sorting_base) if (sorting_base)
{ {
const auto itr = const auto itr = std::find_if(initial_roads_ordering.begin(),
std::find_if(intersection.begin(), initial_roads_ordering.end(),
intersection.end(), [&](const auto &data) {
[&](const IntersectionShapeData &data) { return node_based_graph.GetTarget(
return node_based_graph.GetTarget(data.eid) == *sorting_base; data.road.eid) == *sorting_base;
}); });
if (itr != intersection.end()) if (itr != initial_roads_ordering.end())
return util::bearing::reverse(itr->bearing); return util::bearing::reverse(itr->bearing);
} }
return util::bearing::reverse(intersection.begin()->bearing); return util::bearing::reverse(initial_roads_ordering.begin()->bearing);
}(); }();
std::sort(intersection.begin(),
intersection.end(), // sort roads with respect to the initial bearings, a tie-breaker for equal initial bearings
makeCompareShapeDataAngleToBearing(base_bearing)); // 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;
} }
return intersection; return IntersectionShape{};
} }
// a // a
+125 -21
View File
@@ -2,6 +2,7 @@
#include "extractor/extraction_helper_functions.hpp" #include "extractor/extraction_helper_functions.hpp"
#include "extractor/extraction_node.hpp" #include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_segment.hpp" #include "extractor/extraction_segment.hpp"
#include "extractor/extraction_turn.hpp" #include "extractor/extraction_turn.hpp"
#include "extractor/extraction_way.hpp" #include "extractor/extraction_way.hpp"
@@ -31,6 +32,9 @@ template <> struct is_container<osmium::Node> : std::false_type
template <> struct is_container<osmium::Way> : std::false_type template <> struct is_container<osmium::Way> : std::false_type
{ {
}; };
template <> struct is_container<osmium::Relation> : std::false_type
{
};
} }
namespace osrm namespace osrm
@@ -216,6 +220,14 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"sharp_left", "sharp_left",
extractor::guidance::DirectionModifier::SharpLeft); 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", context.state.new_usertype<RasterContainer>("raster",
"load", "load",
&RasterContainer::LoadRasterSource, &RasterContainer::LoadRasterSource,
@@ -276,6 +288,30 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"version", "version",
&osmium::Way::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", context.state.new_usertype<osmium::Node>("Node",
"location", "location",
&osmium::Node::location, &osmium::Node::location,
@@ -284,7 +320,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"id", "id",
&osmium::Node::id, &osmium::Node::id,
"version", "version",
&osmium::Way::version); &osmium::Node::version);
context.state.new_usertype<ExtractionNode>("ResultNode", context.state.new_usertype<ExtractionNode>("ResultNode",
"traffic_lights", "traffic_lights",
@@ -366,6 +402,18 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
sol::property([](const ExtractionWay &way) { return way.backward_restricted; }, sol::property([](const ExtractionWay &way) { return way.backward_restricted; },
[](ExtractionWay &way, bool flag) { way.backward_restricted = flag; })); [](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", context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
"source", "source",
&ExtractionSegment::source, &ExtractionSegment::source,
@@ -457,10 +505,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
util::Log() << "Using profile api version " << context.api_version; util::Log() << "Using profile api version " << context.api_version;
// version-dependent parts of the api // version-dependent parts of the api
switch (context.api_version) auto initV2Context = [&]() {
{
case 2:
{
// clear global not used in v2 // clear global not used in v2
context.state["properties"] = sol::nullopt; context.state["properties"] = sol::nullopt;
@@ -543,6 +588,22 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
if (force_split_edges != sol::nullopt) if (force_split_edges != sol::nullopt)
context.properties.force_split_edges = force_split_edges.value(); 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; break;
} }
case 1: case 1:
@@ -615,12 +676,15 @@ LuaScriptingContext &Sol2ScriptingEnvironment::GetSol2Context()
void Sol2ScriptingEnvironment::ProcessElements( void Sol2ScriptingEnvironment::ProcessElements(
const osmium::memory::Buffer &buffer, const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser, const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes, 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::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) std::vector<InputConditionalTurnRestriction> &resulting_restrictions)
{ {
ExtractionNode result_node; ExtractionNode result_node;
ExtractionWay result_way; ExtractionWay result_way;
ExtractionRelation result_relation;
auto &local_context = this->GetSol2Context(); auto &local_context = this->GetSol2Context();
for (auto entity = buffer.cbegin(), end = buffer.cend(); entity != end; ++entity) for (auto entity = buffer.cbegin(), end = buffer.cend(); entity != end; ++entity)
@@ -628,33 +692,47 @@ void Sol2ScriptingEnvironment::ProcessElements(
switch (entity->type()) switch (entity->type())
{ {
case osmium::item_type::node: case osmium::item_type::node:
{
const auto &node = static_cast<const osmium::Node &>(*entity);
result_node.clear(); result_node.clear();
if (local_context.has_node_function && if (local_context.has_node_function &&
(!static_cast<const osmium::Node &>(*entity).tags().empty() || (!node.tags().empty() || local_context.properties.call_tagless_node_function))
local_context.properties.call_tagless_node_function))
{ {
local_context.ProcessNode(static_cast<const osmium::Node &>(*entity), result_node); const auto &id = ExtractionRelation::OsmIDTyped(node.id(), osmium::item_type::node);
local_context.ProcessNode(node, result_node, relations.Get(id));
} }
resulting_nodes.push_back(std::pair<const osmium::Node &, ExtractionNode>( resulting_nodes.push_back({node, std::move(result_node)});
static_cast<const osmium::Node &>(*entity), std::move(result_node))); }
break; break;
case osmium::item_type::way: case osmium::item_type::way:
{
const osmium::Way &way = static_cast<const osmium::Way &>(*entity);
result_way.clear(); result_way.clear();
if (local_context.has_way_function) if (local_context.has_way_function)
{ {
local_context.ProcessWay(static_cast<const osmium::Way &>(*entity), result_way); const auto &id = ExtractionRelation::OsmIDTyped(way.id(), osmium::item_type::way);
local_context.ProcessWay(way, result_way, relations.Get(id));
} }
resulting_ways.push_back(std::pair<const osmium::Way &, ExtractionWay>( resulting_ways.push_back({way, std::move(result_way)});
static_cast<const osmium::Way &>(*entity), std::move(result_way))); }
break; break;
case osmium::item_type::relation: case osmium::item_type::relation:
{ {
auto result_res = const auto &relation = static_cast<const osmium::Relation &>(*entity);
restriction_parser.TryParse(static_cast<const osmium::Relation &>(*entity)); if (auto result_res = restriction_parser.TryParse(relation))
if (result_res)
{ {
resulting_restrictions.push_back(*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; break;
default: default:
@@ -732,6 +810,7 @@ std::vector<std::vector<std::string>> Sol2ScriptingEnvironment::GetExcludableCla
auto &context = GetSol2Context(); auto &context = GetSol2Context();
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
return Sol2ScriptingEnvironment::GetStringListsFromTable("excludable"); return Sol2ScriptingEnvironment::GetStringListsFromTable("excludable");
default: default:
@@ -744,6 +823,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetClassNames()
auto &context = GetSol2Context(); auto &context = GetSol2Context();
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("classes"); return Sol2ScriptingEnvironment::GetStringListFromTable("classes");
default: default:
@@ -756,6 +836,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
auto &context = GetSol2Context(); auto &context = GetSol2Context();
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list"); return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list");
case 1: case 1:
@@ -770,6 +851,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
auto &context = GetSol2Context(); auto &context = GetSol2Context();
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions"); return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions");
case 1: case 1:
@@ -785,6 +867,7 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
if (context.has_turn_penalty_function) if (context.has_turn_penalty_function)
{ {
@@ -851,6 +934,7 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
{ {
switch (context.api_version) switch (context.api_version)
{ {
case 3:
case 2: case 2:
context.segment_function(context.profile_table, segment); context.segment_function(context.profile_table, segment);
break; break;
@@ -866,12 +950,17 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
} }
} }
void LuaScriptingContext::ProcessNode(const osmium::Node &node, ExtractionNode &result) void LuaScriptingContext::ProcessNode(const osmium::Node &node,
ExtractionNode &result,
const ExtractionRelationContainer::RelationList &relations)
{ {
BOOST_ASSERT(state.lua_state() != nullptr); BOOST_ASSERT(state.lua_state() != nullptr);
switch (api_version) switch (api_version)
{ {
case 3:
node_function(profile_table, node, result, relations);
break;
case 2: case 2:
node_function(profile_table, node, result); node_function(profile_table, node, result);
break; break;
@@ -882,12 +971,17 @@ void LuaScriptingContext::ProcessNode(const osmium::Node &node, ExtractionNode &
} }
} }
void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &result) void LuaScriptingContext::ProcessWay(const osmium::Way &way,
ExtractionWay &result,
const ExtractionRelationContainer::RelationList &relations)
{ {
BOOST_ASSERT(state.lua_state() != nullptr); BOOST_ASSERT(state.lua_state() != nullptr);
switch (api_version) switch (api_version)
{ {
case 3:
way_function(profile_table, way, result, relations);
break;
case 2: case 2:
way_function(profile_table, way, result); way_function(profile_table, way, result);
break; break;
@@ -897,5 +991,15 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &resu
break; 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
+48 -53
View File
@@ -52,46 +52,49 @@ const static unsigned INIT_OK_START_ENGINE = 0;
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1; const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
const static unsigned INIT_FAILED = -1; const static unsigned INIT_FAILED = -1;
static EngineConfig::Algorithm stringToAlgorithm(std::string algorithm) namespace osrm
{ {
boost::to_lower(algorithm); namespace engine
{
std::istream &operator>>(std::istream &in, EngineConfig::Algorithm &algorithm)
{
std::string token;
in >> token;
boost::to_lower(token);
if (algorithm == "ch") if (token == "ch")
return EngineConfig::Algorithm::CH; algorithm = EngineConfig::Algorithm::CH;
if (algorithm == "corech") else if (token == "corech")
return EngineConfig::Algorithm::CoreCH; algorithm = EngineConfig::Algorithm::CoreCH;
if (algorithm == "mld") else if (token == "mld")
return EngineConfig::Algorithm::MLD; algorithm = EngineConfig::Algorithm::MLD;
throw util::RuntimeError(algorithm, ErrorCode::UnknownAlgorithm, SOURCE_REF); else
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
return in;
}
}
} }
// generate boost::program_options object for the routing part // generate boost::program_options object for the routing part
inline unsigned generateServerProgramOptions(const int argc, inline unsigned generateServerProgramOptions(const int argc,
const char *argv[], const char *argv[],
std::string verbosity,
boost::filesystem::path &base_path, boost::filesystem::path &base_path,
std::string &ip_address, std::string &ip_address,
int &ip_port, int &ip_port,
int &requested_num_threads,
bool &use_shared_memory,
std::string &algorithm,
bool &trial, bool &trial,
int &max_locations_trip, EngineConfig &config)
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::program_options::value;
using boost::filesystem::path; 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 // declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options"); boost::program_options::options_description generic_options("Options");
generic_options.add_options() // generic_options.add_options() //
("version,v", "Show version")("help,h", "Show this help message")( ("version,v", "Show version")("help,h", "Show this help message")(
"verbosity,l", "verbosity,l",
boost::program_options::value<std::string>(&verbosity)->default_value("INFO"), boost::program_options::value<std::string>(&config.verbosity)->default_value("INFO"),
std::string("Log verbosity level: " + util::LogPolicy::GetLevels()).c_str())( std::string("Log verbosity level: " + util::LogPolicy::GetLevels()).c_str())(
"trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization"); "trial", value<bool>(&trial)->implicit_value(true), "Quit after initialization");
@@ -105,31 +108,32 @@ inline unsigned generateServerProgramOptions(const int argc,
value<int>(&ip_port)->default_value(5000), value<int>(&ip_port)->default_value(5000),
"TCP/IP port") // "TCP/IP port") //
("threads,t", ("threads,t",
value<int>(&requested_num_threads)->default_value(8), value<int>(&config.use_threads_number)->default_value(hardware_threads),
"Number of threads to use") // "Number of threads to use") //
("shared-memory,s", ("shared-memory,s",
value<bool>(&use_shared_memory)->implicit_value(true)->default_value(false), value<bool>(&config.use_shared_memory)->implicit_value(true)->default_value(false),
"Load data from shared memory") // "Load data from shared memory") //
("algorithm,a", ("algorithm,a",
value<std::string>(&algorithm)->default_value("CH"), value<EngineConfig::Algorithm>(&config.algorithm)
->default_value(EngineConfig::Algorithm::CH, "CH"),
"Algorithm to use for the data. Can be CH, CoreCH, MLD.") // "Algorithm to use for the data. Can be CH, CoreCH, MLD.") //
("max-viaroute-size", ("max-viaroute-size",
value<int>(&max_locations_viaroute)->default_value(500), value<int>(&config.max_locations_viaroute)->default_value(500),
"Max. locations supported in viaroute query") // "Max. locations supported in viaroute query") //
("max-trip-size", ("max-trip-size",
value<int>(&max_locations_trip)->default_value(100), value<int>(&config.max_locations_trip)->default_value(100),
"Max. locations supported in trip query") // "Max. locations supported in trip query") //
("max-table-size", ("max-table-size",
value<int>(&max_locations_distance_table)->default_value(100), value<int>(&config.max_locations_distance_table)->default_value(100),
"Max. locations supported in distance table query") // "Max. locations supported in distance table query") //
("max-matching-size", ("max-matching-size",
value<int>(&max_locations_map_matching)->default_value(100), value<int>(&config.max_locations_map_matching)->default_value(100),
"Max. locations supported in map matching query") // "Max. locations supported in map matching query") //
("max-nearest-size", ("max-nearest-size",
value<int>(&max_results_nearest)->default_value(100), value<int>(&config.max_results_nearest)->default_value(100),
"Max. results supported in nearest query") // "Max. results supported in nearest query") //
("max-alternatives", ("max-alternatives",
value<int>(&max_alternatives)->default_value(3), value<int>(&config.max_alternatives)->default_value(3),
"Max. number of alternatives supported in the MLD route query"); "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 // hidden options, will be allowed on command line, but will not be shown to the user
@@ -180,19 +184,22 @@ inline unsigned generateServerProgramOptions(const int argc,
boost::program_options::notify(option_variables); boost::program_options::notify(option_variables);
if (!use_shared_memory && option_variables.count("base")) if (!config.use_shared_memory && option_variables.count("base"))
{ {
return INIT_OK_START_ENGINE; return INIT_OK_START_ENGINE;
} }
else if (use_shared_memory && !option_variables.count("base")) else if (config.use_shared_memory && !option_variables.count("base"))
{ {
return INIT_OK_START_ENGINE; return INIT_OK_START_ENGINE;
} }
else if (use_shared_memory && option_variables.count("base")) else if (config.use_shared_memory && option_variables.count("base"))
{ {
util::Log(logWARNING) << "Shared memory settings conflict with path settings."; 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; std::cout << visible_options;
return INIT_OK_DO_NOT_START_ENGINE; return INIT_OK_DO_NOT_START_ENGINE;
} }
@@ -203,28 +210,13 @@ int main(int argc, const char *argv[]) try
bool trial_run = false; bool trial_run = false;
std::string ip_address; std::string ip_address;
int ip_port, requested_thread_num; int ip_port;
EngineConfig config; EngineConfig config;
std::string verbosity;
boost::filesystem::path base_path; boost::filesystem::path base_path;
std::string algorithm;
const unsigned init_result = generateServerProgramOptions(argc, const unsigned init_result =
argv, generateServerProgramOptions(argc, argv, base_path, ip_address, ip_port, trial_run, config);
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) if (init_result == INIT_OK_DO_NOT_START_ENGINE)
{ {
return EXIT_SUCCESS; return EXIT_SUCCESS;
@@ -234,7 +226,7 @@ int main(int argc, const char *argv[]) try
return EXIT_FAILURE; return EXIT_FAILURE;
} }
util::LogPolicy::GetInstance().SetLevel(verbosity); util::LogPolicy::GetInstance().SetLevel(config.verbosity);
if (!base_path.empty()) if (!base_path.empty())
{ {
@@ -253,7 +245,6 @@ int main(int argc, const char *argv[]) try
} }
return EXIT_FAILURE; return EXIT_FAILURE;
} }
config.algorithm = stringToAlgorithm(algorithm);
util::Log() << "starting up engines, " << OSRM_VERSION; util::Log() << "starting up engines, " << OSRM_VERSION;
@@ -262,6 +253,10 @@ int main(int argc, const char *argv[]) try
util::Log() << "Loading from shared memory"; 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() << "Threads: " << requested_thread_num;
util::Log() << "IP address: " << ip_address; util::Log() << "IP address: " << ip_address;
util::Log() << "IP port: " << ip_port; 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")) else if (boost::iequals(level, "DEBUG"))
m_level = logDEBUG; m_level = logDEBUG;
else else
; m_level = logINFO;
} }
LogPolicy &LogPolicy::GetInstance() LogPolicy &LogPolicy::GetInstance()
+1
View File
@@ -153,6 +153,7 @@
{"key": "maxspeed", "value": "ua:urban"}, {"key": "maxspeed", "value": "ua:urban"},
{"key": "maxspeed", "value": "at:rural"}, {"key": "maxspeed", "value": "at:rural"},
{"key": "maxspeed", "value": "de:rural"}, {"key": "maxspeed", "value": "de:rural"},
{"key": "maxspeed", "value": "dk:rural"},
{"key": "maxspeed", "value": "at:trunk"}, {"key": "maxspeed", "value": "at:trunk"},
{"key": "maxspeed", "value": "cz:trunk"}, {"key": "maxspeed", "value": "cz:trunk"},
{"key": "maxspeed", "value": "ro:trunk"}, {"key": "maxspeed", "value": "ro:trunk"},
@@ -34,11 +34,14 @@ class MockScriptingEnvironment : public extractor::ScriptingEnvironment
void ProcessTurn(extractor::ExtractionTurn &) override final {} void ProcessTurn(extractor::ExtractionTurn &) override final {}
void ProcessSegment(extractor::ExtractionSegment &) override final {} void ProcessSegment(extractor::ExtractionSegment &) override final {}
void ProcessElements(const osmium::memory::Buffer &, void ProcessElements(
const extractor::RestrictionParser &, const osmium::memory::Buffer &,
std::vector<std::pair<const osmium::Node &, extractor::ExtractionNode>> &, const extractor::RestrictionParser &,
std::vector<std::pair<const osmium::Way &, extractor::ExtractionWay>> &, const extractor::ExtractionRelationContainer &,
std::vector<extractor::InputConditionalTurnRestriction> &) override final 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
{ {
} }
}; };