Compare commits

...

57 Commits

Author SHA1 Message Date
Daniel Patterson ca464fcd5d Tag for release. 2017-10-02 14:14:05 -07:00
Daniel Patterson e9b7b68427 Move workaround into single TU. 2017-10-02 14:06:49 -07:00
Daniel Patterson 6b8ae24df6 Needs some kind of std:: namespace import to find _throw_out_of_range symbol 2017-10-02 12:58:09 -07:00
Daniel Patterson 65385b55e9 Add include via cmake rather than environment variable - env variable breaks compiler detection. 2017-10-02 12:40:31 -07:00
Daniel Patterson f20dda55c0 Fix relative path to override include. 2017-10-02 12:22:43 -07:00
Daniel Patterson ff7f8557e3 Workaround GLIBC 4.9 importing one useless (to us) symbol that causes a version update. 2017-10-02 12:17:34 -07:00
Daniel Patterson eff1d4e622 Try 4.9 to see if that clears up a few of the C++14 errors. 2017-10-02 11:40:41 -07:00
Daniel Patterson f82908d509 Try downgrading libstdc++ so we can run inside non-upgrade glibc environments. 2017-10-02 11:18:33 -07:00
Frédéric Rodrigo b3b6e16940 Fix check_taginfo.py test for maxspeed tag in lower case 2017-09-30 22:16:51 +02:00
Frédéric Rodrigo f9fb0b84a8 Fix case of maxspeed tag values into taginfo.json 2017-09-30 22:16:51 +02:00
Frédéric Rodrigo 83acb46390 Add missing maxspeed tags into taginfo.json 2017-09-30 22:16:51 +02:00
Frédéric Rodrigo f36b3fb4bc Add to car profile missing BE:motorway maxspeed_table exceptions osm-fr/osmose-backend#232 2017-09-30 22:16:51 +02:00
Michael Krasnyk e7be271c43 Optimize MLD one-to-many getNodeQueryLevel 2017-09-29 13:38:52 +02:00
Michael Krasnyk 790b574114 unordered_multimap compilation fixes 2017-09-29 13:38:52 +02:00
Michael Krasnyk b3f59ab92c Move duplicated code into insert_node lambda 2017-09-29 13:38:52 +02:00
Michael Krasnyk f2333eb31a Break tie for equal weights but different durations
There is no possibility until multiple-weights are implemented
to break tie in the contraction and the direct shortest path plugin
as duration is not computed during contraction.

