Compare commits

...

60 Commits

Author SHA1 Message Date
Daniel Patterson c5167d4ade Bump nodejs version to make new package. 2017-10-03 09:10:03 -07:00
Daniel Patterson 1548803a77 Merge branch 'downgrade_libstdc++' of github.com:Project-OSRM/osrm-backend into downgrade_libstdc++ 2017-10-03 09:09:18 -07:00
Daniel J. Hofmann 2b2906f97a Bumps Boost from Mason to 1.65.1 2017-10-03 12:09:33 +02:00
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 1592 additions and 455 deletions
+27 -22
View File
@@ -68,7 +68,7 @@ matrix:
addons: &gcc6
apt:
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
after_success:
- bash <(curl -s https://codecov.io/bash)
@@ -78,15 +78,15 @@ matrix:
addons: &gcc6
apt:
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']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Debug' TARGET_ARCH='x86_64-asan' ENABLE_SANITIZER=ON CUCUMBER_TIMEOUT=20000
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 LSAN_OPTIONS="suppressions=$TRAVIS_BUILD_DIR/scripts/travis/leaksanitizer.conf"
- os: linux
compiler: "clang-4.0-debug"
addons: &clang40
apt:
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
- os: linux
@@ -94,8 +94,8 @@ matrix:
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-5-dev']
env: CLANG_VERSION='4.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_SANITIZER=ON
packages: ['libstdc++-4.9-dev']
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
- os: linux
@@ -103,7 +103,7 @@ matrix:
addons:
apt:
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
- os: linux
@@ -111,7 +111,7 @@ matrix:
addons: &gcc6
apt:
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'
- os: linux
@@ -125,7 +125,7 @@ matrix:
addons: &gcc6
apt:
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
- os: linux
@@ -133,7 +133,7 @@ matrix:
addons: &gcc49
apt:
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'
- os: osx
@@ -158,7 +158,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', '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'
# Shared Library
@@ -167,7 +167,7 @@ matrix:
addons: &gcc6
apt:
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
# Disabled because CI slowness
@@ -176,7 +176,7 @@ matrix:
#- addons: &clang40
#- apt:
#- sources: ['llvm-toolchain-trusty-4.0', 'ubuntu-toolchain-r-test']
#- packages: ['clang-4.0', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', '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
# Node build jobs. These skip running the tests.
@@ -186,7 +186,7 @@ matrix:
addons:
apt:
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
install:
- pushd ${OSRM_BUILD_DIR}
@@ -195,7 +195,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
@@ -209,7 +210,7 @@ matrix:
addons:
apt:
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
install:
- pushd ${OSRM_BUILD_DIR}
@@ -218,7 +219,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
@@ -232,7 +234,7 @@ matrix:
addons:
apt:
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"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -241,7 +243,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
@@ -255,7 +258,7 @@ matrix:
addons:
apt:
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"
install:
- pushd ${OSRM_BUILD_DIR}
@@ -264,7 +267,8 @@ matrix:
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
@@ -338,7 +342,8 @@ install:
-DENABLE_STXXL=${ENABLE_STXXL:-OFF} \
-DBUILD_TOOLS=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"
- make --jobs=${JOBS}
- make tests --jobs=${JOBS}
+11
View File
@@ -1,4 +1,15 @@
# 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
- 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`.
+13 -27
View File
@@ -31,12 +31,13 @@ option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_GOLD_LINKER "Use GNU gold linker if available" ON)
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")
if(ENABLE_MASON)
# versions in use
set(MASON_BOOST_VERSION "1.63.0")
set(MASON_BOOST_VERSION "1.65.1")
set(MASON_STXXL_VERSION "1.4.1-1")
set(MASON_EXPAT_VERSION "2.2.0")
set(MASON_LUA_VERSION "5.2.4")
@@ -60,7 +61,7 @@ if (POLICY CMP0048)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 12)
set(OSRM_VERSION_MINOR 13)
set(OSRM_VERSION_PATCH 0)
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
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++1y")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(OSRM_CXXFLAGS "${OSRM_CXXFLAGS} -std=c++14")
endif()
# Configuring other platform dependencies
@@ -517,29 +518,10 @@ else()
find_package(BZip2 REQUIRED)
add_dependency_includes(${BZIP2_INCLUDE_DIR})
FIND_PACKAGE(Lua 5.2 EXACT)
IF (LUA_FOUND)
MESSAGE(STATUS "Using Lua ${LUA_VERSION_STRING}")
ELSE()
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()
find_package(Lua 5.2 REQUIRED)
if (LUA_FOUND)
message(STATUS "Using Lua ${LUA_VERSION_STRING}")
endif()
set(USED_LUA_LIBRARIES ${LUA_LIBRARIES})
add_dependency_includes(${LUA_INCLUDE_DIR})
@@ -829,6 +811,10 @@ add_custom_target(uninstall
add_subdirectory(unit_tests)
add_subdirectory(src/benchmarks)
if (ENABLE_GLIBC_WORKAROUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGLIBC_WORKAROUND")
endif()
if (ENABLE_NODE_BINDINGS)
add_subdirectory(src/nodejs)
endif()
+3 -1
View File
@@ -157,7 +157,9 @@ which will check and use pre-built binaries if they're available for this releas
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
+8 -5
View File
@@ -7,19 +7,22 @@ ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SET PROJECT_DIR=%CD%
ECHO PROJECT_DIR^: %PROJECT_DIR%
ECHO NUMBER_OF_PROCESSORS^: %NUMBER_OF_PROCESSORS%
:: Check CMake version
SET CMAKE_VERSION=3.9.2
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
ECHO cmake^: && cmake --version
IF %ERRORLEVEL% NEQ 0 ECHO CMAKE not found && GOTO CMAKE_NOT_OK
cmake --version | findstr /C:"3.7.1" && GOTO CMAKE_OK
cmake --version | findstr /C:%CMAKE_VERSION% && GOTO CMAKE_OK
:CMAKE_NOT_OK
SET CMAKE_VERSION=3.7.1
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 NOT EXIST cmake-%CMAKE_VERSION%-win32-x86 7z -y x cm.zip | %windir%\system32\FIND "ing archive"
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
SET PATH=%PROJECT_DIR%\cmake-%CMAKE_VERSION%-win32-x86\bin;%PATH%
:CMAKE_OK
ECHO CMAKE_OK
@@ -37,7 +40,7 @@ ECHO msbuild version
msbuild /version
:: 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
ECHO.
+3
View File
@@ -36,6 +36,8 @@
# This is because, the lua location is not standardized and may exist in
# locations other than lua/
include(FindPkgConfig)
unset(_lua_include_subdirs)
unset(_lua_library_names)
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}
)
pkg_check_modules(LUA QUIET "lua${ver}")
endforeach ()
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 && \
apk update && \
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" && \
cd /opt && \
@@ -46,8 +46,8 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
rm /usr/local/lib/libstxxl* && \
cd /opt && \
apk del boost-dev && \
apk del g++ cmake libc-dev expat-dev zlib-dev bzip2-dev lua5.1-dev git make gcc && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.1 expat && \
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.2 expat && \
rm -rf /src /opt/stxxl /usr/local/bin/stxxl_tool /usr/local/lib/libosrm*
EXPOSE 5000
+60 -8
View File
@@ -47,7 +47,7 @@ Profiles can also define a `process_segment` function to handle differences in s
At the end of the file, a table if returned with references to the setup and processing functions the profile has defined.
## Understanding speed, weight and rate
## Understanding speed, weight and rate
When computing a route from A to B there can be different measure of what is the best route. That's why there's a need for different profiles.
Because speeds very on different types of roads, the shortest and the fastest route are typically different. But there are many other possible preferences. For example a user might prefer a bicycle route that follow parks or other green areas, even though both duration and distance are a bit longer.
@@ -91,7 +91,7 @@ The `setup` function is called once when the profile is loaded and must return a
Note that processing of data is parallelized and several unconnected LUA interpreters will be running at the same time. The `setup` function will be called once for each. Each LUA iinterpreter will have it's own set of globals.
The following global properties can be set under `properties` in the hash you return in the `setup` function:
The following global properties can be set under `properties` in the hash you return in the `setup` function:
Attribute | Type | Notes
-------------------------------------|----------|----------------------------------------------------------------------------
@@ -114,7 +114,7 @@ classes | Sequence | Determines the allowed
restrictions | Sequence | Determines which turn restrictions will be used for this profile.
suffix_list | Set | List of name suffixes needed for determining if "Highway 101 NW" the same road as "Highway 101 ES".
### process_node(profile, node, result)
### 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.
Argument | Description
@@ -122,6 +122,7 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input node to process (read-only).
result | The output that you will modify.
relations| The list of relation attributes passed from `process_relation` function for this node.
The following attributes can be set on `result`:
@@ -130,7 +131,7 @@ Attribute | Type | Notes
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?
## process_way(profile, way, result)
### 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.
Argument | Description
@@ -138,6 +139,7 @@ Argument | Description
profile | The configuration table you returned in `setup`.
node | The input way to process (read-only).
result | The output that you will modify.
relations| The list of relation attributes passed from `process_relation` function for this way.
Importantly it will set `result.forward_mode` and `result.backward_mode` to indicate the travel mode in each direction, as well as set `result.forward_speed` and `result.backward_speed` to integer values representing the speed for traversing the way.
@@ -177,10 +179,60 @@ road_classification.road_priority_class | Enum | Guidance: order in priority
road_classification.may_be_ignored | Boolean | Guidance: way is non-highway
road_classification.num_lanes | Unsigned | Guidance: total number of lanes in way
### process_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.
### process_relation(profile, relation, result)
On OpenStreetMap way cannot have different tags on different parts of a way. Instead you would split the way into several smaller ways. However many ways are long. For example, many ways pass hills without any change in tags.
Supported since API **version 3**.
Given an OpenStreetMap relation, the `process_relation` function should setup values into result structure.
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input relation to process (read-only).
result | The output that you will modify.
Relation process work flow consist of next steps:
1. Calls `process_relation` function for each relation. It should fill a `result` structure
2. After that each data will be passed for each member of processed relation into `process_node` and `process_way` functions
The following attributes can be set on that result in `process_relation`:
Attribute | Type | Notes
----------------------------------------|----------|--------------------------------------------------------------------------
is_restriction | Boolean | Flag to determine if relation is a turn restriction
Example processing code:
```lua
function process_way(profile, way, result, relations)
for _, r in ipairs(relations) do
for k, v in pairs(r) do
print('data_' .. k .. '_value_' .. v)
end
end
print ('process_way ' .. way:id() .. ' ' .. result.name)
end
function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
if t == "route" then
for _, m in ipairs(relation:members()) do
if m:role == "north" then
result[m]['direction'] = 'north'
print('direction_north')
end
end
print('route_relation')
end
end
```
### process_segment(profile, segment)
The `process_segment` function is called for every segment of OSM ways. A segment is a straight line between two OSM nodes.
On OpenStreetMap way cannot have different tags on different parts of a way. Instead you would split the way into several smaller ways. However many ways are long. For example, many ways pass hills without any change in tags.
Processing each segment of an OSM way makes it possible to have different speeds on different parts of a way based on external data like data about elevation, pollution, noise or scenic value and adjust weight and duration of the segment.
@@ -265,7 +317,7 @@ Example:
function process_segment (profile, segment)
local sourceData = raster:query(profile.raster_source, segment.source.lon, segment.source.lat)
local targetData = raster:query(profile.raster_source, segment.target.lon, segment.target.lat)
local invalid = sourceData.invalid_data()
if sourceData.datum ~= invalid and targetData.datum ~= invalid then
-- use values to adjust weight and duration
+35
View File
@@ -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 |
| 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
# 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.
+21
View File
@@ -1349,3 +1349,24 @@ Feature: Simple Turns
When I route I should get
| waypoints | route | turns |
| a,d | ab,dc,dc | depart,turn left,arrive |
# https://www.openstreetmap.org/node/1332083066
Scenario: Turns ordering must respect initial bearings
Given the node map
"""
a . be .
\ c.
d/ .f . g
"""
And the ways
| nodes | highway | oneway |
| ab | primary | yes |
| bcd | primary | yes |
| befg | primary | yes |
When I route I should get
| waypoints | route | turns |
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
| a,g | ab,befg,befg | depart,fork slight left,arrive |
@@ -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
Given the profile file
"""
api_version = 3
api_version = 4
"""
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 = [],
columnHeaders = tableRows[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) {
columnHeaders.forEach((nodeName) => {
+67
View File
@@ -41,6 +41,17 @@ Feature: Basic Distance Matrix
| c | 30 | 20 | 0 | 30 |
| 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
Given the node map
"""
@@ -132,6 +143,13 @@ Feature: Basic Distance Matrix
| | a | b | e | f |
| 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
Given the node map
"""
@@ -308,3 +326,52 @@ Feature: Basic Distance Matrix
| 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 |
| 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 EdgeDuration to_duration = duration + *subcell_duration;
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.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)))
{
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
if (!heap.WasInserted(to))
{
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.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/json_container.hpp"
#include <tbb/task_scheduler_init.h>
#include <memory>
#include <string>
@@ -53,7 +55,8 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
public:
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), //
nearest_plugin(config.max_results_nearest), //
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;
mutable SearchEngineData<Algorithm> heaps;
tbb::task_scheduler_init task_scheduler;
const plugins::ViaRoutePlugin route_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
bool use_shared_memory = true;
Algorithm algorithm = Algorithm::CH;
int use_threads_number = 1;
std::string verbosity;
};
}
}
+3 -13
View File
@@ -30,7 +30,7 @@ class RoutingAlgorithmsInterface
virtual InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_node_pair) const = 0;
virtual std::vector<EdgeWeight>
virtual std::vector<EdgeDuration>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices) const = 0;
@@ -81,7 +81,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
InternalRouteResult
DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override;
std::vector<EdgeWeight>
std::vector<EdgeDuration>
ManyToManySearch(const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
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);
}
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>
inline routing_algorithms::SubMatchingList RoutingAlgorithms<Algorithm>::MapMatching(
const routing_algorithms::CandidateLists &candidates_list,
@@ -211,7 +201,7 @@ InternalManyRoutesResult inline RoutingAlgorithms<
}
template <>
inline std::vector<EdgeWeight>
inline std::vector<EdgeDuration>
RoutingAlgorithms<routing_algorithms::corech::Algorithm>::ManyToManySearch(
const std::vector<PhantomNode> &,
const std::vector<std::size_t> &,
@@ -17,11 +17,23 @@ namespace routing_algorithms
{
template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
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 engine
@@ -132,44 +132,16 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
}
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)
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const NodeID node,
const EdgeWeight weight,
Args... args)
{
const auto &partition = facade.GetMultiLevelPartition();
const auto &cells = facade.GetCellStorage();
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...);
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.
// 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
+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 Way;
class Relation;
}
namespace std
@@ -44,6 +45,7 @@ namespace extractor
class ExtractionContainers;
struct ExtractionNode;
struct ExtractionWay;
struct ExtractionRelation;
struct ProfileProperties;
struct InputConditionalTurnRestriction;
@@ -153,6 +153,14 @@ class CoordinateExtractor
const double length,
const double rate) const;
// find the coordinate at a specific distance in the vector
util::Coordinate
ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates) const;
util::Coordinate ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &length_cache) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const extractor::CompressedEdgeContainer &compressed_geometries;
@@ -241,14 +249,6 @@ class CoordinateExtractor
const double segment_length,
const std::vector<double> &segment_distances,
const std::uint8_t considered_lanes) const;
// find the coordinate at a specific location in the vector
util::Coordinate ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates,
const std::vector<double> &length_cache) const;
util::Coordinate
ExtractCoordinateAtLength(const double distance,
const std::vector<util::Coordinate> &coordinates) const;
};
} // namespace guidance
+11 -6
View File
@@ -19,6 +19,7 @@ namespace osmium
{
class Node;
class Way;
class Relation;
}
namespace osrm
@@ -33,8 +34,10 @@ namespace extractor
{
class RestrictionParser;
class ExtractionRelationContainer;
struct ExtractionNode;
struct ExtractionWay;
struct ExtractionRelation;
struct ExtractionTurn;
struct ExtractionSegment;
@@ -59,12 +62,14 @@ class ScriptingEnvironment
virtual void ProcessTurn(ExtractionTurn &turn) = 0;
virtual void ProcessSegment(ExtractionSegment &segment) = 0;
virtual void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
virtual void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) = 0;
};
}
}
@@ -1,6 +1,7 @@
#ifndef SCRIPTING_ENVIRONMENT_LUA_HPP
#define SCRIPTING_ENVIRONMENT_LUA_HPP
#include "extractor/extraction_relation.hpp"
#include "extractor/raster_source.hpp"
#include "extractor/scripting_environment.hpp"
@@ -19,8 +20,13 @@ namespace extractor
struct LuaScriptingContext final
{
void ProcessNode(const osmium::Node &, ExtractionNode &result);
void ProcessWay(const osmium::Way &, ExtractionWay &result);
void ProcessNode(const osmium::Node &,
ExtractionNode &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessWay(const osmium::Way &,
ExtractionWay &result,
const ExtractionRelationContainer::RelationList &relations);
void ProcessRelation(const osmium::Relation &, ExtractionRelation &result);
ProfileProperties properties;
RasterContainer raster_sources;
@@ -29,11 +35,13 @@ struct LuaScriptingContext final
bool has_turn_penalty_function;
bool has_node_function;
bool has_way_function;
bool has_relation_function;
bool has_segment_function;
sol::function turn_function;
sol::function way_function;
sol::function node_function;
sol::function relation_function;
sol::function segment_function;
int api_version;
@@ -51,7 +59,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
{
public:
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);
~Sol2ScriptingEnvironment() override = default;
@@ -65,12 +73,14 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
void ProcessTurn(ExtractionTurn &turn) override;
void ProcessSegment(ExtractionSegment &segment) override;
void
ProcessElements(const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
void ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
private:
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());
auto max_results_nearest = params->Get(Nan::New("max_results_nearest").ToLocalChecked());
auto max_alternatives = params->Get(Nan::New("max_alternatives").ToLocalChecked());
auto use_threads_number = params->Get(Nan::New("use_threads_number").ToLocalChecked());
if (!max_locations_trip->IsUndefined() && !max_locations_trip->IsNumber())
{
@@ -217,6 +218,11 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
Nan::ThrowError("max_alternatives must be an integral number");
return engine_config_ptr();
}
if (!use_threads_number->IsUndefined() && !use_threads_number->IsNumber())
{
Nan::ThrowError("use_threads_number must be an integral number");
return engine_config_ptr();
}
if (max_locations_trip->IsNumber())
engine_config->max_locations_trip = static_cast<int>(max_locations_trip->NumberValue());
@@ -233,6 +239,8 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
engine_config->max_results_nearest = static_cast<int>(max_results_nearest->NumberValue());
if (max_alternatives->IsNumber())
engine_config->max_alternatives = static_cast<int>(max_alternatives->NumberValue());
if (use_threads_number->IsNumber())
engine_config->use_threads_number = static_cast<int>(use_threads_number->NumberValue());
return engine_config;
}
+32 -2
View File
@@ -53,10 +53,40 @@ class Log
virtual ~Log();
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:
LogLevel level;
const LogLevel level;
std::ostringstream buffer;
std::ostream &stream;
};
+1 -1
View File
@@ -83,7 +83,7 @@ class Percent
// When not on a TTY, print newlines after each progress indicator so
// so that progress is visible to line-buffered logging systems
if (!IsStdoutATTY())
log << "" << std::endl;
log << std::endl;
}
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "osrm",
"version": "5.12.0-roundaboutexits.1",
"version": "5.13.0-glibc.2",
"private": false,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": {
+5 -2
View File
@@ -536,7 +536,7 @@ function process_way(profile, way, result)
-- handle turn lanes and road classification, used for guidance
WayHandlers.classification,
-- handle allowed start/end modes
WayHandlers.startpoint,
@@ -544,7 +544,10 @@ function process_way(profile, way, result)
WayHandlers.roundabouts,
-- set name, ref and pronunciation
WayHandlers.names
WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
}
WayHandlers.run(profile,way,result,data,handlers)
+2
View File
@@ -250,10 +250,12 @@ function setup()
-- List only exceptions
maxspeed_table = {
["be:motorway"] = 120,
["ch:rural"] = 80,
["ch:trunk"] = 100,
["ch:motorway"] = 120,
["de:living_street"] = 7,
["dk:rural"] = 80,
["ru:living_street"] = 20,
["ru:urban"] = 60,
["ua:urban"] = 60,
+4 -1
View File
@@ -237,7 +237,10 @@ function process_way(profile, way, result)
WayHandlers.startpoint,
-- set name, ref and pronunciation
WayHandlers.names
WayHandlers.names,
-- set weight properties of the way
WayHandlers.weights
}
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["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\_:]+)\"")
+21 -9
View File
@@ -145,7 +145,8 @@ class SVGPrinter (gdb.Command):
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::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
@@ -258,17 +259,27 @@ class SVGPrinter (gdb.Command):
geometry_first = geometry['_M_impl']['_M_start']
for segment, weight in enumerate(iterate(weights)):
ref = 's' + str(node) + '.' + str(segment)
result += '<path id="' + ref + '" class="segment" d="' \
+ 'M' + t(lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))) + ' ' \
+ 'L' + t(lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))) + '" />'\
+ '<text class="segment weight ' + direction + '">'\
+ '<textPath xlink:href="#' + ref + '" startOffset="50%">' \
+ segment_weight(weight) + '</textPath></text>\n'
fr = lonlat(call(facade, 'GetCoordinateOfNode', geometry_first.dereference()))
to = lonlat(call(facade, 'GetCoordinateOfNode', (geometry_first+1).dereference()))
if fr == to:
## node penalty on zero length segment (traffic light)
result += '<text class="segment weight ' + direction \
+ '" 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
## add edge-based edges
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)
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')
@@ -323,7 +334,8 @@ class SVGPrinter (gdb.Command):
re_float = '[-+]?[0-9]*\.?[0-9]+'
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]
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)
except KeyError as 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_viaroute, 2) &&
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;
}
+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 <boost/assert.hpp>
#include <boost/range/iterator_range_core.hpp>
#include <limits>
#include <memory>
@@ -19,17 +20,33 @@ namespace
{
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 duration;
NodeBucket(const unsigned target_id, const EdgeWeight weight, const EdgeWeight duration)
: target_id(target_id), weight(weight), duration(duration)
EdgeDuration duration;
NodeBucket(NodeID middle_node, unsigned column_index, EdgeWeight weight, EdgeDuration duration)
: middle_node(middle_node), column_index(column_index), weight(weight), duration(duration)
{
}
};
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
// partial order comparison
bool operator<(const NodeBucket &rhs) const { return middle_node < rhs.middle_node; }
// functor for equal_range
struct Compare
{
bool operator()(const NodeBucket &lhs, const NodeID &rhs) const
{
return lhs.middle_node < rhs;
}
bool operator()(const NodeID &lhs, const NodeBucket &rhs) const
{
return lhs < rhs.middle_node;
}
};
};
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
const NodeID node,
@@ -74,12 +91,12 @@ void relaxOutgoingEdges(const DataFacade<ch::Algorithm> &facade,
{
const NodeID to = facade.GetTarget(edge);
const EdgeWeight edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration;
const auto edge_weight = data.weight;
const auto edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration;
const auto to_weight = weight + edge_weight;
const auto to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage
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});
}
// 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
query_heap.GetData(to) = {node, to_duration};
@@ -103,13 +121,60 @@ addLoopWeight(const DataFacade<mld::Algorithm> &, const NodeID, EdgeWeight &, Ed
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,
const NodeID node,
const EdgeWeight weight,
const EdgeDuration duration,
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
const PhantomNode &phantom_node)
Args... args)
{
BOOST_ASSERT(!facade.ExcludeNode(node));
@@ -117,13 +182,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
const auto &cells = facade.GetCellStorage();
const auto &metric = facade.GetCellMetric();
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;
};
const auto level = std::min(highest_diffrent_level(phantom_node.forward_segment_id),
highest_diffrent_level(phantom_node.reverse_segment_id));
const auto level = getNodeQueryLevel(partition, node, args...);
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});
}
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.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});
}
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.DecreaseKey(to, to_weight);
@@ -201,12 +262,12 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
continue;
}
const EdgeWeight edge_weight = data.weight;
const EdgeWeight edge_duration = data.duration;
const auto edge_weight = data.weight;
const auto edge_duration = data.duration;
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
const EdgeWeight to_weight = weight + edge_weight;
const EdgeWeight to_duration = duration + edge_duration;
const auto to_weight = weight + edge_weight;
const auto to_duration = duration + edge_duration;
// New Node discovered -> Add to Heap + Node Info Storage
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});
}
// 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
query_heap.GetData(to) = {node, false, to_duration};
@@ -229,49 +291,47 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned row_idx,
const unsigned number_of_targets,
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> &durations_table,
std::vector<EdgeDuration> &durations_table,
const PhantomNode &phantom_node)
{
const NodeID node = query_heap.DeleteMin();
const EdgeWeight source_weight = query_heap.GetKey(node);
const EdgeWeight source_duration = query_heap.GetData(node).duration;
const auto node = query_heap.DeleteMin();
const auto source_weight = query_heap.GetKey(node);
const auto source_duration = query_heap.GetData(node).duration;
// check if each encountered node has an entry
const auto bucket_iterator = search_space_with_buckets.find(node);
// iterate bucket if there exists one
if (bucket_iterator != search_space_with_buckets.end())
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
search_space_with_buckets.end(),
node,
NodeBucket::Compare());
for (const auto &current_bucket : boost::make_iterator_range(bucket_list))
{
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
for (const NodeBucket &current_bucket : bucket_list)
// get target id from bucket entry
const auto column_idx = current_bucket.column_index;
const auto target_weight = current_bucket.weight;
const auto target_duration = current_bucket.duration;
auto &current_weight = weights_table[row_idx * number_of_targets + column_idx];
auto &current_duration = durations_table[row_idx * number_of_targets + column_idx];
// check if new weight is better
auto new_weight = source_weight + target_weight;
auto new_duration = source_duration + target_duration;
if (new_weight < 0)
{
// get target id from bucket entry
const unsigned column_idx = current_bucket.target_id;
const EdgeWeight target_weight = current_bucket.weight;
const EdgeWeight target_duration = current_bucket.duration;
auto &current_weight = weights_table[row_idx * number_of_targets + column_idx];
auto &current_duration = durations_table[row_idx * number_of_targets + column_idx];
// check if new weight is better
auto new_weight = source_weight + target_weight;
auto new_duration = source_duration + target_duration;
if (new_weight < 0)
if (addLoopWeight(facade, node, new_weight, new_duration))
{
if (addLoopWeight(facade, node, new_weight, new_duration))
{
current_weight = std::min(current_weight, new_weight);
current_duration = std::min(current_duration, new_duration);
}
}
else if (new_weight < current_weight)
{
current_weight = new_weight;
current_duration = new_duration;
current_weight = std::min(current_weight, new_weight);
current_duration = std::min(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>(
@@ -282,15 +342,15 @@ template <typename Algorithm>
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
const unsigned column_idx,
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
SearchSpaceWithBuckets &search_space_with_buckets,
std::vector<NodeBucket> &search_space_with_buckets,
const PhantomNode &phantom_node)
{
const NodeID node = query_heap.DeleteMin();
const EdgeWeight target_weight = query_heap.GetKey(node);
const EdgeWeight target_duration = query_heap.GetData(node).duration;
const auto node = query_heap.DeleteMin();
const auto target_weight = query_heap.GetKey(node);
const auto target_duration = query_heap.GetData(node).duration;
// 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>(
facade, node, target_weight, target_duration, query_heap, phantom_node);
@@ -298,111 +358,297 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
}
template <typename Algorithm>
std::vector<EdgeWeight> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices)
std::vector<EdgeDuration> manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices)
{
const auto number_of_sources =
source_indices.empty() ? phantom_nodes.size() : source_indices.size();
const auto number_of_targets =
target_indices.empty() ? phantom_nodes.size() : target_indices.size();
if (source_indices.empty())
{
source_indices.resize(phantom_nodes.size());
std::iota(source_indices.begin(), source_indices.end(), 0);
}
if (target_indices.empty())
{
target_indices.resize(phantom_nodes.size());
std::iota(target_indices.begin(), target_indices.end(), 0);
}
const auto number_of_sources = source_indices.size();
const auto number_of_targets = target_indices.size();
const auto number_of_entries = number_of_sources * number_of_targets;
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;
const auto search_target_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert target nodes
query_heap.Clear();
insertTargetInHeap(query_heap, phantom);
// explore search space
std::vector<NodeBucket> local_buckets;
while (!query_heap.Empty())
{
backwardRoutingStep(facade, column_idx, query_heap, local_buckets, phantom);
}
// explore search space
while (!query_heap.Empty())
{
backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets, phantom);
}
++column_idx;
};
{ // Insert local buckets into the global search space
std::lock_guard<std::mutex> guard{lock};
search_space_with_buckets.insert(std::end(search_space_with_buckets),
std::begin(local_buckets),
std::end(local_buckets));
}
}
});
// for each source do forward search
unsigned row_idx = 0;
const auto search_source_phantom = [&](const PhantomNode &phantom) {
// clear heap and insert source nodes
query_heap.Clear();
insertSourceInHeap(query_heap, phantom);
tbb::parallel_sort(search_space_with_buckets.begin(), search_space_with_buckets.end());
// explore search space
while (!query_heap.Empty())
{
forwardRoutingStep(facade,
row_idx,
number_of_targets,
query_heap,
search_space_with_buckets,
weights_table,
durations_table,
phantom);
}
++row_idx;
};
// For each source do forward search
tbb::parallel_for(tbb::blocked_range<std::size_t>{0, source_indices.size()},
[&](const tbb::blocked_range<std::size_t> &chunk) {
for (auto row_idx = chunk.begin(), end = chunk.end(); row_idx != end;
++row_idx)
{
const auto index = source_indices[row_idx];
const auto &phantom = phantom_nodes[index];
if (target_indices.empty())
{
for (const auto &phantom : phantom_nodes)
{
search_target_phantom(phantom);
}
}
else
{
for (const auto index : target_indices)
{
const auto &phantom = phantom_nodes[index];
search_target_phantom(phantom);
}
}
// clear heap and insert source nodes
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(
facade.GetNumberOfNodes());
auto &query_heap = *(engine_working_data.many_to_many_heap);
insertSourceInHeap(query_heap, phantom);
if (source_indices.empty())
{
for (const auto &phantom : phantom_nodes)
{
search_source_phantom(phantom);
}
}
else
{
for (const auto index : source_indices)
{
const auto &phantom = phantom_nodes[index];
search_source_phantom(phantom);
}
}
// explore search space
while (!query_heap.Empty())
{
forwardRoutingStep(facade,
row_idx,
number_of_targets,
query_heap,
search_space_with_buckets,
weights_table,
durations_table,
phantom);
}
}
});
return durations_table;
}
template std::vector<EdgeWeight>
template std::vector<EdgeDuration>
manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
std::vector<std::size_t> source_indices,
std::vector<std::size_t> target_indices);
template std::vector<EdgeWeight>
template std::vector<EdgeDuration>
manyToManySearch(SearchEngineData<mld::Algorithm> &engine_working_data,
const DataFacade<mld::Algorithm> &facade,
const std::vector<PhantomNode> &phantom_nodes,
const std::vector<std::size_t> &source_indices,
const std::vector<std::size_t> &target_indices);
std::vector<std::size_t> source_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 engine
+46 -9
View File
@@ -3,6 +3,7 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/files.hpp"
@@ -288,12 +289,13 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
const osmium::io::File input_file(config.input_path.string());
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_ways = 0;
@@ -331,6 +333,7 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
timestamp_file.WriteFrom(timestamp.c_str(), timestamp.length());
ExtractionRelationContainer relations;
std::vector<std::string> restrictions = scripting_environment.GetRestrictions();
// setup restriction parser
const RestrictionParser restriction_parser(
@@ -338,20 +341,19 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
config.parse_conditionals,
restrictions);
std::mutex process_mutex;
using SharedBuffer = std::shared_ptr<const osmium::memory::Buffer>;
struct ParsedBuffer
{
SharedBuffer buffer;
std::vector<std::pair<const osmium::Node &, ExtractionNode>> resulting_nodes;
std::vector<std::pair<const osmium::Way &, ExtractionWay>> resulting_ways;
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> resulting_relations;
std::vector<InputConditionalTurnRestriction> resulting_restrictions;
};
tbb::filter_t<void, SharedBuffer> buffer_reader(
tbb::filter::serial_in_order, [&](tbb::flow_control &fc) {
if (auto buffer = reader.read())
if (auto buffer = reader->read())
{
return std::make_shared<const osmium::memory::Buffer>(std::move(buffer));
}
@@ -370,8 +372,10 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
parsed_buffer->buffer = buffer;
scripting_environment.ProcessElements(*buffer,
restriction_parser,
relations,
parsed_buffer->resulting_nodes,
parsed_buffer->resulting_ways,
parsed_buffer->resulting_relations,
parsed_buffer->resulting_restrictions);
return parsed_buffer;
});
@@ -391,13 +395,46 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
{
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)
{
extractor_callbacks->ProcessRestriction(result);
}
});
/* Main trick that we can use the same pipeline. It just receive relation objects
* from osmium. So other containers would be empty and doesn't process anything
*/
util::Log() << "Parse relations ...";
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
buffer_reader & buffer_transform & buffer_storage_relation);
reader->close();
/* At this step we just filter ways and nodes from osmium, so any relation wouldn't be
* processed there.
*/
util::Log() << "Parse ways and nodes ...";
reader.reset(new osmium::io::Reader(
input_file,
osmium::osm_entity_bits::node | osmium::osm_entity_bits::way,
(config.use_metadata ? osmium::io::read_meta::yes : osmium::io::read_meta::no)));
// Number of pipeline tokens that yielded the best speedup was about 1.5 * num_cores
tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
buffer_reader & buffer_transform & buffer_storage);
+25 -12
View File
@@ -287,23 +287,36 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
return lane_description;
};
// convert the lane description into an ID and, if necessary, remember the description in the
// description_map
const auto requestId = [&](const std::string &lane_string) {
if (lane_string.empty())
return INVALID_LANE_DESCRIPTIONID;
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
return lane_description_map.ConcurrentFindOrAdd(lane_description);
};
// If we could parse turn lanes but could not parse number of lanes,
// count the turn lanes and use them for the way's number of lanes.
auto road_classification = parsed_way.road_classification;
std::uint8_t road_deduced_num_lanes = 0;
// Deduplicates street names, refs, destinations, pronunciation, exits.
// 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.
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward);
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward);
auto turn_lane_id_forward = INVALID_LANE_DESCRIPTIONID;
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
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 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);
intersection.reserve(intersection_degree);
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
const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection);
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(
node_at_center_of_intersection, edge_connected_to_intersection, !INVERT, to_node);
const auto close_coordinate =
coordinate_extractor.ExtractCoordinateAtLength(2. /*m*/, coordinates);
const auto initial_bearing =
util::coordinate_calculation::bearing(turn_coordinate, close_coordinate);
const auto segment_length = util::coordinate_calculation::getLength(
coordinates.begin(),
coordinates.end(),
@@ -123,31 +135,79 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
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)
{
const auto itr =
std::find_if(intersection.begin(),
intersection.end(),
[&](const IntersectionShapeData &data) {
return node_based_graph.GetTarget(data.eid) == *sorting_base;
});
if (itr != intersection.end())
const auto itr = std::find_if(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
[&](const auto &data) {
return node_based_graph.GetTarget(
data.road.eid) == *sorting_base;
});
if (itr != initial_roads_ordering.end())
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(),
makeCompareShapeDataAngleToBearing(base_bearing));
// sort roads with respect to the initial bearings, a tie-breaker for equal initial bearings
// is to order roads via final bearings to have roads in clockwise order
//
// rhs <---. lhs <----.
// / /
// lhs / rhs /
//
// lhs road is before rhs one rhs road is before lhs one
// bearing::angleBetween < 180 bearing::angleBetween > 180
const auto initial_bearing_order = makeCompareShapeDataAngleToBearing(base_initial_bearing);
std::sort(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
[&initial_bearing_order](const auto &lhs, const auto &rhs) {
return initial_bearing_order(lhs, rhs) ||
(lhs.bearing == rhs.bearing &&
util::bearing::angleBetween(lhs.road.bearing, rhs.road.bearing) <
180);
});
// copy intersection data in the initial order
IntersectionShape intersection;
intersection.reserve(initial_roads_ordering.size());
std::transform(initial_roads_ordering.begin(),
initial_roads_ordering.end(),
std::back_inserter(intersection),
[](const auto &entry) { return entry.road; });
if (intersection.size() > 2)
{ // Check bearings ordering with respect to true bearings
const auto base_bearing = intersection.front().bearing;
const auto bearings_order =
makeCompareShapeDataAngleToBearing(util::bearing::reverse(base_bearing));
for (auto curr = intersection.begin(), next = std::next(curr);
next != intersection.end();
++curr, ++next)
{
if (bearings_order(*next, *curr))
{ // If the true bearing is out of the initial order (next before current) then
// adjust the next bearing to keep the order. The adjustment angle is at most
// 0.5° or a half-angle between the current bearing and the base bearing.
// to prevent overlapping over base bearing + 360°.
const auto angle_adjustment = std::min(
.5, util::restrictAngleToValidRange(base_bearing - curr->bearing) / 2.);
next->bearing =
util::restrictAngleToValidRange(curr->bearing + angle_adjustment);
}
}
}
return intersection;
}
return intersection;
return IntersectionShape{};
}
// a
+125 -21
View File
@@ -2,6 +2,7 @@
#include "extractor/extraction_helper_functions.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_relation.hpp"
#include "extractor/extraction_segment.hpp"
#include "extractor/extraction_turn.hpp"
#include "extractor/extraction_way.hpp"
@@ -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::Relation> : std::false_type
{
};
}
namespace osrm
@@ -216,6 +220,14 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"sharp_left",
extractor::guidance::DirectionModifier::SharpLeft);
context.state.new_enum("item_type",
"node",
osmium::item_type::node,
"way",
osmium::item_type::way,
"relation",
osmium::item_type::relation);
context.state.new_usertype<RasterContainer>("raster",
"load",
&RasterContainer::LoadRasterSource,
@@ -276,6 +288,30 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"version",
&osmium::Way::version);
context.state.new_usertype<osmium::RelationMember>(
"RelationMember",
"role",
&osmium::RelationMember::role,
"type",
&osmium::RelationMember::type,
"id",
[](const osmium::RelationMember &member) -> osmium::object_id_type {
return member.ref();
});
context.state.new_usertype<osmium::Relation>(
"Relation",
"get_value_by_key",
&get_value_by_key<osmium::Relation>,
"id",
&osmium::Relation::id,
"version",
&osmium::Relation::version,
"members",
[](const osmium::Relation &rel) -> const osmium::RelationMemberList & {
return rel.members();
});
context.state.new_usertype<osmium::Node>("Node",
"location",
&osmium::Node::location,
@@ -284,7 +320,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"id",
&osmium::Node::id,
"version",
&osmium::Way::version);
&osmium::Node::version);
context.state.new_usertype<ExtractionNode>("ResultNode",
"traffic_lights",
@@ -366,6 +402,18 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
sol::property([](const ExtractionWay &way) { return way.backward_restricted; },
[](ExtractionWay &way, bool flag) { way.backward_restricted = flag; }));
context.state.new_usertype<ExtractionRelation>(
"ExtractionRelation",
sol::meta_function::new_index,
[](ExtractionRelation &rel, const osmium::RelationMember &member)
-> ExtractionRelation::AttributesMap & { return rel.GetMember(member); },
sol::meta_function::index,
[](ExtractionRelation &rel, const osmium::RelationMember &member)
-> ExtractionRelation::AttributesMap & { return rel.GetMember(member); },
"restriction",
sol::property([](const ExtractionRelation &rel) { return rel.is_restriction; },
[](ExtractionRelation &rel, bool flag) { rel.is_restriction = flag; }));
context.state.new_usertype<ExtractionSegment>("ExtractionSegment",
"source",
&ExtractionSegment::source,
@@ -457,10 +505,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
util::Log() << "Using profile api version " << context.api_version;
// version-dependent parts of the api
switch (context.api_version)
{
case 2:
{
auto initV2Context = [&]() {
// clear global not used in v2
context.state["properties"] = sol::nullopt;
@@ -543,6 +588,22 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
if (force_split_edges != sol::nullopt)
context.properties.force_split_edges = force_split_edges.value();
}
};
switch (context.api_version)
{
case 3:
{
initV2Context();
context.relation_function = function_table.value()["process_relation"];
context.has_relation_function = context.relation_function.valid();
break;
}
case 2:
{
initV2Context();
break;
}
case 1:
@@ -615,12 +676,15 @@ LuaScriptingContext &Sol2ScriptingEnvironment::GetSol2Context()
void Sol2ScriptingEnvironment::ProcessElements(
const osmium::memory::Buffer &buffer,
const RestrictionParser &restriction_parser,
const ExtractionRelationContainer &relations,
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions)
{
ExtractionNode result_node;
ExtractionWay result_way;
ExtractionRelation result_relation;
auto &local_context = this->GetSol2Context();
for (auto entity = buffer.cbegin(), end = buffer.cend(); entity != end; ++entity)
@@ -628,33 +692,47 @@ void Sol2ScriptingEnvironment::ProcessElements(
switch (entity->type())
{
case osmium::item_type::node:
{
const auto &node = static_cast<const osmium::Node &>(*entity);
result_node.clear();
if (local_context.has_node_function &&
(!static_cast<const osmium::Node &>(*entity).tags().empty() ||
local_context.properties.call_tagless_node_function))
(!node.tags().empty() || 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>(
static_cast<const osmium::Node &>(*entity), std::move(result_node)));
break;
resulting_nodes.push_back({node, std::move(result_node)});
}
break;
case osmium::item_type::way:
{
const osmium::Way &way = static_cast<const osmium::Way &>(*entity);
result_way.clear();
if (local_context.has_way_function)
{
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>(
static_cast<const osmium::Way &>(*entity), std::move(result_way)));
break;
resulting_ways.push_back({way, std::move(result_way)});
}
break;
case osmium::item_type::relation:
{
auto result_res =
restriction_parser.TryParse(static_cast<const osmium::Relation &>(*entity));
if (result_res)
const auto &relation = static_cast<const osmium::Relation &>(*entity);
if (auto result_res = restriction_parser.TryParse(relation))
{
resulting_restrictions.push_back(*result_res);
}
if (local_context.api_version > 2)
{
result_relation.clear();
if (local_context.has_relation_function)
{
local_context.ProcessRelation(relation, result_relation);
}
resulting_relations.push_back({relation, std::move(result_relation)});
}
}
break;
default:
@@ -732,6 +810,7 @@ std::vector<std::vector<std::string>> Sol2ScriptingEnvironment::GetExcludableCla
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListsFromTable("excludable");
default:
@@ -744,6 +823,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetClassNames()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("classes");
default:
@@ -756,6 +836,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetNameSuffixList()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("suffix_list");
case 1:
@@ -770,6 +851,7 @@ std::vector<std::string> Sol2ScriptingEnvironment::GetRestrictions()
auto &context = GetSol2Context();
switch (context.api_version)
{
case 3:
case 2:
return Sol2ScriptingEnvironment::GetStringListFromTable("restrictions");
case 1:
@@ -785,6 +867,7 @@ void Sol2ScriptingEnvironment::ProcessTurn(ExtractionTurn &turn)
switch (context.api_version)
{
case 3:
case 2:
if (context.has_turn_penalty_function)
{
@@ -851,6 +934,7 @@ void Sol2ScriptingEnvironment::ProcessSegment(ExtractionSegment &segment)
{
switch (context.api_version)
{
case 3:
case 2:
context.segment_function(context.profile_table, segment);
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);
switch (api_version)
{
case 3:
node_function(profile_table, node, result, relations);
break;
case 2:
node_function(profile_table, node, result);
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);
switch (api_version)
{
case 3:
way_function(profile_table, way, result, relations);
break;
case 2:
way_function(profile_table, way, result);
break;
@@ -897,5 +991,15 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way, ExtractionWay &resu
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_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")
return EngineConfig::Algorithm::CH;
if (algorithm == "corech")
return EngineConfig::Algorithm::CoreCH;
if (algorithm == "mld")
return EngineConfig::Algorithm::MLD;
throw util::RuntimeError(algorithm, ErrorCode::UnknownAlgorithm, SOURCE_REF);
if (token == "ch")
algorithm = EngineConfig::Algorithm::CH;
else if (token == "corech")
algorithm = EngineConfig::Algorithm::CoreCH;
else if (token == "mld")
algorithm = EngineConfig::Algorithm::MLD;
else
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
return in;
}
}
}
// generate boost::program_options object for the routing part
inline unsigned generateServerProgramOptions(const int argc,
const char *argv[],
std::string verbosity,
boost::filesystem::path &base_path,
std::string &ip_address,
int &ip_port,
int &requested_num_threads,
bool &use_shared_memory,
std::string &algorithm,
bool &trial,
int &max_locations_trip,
int &max_locations_viaroute,
int &max_locations_distance_table,
int &max_locations_map_matching,
int &max_results_nearest,
int &max_alternatives)
EngineConfig &config)
{
using boost::program_options::value;
using boost::filesystem::path;
const auto hardware_threads = std::max<int>(1, std::thread::hardware_concurrency());
// declare a group of options that will be allowed only on command line
boost::program_options::options_description generic_options("Options");
generic_options.add_options() //
("version,v", "Show version")("help,h", "Show this help message")(
"verbosity,l",
boost::program_options::value<std::string>(&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())(
"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),
"TCP/IP port") //
("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") //
("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") //
("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.") //
("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-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-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-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-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-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");
// 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);
if (!use_shared_memory && option_variables.count("base"))
if (!config.use_shared_memory && option_variables.count("base"))
{
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;
}
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.";
}
// Adjust number of threads to hardware concurrency
config.use_threads_number = std::min(hardware_threads, config.use_threads_number);
std::cout << visible_options;
return INIT_OK_DO_NOT_START_ENGINE;
}
@@ -203,28 +210,13 @@ int main(int argc, const char *argv[]) try
bool trial_run = false;
std::string ip_address;
int ip_port, requested_thread_num;
int ip_port;
EngineConfig config;
std::string verbosity;
boost::filesystem::path base_path;
std::string algorithm;
const unsigned init_result = generateServerProgramOptions(argc,
argv,
verbosity,
base_path,
ip_address,
ip_port,
requested_thread_num,
config.use_shared_memory,
algorithm,
trial_run,
config.max_locations_trip,
config.max_locations_viaroute,
config.max_locations_distance_table,
config.max_locations_map_matching,
config.max_results_nearest,
config.max_alternatives);
const unsigned init_result =
generateServerProgramOptions(argc, argv, base_path, ip_address, ip_port, trial_run, config);
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
{
return EXIT_SUCCESS;
@@ -234,7 +226,7 @@ int main(int argc, const char *argv[]) try
return EXIT_FAILURE;
}
util::LogPolicy::GetInstance().SetLevel(verbosity);
util::LogPolicy::GetInstance().SetLevel(config.verbosity);
if (!base_path.empty())
{
@@ -253,7 +245,6 @@ int main(int argc, const char *argv[]) try
}
return EXIT_FAILURE;
}
config.algorithm = stringToAlgorithm(algorithm);
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";
}
// Use the same number of threads for Server and TBB threads pools
// It doubles number of used threads
auto requested_thread_num = config.use_threads_number;
util::Log() << "Threads: " << requested_thread_num;
util::Log() << "IP address: " << ip_address;
util::Log() << "IP port: " << ip_port;
+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"))
m_level = logDEBUG;
else
;
m_level = logINFO;
}
LogPolicy &LogPolicy::GetInstance()
+26 -23
View File
@@ -144,29 +144,32 @@
{"key": "maxspeed", "value": "rural"},
{"key": "maxspeed", "value": "trunk"},
{"key": "maxspeed", "value": "motorway"},
{"key": "maxspeed", "value": "ch:rural"},
{"key": "maxspeed", "value": "ch:trunk"},
{"key": "maxspeed", "value": "ch:motorway"},
{"key": "maxspeed", "value": "de:living_street"},
{"key": "maxspeed", "value": "ru:living_street"},
{"key": "maxspeed", "value": "ru:urban"},
{"key": "maxspeed", "value": "ua:urban"},
{"key": "maxspeed", "value": "at:rural"},
{"key": "maxspeed", "value": "de:rural"},
{"key": "maxspeed", "value": "at:trunk"},
{"key": "maxspeed", "value": "cz:trunk"},
{"key": "maxspeed", "value": "ro:trunk"},
{"key": "maxspeed", "value": "cz:motorway"},
{"key": "maxspeed", "value": "de:motorway"},
{"key": "maxspeed", "value": "ru:motorway"},
{"key": "maxspeed", "value": "gb:nsl_single"},
{"key": "maxspeed", "value": "gb:nsl_dual"},
{"key": "maxspeed", "value": "gb:motorway"},
{"key": "maxspeed", "value": "uk:nsl_single"},
{"key": "maxspeed", "value": "uk:nsl_dual"},
{"key": "maxspeed", "value": "uk:motorway"},
{"key": "maxspeed", "value": "nl:rural"},
{"key": "maxspeed", "value": "nl:trunk"},
{"key": "maxspeed", "value": "BE:motorway"},
{"key": "maxspeed", "value": "CH:rural"},
{"key": "maxspeed", "value": "CH:trunk"},
{"key": "maxspeed", "value": "CH:motorway"},
{"key": "maxspeed", "value": "DE:living_street"},
{"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "RU:living_street"},
{"key": "maxspeed", "value": "RU:urban"},
{"key": "maxspeed", "value": "UA:urban"},
{"key": "maxspeed", "value": "AT:rural"},
{"key": "maxspeed", "value": "DE:rural"},
{"key": "maxspeed", "value": "DK:rural"},
{"key": "maxspeed", "value": "AT:trunk"},
{"key": "maxspeed", "value": "CZ:trunk"},
{"key": "maxspeed", "value": "RO:trunk"},
{"key": "maxspeed", "value": "CZ:motorway"},
{"key": "maxspeed", "value": "DE:motorway"},
{"key": "maxspeed", "value": "RU:motorway"},
{"key": "maxspeed", "value": "GB:nsl_single"},
{"key": "maxspeed", "value": "GB:nsl_dual"},
{"key": "maxspeed", "value": "GB:motorway"},
{"key": "maxspeed", "value": "UK:nsl_single"},
{"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": "bad"},
{"key": "smoothness", "value": "very_bad"},
+1 -1
View File
@@ -1 +1 @@
n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02
n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02
@@ -34,11 +34,14 @@ class MockScriptingEnvironment : public extractor::ScriptingEnvironment
void ProcessTurn(extractor::ExtractionTurn &) override final {}
void ProcessSegment(extractor::ExtractionSegment &) override final {}
void ProcessElements(const osmium::memory::Buffer &,
const extractor::RestrictionParser &,
std::vector<std::pair<const osmium::Node &, extractor::ExtractionNode>> &,
std::vector<std::pair<const osmium::Way &, extractor::ExtractionWay>> &,
std::vector<extractor::InputConditionalTurnRestriction> &) override final
void ProcessElements(
const osmium::memory::Buffer &,
const extractor::RestrictionParser &,
const extractor::ExtractionRelationContainer &,
std::vector<std::pair<const osmium::Node &, extractor::ExtractionNode>> &,
std::vector<std::pair<const osmium::Way &, extractor::ExtractionWay>> &,
std::vector<std::pair<const osmium::Relation &, extractor::ExtractionRelation>> &,
std::vector<extractor::InputConditionalTurnRestriction> &) override final
{
}
};