This must be fixed after multiple-weights implementation
by using `std::tie(weight, duration)` pairs everywhere.
2017-09-29 13:38:52 +02:00
Michael Krasnyk a862e5fb3a Implement one-to-many unidirectional MLD search 2017-09-29 13:38:52 +02:00
Michael Krasnyk 2715e5758b Split MLD many-to-many method 2017-09-29 13:38:52 +02:00
Michael Krasnyk 454487dd41 Refactor to reuse relaxOutgoingEdges in many-to-many plugin 2017-09-29 13:38:52 +02:00
Michael Krasnyk 2ed4f6eb0c Add suppression of libtbb memory leaks checking 2017-09-28 12:35:27 +02:00
Daniel J. Hofmann d7bcafcb59 Uses parsed len(turn:lanes) to fixup number of lanes, resolves #4472 2017-09-28 00:24:14 +02:00
Marcel Radischat c37a8ddd83 Update README.md with Docker+Node.js example 2017-09-26 09:16:59 +02:00
Michael Krasnyk fc3f96abcb Use pkg-config to find lua in non-standard locations 2017-09-26 09:03:57 +02:00
Michael Krasnyk c37ea441fc Bump osrm-deps package version 2017-09-25 12:26:47 +02: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
51 changed files with 1591 additions and 454 deletions
+27 -22
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,15 +78,15 @@ 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 LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
- os: linux - os: linux
compiler: "clang-4.0-debug" compiler: "clang-4.0-debug"
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++-4.9-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
@@ -94,8 +94,8 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
# Release Builds # Release Builds
- os: linux - os: linux
@@ -103,7 +103,7 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON RUN_CLANG_FORMAT=ON ENABLE_LTO=ON
- 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.
@@ -186,7 +186,7 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install: install:
- pushd ${OSRM_BUILD_DIR} - pushd ${OSRM_BUILD_DIR}
@@ -195,7 +195,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \ -DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \ -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \ -DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS} - make --jobs=${JOBS}
- popd - popd
script: script:
@@ -209,7 +210,7 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3
install: install:
- pushd ${OSRM_BUILD_DIR} - pushd ${OSRM_BUILD_DIR}
@@ -218,7 +219,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \ -DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \ -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \ -DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS} - make --jobs=${JOBS}
- popd - popd
script: script:
@@ -232,7 +234,7 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6" env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install: install:
- pushd ${OSRM_BUILD_DIR} - pushd ${OSRM_BUILD_DIR}
@@ -241,7 +243,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \ -DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \ -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \ -DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS} - make --jobs=${JOBS}
- popd - popd
script: script:
@@ -255,7 +258,7 @@ matrix:
addons: addons:
apt: apt:
sources: ['ubuntu-toolchain-r-test'] sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev'] packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6" env: CLANG_VERSION='4.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="6"
install: install:
- pushd ${OSRM_BUILD_DIR} - pushd ${OSRM_BUILD_DIR}
@@ -264,7 +267,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \ -DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \ -DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \ -DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS} - make --jobs=${JOBS}
- popd - popd
script: script:
@@ -338,7 +342,8 @@ install:
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \ -DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
-DBUILD_TOOLS=ON \ -DBUILD_TOOLS=ON \
-DENABLE_CCACHE=ON \ -DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} -DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=${ENABLE_GLIBC_WORKAROUND:-OFF}
- echo "travis_fold:start:MAKE" - echo "travis_fold:start:MAKE"
- make --jobs=${JOBS} - make --jobs=${JOBS}
- make tests --jobs=${JOBS} - make tests --jobs=${JOBS}
+11
View File
@@ -1,4 +1,15 @@
# UNRELEASED # UNRELEASED
- Profile:
- New function to support relations: `process_relation`. Read more in profiles documentation.
- 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
- Internals
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices
# 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`.
+12 -26
View File
@@ -31,6 +31,7 @@ option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF) option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON) option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF) option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
option(ENABLE_GLIBC_WORKAROUND "Workaround GLIBC symbol exports" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
@@ -60,7 +61,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 +380,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
@@ -517,29 +518,10 @@ else()
find_package(BZip2 REQUIRED) find_package(BZip2 REQUIRED)
add_dependency_includes(${BZIP2_INCLUDE_DIR}) add_dependency_includes(${BZIP2_INCLUDE_DIR})
FIND_PACKAGE(Lua 5.2 EXACT) find_package(Lua 5.2 REQUIRED)
IF (LUA_FOUND) if (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}") message(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE() endif()
FIND_PACKAGE(Lua 5.1 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
# Now fall back to a lua verison without exact
# in case this cmake version also forces patch versions
FIND_PACKAGE(Lua 5.2)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
FIND_PACKAGE(Lua 5.1)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
MESSAGE(FATAL_ERROR "Lua 5.1 or 5.2 was not found.")
ENDIF()
ENDIF()
ENDIF()
ENDIF()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES}) set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
add_dependency_includes(${LUA_INCLUDE_DIR}) add_dependency_includes(${LUA_INCLUDE_DIR})
@@ -829,6 +811,10 @@ add_custom_target(uninstall
add_subdirectory(unit_tests) add_subdirectory(unit_tests)
add_subdirectory(src/benchmarks) add_subdirectory(src/benchmarks)
if (ENABLE_GLIBC_WORKAROUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLIBC_WORKAROUND")
endif()
if (ENABLE_NODE_BINDINGS) if (ENABLE_NODE_BINDINGS)
add_subdirectory(src/nodejs) add_subdirectory(src/nodejs)
endif() endif()
+2
View File
@@ -159,6 +159,8 @@ to always force building the Node.js bindings from source.
For usage details have a look [these API docs](docs/nodejs/api.md). For usage details have a look [these API docs](docs/nodejs/api.md).
An exemplary implementation by a 3rd party with Docker and Node.js can be found [here](https://github.com/door2door-io/osrm-express-server-demo).
## References in publications ## References in publications
+8 -5
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
@@ -37,7 +40,7 @@ ECHO msbuild version
msbuild /version msbuild /version
:: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive :: HARDCODE "x64" as it is uppercase on AppVeyor and download from S3 is case sensitive
SET DEPSPKG=osrm-deps-win-x64-14.0.7z SET DEPSPKG=osrm-deps-win-x64-14.0-2017.09.7z
:: local development :: local development
ECHO. ECHO.
+3
View File
@@ -36,6 +36,8 @@
# This is because, the lua location is not standardized and may exist in # This is because, the lua location is not standardized and may exist in
# locations other than lua/ # locations other than lua/
include(FindPkgConfig)
unset(_lua_include_subdirs) unset(_lua_include_subdirs)
unset(_lua_library_names) unset(_lua_library_names)
unset(_lua_append_versions) unset(_lua_append_versions)
@@ -81,6 +83,7 @@ function(_lua_set_version_vars)
lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2} lua-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2} lua.${CMAKE_MATCH_1}.${CMAKE_MATCH_2}
) )
pkg_check_modules(LUA QUIET "lua${ver}")
endforeach () endforeach ()
set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE) set(_lua_include_subdirs "${_lua_include_subdirs}" PARENT_SCOPE)
+3 -3
View File
@@ -7,7 +7,7 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \ echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \ apk update && \
apk upgrade && \ apk upgrade && \
apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.1-dev libtbb@testing libtbb-dev@testing && \ apk add git cmake wget make libc-dev gcc g++ bzip2-dev boost-dev zlib-dev expat-dev lua5.2-dev libtbb@testing libtbb-dev@testing && \
\ \
echo "Building libstxxl" && \ echo "Building libstxxl" && \
cd /opt && \ cd /opt && \
@@ -46,8 +46,8 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
rm /usr/local/lib/libstxxl* && \ rm /usr/local/lib/libstxxl* && \
cd /opt && \ cd /opt && \
apk del boost-dev && \ apk del boost-dev && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.1-dev git make gcc && \ apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.2-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.1 expat && \ apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat && \
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm* rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
EXPOSE 5000 EXPOSE 5000
+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 |
+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 |
+29
View File
@@ -280,6 +280,35 @@ Feature: Simple Turns
| a,d | road,road | depart,arrive | | a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive | | e,a | road,road | depart,arrive |
Scenario: Splitting Road with many lanes; same as above makes sure len(turn:lanes) work as expected
Given the node map
"""
f - - - - - - - - - - - - - - - - - - - - e
'
'
'
'
'
a - - - - - b
'
'
'
'
'
c - - - - - - - - - - - - - - - - - - - - d
"""
And the ways
| nodes | highway | name | turn:lanes | oneway |
| ab | primary | road | left\|left\|right\|right | no |
| bcd | primary | road | through\|through | yes |
| efb | primary | road | through\|through | yes |
When I route I should get
| waypoints | route | turns |
| a,d | road,road | depart,arrive |
| e,a | road,road | depart,arrive |
@todo @todo
# currently the intersections don't match up do to the `merging` process. # currently the intersections don't match up do to the `merging` process.
# The intermediate intersection is technically no-turn at all, since the road continues. # The intermediate intersection is technically no-turn at all, since the road continues.
+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 |
+1 -1
View File
@@ -11,7 +11,7 @@ module.exports = function () {
var waypoints = [], var waypoints = [],
columnHeaders = tableRows[0].slice(1), columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1), rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.every((ele, i) => ele === rowHeaders[i]); symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
if (symmetric) { if (symmetric) {
columnHeaders.forEach((nodeName) => { columnHeaders.forEach((nodeName) => {
+67
View File
@@ -41,6 +41,17 @@ Feature: Basic Distance Matrix
| c | 30 | 20 | 0 | 30 | | c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 | | d | 60 | 50 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel time matrix with fuzzy match Scenario: Testbot - Travel time matrix with fuzzy match
Given the node map Given the node map
""" """
@@ -132,6 +143,13 @@ Feature: Basic Distance Matrix
| | a | b | e | f | | | a | b | e | f |
| a | 0 | 10 | 20 | 30 | | a | 0 | 10 | 20 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
Scenario: Testbot - Travel time 3x2 matrix Scenario: Testbot - Travel time 3x2 matrix
Given the node map Given the node map
""" """
@@ -308,3 +326,52 @@ Feature: Basic Distance Matrix
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 | | 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 | | 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 | | 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
Scenario: Testbot - Travel time matrix with ties
Given the profile file
"""
local functions = require('testbot')
functions.process_segment = function(profile, segment)
segment.weight = 1
segment.duration = 1
end
functions.process_turn = function(profile, turn)
if turn.angle >= 0 then
turn.duration = 16
else
turn.duration = 4
end
turn.weight = 0
end
return functions
"""
And the node map
"""
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
+9 -5
View File
@@ -159,14 +159,16 @@ class CellCustomizer
} }
const EdgeWeight to_weight = weight + subcell_weight; const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
if (!heap.WasInserted(to)) if (!heap.WasInserted(to))
{ {
heap.Insert(to, to_weight, {true, duration + *subcell_duration}); heap.Insert(to, to_weight, {true, to_duration});
} }
else if (to_weight < heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
{ {
heap.DecreaseKey(to, to_weight); heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {true, duration + *subcell_duration}; heap.GetData(to) = {true, to_duration};
} }
} }
@@ -191,14 +193,16 @@ class CellCustomizer
partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to))) partition.GetCell(level - 1, node) != partition.GetCell(level - 1, to)))
{ {
const EdgeWeight to_weight = weight + data.weight; const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
if (!heap.WasInserted(to)) if (!heap.WasInserted(to))
{ {
heap.Insert(to, to_weight, {false, duration + data.duration}); heap.Insert(to, to_weight, {false, duration + data.duration});
} }
else if (to_weight < heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(heap.GetKey(to), heap.GetData(to).duration))
{ {
heap.DecreaseKey(to, to_weight); heap.DecreaseKey(to, to_weight);
heap.GetData(to) = {false, duration + data.duration}; heap.GetData(to) = {false, to_duration};
} }
} }
} }
+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;
}; };
} }
} }
+3 -13
View File
@@ -30,7 +30,7 @@ class RoutingAlgorithmsInterface
virtual InternalRouteResult virtual InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0; DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::vector<EdgeWeight> virtual std::vector<EdgeDuration>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0; const std::vector<std::size_t> &target_indices) const = 0;
@@ -81,7 +81,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
InternalRouteResult InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override; DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
std::vector<EdgeWeight> std::vector<EdgeDuration>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes, ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices, const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const final override; const std::vector<std::size_t> &target_indices) const final override;
@@ -166,16 +166,6 @@ RoutingAlgorithms<Algorithm>::DirectShortestPathSearch(const PhantomNodes &phant
return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes); return routing_algorithms::directShortestPathSearch(heaps, *facade, phantom_nodes);
} }
template <typename Algorithm>
std::vector<EdgeWeight>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
template <typename Algorithm> template <typename Algorithm>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching( inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
const routing_algorithms::CandidateLists &candidates_list, const routing_algorithms::CandidateLists &candidates_list,
@@ -211,7 +201,7 @@ InternalManyRoutesResult inline RoutingAlgorithms<
} }
template <> template <>
inline std::vector<EdgeWeight> inline std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch( RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &, const std::vector<PhantomNode> &,
const std::vector<std::size_t> &, const std::vector<std::size_t> &,
@@ -17,11 +17,23 @@ namespace routing_algorithms
{ {
template <typename Algorithm> template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data, std::vector<EdgeDuration> 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 mld
{
template <bool DIRECTION>
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
} // mld
} // namespace routing_algorithms } // namespace routing_algorithms
} // namespace engine } // namespace engine
@@ -132,44 +132,16 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
} }
template <bool DIRECTION, typename Algorithm, typename... Args> template <bool DIRECTION, typename Algorithm, typename... Args>
void routingStep(const DataFacade<Algorithm> &facade, void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap, typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap, const NodeID node,
NodeID &middle_node, const EdgeWeight weight,
EdgeWeight &path_upper_bound, Args... args)
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{ {
const auto &partition = facade.GetMultiLevelPartition(); const auto &partition = facade.GetMultiLevelPartition();
const auto &cells = facade.GetCellStorage(); const auto &cells = facade.GetCellStorage();
const auto &metric = facade.GetCellMetric(); const auto &metric = facade.GetCellMetric();
const auto node = forward_heap.DeleteMin();
const auto weight = forward_heap.GetKey(node);
BOOST_ASSERT(!facade.ExcludeNode(node));
// Upper bound for the path source -> target with
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
// is weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(node))
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
}
}
const auto level = getNodeQueryLevel(partition, node, args...); const auto level = getNodeQueryLevel(partition, node, args...);
if (level >= 1 && !forward_heap.GetData(node).from_clique_arc) if (level >= 1 && !forward_heap.GetData(node).from_clique_arc)
@@ -258,6 +230,45 @@ void routingStep(const DataFacade<Algorithm> &facade,
} }
} }
template <bool DIRECTION, typename Algorithm, typename... Args>
void routingStep(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const bool force_loop_forward,
const bool force_loop_reverse,
Args... args)
{
const auto node = forward_heap.DeleteMin();
const auto weight = forward_heap.GetKey(node);
BOOST_ASSERT(!facade.ExcludeNode(node));
// Upper bound for the path source -> target with
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
// is weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(node))
{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
// if loops are forced, they are so at the source
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
(path_weight >= 0) && (path_weight < path_upper_bound))
{
middle_node = node;
path_upper_bound = path_weight;
}
}
// Relax outgoing edges from node
relaxOutgoingEdges<DIRECTION>(facade, forward_heap, node, weight, args...);
}
// With (s, middle, t) we trace back the paths middle -> s and middle -> t. // With (s, middle, t) we trace back the paths middle -> s and middle -> t.
// This gives us a packed path (node ids) from the base graph around s and t, // This gives us a packed path (node ids) from the base graph around s and t,
// and overlay node ids otherwise. We then have to unpack the overlay clique // and overlay node ids otherwise. We then have to unpack the overlay clique
+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-glibc.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)
+2
View File
@@ -250,10 +250,12 @@ function setup()
-- List only exceptions -- List only exceptions
maxspeed_table = { maxspeed_table = {
["be:motorway"] = 120,
["ch:rural"] = 80, ["ch:rural"] = 80,
["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,
+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)
+2
View File
@@ -19,6 +19,8 @@ with open(taginfo_path) as f:
valid_strings = [t["key"] for t in taginfo["tags"]] valid_strings = [t["key"] for t in taginfo["tags"]]
valid_strings += [t["value"] for t in taginfo["tags"] if "value" in t] valid_strings += [t["value"] for t in taginfo["tags"] if "value" in t]
valid_strings += [t["value"].lower() for t in taginfo["tags"] if "value" in t] # lower is for max speed
valid_strings = set(valid_strings)
string_regxp = re.compile("\"([\d\w\_:]+)\"") string_regxp = re.compile("\"([\d\w\_:]+)\"")
+21 -9
View File
@@ -145,7 +145,8 @@ class SVGPrinter (gdb.Command):
self.to_svg = { self.to_svg = {
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> &': self.Facade, 'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> &': self.Facade,
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::corech::Algorithm> &': self.Facade, 'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::corech::Algorithm> &': self.Facade,
'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::mld::Algorithm> &': self.Facade} 'const osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<osrm::engine::routing_algorithms::mld::Algorithm> &': self.Facade,
'osrm::engine::DataFacade': self.Facade}
@staticmethod @staticmethod
@@ -258,17 +259,27 @@ class SVGPrinter (gdb.Command):
geometry_first = geometry['_M_impl']['_M_start'] geometry_first = geometry['_M_impl']['_M_start']
for segment, weight in enumerate(iterate(weights)): for segment, weight in enumerate(iterate(weights)):
ref = 's' + str(node) + '.' + str(segment) ref = 's' + str(node) + '.' + str(segment)
result += '<path id="' + ref + '" class="segment" d="' \ fr = lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))
+ 'M' + t(lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))) + ' ' \ to = lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))
+ 'L' + t(lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))) + '" />'\ if fr == to:
+ '<text class="segment weight ' + direction + '">'\ ## node penalty on zero length segment (traffic light)
+ '<textPath xlink:href="#' + ref + '" startOffset="50%">' \ result += '<text class="segment weight ' + direction \
+ segment_weight(weight) + '</textPath></text>\n' + '" x="' + str(tx(fr[0])) + '" y="' + str(ty(fr[1])) \
+ '" font="Arial" font-size="32" rotate="0" text-anchor="middle" >' \
+ '&#x1F6A6; ' + segment_weight(weight) + '</text>\n'
else:
## normal segment
result += '<path id="' + ref + '" class="segment" d="' \
+ 'M' + t(fr) + ' ' \
+ 'L' + t(to) + '" />'\
+ '<text class="segment weight ' + direction + '">'\
+ '<textPath xlink:href="#' + ref + '" startOffset="50%">' \
+ segment_weight(weight) + '</textPath></text>\n'
geometry_first += 1 geometry_first += 1
## add edge-based edges ## add edge-based edges
s0, s1 = geometry['_M_impl']['_M_start'].dereference(), (geometry['_M_impl']['_M_start'] + 1).dereference() s0, s1 = geometry['_M_impl']['_M_start'].dereference(), (geometry['_M_impl']['_M_start'] + 1).dereference()
for edge in range(call(facade, 'BeginEdges', node), call(facade, 'EndEdges', node)): for edge in []: # range(call(facade, 'BeginEdges', node), call(facade, 'EndEdges', node)): adjust to GetAdjacentEdgeRange
target, edge_data = call(facade, 'GetTarget', edge), call(facade, 'GetEdgeData', edge) target, edge_data = call(facade, 'GetTarget', edge), call(facade, 'GetEdgeData', edge)
direction = 'both' if edge_data['forward'] and edge_data['backward'] else 'forward' if edge_data['forward'] else 'backward' direction = 'both' if edge_data['forward'] and edge_data['backward'] else 'forward' if edge_data['forward'] else 'backward'
target_geometry = SVGPrinter.getByGeometryId(facade, call(facade, 'GetGeometryIndex', target), 'Geometry') target_geometry = SVGPrinter.getByGeometryId(facade, call(facade, 'GetGeometryIndex', target), 'Geometry')
@@ -323,7 +334,8 @@ class SVGPrinter (gdb.Command):
re_float = '[-+]?[0-9]*\.?[0-9]+' re_float = '[-+]?[0-9]*\.?[0-9]+'
bbox = re.search('(' + re_float + '),(' + re_float + ');(' + re_float + '),(' + re_float +')', arg) bbox = re.search('(' + re_float + '),(' + re_float + ');(' + re_float + '),(' + re_float +')', arg)
bbox = [float(x) for x in bbox.groups()] if bbox else [-180, -90, 180, 90] bbox = [float(x) for x in bbox.groups()] if bbox else [-180, -90, 180, 90]
svg = self.to_svg[str(val.type)](val, width, height, bbox) type = val.type.target().unqualified() if val.type.code == gdb.TYPE_CODE_REF else val.type
svg = self.to_svg[str(type)](val, width, height, bbox)
self.show_svg(svg, width, height) self.show_svg(svg, width, height)
except KeyError as e: except KeyError as e:
print ('no SVG printer for: ' + str(e)) print ('no SVG printer for: ' + str(e))
+8
View File
@@ -0,0 +1,8 @@
# Configuration file for LeakSanitizer run on the Travis CI
# TBB leaks some memory allocated in singleton depending on deinitialization order
# Direct leak of 1560 byte(s) in 3 object(s) allocated from:
# #0 0x7f7ae72a80a0 in operator new[](unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.3+0xc80a0)
# #1 0x7f7ae595d13e (/usr/lib/x86_64-linux-gnu/libtbb.so.2+0x2213e)
leak:libtbb.so
+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;
} }
+56
View File
@@ -0,0 +1,56 @@
#include "engine/routing_algorithms.hpp"
namespace osrm
{
namespace engine
{
template <typename Algorithm>
std::vector<EdgeDuration>
RoutingAlgorithms<Algorithm>::ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
template std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::ch::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const;
template std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const;
// One-to-many and many-to-one can be handled with MLD separately from many-to-many search.
// One-to-many (many-to-one) search is a unidirectional forward (backward) Dijkstra search
// with the candidate node level min(GetQueryLevel(phantom_node, phantom_nodes, node)
template <>
std::vector<EdgeDuration> RoutingAlgorithms<routing_algorithms::mld::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const
{
if (source_indices.size() == 1)
{ // TODO: check if target_indices.size() == 1 and do a bi-directional search
return routing_algorithms::mld::oneToManySearch<routing_algorithms::FORWARD_DIRECTION>(
heaps, *facade, phantom_nodes, source_indices.front(), target_indices);
}
if (target_indices.size() == 1)
{
return routing_algorithms::mld::oneToManySearch<routing_algorithms::REVERSE_DIRECTION>(
heaps, *facade, phantom_nodes, target_indices.front(), source_indices);
}
return routing_algorithms::manyToManySearch(
heaps, *facade, phantom_nodes, source_indices, target_indices);
}
} // namespace engine
} // namespace osrm
+393 -147
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))
@@ -87,7 +104,8 @@ void relaxOutgoingEdges(const DataFacade<ch::Algorithm> &facade,
query_heap.Insert(to, to_weight, {node, to_duration}); query_heap.Insert(to, to_weight, {node, to_duration});
} }
// Found a shorter Path -> Update weight // Found a shorter Path -> Update weight
else if (to_weight < query_heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
{ {
// new parent // new parent
query_heap.GetData(to) = {node, to_duration}; query_heap.GetData(to) = {node, to_duration};
@@ -103,13 +121,60 @@ addLoopWeight(const DataFacade<mld::Algorithm> &, const NodeID, EdgeWeight &, Ed
return false; return false;
} }
template <bool DIRECTION> template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node,
const PhantomNode &phantom_node)
{
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) {
if (phantom_node.enabled)
return partition.GetHighestDifferentLevel(phantom_node.id, node);
return INVALID_LEVEL_ID;
};
return std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
}
template <typename MultiLevelPartition>
inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
NodeID node,
const std::vector<PhantomNode> &phantom_nodes,
const std::size_t phantom_index,
const std::vector<std::size_t> &phantom_indices)
{
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
const auto &forward_segment = phantom_node.forward_segment_id;
const auto forward_level =
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
: INVALID_LEVEL_ID;
const auto &reverse_segment = phantom_node.reverse_segment_id;
const auto reverse_level =
reverse_segment.enabled ? partition.GetHighestDifferentLevel(node, reverse_segment.id)
: INVALID_LEVEL_ID;
return std::min(forward_level, reverse_level);
};
// Get minimum level over all phantoms of the highest different level with respect to node
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
auto result = min_level(phantom_nodes[phantom_index]);
for (const auto &index : phantom_indices)
{
result = std::min(result, min_level(phantom_nodes[index]));
}
return result;
}
template <bool DIRECTION, typename... Args>
void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade, void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const NodeID node, const NodeID node,
const EdgeWeight weight, const EdgeWeight weight,
const EdgeDuration duration, const EdgeDuration duration,
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap, typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
const PhantomNode &phantom_node) Args... args)
{ {
BOOST_ASSERT(!facade.ExcludeNode(node)); BOOST_ASSERT(!facade.ExcludeNode(node));
@@ -117,13 +182,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const auto &cells = facade.GetCellStorage(); const auto &cells = facade.GetCellStorage();
const auto &metric = facade.GetCellMetric(); const auto &metric = facade.GetCellMetric();
auto highest_diffrent_level = [&partition, node](const SegmentID &phantom_node) { const auto level = getNodeQueryLevel(partition, node, args...);
if (phantom_node.enabled)
return partition.GetHighestDifferentLevel(phantom_node.id, node);
return INVALID_LEVEL_ID;
};
const auto level = std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
const auto &node_data = query_heap.GetData(node); const auto &node_data = query_heap.GetData(node);
@@ -148,7 +207,8 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
{ {
query_heap.Insert(to, to_weight, {node, true, to_duration}); query_heap.Insert(to, to_weight, {node, true, to_duration});
} }
else if (to_weight < query_heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
{ {
query_heap.GetData(to) = {node, true, to_duration}; query_heap.GetData(to) = {node, true, to_duration};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
@@ -177,7 +237,8 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
{ {
query_heap.Insert(to, to_weight, {node, true, to_duration}); query_heap.Insert(to, to_weight, {node, true, to_duration});
} }
else if (to_weight < query_heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
{ {
query_heap.GetData(to) = {node, true, to_duration}; query_heap.GetData(to) = {node, true, to_duration};
query_heap.DecreaseKey(to, to_weight); query_heap.DecreaseKey(to, to_weight);
@@ -201,12 +262,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))
@@ -214,7 +275,8 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
query_heap.Insert(to, to_weight, {node, false, to_duration}); query_heap.Insert(to, to_weight, {node, false, to_duration});
} }
// Found a shorter Path -> Update weight // Found a shorter Path -> Update weight
else if (to_weight < query_heap.GetKey(to)) else if (std::tie(to_weight, to_duration) <
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
{ {
// new parent // new parent
query_heap.GetData(to) = {node, false, to_duration}; query_heap.GetData(to) = {node, false, to_duration};
@@ -229,49 +291,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 (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
{
current_weight = new_weight;
current_duration = new_duration;
}
} }
relaxOutgoingEdges<FORWARD_DIRECTION>( relaxOutgoingEdges<FORWARD_DIRECTION>(
@@ -282,15 +342,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);
@@ -298,111 +358,297 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
} }
template <typename Algorithm> template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data, std::vector<EdgeDuration> 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;
} }
template std::vector<EdgeWeight> template std::vector<EdgeDuration>
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<EdgeDuration>
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 mld
{
// Unidirectional multi-layer Dijkstra search for 1-to-N and N-to-1 matrices
template <bool DIRECTION>
std::vector<EdgeDuration> oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices)
{
if (phantom_indices.empty())
{
phantom_indices.resize(phantom_nodes.size());
std::iota(phantom_indices.begin(), phantom_indices.end(), 0);
}
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
// Collect destination (source) nodes into a map
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration>>
target_nodes_index;
target_nodes_index.reserve(phantom_indices.size());
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
{
const auto &phantom_index = phantom_indices[index];
const auto &phantom_node = phantom_nodes[phantom_index];
if (DIRECTION == FORWARD_DIRECTION)
{
if (phantom_node.IsValidForwardTarget())
target_nodes_index.insert(
{phantom_node.forward_segment_id.id,
std::make_tuple(index,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration())});
if (phantom_node.IsValidReverseTarget())
target_nodes_index.insert(
{phantom_node.reverse_segment_id.id,
std::make_tuple(index,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration())});
}
else if (DIRECTION == REVERSE_DIRECTION)
{
if (phantom_node.IsValidForwardSource())
target_nodes_index.insert(
{phantom_node.forward_segment_id.id,
std::make_tuple(index,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration())});
if (phantom_node.IsValidReverseSource())
target_nodes_index.insert(
{phantom_node.reverse_segment_id.id,
std::make_tuple(index,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration())});
}
}
// Initialize query heap
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
// Check if node is in the destinations list and update weights/durations
auto update_values = [&](NodeID node, EdgeWeight weight, EdgeDuration duration) {
auto candidates = target_nodes_index.equal_range(node);
for (auto it = candidates.first; it != candidates.second;)
{
std::size_t index;
EdgeWeight target_weight;
EdgeDuration target_duration;
std::tie(index, target_weight, target_duration) = it->second;
const auto path_weight = weight + target_weight;
if (path_weight >= 0)
{
const auto path_duration = duration + target_duration;
if (std::tie(path_weight, path_duration) <
std::tie(weights[index], durations[index]))
{
weights[index] = path_weight;
durations[index] = path_duration;
}
// Remove node from destinations list
it = target_nodes_index.erase(it);
}
else
{
++it;
}
}
};
// Check a single path result and insert adjacent nodes into heap
auto insert_node = [&](NodeID node, EdgeWeight initial_weight, EdgeDuration initial_duration) {
// Update single node paths
update_values(node, initial_weight, initial_duration);
// Place adjacent nodes into heap
for (auto edge : facade.GetAdjacentEdgeRange(node))
{
const auto &data = facade.GetEdgeData(edge);
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
{
query_heap.Insert(facade.GetTarget(edge),
data.weight + initial_weight,
{node, data.duration + initial_duration});
}
}
};
{ // Place source (destination) adjacent nodes into the heap
const auto &phantom_node = phantom_nodes[phantom_index];
if (DIRECTION == FORWARD_DIRECTION)
{
if (phantom_node.IsValidForwardSource())
insert_node(phantom_node.forward_segment_id.id,
-phantom_node.GetForwardWeightPlusOffset(),
-phantom_node.GetForwardDuration());
if (phantom_node.IsValidReverseSource())
insert_node(phantom_node.reverse_segment_id.id,
-phantom_node.GetReverseWeightPlusOffset(),
-phantom_node.GetReverseDuration());
}
else if (DIRECTION == REVERSE_DIRECTION)
{
if (phantom_node.IsValidForwardTarget())
insert_node(phantom_node.forward_segment_id.id,
phantom_node.GetForwardWeightPlusOffset(),
phantom_node.GetForwardDuration());
if (phantom_node.IsValidReverseTarget())
insert_node(phantom_node.reverse_segment_id.id,
phantom_node.GetReverseWeightPlusOffset(),
phantom_node.GetReverseDuration());
}
}
while (!query_heap.Empty() && !target_nodes_index.empty())
{
// Extract node from the heap
const auto node = query_heap.DeleteMin();
const auto weight = query_heap.GetKey(node);
const auto duration = query_heap.GetData(node).duration;
// Update values
update_values(node, weight, duration);
// Relax outgoing edges
relaxOutgoingEdges<DIRECTION>(facade,
node,
weight,
duration,
query_heap,
phantom_nodes,
phantom_index,
phantom_indices);
}
return durations;
}
template std::vector<EdgeDuration>
oneToManySearch<FORWARD_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
template std::vector<EdgeDuration>
oneToManySearch<REVERSE_DIRECTION>(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::size_t phantom_index,
std::vector<std::size_t> phantom_indices);
} // mld
} // 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);
+25 -12
View File
@@ -287,23 +287,36 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
return lane_description; return lane_description;
}; };
// convert the lane description into an ID and, if necessary, remember the description in the // If we could parse turn lanes but could not parse number of lanes,
// description_map // count the turn lanes and use them for the way's number of lanes.
const auto requestId = [&](const std::string &lane_string) { auto road_classification = parsed_way.road_classification;
if (lane_string.empty()) std::uint8_t road_deduced_num_lanes = 0;
return INVALID_LANE_DESCRIPTIONID;
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
return lane_description_map.ConcurrentFindOrAdd(lane_description);
};
// Deduplicates street names, refs, destinations, pronunciation, exits. // Deduplicates street names, refs, destinations, pronunciation, exits.
// In case we do not already store the key, inserts (key, id) tuple and return id. // In case we do not already store the key, inserts (key, id) tuple and return id.
// Otherwise fetches the id based on the name and returns it without insertion. // Otherwise fetches the id based on the name and returns it without insertion.
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward); auto turn_lane_id_forward = INVALID_LANE_DESCRIPTIONID;
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward); auto turn_lane_id_backward = INVALID_LANE_DESCRIPTIONID;
const auto road_classification = parsed_way.road_classification; // RoadClassification represents a the class for unidirectional ways,
// therefore we need to add up deduced forward and backward lane counts.
if (!parsed_way.turn_lanes_forward.empty())
{
auto desc = laneStringToDescription(parsed_way.turn_lanes_forward);
turn_lane_id_forward = lane_description_map.ConcurrentFindOrAdd(desc);
road_deduced_num_lanes += desc.size();
}
if (!parsed_way.turn_lanes_backward.empty())
{
auto desc = laneStringToDescription(parsed_way.turn_lanes_backward);
turn_lane_id_backward = lane_description_map.ConcurrentFindOrAdd(desc);
road_deduced_num_lanes += desc.size();
}
road_classification.SetNumberOfLanes(std::max(road_deduced_num_lanes, // len(turn:lanes)
road_classification.GetNumberOfLanes()));
// Get the unique identifier for the street name, destination, and ref // Get the unique identifier for the street name, destination, and ref
const auto name_iterator = string_map.find(MapKey(parsed_way.name, const auto name_iterator = string_map.find(MapKey(parsed_way.name,
@@ -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;
+31
View File
@@ -0,0 +1,31 @@
#ifdef GLIBC_WORKAROUND
#include <stdexcept>
// https://github.com/bitcoin/bitcoin/pull/4042
// allows building against libstdc++-dev-4.9 while avoiding
// GLIBCXX_3.4.20 dep
// This is needed because libstdc++ itself uses this API - its not
// just an issue of your code using it, ughhh
// Note: only necessary on Linux
#ifdef __linux__
#define _ENABLE_GLIBC_WORKAROUND
#warning building with workaround
#else
#warning not building with workaround
#endif
#ifdef _ENABLE_GLIBC_WORKAROUND
namespace std
{
void __throw_out_of_range_fmt(const char *, ...) __attribute__((__noreturn__));
void __throw_out_of_range_fmt(const char *err, ...)
{
// Safe and over-simplified version. Ignore the format and print it as-is.
__throw_out_of_range(err);
}
}
#endif // _ENABLE_GLIBC_WORKAROUND
#endif // GLIBC_WORKAROUND
+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()
+26 -23
View File
@@ -144,29 +144,32 @@
{"key": "maxspeed", "value": "rural"}, {"key": "maxspeed", "value": "rural"},
{"key": "maxspeed", "value": "trunk"}, {"key": "maxspeed", "value": "trunk"},
{"key": "maxspeed", "value": "motorway"}, {"key": "maxspeed", "value": "motorway"},
{"key": "maxspeed", "value": "ch:rural"}, {"key": "maxspeed", "value": "BE:motorway"},
{"key": "maxspeed", "value": "ch:trunk"}, {"key": "maxspeed", "value": "CH:rural"},
{"key": "maxspeed", "value": "ch:motorway"}, {"key": "maxspeed", "value": "CH:trunk"},
{"key": "maxspeed", "value": "de:living_street"}, {"key": "maxspeed", "value": "CH:motorway"},
{"key": "maxspeed", "value": "ru:living_street"}, {"key": "maxspeed", "value": "DE:living_street"},
{"key": "maxspeed", "value": "ru:urban"}, {"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "ua:urban"}, {"key": "maxspeed", "value": "RU:living_street"},
{"key": "maxspeed", "value": "at:rural"}, {"key": "maxspeed", "value": "RU:urban"},
{"key": "maxspeed", "value": "de:rural"}, {"key": "maxspeed", "value": "UA:urban"},
{"key": "maxspeed", "value": "at:trunk"}, {"key": "maxspeed", "value": "AT:rural"},
{"key": "maxspeed", "value": "cz:trunk"}, {"key": "maxspeed", "value": "DE:rural"},
{"key": "maxspeed", "value": "ro:trunk"}, {"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "cz:motorway"}, {"key": "maxspeed", "value": "AT:trunk"},
{"key": "maxspeed", "value": "de:motorway"}, {"key": "maxspeed", "value": "CZ:trunk"},
{"key": "maxspeed", "value": "ru:motorway"}, {"key": "maxspeed", "value": "RO:trunk"},
{"key": "maxspeed", "value": "gb:nsl_single"}, {"key": "maxspeed", "value": "CZ:motorway"},
{"key": "maxspeed", "value": "gb:nsl_dual"}, {"key": "maxspeed", "value": "DE:motorway"},
{"key": "maxspeed", "value": "gb:motorway"}, {"key": "maxspeed", "value": "RU:motorway"},
{"key": "maxspeed", "value": "uk:nsl_single"}, {"key": "maxspeed", "value": "GB:nsl_single"},
{"key": "maxspeed", "value": "uk:nsl_dual"}, {"key": "maxspeed", "value": "GB:nsl_dual"},
{"key": "maxspeed", "value": "uk:motorway"}, {"key": "maxspeed", "value": "GB:motorway"},
{"key": "maxspeed", "value": "nl:rural"}, {"key": "maxspeed", "value": "UK:nsl_single"},
{"key": "maxspeed", "value": "nl:trunk"}, {"key": "maxspeed", "value": "UK:nsl_dual"},
{"key": "maxspeed", "value": "UK:motorway"},
{"key": "maxspeed", "value": "NL:rural"},
{"key": "maxspeed", "value": "NL:trunk"},
{"key": "smoothness", "value": "intermediate"}, {"key": "smoothness", "value": "intermediate"},
{"key": "smoothness", "value": "bad"}, {"key": "smoothness", "value": "bad"},
{"key": "smoothness", "value": "very_bad"}, {"key": "smoothness", "value": "very_bad"},
@@ -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
{ {
} }
}; };