Compare commits

..

26 Commits

Author SHA1 Message Date
Patrick Niklaus 860c452b83 Bump version to 5.16.3 2018-03-09 16:02:11 +01:00
Michael Krasnyk 3b096963a0 Remove correctly the last segment in annotation 2018-03-09 16:02:11 +01:00
Daniel Patterson 7154ed9d59 Avoid copying json::Value objects a lot when reallocating vector 2018-03-08 15:10:07 +00:00
Michael Krasnyk 8f633e61bf Bump version 5.16.2 2018-02-28 15:54:44 +01:00
karenzshea 86dd319d29 avoid testing self-intersecting way 2018-02-28 15:52:56 +01:00
Michael Krasnyk 89d32eca94 Use smaller range for U-turn angles in map-matching 2018-02-28 15:52:45 +01:00
Karen Shea f5120d1cec Remove deduplication of unpacked_path_segments in MM collapsing (#4911) 2018-02-24 21:37:36 -08:00
Huyen Chau Nguyen d30d28cf4a final 5.16 version 2018-02-23 13:23:34 +01:00
Michael Krasnyk 87de37168b Bump RC7 2018-02-22 11:44:01 +01:00
Michael Krasnyk 658b8ef738 Renumber node IDs in .osrm.maneuver_overrides 2018-02-22 11:43:34 +01:00
Michael Krasnyk a2c7f82ec8 Bump RC6 2018-02-21 15:08:36 +01:00
Michael Krasnyk be49ed3e91 Check required tags of maneuver relations 2018-02-21 14:49:53 +01:00
Michael Krasnyk 6763d4c097 Handle motorway forks with links as a normal motorway ...
passing some ramps or mering onto another motorway
2018-02-21 14:21:52 +01:00
Michael Krasnyk 6d2860e909 Test case for a highway fork with a link 2018-02-21 14:21:48 +01:00
Michael Krasnyk d2764bc405 Don't use obvious directions at ramp bifurcations, #4895 2018-02-21 13:41:43 +01:00
Michael Krasnyk 005a146223 Test for a ramp bifurcation obviousness 2018-02-21 13:41:38 +01:00
Huyen Chau Nguyen 02754647f4 update package.json (#4889) 2018-02-15 16:15:01 +01:00
Huyen Chau Nguyen 82cebfa1f8 bump RC 5 2018-02-15 14:53:41 +01:00
Huyen Chau Nguyen 986bb6f93d Update package.json
add mkdirp and rimraf to bundledependencies in order for node-pre-gyp to properly install with node
2018-02-15 14:38:23 +01:00
Huyen Chau Nguyen 0c0ab78f13 move on to release candidate 4 2018-02-15 11:11:50 +01:00
Huyen Chau Nguyen 99cda66b58 bump RC3 2018-02-14 15:03:19 +01:00
Michael Krasnyk 27fa2fc1d0 Use links with lower priority in the motorway handler
Ref:
https://wiki.openstreetmap.org/wiki/Highway_link
https://wiki.openstreetmap.org/wiki/Link_roads_between_different_highways_types
2018-02-14 14:50:03 +01:00
Michael Krasnyk 7434f18d04 Add OSM node barrier=height_restrictor handling 2018-02-14 14:49:36 +01:00
Huyen Chau Nguyen 7d1a12a12d build osx binary for node4 and bump to RC 2 2018-02-13 15:43:08 +01:00
Patrick Niklaus 6d7420e4e5 Bump version to RC1 2018-02-10 00:37:41 +00:00
Patrick Niklaus 8a44660102 Enable 5.16 branch on travis 2018-02-10 00:36:49 +00:00
1085 changed files with 12828 additions and 82895 deletions
-30
View File
@@ -1,30 +0,0 @@
# EditorConfig is awesome: http://EditorConfig.org
#
# NOTE: Keep settings in sync with the master .clang-format file
#
# top-most EditorConfig file
root = true
# CMake configuration files
[{CMakeLists.txt,CMakeSettings.json,*.cmake}]
indent_size = 2
indent_style = space
trim_trailing_whitespace = true
# CI configuration files
[{.travis.yml,appveyor.yml}]
indent_size = 2
indent_style = space
trim_trailing_whitespace = true
# Unix shell scripts
[*.sh]
end_of_line = lf
indent_style = space
trim_trailing_whitespace = true
# Windows shell scripts
[*.bat]
end_of_line = crlf
indent_style = space
trim_trailing_whitespace = true
-1
View File
@@ -66,7 +66,6 @@ Thumbs.db
######################################
/.vs*
/*.local.bat
/CMakeSettings.json
# stxxl related files #
#######################
+2 -59
View File
@@ -13,7 +13,7 @@ notifications:
branches:
only:
- master
- "5.20.1"
- "5.16"
# enable building tags
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
@@ -60,7 +60,6 @@ matrix:
- ./scripts/check_taginfo.py taginfo.json profiles/car.lua
- ${MASON} install clang-format 3.8.1
- PATH=$(${MASON} prefix clang-format 3.8.1)/bin:${PATH} ./scripts/format.sh && ./scripts/error_on_dirty.sh
- node ./scripts/validate_changelog.js
# See issue 4043
#- npm run docs && ./scripts/error_on_dirty.sh
after_success:
@@ -155,14 +154,6 @@ matrix:
packages: ['g++-6', 'libbz2-dev', 'libxml2-dev', 'libzip-dev', 'liblua5.2-dev', 'libtbb-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-6' CXXCOMPILER='g++-6' BUILD_TYPE='Release'
- os: osx
osx_image: xcode9.2
compiler: "mason-osx-release-node-10"
# we use the xcode provides clang and don't install our own
env: ENABLE_MASON=ON BUILD_TYPE='Release' CUCUMBER_TIMEOUT=60000 CCOMPILER='clang' CXXCOMPILER='clang++' ENABLE_ASSERTIONS=ON ENABLE_LTO=ON NODE="10"
after_success:
- ./scripts/travis/publish.sh
- os: osx
osx_image: xcode9.2
compiler: "mason-osx-release-node-8"
@@ -285,54 +276,6 @@ matrix:
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-release"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Release' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
- os: linux
sudo: false
compiler: "node-10-mason-linux-debug"
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['libstdc++-4.9-dev']
env: CLANG_VERSION='5.0.0' BUILD_TYPE='Debug' ENABLE_MASON=ON ENABLE_LTO=ON JOBS=3 NODE="10"
install:
- pushd ${OSRM_BUILD_DIR}
- |
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_MASON=${ENABLE_MASON:-OFF} \
-DENABLE_NODE_BINDINGS=${ENABLE_NODE_BINDINGS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
-DENABLE_GLIBC_WORKAROUND=ON
- make --jobs=${JOBS}
- popd
script:
- npm run nodejs-tests
after_success:
- ./scripts/travis/publish.sh
before_install:
- source $NVM_DIR/nvm.sh
- nvm install $NODE
@@ -353,7 +296,7 @@ before_install:
fi
- |
if [[ ! -f $(which yarn) ]]; then
npm install -g yarn@1.11.1
npm install -g yarn
fi
- export PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
- export PUBLISH=$([[ "${TRAVIS_TAG:-}" == "v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off")
+12 -90
View File
@@ -1,96 +1,18 @@
# 5.20.1 RC 2
- Changes from 5.20.0
- Features:
- ADDED: all waypoints in responses now contain a distance property between the original coordinate and the snapped location. [#5255](https://github.com/Project-OSRM/osrm-backend/pull/5255)
- Table:
- ADDED: new parameter `scale_factor` which will scale the cell `duration` values by this factor. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5298)
- FIXED: only trigger `scale_factor` code to scan matrix when necessary. [#5303](https://github.com/Project-OSRM/osrm-backend/pull/5303)
# 5.20.0
- Changes from 5.19.0:
- Table:
- CHANGED: switch to pre-calculated distances for table responses for large speedup and 10% memory increase. [#5251](https://github.com/Project-OSRM/osrm-backend/pull/5251)
- ADDED: new parameter `fallback_speed` which will fill `null` cells with estimated value [#5257](https://github.com/Project-OSRM/osrm-backend/pull/5257)
- CHANGED: Remove API check for matrix sources/destination length to be less than or equal to coordinates length. [#5298](https://github.com/Project-OSRM/osrm-backend/pull/5289)
- FIXED: Fix crashing bug when using fallback_speed parameter with more sources than destinations. [#5291](https://github.com/Project-OSRM/osrm-backend/pull/5291)
- Features:
- ADDED: direct mmapping of datafiles is now supported via the `--mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- ADDED: Now publishing Node 10.x LTS binary modules [#5246](https://github.com/Project-OSRM/osrm-backend/pull/5246)
- Windows:
- FIXED: Windows builds again. [#5249](https://github.com/Project-OSRM/osrm-backend/pull/5249)
# 5.19.0
- Changes from 5.18.0:
- Optimizations:
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
- Profiles:
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
- Bugfixes:
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
- Misc:
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
# 5.18.0
- Changes from 5.17.0:
- Features:
- ADDED: `table` plugin now optionally returns `distance` matrix as part of response [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
- ADDED: New optional parameter `annotations` for `table` that accepts `distance`, `duration`, or both `distance,duration` as values [#4990](https://github.com/Project-OSRM/osrm-backend/pull/4990)
- Infrastructure:
- ADDED: Updated libosmium and added protozero and vtzero libraries [#5037](https://github.com/Project-OSRM/osrm-backend/pull/5037)
- CHANGED: Use vtzero library in tile plugin [#4686](https://github.com/Project-OSRM/osrm-backend/pull/4686)
- Profile:
- ADDED: Bicycle profile now returns classes for ferry and tunnel routes. [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
- ADDED: Bicycle profile allows to exclude ferry routes (default to not enabled) [#5054](https://github.com/Project-OSRM/osrm-backend/pull/5054)
# 5.17.1
- Changes from 5.17.0:
- Bugfixes:
- FIXED: Do not combine a segregated edge with a roundabout [#5039](https://github.com/Project-OSRM/osrm-backend/issues/5039)
# 5.17.0
- Changes from 5.16.0:
- Bugfixes:
- FIXED: deduplication of route steps when waypoints are used [#4909](https://github.com/Project-OSRM/osrm-backend/issues/4909)
- FIXED: Use smaller range for U-turn angles in map-matching [#4920](https://github.com/Project-OSRM/osrm-backend/pull/4920)
# 5.16.3
- Changes from 5.16.2:
- FIXED: Remove the last short annotation segment in `trimShortSegments` [#4946](https://github.com/Project-OSRM/osrm-backend/pull/4946)
- FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949)
- FIXED: Don't apply unimplemented SH and PH conditions in OpeningHours and add inversed date ranges [#4992](https://github.com/Project-OSRM/osrm-backend/issues/4992)
- FIXED: integer overflow in `DynamicGraph::Renumber` [#5021](https://github.com/Project-OSRM/osrm-backend/pull/5021)
- Profile:
- CHANGED: Handle oneways in get_forward_backward_by_key [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- FIXED: Do not route against oneway road if there is a cycleway in the wrong direction; also review bike profile [#4943](https://github.com/Project-OSRM/osrm-backend/issues/4943)
- CHANGED: Make cyclability weighting of the bike profile prefer safer routes more strongly [#5015](https://github.com/Project-OSRM/osrm-backend/issues/5015)
- Guidance:
- CHANGED: Don't use obviousness for links bifurcations [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- FIXED: Adjust Straight direction modifiers of side roads in driveway handler [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- CHANGED: Added post process logic to collapse segregated turn instructions [#4925](https://github.com/Project-OSRM/osrm-backend/pull/4925)
- ADDED: Maneuver relation now supports `straight` as a direction [#4995](https://github.com/Project-OSRM/osrm-backend/pull/4995)
- FIXED: Support spelling maneuver relation with British spelling [#4950](https://github.com/Project-OSRM/osrm-backend/issues/4950)
- Tools:
- ADDED: `osrm-routed` accepts a new property `--memory_file` to store memory in a file on disk. [#4881](https://github.com/Project-OSRM/osrm-backend/pull/4881)
- ADDED: `osrm-datastore` accepts a new parameter `--dataset-name` to select the name of the dataset. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
- ADDED: `osrm-datastore` accepts a new parameter `--list` to list all datasets loaded into memory. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
- ADDED: `osrm-datastore` accepts a new parameter `--only-metric` to only reload the data that can be updated by a weight update (reduces memory for traffic updates). [#5002](https://github.com/Project-OSRM/osrm-backend/pull/5002)
- ADDED: `osrm-routed` accepts a new parameter `--dataset-name` to select the shared-memory dataset to use. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
- NodeJS:
- ADDED: `OSRM` object accepts a new option `memory_file` that stores the memory in a file on disk. [#4881](https://github.com/Project-OSRM/osrm-backend/pull/4881)
- ADDED: `OSRM` object accepts a new option `dataset_name` to select the shared-memory dataset. [#4982](https://github.com/Project-OSRM/osrm-backend/pull/4982)
- Internals
- CHANGED: Updated segregated intersection identification [#4845](https://github.com/Project-OSRM/osrm-backend/pull/4845) [#4968](https://github.com/Project-OSRM/osrm-backend/pull/4968)
- REMOVED: Remove `.timestamp` file since it was unused [#4960](https://github.com/Project-OSRM/osrm-backend/pull/4960)
- Documentation:
- ADDED: Add documentation about OSM node ids in nearest service response [#4436](https://github.com/Project-OSRM/osrm-backend/pull/4436)
- Performance
- FIXED: Speed up response time when lots of legs exist and geojson is used with `steps=true` [#4936](https://github.com/Project-OSRM/osrm-backend/pull/4936)
- FIXED: Return iterators instead of vectors in datafacade_base functions [#4969](https://github.com/Project-OSRM/osrm-backend/issues/4969)
- Misc:
- ADDED: expose name for datasource annotations as metadata [#4973](https://github.com/Project-OSRM/osrm-backend/pull/4973)
# 5.16.2
- Changes from 5.16.1:
- Bugfixes:
- FIXED #4920: Use smaller range for U-turn angles in map-matching [#4920](https://github.com/Project-OSRM/osrm-backend/pull/4920)
# 5.16.1
- Changes from 5.16.0:
- Bugfixes
- FIXED #4909: deduplication of route steps when waypoints are used [#4909](https://github.com/Project-OSRM/osrm-backend/issues/4909)
# 5.16.0
- Changes from 5.15.2:
+26 -51
View File
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 2.8.11)
# we depend on 2.8.11 introducing target_include_directories
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE)
message(FATAL_ERROR "In-source builds are not allowed.
@@ -58,26 +59,12 @@ if (POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 16)
set(OSRM_VERSION_PATCH 3)
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
include(JSONParser)
file(READ "package.json" packagejsonraw)
sbeParseJson(packagejson packagejsonraw)
if (packagejson.version MATCHES "^([0-9]+)\.([0-9]+)\.([0-9]+)")
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
else()
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible X.Y.Z, but found ${packagejson.version}")
endif()
if (MSVC)
add_definitions("-DOSRM_PROJECT_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\"")
else()
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
endif()
add_definitions(-DOSRM_PROJECT_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
# these two functions build up custom variables:
# DEPENDENCIES_INCLUDE_DIRS and OSRM_DEFINES
@@ -166,15 +153,15 @@ add_executable(osrm-partition src/tools/partition.cpp)
add_executable(osrm-customize src/tools/customize.cpp)
add_executable(osrm-contract src/tools/contract.cpp)
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_executable(osrm-datastore src/tools/store.cpp $<TARGET_OBJECTS:UTIL>)
add_library(osrm src/osrm/osrm.cpp $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:STORAGE>)
add_library(osrm_contract src/osrm/contractor.cpp $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_extract src/osrm/extractor.cpp $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_extract src/osrm/extractor.cpp $<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_guidance $<TARGET_OBJECTS:GUIDANCE> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_partition src/osrm/partitioner.cpp $<TARGET_OBJECTS:PARTITIONER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_customize src/osrm/customizer.cpp $<TARGET_OBJECTS:CUSTOMIZER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_update $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_partition src/osrm/partitioner.cpp $<TARGET_OBJECTS:PARTITIONER> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_customize src/osrm/customizer.cpp $<TARGET_OBJECTS:CUSTOMIZER> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_update $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)
add_library(osrm_store $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)
if(ENABLE_GOLD_LINKER)
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
@@ -416,30 +403,11 @@ if(UNIX AND NOT APPLE)
set(MAYBE_RT_LIBRARY -lrt)
endif()
# Disallow deprecated protozero APIs
add_definitions(-DPROTOZERO_STRICT_API)
find_package(Threads REQUIRED)
# Third-party libraries
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
set(MICROTAR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src")
include_directories(SYSTEM ${MICROTAR_INCLUDE_DIR})
set(MBXGEOM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/geometry.hpp-0.9.2/include")
include_directories(SYSTEM ${MBXGEOM_INCLUDE_DIR})
set(CHEAPRULER_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/cheap-ruler-cpp-2.5.4/include")
include_directories(SYSTEM ${CHEAPRULER_INCLUDE_DIR})
add_library(MICROTAR OBJECT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/microtar/src/microtar.c")
set_property(TARGET MICROTAR PROPERTY POSITION_INDEPENDENT_CODE ON)
set(PROTOZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/protozero/include")
include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
set(VTZERO_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/vtzero/include")
include_directories(SYSTEM ${VTZERO_INCLUDE_DIR})
# if mason is enabled no find_package calls are made
# to ensure that we are only compiling and linking against
# fully portable mason packages
@@ -514,6 +482,9 @@ if(ENABLE_MASON)
# note: we avoid calling find_package(Osmium ...) here to ensure that the
# expat and bzip2 are used from mason rather than the system
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/libosmium/include)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include)
else()
find_package(Boost 1.54 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
@@ -571,6 +542,10 @@ else()
endif()
find_package(Osmium REQUIRED COMPONENTS io)
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIR})
set(RAPIDJSON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/rapidjson/include")
include_directories(SYSTEM ${RAPIDJSON_INCLUDE_DIR})
endif()
# prefix compilation with ccache by default if available and on clang or gcc
@@ -711,7 +686,7 @@ target_link_libraries(osrm_customize ${CUSTOMIZER_LIBRARIES} osrm_update osrm_st
target_link_libraries(osrm_store ${STORAGE_LIBRARIES})
# BUILD_COMPONENTS
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:MICROTAR> $<TARGET_OBJECTS:UTIL>)
add_executable(osrm-components src/tools/components.cpp $<TARGET_OBJECTS:UTIL>)
target_link_libraries(osrm-components ${TBB_LIBRARIES} ${BOOST_BASE_LIBRARIES} ${UTIL_LIBRARIES})
install(TARGETS osrm-components DESTINATION bin)
@@ -873,4 +848,4 @@ if (ENABLE_NODE_BINDINGS)
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
endif()
endif()
+1 -1
View File
@@ -9,7 +9,7 @@ High performance routing engine written in C++14 designed to run on OpenStreetMa
The following services are available via HTTP API, C++ library interface and NodeJs wrapper:
- Nearest - Snaps coordinates to the street network and returns the nearest matches
- Route - Finds the fastest route between coordinates
- Table - Computes the duration or distances of the fastest route between all pairs of supplied coordinates
- Table - Computes the duration of the fastest route between all pairs of supplied coordinates
- Match - Snaps noisy GPS traces to the road network in the most plausible way
- Trip - Solves the Traveling Salesman Problem using a greedy heuristic
- Tile - Generates Mapbox Vector Tiles with internal routing metadata
-290
View File
@@ -1,290 +0,0 @@
# https://github.com/sbellus/json-cmake/blob/9913da8800b95322d393894d3525d634568f305e/JSONParser.cmake
# MIT Licensed - https://github.com/sbellus/json-cmake/blob/master/LICENSE
cmake_minimum_required(VERSION 3.1)
if (DEFINED JSonParserGuard)
return()
endif()
set(JSonParserGuard yes)
macro(sbeParseJson prefix jsonString)
cmake_policy(PUSH)
set(json_string "${${jsonString}}")
string(LENGTH "${json_string}" json_jsonLen)
set(json_index 0)
set(json_AllVariables ${prefix})
set(json_ArrayNestingLevel 0)
set(json_MaxArrayNestingLevel 0)
_sbeParse(${prefix})
unset(json_index)
unset(json_AllVariables)
unset(json_jsonLen)
unset(json_string)
unset(json_value)
unset(json_inValue)
unset(json_name)
unset(json_inName)
unset(json_newPrefix)
unset(json_reservedWord)
unset(json_arrayIndex)
unset(json_char)
unset(json_end)
unset(json_ArrayNestingLevel)
foreach(json_nestingLevel RANGE ${json_MaxArrayNestingLevel})
unset(json_${json_nestingLevel}_arrayIndex)
endforeach()
unset(json_nestingLevel)
unset(json_MaxArrayNestingLevel)
cmake_policy(POP)
endmacro()
macro(sbeClearJson prefix)
foreach(json_var ${${prefix}})
unset(${json_var})
endforeach()
unset(${prefix})
unset(json_var)
endmacro()
macro(sbePrintJson prefix)
foreach(json_var ${${prefix}})
message("${json_var} = ${${json_var}}")
endforeach()
endmacro()
macro(_sbeParse prefix)
while(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if("\"" STREQUAL "${json_char}")
_sbeParseNameValue(${prefix})
elseif("{" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
_sbeParseObject(${prefix})
elseif("[" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
_sbeParseArray(${prefix})
endif()
if(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
else()
break()
endif()
if ("}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}")
break()
endif()
_sbeMoveToNextNonEmptyCharacter()
endwhile()
endmacro()
macro(_sbeParseNameValue prefix)
set(json_name "")
set(json_inName no)
while(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
# check if name ends
if("\"" STREQUAL "${json_char}" AND json_inName)
set(json_inName no)
_sbeMoveToNextNonEmptyCharacter()
if(NOT ${json_index} LESS ${json_jsonLen})
break()
endif()
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
set(json_newPrefix ${prefix}.${json_name})
set(json_name "")
if(":" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
if(NOT ${json_index} LESS ${json_jsonLen})
break()
endif()
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if("\"" STREQUAL "${json_char}")
_sbeParseValue(${json_newPrefix})
break()
elseif("{" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
_sbeParseObject(${json_newPrefix})
break()
elseif("[" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
_sbeParseArray(${json_newPrefix})
break()
else()
# reserved word starts
_sbeParseReservedWord(${json_newPrefix})
break()
endif()
else()
# name without value
list(APPEND ${json_AllVariables} ${json_newPrefix})
set(${json_newPrefix} "")
break()
endif()
endif()
if(json_inName)
# remove escapes
if("\\" STREQUAL "${json_char}")
math(EXPR json_index "${json_index} + 1")
if(NOT ${json_index} LESS ${json_jsonLen})
break()
endif()
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
endif()
set(json_name "${json_name}${json_char}")
endif()
# check if name starts
if("\"" STREQUAL "${json_char}" AND NOT json_inName)
set(json_inName yes)
endif()
_sbeMoveToNextNonEmptyCharacter()
endwhile()
endmacro()
macro(_sbeParseReservedWord prefix)
set(json_reservedWord "")
set(json_end no)
while(${json_index} LESS ${json_jsonLen} AND NOT json_end)
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if("," STREQUAL "${json_char}" OR "}" STREQUAL "${json_char}" OR "]" STREQUAL "${json_char}")
set(json_end yes)
else()
set(json_reservedWord "${json_reservedWord}${json_char}")
math(EXPR json_index "${json_index} + 1")
endif()
endwhile()
list(APPEND ${json_AllVariables} ${prefix})
string(STRIP "${json_reservedWord}" json_reservedWord)
set(${prefix} ${json_reservedWord})
endmacro()
macro(_sbeParseValue prefix)
cmake_policy(SET CMP0054 NEW) # turn off implicit expansions in if statement
set(json_value "")
set(json_inValue no)
while(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
# check if json_value ends, it is ended by "
if("\"" STREQUAL "${json_char}" AND json_inValue)
set(json_inValue no)
set(${prefix} ${json_value})
list(APPEND ${json_AllVariables} ${prefix})
_sbeMoveToNextNonEmptyCharacter()
break()
endif()
if(json_inValue)
# if " is escaped consume
if("\\" STREQUAL "${json_char}")
math(EXPR json_index "${json_index} + 1")
if(NOT ${json_index} LESS ${json_jsonLen})
break()
endif()
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if(NOT "\"" STREQUAL "${json_char}")
# if it is not " then copy also escape character
set(json_char "\\${json_char}")
endif()
endif()
_sbeAddEscapedCharacter("${json_char}")
endif()
# check if value starts
if("\"" STREQUAL "${json_char}" AND NOT json_inValue)
set(json_inValue yes)
endif()
math(EXPR json_index "${json_index} + 1")
endwhile()
endmacro()
macro(_sbeAddEscapedCharacter char)
string(CONCAT json_value "${json_value}" "${char}")
endmacro()
macro(_sbeParseObject prefix)
_sbeParse(${prefix})
_sbeMoveToNextNonEmptyCharacter()
endmacro()
macro(_sbeParseArray prefix)
math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} + 1")
set(json_${json_ArrayNestingLevel}_arrayIndex 0)
set(${prefix} "")
list(APPEND ${json_AllVariables} ${prefix})
while(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if("\"" STREQUAL "${json_char}")
# simple value
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
_sbeParseValue(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
elseif("{" STREQUAL "${json_char}")
# object
_sbeMoveToNextNonEmptyCharacter()
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
_sbeParseObject(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
else()
list(APPEND ${prefix} ${json_${json_ArrayNestingLevel}_arrayIndex})
_sbeParseReservedWord(${prefix}_${json_${json_ArrayNestingLevel}_arrayIndex})
endif()
if(NOT ${json_index} LESS ${json_jsonLen})
break()
endif()
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
if("]" STREQUAL "${json_char}")
_sbeMoveToNextNonEmptyCharacter()
break()
elseif("," STREQUAL "${json_char}")
math(EXPR json_${json_ArrayNestingLevel}_arrayIndex "${json_${json_ArrayNestingLevel}_arrayIndex} + 1")
endif()
_sbeMoveToNextNonEmptyCharacter()
endwhile()
if(${json_MaxArrayNestingLevel} LESS ${json_ArrayNestingLevel})
set(json_MaxArrayNestingLevel ${json_ArrayNestingLevel})
endif()
math(EXPR json_ArrayNestingLevel "${json_ArrayNestingLevel} - 1")
endmacro()
macro(_sbeMoveToNextNonEmptyCharacter)
math(EXPR json_index "${json_index} + 1")
if(${json_index} LESS ${json_jsonLen})
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
while(${json_char} MATCHES "[ \t\n\r]" AND ${json_index} LESS ${json_jsonLen})
math(EXPR json_index "${json_index} + 1")
string(SUBSTRING "${json_string}" ${json_index} 1 json_char)
endwhile()
endif()
endmacro()
+1 -1
View File
@@ -3,5 +3,5 @@ module.exports = {
verify: '--strict --tags ~@stress --tags ~@todo --tags ~@mld-only -f progress --require features/support --require features/step_definitions',
todo: '--strict --tags @todo --require features/support --require features/step_definitions',
all: '--strict --require features/support --require features/step_definitions',
mld: '--strict --tags ~@stress --tags ~@todo --tags ~@ch --require features/support --require features/step_definitions -f progress'
mld: '--strict --tags ~@stress --tags ~@todo --require features/support --require features/step_definitions -f progress'
};
+12 -13
View File
@@ -1,13 +1,15 @@
FROM debian:buster-slim as builder
FROM alpine:3.6 as buildstage
ARG DOCKER_TAG
RUN mkdir -p /src && mkdir -p /opt
COPY . /src
WORKDIR /src
RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
apt-get update && \
apt-get -y --no-install-recommends install cmake make git gcc g++ libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
libzip-dev libboost-all-dev lua5.2 liblua5.2-dev libtbb-dev -o APT::Install-Suggests=0 -o APT::Install-Recommends=0 && \
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.2-dev libtbb@testing libtbb-dev@testing && \
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
echo "Building OSRM ${DOCKER_TAG}" && \
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
@@ -31,16 +33,13 @@ RUN NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
FROM debian:buster-slim as runstage
FROM alpine:3.6 as runstage
RUN mkdir -p /src && mkdir -p /opt
RUN apt-get update && \
apt-get install -y --no-install-recommends libboost-program-options1.62.0 libboost-regex1.62.0 \
libboost-date-time1.62.0 libboost-chrono1.62.0 libboost-filesystem1.62.0 \
libboost-iostreams1.62.0 libboost-thread1.62.0 expat liblua5.2-0 libtbb2 &&\
rm -rf /var/lib/apt/lists/*
COPY --from=builder /usr/local /usr/local
COPY --from=builder /opt /opt
RUN chmod 0644 -R /opt
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk update && \
apk add boost-filesystem boost-program_options boost-regex boost-iostreams boost-thread libgomp lua5.2 expat libtbb@testing
COPY --from=buildstage /usr/local /usr/local
COPY --from=buildstage /opt /opt
WORKDIR /opt
EXPOSE 5000
+10 -138
View File
@@ -119,7 +119,7 @@ In addition to the [general options](#general-options) the following options are
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `waypoints` array of `Waypoint` objects sorted by distance to the input coordinate. Each object has at least the following additional properties:
- `nodes`: Array of OpenStreetMap node ids.
- `distance`: Distance in meters to the supplied input coordinate.
#### Example Requests
@@ -134,10 +134,6 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
{
"waypoints" : [
{
"nodes": [
2264199819,
0
],
"hint" : "KSoKADRYroqUBAEAEAAAABkAAAAGAAAAAAAAABhnCQCLtwAA_0vMAKlYIQM8TMwArVghAwEAAQH1a66g",
"distance" : 4.152629,
"name" : "Friedrichstraße",
@@ -147,10 +143,6 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
]
},
{
"nodes": [
2045820592,
0
],
"hint" : "KSoKADRYroqUBAEABgAAAAAAAAAAAAAAKQAAABhnCQCLtwAA7kvMAAxZIQM8TMwArVghAwAAAQH1a66g",
"distance" : 11.811961,
"name" : "Friedrichstraße",
@@ -160,10 +152,6 @@ curl 'http://router.project-osrm.org/nearest/v1/driving/13.388860,52.517037?numb
]
},
{
"nodes": [
0,
21487242
],
"hint" : "KioKgDbbDgCUBAEAAAAAABoAAAAAAAAAPAAAABlnCQCLtwAA50vMADJZIQM8TMwArVghAwAAAQH1a66g",
"distance" : 15.872438,
"name" : "Friedrichstraße",
@@ -221,13 +209,13 @@ curl 'http://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.397
### Table service
Computes the duration of the fastest route between all pairs of supplied coordinates. Returns the durations or distances or both between the coordinate pairs. Note that the distances are not the shortest distance between two coordinates, but rather the distances of the fastest routes. Duration is in seconds and distances is in meters.
Computes the duration of the fastest route between all pairs of supplied coordinates.
```endpoint
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&{destinations}=[{elem}...]&annotations={duration|distance|duration,distance}
GET /table/v1/{profile}/{coordinates}?{sources}=[{elem}...];&destinations=[{elem}...]
```
**Options**
**Coordinates**
In addition to the [general options](#general-options) the following options are supported for this service:
@@ -235,10 +223,6 @@ In addition to the [general options](#general-options) the following options are
|------------|--------------------------------------------------|---------------------------------------------|
|sources |`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as source. |
|destinations|`{index};{index}[;{index} ...]` or `all` (default)|Use location with given index as destination.|
|annotations |`duration` (default), `distance`, or `duration,distance`|Return the requested table or tables in response. |
|fallback_speed|`double > 0`| If no route found between a source/destination pair, calculate the as-the-crow-flies distance, then use this speed to estimate duration.|
|fallback_coordinate|`input` (default), or `snapped`| When using a `fallback_speed`, use the user-supplied coordinate (`input`), or the snapped location (`snapped`) for calculating distances.|
|scale_factor|`double > 0`| Use in conjunction with `annotations=durations`. Scales the table `duration` values by this number.|
Unlike other array encoded options, the length of `sources` and `destinations` can be **smaller or equal**
to number of input locations;
@@ -256,23 +240,14 @@ sources=0;5;7&destinations=5;1;4;2;3;6
#### Example Request
```curl
# Returns a 3x3 duration matrix:
# Returns a 3x3 matrix:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219'
# Returns a 1x3 duration matrix
# Returns a 1x3 matrix
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?sources=0'
# Returns a asymmetric 3x2 duration matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
# Returns a asymmetric 3x2 matrix with from the polyline encoded locations `qikdcB}~dpXkkHz`:
curl 'http://router.project-osrm.org/table/v1/driving/polyline(egs_Iq_aqAppHzbHulFzeMe`EuvKpnCglA)?sources=0;1;3&destinations=2;4'
# Returns a 3x3 duration matrix:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=duration'
# Returns a 3x3 distance matrix for CH:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance'
# Returns a 3x3 duration matrix and a 3x3 distance matrix for CH:
curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397634,52.529407;13.428555,52.523219?annotations=distance,duration'
```
**Response**
@@ -280,115 +255,17 @@ curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397
- `code` if the request was successful `Ok` otherwise see the service dependent and general status codes.
- `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from
the i-th waypoint to the j-th waypoint. Values are given in seconds. Can be `null` if no route between `i` and `j` can be found.
- `distances` array of arrays that stores the matrix in row-major order. `distances[i][j]` gives the travel distance from
the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned.
- `sources` array of `Waypoint` objects describing all sources in order
- `destinations` array of `Waypoint` objects describing all destinations in order
In case of error the following `code`s are supported in addition to the general ones:
| Type | Description |
|------------------|-----------------|
| Type | Description |
|-------------------|-----------------|
| `NoTable` | No route found. |
| `NotImplemented` | This request is not supported |
All other properties might be undefined.
#### Example Response
```json
{
"sources": [
{
"location": [
13.3888,
52.517033
],
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
"name": "Friedrichstraße"
},
{
"location": [
13.397631,
52.529432
],
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
"name": "Torstraße"
},
{
"location": [
13.428554,
52.523239
],
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
"name": "Platz der Vereinten Nationen"
}
],
"durations": [
[
0,
192.6,
382.8
],
[
199,
0,
283.9
],
[
344.7,
222.3,
0
]
],
"destinations": [
{
"location": [
13.3888,
52.517033
],
"hint": "PAMAgEVJAoAUAAAAIAAAAAcAAAAAAAAArss0Qa7LNEHiVIRA4lSEQAoAAAAQAAAABAAAAAAAAADMAAAAAEzMAKlYIQM8TMwArVghAwEA3wps52D3",
"name": "Friedrichstraße"
},
{
"location": [
13.397631,
52.529432
],
"hint": "WIQBgL6mAoAEAAAABgAAAAAAAAA7AAAAhU6PQHvHj0IAAAAAQbyYQgQAAAAGAAAAAAAAADsAAADMAAAAf27MABiJIQOCbswA_4ghAwAAXwVs52D3",
"name": "Torstraße"
},
{
"location": [
13.428554,
52.523239
],
"hint": "7UcAgP___38fAAAAUQAAACYAAABTAAAAhSQKQrXq5kKRbiZCWJo_Qx8AAABRAAAAJgAAAFMAAADMAAAASufMAOdwIQNL58wA03AhAwMAvxBs52D3",
"name": "Platz der Vereinten Nationen"
}
],
"code": "Ok",
"distances": [
[
0,
1886.89,
3791.3
],
[
1824,
0,
2838.09
],
[
3275.36,
2361.73,
0
]
]
}
```
### Match service
Map matching matches/snaps given GPS points to the road network in the most plausible way.
@@ -657,7 +534,6 @@ With `steps=false` and `annotations=true`:
"distance": [5,5,10,5,5],
"duration": [15,15,40,15,15],
"datasources": [1,0,0,0,1],
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
}
@@ -672,12 +548,10 @@ Annotation of the whole route leg with fine-grained information about each segme
- `distance`: The distance, in metres, between each pair of coordinates
- `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns.
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`. String-like names are in the `metadata.datasource_names` array.
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
- `weight`: The weights between each pair of coordinates. Does not include any turn costs.
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
- `metadata`: Metadata related to other annotations
- `datasource_names`: The names of the datasources used for the speed between each pair of coordinates. `lua profile` is the default profile, other values arethe filenames supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`
#### Example
@@ -686,7 +560,6 @@ Annotation of the whole route leg with fine-grained information about each segme
"distance": [5,5,10,5,5],
"duration": [15,15,40,15,15],
"datasources": [1,0,0,0,1],
"metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] },
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
"weight": [15,15,40,15,15]
}
@@ -906,7 +779,6 @@ Object used to describe waypoint on a route.
- `name` Name of the street the coordinate snapped to
- `location` Array that contains the `[longitude, latitude]` pair of the snapped coordinate
- `distance` The distance, in metres, from the input coordinate to the snapped coordinate
- `hint` Unique internal identifier of the segment (ephemeral, not constant over data updates)
This can be used on subsequent request to significantly speed up the query and to connect multiple services.
E.g. you can use the `hint` value obtained by the `nearest` query as `hint` values for `route` inputs.
+21 -48
View File
@@ -25,9 +25,6 @@ var osrm = new OSRM('network.osrm');
Make sure you prepared the dataset with the correct toolchain.
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
- `options.memory_file` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** *DEPRECATED*
Old behaviour: Path to a file on disk to store the memory using mmap. Current behaviour: setting this value is the same as setting `mmap_memory: true`.
- `options.mmap_memory` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Map on-disk files to virtual memory addresses (mmap), rather than loading into RAM.
- `options.path` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The path to the `.osrm` files. This is mutually exclusive with setting {options.shared_memory} to true.
- `options.max_locations_trip` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in trip query (default: unlimited).
- `options.max_locations_viaroute` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Max. locations supported in viaroute query (default: unlimited).
@@ -58,13 +55,13 @@ Returns the fastest route between two or more coordinates while visiting the way
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
`null`/`true`/`false`
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
```javascript
var osrm = new OSRM("berlin-latest.osrm");
osrm.route({coordinates: [[13.438640,52.519930], [13.415852,52.513191]]}, function(err, result) {
osrm.route({coordinates: [[52.519930,13.438640], [52.513191,13.415852]]}, function(err, result) {
if(err) throw err;
console.log(result.waypoints); // array of Waypoint objects representing all waypoints in order
console.log(result.routes); // array of Route objects ordered by descending recommendation rank
@@ -90,7 +87,7 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
- `options.number` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -112,8 +109,8 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
### table
Computes duration table for the given locations. Allows for both symmetric and asymmetric
tables. Optionally returns distance table.
Computes duration tables for the given locations. Allows for both symmetric and asymmetric
tables.
**Parameters**
@@ -129,10 +126,7 @@ tables. Optionally returns distance table.
- `options.destinations` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer <
#coordinates`) to use location with given index as destination. Default is to use all.
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.fallback_speed` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second.
- `options.fallback_coordinate` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies diestance between two points.
- `options.scale_factor` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Multiply the table duration values in the table by this number for more controlled input into a route optimization solver.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -172,7 +166,7 @@ and what weights they have applied.
- `ZXY` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)** an array consisting of `x`, `y`, and `z` values representing tile coordinates like
[wiki.openstreetmap.org/wiki/Slippy_map_tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames)
and are supported by vector tile viewers like [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -209,7 +203,7 @@ if they can not be matched successfully.
- `options.radiuses` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy. Can be `null` for default value `5` meters or `double >= 0`.
- `options.gaps` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** Allows the input track splitting based on huge timestamp gaps between points. Either `split` or `ignore` (optional, default `split`).
- `options.tidy` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Allows the input track modification to obtain better matching quality for noisy tracks (optional, default `false`).
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -273,7 +267,7 @@ Right now, the following combinations are possible:
- `options.source` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
- `callback` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)**
**Examples**
@@ -302,39 +296,18 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
2) `waypoint_index`: index of the point in the trip.
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
## Plugin behaviour
All plugins support a second additional object that is available to configure some NodeJS specific behaviours.
- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.
**Examples**
```javascript
var osrm = new OSRM('network.osrm');
var options = {
coordinates: [
[13.36761474609375, 52.51663871100423],
[13.374481201171875, 52.506191342034576]
]
};
osrm.route(options, { format: "json_buffer" }, function(err, response) {
if (err) throw err;
console.log(response.toString("utf-8"));
});
```
## Responses
Responses
### Route
Represents a route through (potentially multiple) waypoints.
**Parameters**
- **documentation** in
[`osrm-backend`](../http.md#route-object)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#route)
### RouteLeg
@@ -342,8 +315,8 @@ Represents a route between two waypoints.
**Parameters**
- **documentation** in
[`osrm-backend`](../http.md#routeleg-object)
- `exteral` **documentation** in
[`osrm-backend`](../http.md#routeleg)
### RouteStep
@@ -352,15 +325,15 @@ single way to the subsequent step.
**Parameters**
- **documentation** in
[`osrm-backend`](../http.md#routestep-object)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#routestep)
### StepManeuver
**Parameters**
- **documentation** in
[`osrm-backend`](../http.md#stepmaneuver-object)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#stepmaneuver)
### Waypoint
@@ -368,5 +341,5 @@ Object used to describe waypoint on a route.
**Parameters**
- **documentation** in
[`osrm-backend`](../http.md#waypoint-object)
- `exteral` **documentation** in
[`osrm-backend`](https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md#waypoint)
+5 -5
View File
@@ -68,7 +68,7 @@ If you want to prioritize certain streets, increase the rate on these.
## Elements
### api_version
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 4.
A profile should set `api_version` at the top of your profile. This is done to ensure that older profiles are still supported when the api changes. If `api_version` is not defined, 0 will be assumed. The current api version is 2.
### Library files
The folder [profiles/lib/](../profiles/lib/) contains LUA library files for handling many common processing tasks.
@@ -138,7 +138,7 @@ Given an OpenStreetMap way, the `process_way` function will either return nothin
Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
way | The input way to process (read-only).
node | The input way to process (read-only).
result | The output that you will modify.
relations| Storage of relations to access relations, where `way` is a member.
@@ -199,7 +199,7 @@ source.lon | Read | Float | Co-ordinates of segment start
source.lat | Read | Float | ""
target.lon | Read | Float | Co-ordinates of segment end
target.lat | Read | Float | ""
distance | Read | Float | Length of segment
target.distance | Read | Float | Length of segment
weight | Read/write | Float | Routing weight for this segment
duration | Read/write | Float | Duration for this segment
@@ -224,8 +224,8 @@ source_highway_turn_classification | Read | Integer |
source_access_turn_classification | Read | Integer | Classification based on access tag defined by user during setup. (default when not set: 0, allowed classification values are: 0-15))
source_speed | Read | Integer | Speed on this source road in km/h
source_priority_class | Read | Enum | The type of road priority class of the source. Defined in `include/extractor/guidance/road_classification.hpp`
target_restricted | Read | Boolean | Is the target a restricted access road? (See definition in `process_way`)
target_mode | Read | Enum | Travel mode after the turn. Defined in `include/extractor/travel_mode.hpp`
target_restricted | Read | Boolean | Is it from a restricted access road? (See definition in `process_way`)
target_mode | Read | Enum | Travel mode before the turn. Defined in `include/extractor/travel_mode.hpp`
target_is_motorway | Read | Boolean | Is the target road a motorway?
target_is_link | Read | Boolean | Is the target road a link?
target_number_of_lanes | Read | Integer | How many lanes does the target road have? (default when not tagged: 0)
+6 -8
View File
@@ -43,14 +43,12 @@ We may introduce forward-compatible changes: query parameters and response prope
1. Check out the appropriate release branch `x.y`
2. Make sure `CHANGELOG.md` is up to date.
3. Make sure the `package.json` on branch `x.y` has been committed.
4. Make sure all tests are passing (e.g. Travis CI gives you a :green_apple:)
5. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries. Commit should be one in which the `package.json` version matches the version you want to release.
6. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
7. Push tags and commits: `git push; git push --tags`
8. On https://github.com/Project-OSRM/osrm-backend/releases press `Draft a new release`,
write the release tag `vx.y.z` in the `Tag version` field, write the changelog entries in the `Describe this release` field
and press `Publish release`.
3. Make sure the OSRM version in `CMakeLists.txt` is up to date
4. Make sure the `package.json` is up to date.
5. Make sure all tests are passing (e.g. Travis CI gives you a :thumbs_up:)
6. Use an annotated tag to mark the release: `git tag vx.y.z -a` Body of the tag description should be the changelog entries.
7. Use `npm run docs` to generate the API documentation. Copy `build/docs/*` to `https://github.com/Project-OSRM/project-osrm.github.com` in the `docs/vN.N.N/api` directory
8. Push tags and commits: `git push; git push --tags`
9. If not a release-candidate: Write a mailing-list post to osrm-talk@openstreetmap.org to announce the release
10. Wait until the travis build has been completed and check if the node binaries were published by doing:
`rm -rf node_modules && npm install` locally.
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | x |
| some_tag | |
| block | x |
Scenario: Bike - Access tag trumphs barriers
-92
View File
@@ -1,92 +0,0 @@
@routing @bicycle @mode
Feature: Bicycle - Mode flag
Background:
Given the profile "bicycle"
Scenario: Bicycle - We tag ferries with a class
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | route |
| ab | primary | |
| bc | | ferry |
| cd | primary | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,bc,cd,cd | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| d | a | cd,bc,ab,ab | depart,notification right,notification left,arrive | [()],[(ferry)],[()],[()] |
| c | a | bc,ab,ab | depart,notification left,arrive | [(ferry)],[()],[()] |
| d | b | cd,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| a | c | ab,bc,bc | depart,notification right,arrive | [()],[(ferry)],[()] |
| b | d | bc,cd,cd | depart,notification left,arrive | [(ferry)],[()],[()] |
Scenario: Bicycle - We tag tunnel with a class
Background:
Given a grid size of 200 meters
Given the node map
"""
a b
c d
"""
And the ways
| nodes | tunnel |
| ab | no |
| bc | yes |
| cd | |
When I route I should get
| from | to | route | turns | classes |
| a | d | ab,bc,cd,cd | depart,new name right,new name left,arrive | [()],[(tunnel)],[()],[()] |
Scenario: Bicycle - We tag classes without intersections
Background:
Given a grid size of 200 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes | name | tunnel |
| ab | road | |
| bc | road | yes |
| cd | road | |
When I route I should get
| from | to | route | turns | classes |
| a | d | road,road | depart,arrive | [(),(tunnel),()],[()] |
Scenario: Bicycle - From roundabout on ferry
Given the node map
"""
c
/ \
a---b d---f--h
\ /
e
|
g
"""
And the ways
| nodes | oneway | highway | junction | route |
| ab | yes | service | | |
| cb | yes | service | roundabout | |
| dc | yes | service | roundabout | |
| be | yes | service | roundabout | |
| ed | yes | service | roundabout | |
| eg | yes | service | | |
| df | | | | ferry |
| fh | yes | service | | |
When I route I should get
| from | to | route | turns | classes |
| a | h | ab,df,df,fh,fh | depart,roundabout-exit-2,exit roundabout slight right,notification straight,arrive | [()],[(),()],[(ferry)],[()],[()] |
+8 -10
View File
@@ -46,14 +46,12 @@ Feature: Bike - Cycle tracks/lanes
| primary | | | | x | x |
| motorway | | | | | |
| motorway | track | | | x | |
| motorway | opposite | | | x | x |
| motorway | | track | | x | |
| motorway | | opposite | | x | x |
| motorway | opposite | | | | x |
| motorway | | track | | | x |
| motorway | | opposite | | | x |
| motorway | | | track | x | |
| motorway | | | opposite | x | x |
# motorways are implicit oneways and cycleway tracks next to oneways always
# follow the oneway direction (unless tagged as opposite)
| motorway | | track | track | x | |
| motorway | | | opposite | x | |
| motorway | | track | track | x | x |
| motorway | | opposite | opposite | x | x |
| motorway | | track | opposite | x | x |
| motorway | | opposite | track | x | x |
@@ -94,6 +92,6 @@ Feature: Bike - Cycle tracks/lanes
Then routability should be
| highway | cycleway | oneway | forw | backw |
| motorway | track | yes | 15 km/h | |
| residential | track | yes | 15 km/h | 4 km/h +-1 |
| cycleway | track | yes | 15 km/h | 4 km/h +-1 |
| footway | track | yes | 15 km/h | 4 km/h +-1 |
| residential | track | yes | 15 km/h | 6 km/h +-1 |
| cycleway | track | yes | 15 km/h | 6 km/h +-1 |
| footway | track | yes | 15 km/h | 6 km/h +-1 |
-55
View File
@@ -1,55 +0,0 @@
@routing @bicycle @exclude
Feature: Bicycle - Exclude flags
Background:
Given the profile file "bicycle" initialized with
"""
profile.excludable = Sequence { Set { 'ferry' } }
"""
Given the node map
"""
a....b~~~~~c...f
: :
d.....e
"""
And the ways
| nodes | highway | route | duration | # |
| ab | service | | | always drivable |
| bc | | ferry | 00:00:01 | not drivable for exclude=ferry, but fast. |
| bd | service | | | always drivable |
| de | service | | | always drivable |
| ec | service | | | always drivable |
| cf | service | | | always drivable |
Scenario: Bicycle - exclude nothing
When I route I should get
| from | to | route |
| a | f | ab,bc,cf,cf |
When I match I should get
| trace | matchings | duration |
| abcf | abcf | 109 |
When I request a travel time matrix I should get
| | a | f |
| a | 0 | 109 |
| f | 109 | 0 |
Scenario: Bicycle - exclude ferry
Given the query options
| exclude | ferry |
When I route I should get
| from | to | route |
| a | f | ab,bd,de,ec,cf,cf |
When I match I should get
| trace | matchings | duration |
| abcf | abcf | 301.2 |
When I request a travel time matrix I should get
| | a | f |
| a | 0 | 301 +- 1 |
| f | 301.2 +- 1 | 0 |
+2 -9
View File
@@ -141,12 +141,5 @@ Feature: Bike - Oneway streets
| highway | oneway | cycleway:left | cycleway:right | forw | backw |
| primary | yes | | | cycling | pushing bike |
| primary | yes | | track | cycling | pushing bike |
| primary | yes | track | | cycling | pushing bike |
| primary | yes | track | track | cycling | pushing bike |
Scenario: Bike - Left/right cycleways on any oneways
Then routability should be
| foot | oneway | cycleway:left | cycleway:right | forw | backw |
| no | yes | track | | cycling | |
| yes | yes | track | | cycling | pushing bike |
| yes | -1 | track | | pushing bike | cycling |
| primary | yes | track | | cycling | cycling |
| primary | yes | track | track | cycling | cycling |
+31 -31
View File
@@ -11,15 +11,15 @@ Feature: Bicycle - Adds penalties to unsafe roads
Then routability should be
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| motorway | | | | | |
| primary | | 15 km/h | 15 km/h | 2.1 | 2.1 |
| secondary | | 15 km/h | 15 km/h | 2.7 | 2.7 |
| primary | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| tertiary | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| primary_link | | 15 km/h | 15 km/h | 2.1 | 2.1 |
| secondary_link | | 15 km/h | 15 km/h | 2.7 | 2.7 |
| primary_link | | 15 km/h | 15 km/h | 2.9 | 2.9 |
| secondary_link | | 15 km/h | 15 km/h | 3.1 | 3.1 |
| tertiary_link | | 15 km/h | 15 km/h | 3.3 | 3.3 |
| residential | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | 4 km/h +-1 | 4 km/h +-1 | 1.1 | 1.1 |
| footway | | 6 km/h +-1 | 6 km/h +-1 | 1.7 | 1.7 |
Scenario: Bike - Apply no penalties to ways with cycleways
Then routability should be
@@ -51,49 +51,49 @@ Feature: Bicycle - Adds penalties to unsafe roads
Then routability should be
| highway | cycleway:right | cycleway:left | forw | backw | forw_rate | backw_rate |
| motorway | track | | 15 km/h | | 4.2 | |
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| primary | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| primary_link | track | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary_link | track | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | track | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | track | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
| motorway | | track | 15 km/h | | 4.2 | |
| primary | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
| footway | track | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
| motorway | | track | | 15 km/h | | 4.2 |
| primary | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | track | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary_link | | track | 15 km/h | 15 km/h | 2.7 | 4.2 |
| primary_link | | track | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | track | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary_link | | track | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | track | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | track | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
| footway | | track | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
| motorway | lane | | 15 km/h | | 4.2 | |
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| primary | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.7 |
| primary_link | lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| secondary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.1 |
| tertiary_link | lane | | 15 km/h | 15 km/h | 4.2 | 3.3 |
| residential | lane | | 15 km/h +-1 | 15 km/h +-1 | 4.2 | 4.2 |
| cycleway | lane | | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | lane | | 15 km/h | 4 km/h +-1 | 4.2 | 1.1 |
| motorway | | lane | 15 km/h | | 4.2 | |
| primary | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 2.7 | 4.2 |
| footway | lane | | 15 km/h | 6 km/h +-1 | 4.2 | 1.7 |
| motorway | | lane | | 15 km/h | | 4.2 |
| primary | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary | | lane | 15 km/h +-1 | 15 km/h +-1 | 3.1 | 4.2 |
| tertiary | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| primary_link | | lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
| secondary_link | | lane | 15 km/h | 15 km/h | 2.7 | 4.2 |
| primary_link | | lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
| secondary_link | | lane | 15 km/h | 15 km/h | 3.1 | 4.2 |
| tertiary_link | | lane | 15 km/h | 15 km/h | 3.3 | 4.2 |
| residential | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| cycleway | | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| footway | | lane | 4 km/h +-1 | 15 km/h | 1.1 | 4.2 |
| footway | | lane | 6 km/h +-1 | 15 km/h | 1.7 | 4.2 |
| motorway | shared_lane | | 15 km/h | | 4.2 | |
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.1 |
| motorway | | shared_lane | 15 km/h | | 4.2 | |
| primary | | shared_lane | 15 km/h | 15 km/h | 2.1 | 4.2 |
| primary | shared_lane | | 15 km/h | 15 km/h | 4.2 | 2.9 |
| motorway | | shared_lane | | 15 km/h | | 4.2 |
| primary | | shared_lane | 15 km/h | 15 km/h | 2.9 | 4.2 |
Scenario: Bike - Don't apply penalties for all kind of cycleways
@@ -101,4 +101,4 @@ Feature: Bicycle - Adds penalties to unsafe roads
| highway | cycleway | forw | backw | forw_rate | backw_rate |
| tertiary | shared_lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | lane | 15 km/h | 15 km/h | 4.2 | 4.2 |
| tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 3.3 |
| tertiary | opposite | 15 km/h | 15 km/h | 3.3 | 4.2 |
+3 -3
View File
@@ -54,6 +54,6 @@ Feature: Bike - Surfaces
When I route I should get
| from | to | route | modes | speed |
| a | b | ab,ab | cycling,cycling | 15 km/h |
| b | a | ab,ab | pushing bike,pushing bike | 4 km/h |
| c | d | cd,cd | pushing bike,pushing bike | 4 km/h |
| d | c | cd,cd | pushing bike,pushing bike | 4 km/h |
| b | a | ab,ab | pushing bike,pushing bike | 6 km/h |
| c | d | cd,cd | pushing bike,pushing bike | 6 km/h |
| d | c | cd,cd | pushing bike,pushing bike | 6 km/h |
+18 -18
View File
@@ -691,14 +691,14 @@ Feature: Car - Turn restrictions
# """
Given the node locations
| node | lat | lon |
| a | 38.91124 | -77.00909 |
| b | 38.91080 | -77.00909 |
| c | 38.91038 | -77.00909 |
| d | 38.91105 | -77.00967 |
| e | 38.91037 | -77.00807 |
| f | 38.91036 | -77.00899 |
| g | 38.91076 | -77.00901 |
| h | 38.91124 | -77.00900 |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
And the ways
| nodes | oneway | name |
@@ -719,7 +719,7 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida nw,florida nw,florida ne | depart,turn right,continue uturn,arrive |
| f | d | cap north,florida nw,florida nw | depart,turn left,arrive |
| f | d | cap north,florida,florida nw | depart,turn left,arrive |
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
@no_turning @conditionals
@@ -738,14 +738,14 @@ Feature: Car - Turn restrictions
# """
Given the node locations
| node | lat | lon |
| a | 38.91124 | -77.00909 |
| b | 38.91080 | -77.00909 |
| c | 38.91038 | -77.00909 |
| d | 38.91105 | -77.00967 |
| e | 38.91037 | -77.00807 |
| f | 38.91036 | -77.00899 |
| g | 38.91076 | -77.00901 |
| h | 38.91124 | -77.00900 |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
And the ways
| nodes | oneway | name |
@@ -765,7 +765,7 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida ne,florida ne | depart,turn left,arrive |
| a | e | cap south,florida,florida ne | depart,turn left,arrive |
| f | d | cap north,florida ne,florida ne,florida nw | depart,turn sharp right,continue uturn,arrive |
| e | c | florida ne,cap south,cap south | depart,turn left,arrive |
+8 -9
View File
@@ -135,12 +135,12 @@ Feature: Car - Destination only, no passing through
Scenario: Car - Routing through a parking lot tagged access=destination,service
Given the node map
"""
a----c++++b+++g------h---i
| + + + /
| + + + /
| + + + /
a----c++++b+++g----h---i
| + + + |
| + + + |
| + + + |
| d++++e+f /
z--------------y
z---------------y
"""
And the ways
@@ -155,10 +155,9 @@ Feature: Car - Destination only, no passing through
| gf | destination | service |
When I route I should get
| from | to | route |
| a | i | azyhi,azyhi |
| b | f | be,def,def |
| b | i | cbg,ghi,azyhi,azyhi |
| from | to | route |
| a | i | azyhi,azyhi |
| b | f | be,def,def |
Scenario: Car - Disallow snapping to access=private,highway=service
Given a grid size of 20 meters
-19
View File
@@ -48,22 +48,3 @@ Feature: Car - Handle physical limitation
| primary | | none | x |
| primary | | no-sign | x |
| primary | | unsigned | x |
Scenario: Car - Limited by length
Then routability should be
| highway | maxlength | bothw |
| primary | | x |
| primary | 1 | |
| primary | 5 | x |
| primary | unsigned | x |
Scenario: Car - Limited by weight
Then routability should be
| highway | maxweight | bothw |
| primary | | x |
| primary | 1 | |
| primary | 3.5 | x |
| primary | 35000 kg | x |
| primary | 8.9t | x |
| primary | 0.1 lbs | |
| primary | unsigned | x |
+1 -1
View File
@@ -19,7 +19,7 @@ Feature: Barriers
| entrance | x |
| wall | |
| fence | |
| some_tag | x |
| some_tag | |
| block | x |
Scenario: Foot - Access tag trumphs barriers
+5 -5
View File
@@ -22,11 +22,11 @@ Feature: Bike - Mode flag
| c | traffic_signals |
And the ways
| nodes | highway | name | oneway:bicycle | maxspeed:forward |
| abcd | cycleway | street | | 4 km/h |
| eb | path | | yes | |
| icef | tertiary | road | | 4 km/h |
| geh | secondary | street | | |
| nodes | highway | name | oneway:bicycle |
| abcd | cycleway | street | |
| eb | path | | yes |
| icef | tertiary | road | |
| geh | secondary | street | |
When I route I should get
| waypoints | route | turns |
+53 -55
View File
@@ -35,20 +35,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Segregated Intersection, Cross Belonging to Single Street
Given the node map
@@ -74,7 +74,7 @@ Feature: Collapse
When I route I should get
| waypoints | route | turns | locations |
| a,i | first,third,third | depart,turn sharp left,arrive | a,b,i |
| a,i | first,second,third,third | depart,turn left,turn slight left,arrive | a,b,e,i |
Scenario: Segregated Intersection, Cross Belonging to Correct Street
Given the node map
@@ -106,20 +106,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
Given the node map
@@ -151,20 +151,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Partly Segregated Intersection, Two Segregated Roads
Given the node map
@@ -209,11 +209,11 @@ Feature: Collapse
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
| g,j | second,second | depart,arrive | g,j |
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
| i,h | second,second | depart,arrive | i,h |
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
@@ -263,11 +263,11 @@ Feature: Collapse
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
| g,j | second,second | depart,arrive | g,j |
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
| i,h | second,second | depart,arrive | i,h |
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
@@ -300,20 +300,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
Given the node map
@@ -345,29 +345,28 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
Scenario: Entering a segregated road
Given the node map
"""
h
a f | g
| | i '
b-e ' |
/ / j
a f g
| | . '
b-e '
/ /
/ /
c d
"""
@@ -377,8 +376,7 @@ Feature: Collapse
| abc | primary | first | yes |
| def | primary | first | yes |
| be | primary | first | no |
| gie | primary | second | no |
| hij | primary | maple | no |
| ge | primary | second | no |
When I route I should get
| waypoints | route | turns | locations |
@@ -387,7 +385,7 @@ Feature: Collapse
| a,g | first,second,second | depart,turn left,arrive | a,b,g |
| d,g | first,second,second | depart,turn right,arrive | d,e,g |
| g,f | second,first,first | depart,turn right,arrive | g,e,f |
| g,c | second,first,first | depart,end of road left,arrive | g,e,c |
| g,c | second,first,first | depart,turn left,arrive | g,e,c |
Scenario: Do not collapse turning roads
Given the node map
@@ -605,7 +603,7 @@ Feature: Collapse
When I route I should get
| waypoints | route | turns | locations |
| i,h | in,road,road | depart,turn slight left,arrive | i,c,h |
| i,h | in,road,road | depart,turn left,arrive | i,f,h |
| a,d | road,road | depart,arrive | a,d |
| a,j | road,out,out | depart,turn slight right,arrive | a,b,j |
@@ -1012,7 +1010,7 @@ Feature: Collapse
| f,j | hohe,hohe | depart,arrive | f,j |
| a,t | hohe,a100,a100 | depart,on ramp right,arrive | a,b,t |
| f,e | | | |
| q,j | a100,hohe,hohe | depart,turn right,arrive | q,i,j |
| q,j | a100,hohe,hohe | depart,turn right,arrive | q,p,j |
| q,e | a100,hohebruecke,hohe | depart,turn left,arrive | q,p,e |
Scenario: Forking before a turn (forky)
@@ -687,7 +687,7 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get
| waypoints | route | turns | locations |
| s,f | sabc,ae,dbef,dbef | depart,fork slight right,turn right,arrive | s,a,e,f |
| s,f | sabc,ae,dbef,dbef | depart,turn slight right,turn right,arrive | s,a,e,f |
@sliproads
Scenario: Traffic Signal on Sliproad
+13 -50
View File
@@ -13,23 +13,19 @@ Feature: Divided road entry
d-------e-----f
|
|
i---g---j
|
|
h
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| egh | side st | residential | |
| igj | maple st | residential | |
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| eg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| h,a | side st,main st,main st| depart,end of road left,arrive |
| g,a | side st,main st,main st| depart,end of road left,arrive |
# Similar to previous one, but the joining way is tagged with the side-street name
@@ -41,22 +37,18 @@ Feature: Divided road entry
d-------e-----f
|
|
i---g---j
|
|
h
g
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| begh | side st | residential | |
| igj | maple st | residential | |
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| beg | side st | residential | |
When I route I should get
| waypoints | route | turns |
| h,a | side st,main st,main st| depart,end of road left,arrive |
| g,a | side st,main st,main st| depart,end of road left,arrive |
# Center join named after crossroad
@@ -108,32 +100,3 @@ Feature: Divided road entry
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,turn left,arrive |
# Verify end of road left turn across divided roads
Scenario: Join on a divided road, named after the side street
Given the node map
"""
a-----h--b-----c
| |
d-----i--e-----f
| |
| |
m---j--g---n
| |
| |
k l
"""
And the ways
| nodes | name | highway | oneway |
| ahbc | main st | residential | -1 |
| dief | main st | residential | yes |
| begl | side st | residential | -1 |
| hijk | side st | residential | yes |
| mjgn | maple st| residential | no |
When I route I should get
| waypoints | route | turns |
| l,a | side st,main st,main st| depart,end of road left,arrive |
-20
View File
@@ -46,23 +46,3 @@ Feature: Driveways intersections
When I route I should get
| waypoints | route | turns | locations |
| a,d | ,second | depart,arrive | a,d |
Scenario: Road with a turn to service road
Given the node map
"""
/-----------------e
a---b------------------c
`-----------------d
"""
And the ways
| nodes | highway | name | oneway |
| abc | trunk | road | yes |
| bd | service | serv | yes |
| be | service | serv | yes |
When I route I should get
| waypoints | route | turns | locations |
| a,d | road,serv,serv | depart,turn slight right,arrive | a,b,d |
| a,e | road,serv,serv | depart,turn slight left,arrive | a,b,e |
@@ -1,46 +0,0 @@
@guidance
Feature: Internal Intersection Model
Background:
Given the profile "car"
Given a grid size of 10 meters
Scenario: Dual-carriage way intersection
Given the node map
"""
a b
| |
c--d--e--f
| |
g--h--i--j
| |
k l
"""
And the ways
| nodes | oneway | name |
| adhk | yes | Broken Land Parkway |
| lieb | yes | Broken Land Parkway |
| fed | yes | Snowden River Parkway |
| dc | yes | Patuxent Woods Drive |
| gh | yes | Patuxent Woods Drive |
| hij | yes | Snowden River Parkway |
When I route I should get
| waypoints | route | turns | # |
| a,k | Broken Land Parkway,Broken Land Parkway | depart,arrive ||
| l,b | Broken Land Parkway,Broken Land Parkway | depart,arrive ||
# | g,j | Patuxent Woods Drive,Snowden River Parkway,Snowden River Parkway | depart,continue,arrive | did not work as expected - might be another issue to handle in post process? |
# | f,c | Snowden River Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,continue,arrive | did not work as expected - might be another issue to handle in post process? |
| a,c | Broken Land Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,turn right,arrive ||
| g,k | Patuxent Woods Drive,Broken Land Parkway,Broken Land Parkway | depart,turn right,arrive ||
| l,j | Broken Land Parkway,Snowden River Parkway,Snowden River Parkway | depart,turn right,arrive ||
| f,b | Snowden River Parkway,Broken Land Parkway,Broken Land Parkway | depart,turn right,arrive ||
| a,j | Broken Land Parkway,Snowden River Parkway,Snowden River Parkway | depart,turn left,arrive ||
| g,b | Patuxent Woods Drive,Broken Land Parkway,Broken Land Parkway | depart,turn left,arrive ||
| l,c | Broken Land Parkway,Patuxent Woods Drive,Patuxent Woods Drive | depart,turn left,arrive ||
| f,k | Snowden River Parkway,Broken Land Parkway,Broken Land Parkway | depart,turn left,arrive ||
| a,b | Broken Land Parkway,Broken Land Parkway,Broken Land Parkway | depart,continue uturn,arrive ||
| g,c | Patuxent Woods Drive,Patuxent Woods Drive,Patuxent Woods Drive | depart,continue uturn,arrive ||
| l,k | Broken Land Parkway,Broken Land Parkway,Broken Land Parkway | depart,continue uturn,arrive ||
| f,j | Snowden River Parkway,Snowden River Parkway,Snowden River Parkway | depart,continue uturn,arrive ||
+3 -3
View File
@@ -64,9 +64,9 @@ Feature: Exceptions for routing onto low-priority roads
| bc | service | |
When I route I should get
| waypoints | route | turns |
| e,c | service, | depart,arrive |
| c,e | ,service | depart,arrive |
| waypoints | route | turns |
| e,c | service, | depart,arrive |
| c,e | ,service,service | depart,turn straight,arrive |
Scenario: Straight onto low-priority
Given the node map
-9
View File
@@ -27,12 +27,6 @@ Feature: Maneuver tag support
| maneuver | abc | c | cgi | turn | sharp_right |
| maneuver | hij | i | cde | turn | sharp_left |
| maneuver | abc | c | cde | turn | slight_left |
| maneuver | cde | c | cgi | turn | straight |
| manoeuvre| cgi | c | abc | turn | right |
And the relations
| type | way:from | node:via | way:to | manoeuvre | maneuver | direction |
| maneuver | cgi | c | cde | fork | turn | slight_right |
When I route I should get
| waypoints | route | turns |
@@ -41,9 +35,6 @@ Feature: Maneuver tag support
| b,g | A Street,C Street,C Street | depart,turn sharp right,arrive |
# Testing re-awakening suppressed turns
| a,e | A Street,B Street,B Street | depart,turn slight left,arrive |
| e,i | B Street,C Street,C Street | depart,turn straight,arrive |
| i,e | C Street,B Street,B Street | depart,fork slight right,arrive |
| i,a | C Street,A Street,A Street | depart,turn right,arrive |
Scenario: single via-way
Given the node map
@@ -384,9 +384,9 @@ Feature: Merge Segregated Roads
| cd | right | no |
When I route I should get
| waypoints | route | intersections |
| a,d | left,circle,right,right | true:90,false:90 true:120 false:270;true:60 true:180 false:300;true:90 false:240 true:270;true:270 |
| g,d | bottom,circle,right,right | true:0;true:60 false:180 false:300;true:90 false:240 true:270;true:270 |
| waypoints | route | intersections |
| a,d | left,circle,circle,right,right | true:90;false:90 true:120 false:270;true:60 true:180 false:300;true:90 false:240 true:270;true:270 |
| g,d | bottom,circle,right,right | true:0;true:60 false:180 false:300;true:90 false:240 true:270;true:270 |
Scenario: Middle Island
Given the node map
@@ -644,7 +644,7 @@ Feature: Merge Segregated Roads
| k,j | marianne,albrecht,luise,luise | depart,turn left,turn left,arrive |
| k,d | marianne,schwert,schwert | depart,turn right,arrive |
| i,j | luise,luise | depart,arrive |
| i,d | luise,albrecht,schwert | depart,turn left,arrive |
| i,d | luise,albrecht,schwert,schwert | depart,turn left,turn straight,arrive |
| i,l | luise,albrecht,marianne,marianne | depart,turn left,turn left,arrive |
# https://www.openstreetmap.org/#map=19/52.46339/13.40272
+2 -2
View File
@@ -201,7 +201,7 @@ Feature: Motorway Guidance
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight left,arrive |
| a,i | abcde,chi,chi | depart,off ramp slight right,arrive |
| f,i | fgc,chi,chi | depart,off ramp slight right,arrive |
| f,i | fgc,chi,chi | depart,off ramp right,arrive |
Scenario: On And Off Ramp Left
Given the node map
@@ -221,7 +221,7 @@ Feature: Motorway Guidance
| a,e | abcde,abcde | depart,arrive |
| f,e | fgc,abcde,abcde | depart,merge slight right,arrive |
| a,i | abcde,chi,chi | depart,off ramp slight left,arrive |
| f,i | fgc,chi,chi | depart,off ramp slight left,arrive |
| f,i | fgc,chi,chi | depart,off ramp left,arrive |
Scenario: Merging Motorways
Given the node map
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -848,7 +848,6 @@ Feature: Simple Turns
| h,a | Heide,Perle,Perle | depart,turn left,arrive | true:16;true:90 true:195 true:270 true:345;true:90 |
#http://www.openstreetmap.org/#map=19/52.53293/13.32956
# adjusted ways to reflect the case geometry for 2/3/2018
Scenario: Curved Exit from Curved Road
Given the node map
"""
@@ -875,16 +874,16 @@ Feature: Simple Turns
And the ways
| nodes | name | oneway | lanes | highway |
| ab | Siemens | no | 5 | secondary |
| bcdefg | Erna | no | 3 | secondary |
| abcd | Siemens | no | 5 | secondary |
| defg | Erna | no | 3 | secondary |
| dhij | Siemens | no | | residential |
When I route I should get
| waypoints | route | turns |
| a,j | Siemens,Siemens,Siemens | depart,turn slight right,arrive |
| a,g | Siemens,Erna | depart,arrive |
| g,j | Erna,Siemens,Siemens | depart,turn left,arrive |
| g,a | Erna,Siemens | depart,arrive |
| waypoints | route | turns |
| a,j | Siemens,Siemens,Siemens | depart,continue slight right,arrive |
| a,g | Siemens,Erna | depart,arrive |
| g,j | Erna,Siemens,Siemens | depart,turn left,arrive |
| g,a | Erna,Siemens | depart,arrive |
#http://www.openstreetmap.org/#map=19/52.51303/13.32170
Scenario: Ernst Reuter Platz
+21 -26
View File
@@ -301,7 +301,7 @@ Feature: Turn Lane Guidance
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross | depart,arrive | ;;left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false;left:true straight:false;left:true straight:false;left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ;,left:true straight:false;left:true straight:false;left:false straight:true, |
@partition-lanes
Scenario: Turn Lanes at Segregated Road
@@ -614,9 +614,8 @@ Feature: Turn Lane Guidance
| |
| |
b d
h-----c
| `-f
g
h c
' -- g - - f
"""
And the ways
@@ -937,52 +936,48 @@ Feature: Turn Lane Guidance
Scenario: Partitioned turn, Slight Curve - maxspeed
Given the node map
"""
f e
| |
i | |
| | c
h - a - b ' |
j g d
f e
| |
| |
| c
a - b ' |
g d
"""
And the ways
| nodes | name | highway | oneway | turn:lanes:forward | maxspeed |
| ha | road | primary | yes | | 1 |
| ab | road | primary | yes | left\|right | 1 |
| bc | cross | primary | yes | | 1 |
| fbg | cross | primary | yes | | 1 |
| dce | cross | primary | yes | | 1 |
| iaj | kross | primary | no | | 1 |
When I route I should get
| waypoints | route | turns | lanes | locations |
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
Scenario: Partitioned turn, Slight Curve
Given the node map
"""
f e
| |
i | |
| | c
h - a - b ' |
j g d
f e
| |
| |
| c
a - b ' |
g d
"""
And the ways
| nodes | name | highway | oneway | turn:lanes:forward |
| ha | road | primary | yes | |
| ab | road | primary | yes | left\|right |
| bc | cross | primary | yes | |
| fbg | cross | primary | yes | |
| dce | cross | primary | yes | |
| iaj | kross | primary | no | |
When I route I should get
| waypoints | route | turns | lanes | locations |
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
| waypoints | route | turns | lanes | locations |
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
Scenario: Lane Parsing Issue #2694
Given the node map
@@ -1248,4 +1243,4 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes | locations |
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ,;left:true straight:false straight;right:false;;, | a,c,f |
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ;left:false straight:true straight;right:false,left:true straight:false straight;right:false;;, | a,d,f |
+29 -59
View File
@@ -899,9 +899,9 @@ Feature: Simple Turns
"""
And the ways
| nodes | highway | name | lanes |
| abc | primary | road | 3 |
| bd | residential | in | 1 |
| nodes | highway | name |
| abc | primary | road |
| bd | residential | in |
When I route I should get
| waypoints | turns | route |
@@ -964,15 +964,15 @@ Feature: Simple Turns
Given the node map
"""
g
|
_--f-----y
i-' |
j-k-a]|[b---x
e 'c
|'d'
|
f y
i
j k a b x
e c
d
h
|
q
"""
@@ -1373,36 +1373,6 @@ Feature: Simple Turns
| a,d | ab,bcd,bcd | depart,fork slight right,arrive |
| a,g | ab,befg,befg | depart,fork slight left,arrive |
@routing @car
Scenario: No turn instruction when turning from unnamed onto unnamed
Given the node map
"""
a
|
|
|
|
b----------------c
|
|
|
|
|
|
d
"""
And the ways
| nodes | highway | name | ref |
| ab | trunk_link | | |
| db | secondary | | L 460 |
| bc | secondary | | |
When I route I should get
| from | to | route | ref | turns |
| d | c | ,, | L 460,, | depart,turn right,arrive |
| c | d | ,, | ,L 460,L 460 | depart,turn left,arrive |
# https://www.openstreetmap.org/#map=18/52.25130/10.42545
Scenario: Turn for roads with no name, ref changes
Given the node map
@@ -1434,21 +1404,21 @@ Feature: Simple Turns
Scenario: Turn for roads with no name, ref changes
Given the node map
"""
x
.
.
d
. .
. .
. .
e. . t . c . p. .f
. .
. .
. .
b
.
.
a
x
.
.
d
. .
. .
. .
e. . t . c . p. .f
. .
. .
. .
b
.
.
a
"""
And the ways
@@ -1460,6 +1430,6 @@ Feature: Simple Turns
| etcpf | primary | B 1 | | no |
When I route I should get
| waypoints | route | turns |
| e,x | ,, | depart,turn left,arrive |
| f,a | ,, | depart,turn left,arrive |
| waypoints | route | turns |
| e,x | ,,, | depart,turn sharp left,turn right,arrive |
| f,a | ,, | depart,turn left,arrive |
+8 -59
View File
@@ -47,7 +47,7 @@ class OSRMBaseLoader{
if (err) {
if (retryCount < 10) {
retryCount++;
setTimeout(() => { tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry); }, 10);
setTimeout(() => { tryConnect(this.scope.OSRM_PORT, retry); }, 10);
} else {
callback(new Error("Could not connect to osrm-routed after ten retries."));
}
@@ -58,7 +58,7 @@ class OSRMBaseLoader{
}
};
tryConnect(this.scope.OSRM_IP, this.scope.OSRM_PORT, retry);
tryConnect(this.scope.OSRM_PORT, retry);
}
};
@@ -77,54 +77,14 @@ class OSRMDirectLoader extends OSRMBaseLoader {
osrmUp (callback) {
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
const command_arguments = util.format('%s -p %d -i %s -a %s', this.inputFile, this.scope.OSRM_PORT, this.scope.OSRM_IP, this.scope.ROUTING_ALGORITHM);
const command_arguments = util.format('%s -p %d -a %s', this.inputFile, this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
}
};
class OSRMmmapLoader extends OSRMBaseLoader {
constructor (scope) {
super(scope);
}
load (inputFile, callback) {
this.inputFile = inputFile;
this.shutdown(() => {
this.launch(callback);
});
}
osrmUp (callback) {
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
const command_arguments = util.format('%s -p %d -i %s -a %s --mmap', this.inputFile, this.scope.OSRM_PORT, this.scope.OSRM_IP, this.scope.ROUTING_ALGORITHM);
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
callback();
}
};
@@ -147,8 +107,7 @@ class OSRMDatastoreLoader extends OSRMBaseLoader {
}
loadData (callback) {
const command_arguments = util.format('--dataset-name=%s %s', this.scope.DATASET_NAME, this.inputFile);
this.scope.runBin('osrm-datastore', command_arguments, this.scope.environment, (err) => {
this.scope.runBin('osrm-datastore', this.inputFile, this.scope.environment, (err) => {
if (err) return callback(new Error('*** osrm-datastore exited with ' + err.code + ': ' + err));
callback();
});
@@ -157,7 +116,7 @@ class OSRMDatastoreLoader extends OSRMBaseLoader {
osrmUp (callback) {
if (this.osrmIsRunning()) return callback();
const command_arguments = util.format('--dataset-name=%s -s -i %s -p %d -a %s', this.scope.DATASET_NAME, this.scope.OSRM_IP, this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
const command_arguments = util.format('--shared-memory=1 -p %d -a %s', this.scope.OSRM_PORT, this.scope.ROUTING_ALGORITHM);
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
@@ -175,32 +134,22 @@ class OSRMLoader {
this.scope = scope;
this.sharedLoader = new OSRMDatastoreLoader(this.scope);
this.directLoader = new OSRMDirectLoader(this.scope);
this.mmapLoader = new OSRMmmapLoader(this.scope);
this.method = scope.DEFAULT_LOAD_METHOD;
}
load (inputFile, callback) {
if (!this.loader) {
this.loader = {shutdown: (cb) => cb() };
}
if (this.method === 'datastore') {
this.loader.shutdown((err) => {
this.directLoader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.sharedLoader;
this.sharedLoader.load(inputFile, callback);
});
} else if (this.method === 'directly') {
this.loader.shutdown((err) => {
this.sharedLoader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.directLoader;
this.directLoader.load(inputFile, callback);
});
} else if (this.method === 'mmap') {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.mmapLoader;
this.mmapLoader.load(inputFile, callback);
});
} else {
callback(new Error('*** Unknown load method ' + method));
}
+2 -2
View File
@@ -3,8 +3,8 @@
const net = require('net');
const Timeout = require('node-timeout');
module.exports = function tryConnect(host, port, callback) {
net.connect({ port: port, host: host })
module.exports = function tryConnect(port, callback) {
net.connect({ port: port, host: '127.0.0.1' })
.on('connect', () => { callback(); })
.on('error', () => {
callback(new Error('Could not connect.'));
@@ -1,44 +0,0 @@
@datastore @options @help
Feature: osrm-datastore command line options
Background:
Given the profile "testbot"
And the node map
"""
a b
"""
And the ways
| nodes |
| ab |
And the data has been contracted
Scenario: osrm-datastore - Help should be shown when no options are passed
When I try to run "osrm-datastore --dataset-name test_dataset_42 {processed_file}"
Then it should exit successfully
When I try to run "osrm-datastore --list"
Then it should exit successfully
And stdout should contain "test_dataset_42/static"
And stdout should contain "test_dataset_42/updatable"
Scenario: osrm-datastore - Only metric update should work
Given the speed file
"""
0,1,50
"""
And the data has been extracted
When I try to run "osrm-datastore {processed_file} --dataset-name cucumber/only_metric_test"
Then it should exit successfully
When I try to run "osrm-customize --segment-speed-file {speeds_file} {processed_file}"
Then it should exit successfully
When I try to run "osrm-datastore {processed_file} --dataset-name cucumber/only_metric_test --only-metric"
Then it should exit successfully
Scenario: osrm-datastore - Displaying help should work
When I try to run "osrm-datastore {processed_file} --help"
Then it should exit successfully
Scenario: osrm-datastore - Errors on invalid path
When I try to run "osrm-datastore invalid_path.osrm"
Then stderr should contain "[error] Config contains invalid file paths."
And stderr should contain "Missing/Broken"
And it should exit with an error
@@ -152,7 +152,7 @@ Feature: Turn Function Information
And stdout should contain "number_of_roads 3"
And stdout should contain "source_priority_class 4"
And stdout should contain "target_priority_class 0"
And stdout should contain "target_priority_class 10"
And stdout should contain "target_priority_class 11"
# turning abd, give information about bc
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: false, is_outgoing: true, highway_turn_classification: 4, access_turn_classification: 0/
# turning abc, give information about bd
@@ -180,3 +180,7 @@ Feature: Turn Function Information
And stdout should contain /roads_on_the_right \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 3, access_turn_classification: 0/
# turning abc, give information about about db
And stdout should contain /roads_on_the_left \[1\] speed: [0-9]+, is_incoming: true, is_outgoing: false, highway_turn_classification: 0, access_turn_classification: 1/
+60 -74
View File
@@ -1,88 +1,74 @@
var util = require('util');
module.exports = function () {
const durationsRegex = new RegExp(/^I request a travel time matrix I should get$/);
const distancesRegex = new RegExp(/^I request a travel distance matrix I should get$/);
this.When(/^I request a travel time matrix I should get$/, (table, callback) => {
var NO_ROUTE = 2147483647; // MAX_INT
const DURATIONS_NO_ROUTE = 2147483647; // MAX_INT
const DISTANCES_NO_ROUTE = 3.40282e+38; // MAX_FLOAT
var tableRows = table.raw();
this.When(durationsRegex, function(table, callback) {tableParse.call(this, table, DURATIONS_NO_ROUTE, 'durations', callback);}.bind(this));
this.When(distancesRegex, function(table, callback) {tableParse.call(this, table, DISTANCES_NO_ROUTE, 'distances', callback);}.bind(this));
};
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
const durationsParse = function(v) { return isNaN(parseInt(v)); };
const distancesParse = function(v) { return isNaN(parseFloat(v)); };
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
function tableParse(table, noRoute, annotation, callback) {
const parse = annotation == 'distances' ? distancesParse : durationsParse;
const params = this.queryParams;
params.annotations = annotation == 'distances' ? 'distance' : 'duration';
var tableRows = table.raw();
if (tableRows[0][0] !== '') throw new Error('*** Top-left cell of matrix table must be empty');
var waypoints = [],
columnHeaders = tableRows[0].slice(1),
rowHeaders = tableRows.map((h) => h[0]).slice(1),
symmetric = columnHeaders.length == rowHeaders.length && columnHeaders.every((ele, i) => ele === rowHeaders[i]);
if (symmetric) {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'loc' });
});
} else {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'dst' });
});
rowHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'src' });
});
}
var actual = [];
actual.push(table.headers);
this.reprocessAndLoadData((e) => {
if (e) return callback(e);
// compute matrix
this.requestTable(waypoints, params, (err, response) => {
if (err) return callback(err);
if (!response.body.length) return callback(new Error('Invalid response body'));
var json = JSON.parse(response.body);
var result = json[annotation].map(row => {
var hashes = {};
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = parse(v) ? '' : v; });
return hashes;
if (symmetric) {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'loc' });
});
} else {
columnHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'dst' });
});
rowHeaders.forEach((nodeName) => {
var node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown node "%s"', nodeName));
waypoints.push({ coord: node, type: 'src' });
});
}
var testRow = (row, ri, cb) => {
for (var k in result[ri]) {
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
result[ri][k] = row[k];
} else if (row[k] === '' && result[ri][k] === noRoute) {
result[ri][k] = '';
} else {
result[ri][k] = result[ri][k].toString();
var actual = [];
actual.push(table.headers);
this.reprocessAndLoadData((e) => {
if (e) return callback(e);
// compute matrix
var params = this.queryParams;
this.requestTable(waypoints, params, (err, response) => {
if (err) return callback(err);
if (!response.body.length) return callback(new Error('Invalid response body'));
var json = JSON.parse(response.body);
var result = json['durations'].map(row => {
var hashes = {};
row.forEach((v, i) => { hashes[tableRows[0][i+1]] = isNaN(parseInt(v)) ? '' : v; });
return hashes;
});
var testRow = (row, ri, cb) => {
for (var k in result[ri]) {
if (this.FuzzyMatch.match(result[ri][k], row[k])) {
result[ri][k] = row[k];
} else if (row[k] === '' && result[ri][k] === NO_ROUTE) {
result[ri][k] = '';
} else {
result[ri][k] = result[ri][k].toString();
}
}
}
result[ri][''] = row[''];
cb(null, result[ri]);
};
result[ri][''] = row[''];
cb(null, result[ri]);
};
this.processRowsAndDiff(table, testRow, callback);
this.processRowsAndDiff(table, testRow, callback);
});
});
});
}
};
+1 -7
View File
@@ -21,8 +21,7 @@ module.exports = {
matchRe = want.match(/^\/(.*)\/$/),
// we use this for matching before/after bearing
matchBearingListAbs = want.match(/^((\d+)->(\d+))(,(\d+)->(\d+))*\s+\+\-(.+)$/),
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/),
matchRangeNumbers = want.match(/\d+\+\-\d+/);
matchIntersectionListAbs = want.match(/^(((((true|false):\d+)\s{0,1})+,{0,1})+;{0,1})+\s+\+\-(.+)$/);
function inRange(margin, got, want) {
var fromR = parseFloat(want) - margin,
@@ -106,11 +105,6 @@ module.exports = {
return inRange(margin, got, matchAbs[1]);
} else if (matchRe) { // regex: /a,b,.*/
return got.match(matchRe[1]);
} else if (matchRangeNumbers) {
let real_want_and_margin = want.split('+-'),
margin = parseFloat(real_want_and_margin[1].trim()),
real_want = parseFloat(real_want_and_margin[0].trim());
return inRange(margin, got, real_want);
} else {
return false;
}
+4 -6
View File
@@ -27,12 +27,11 @@ module.exports = function () {
return callback(new Error('*** '+stxxl_config+ 'does not exist'));
}
this.DATASET_NAME = 'cucumber';
this.PLATFORM_WINDOWS = process.platform.match(/^win.*/);
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
this.DEFAULT_PROFILE = 'bicycle';
this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_LOAD_METHOD = process.argv[process.argv.indexOf('-m') +1].match('mmap') ? 'mmap' : 'datastore';
this.DEFAULT_LOAD_METHOD = 'datastore';
this.DEFAULT_ORIGIN = [1,1];
this.OSM_USER = 'osrm';
this.OSM_UID = 1;
@@ -44,8 +43,7 @@ module.exports = function () {
this.TIMEZONE_NAMES = this.PLATFORM_WINDOWS ? 'win' : 'iana';
this.OSRM_PORT = process.env.OSRM_PORT && parseInt(process.env.OSRM_PORT) || 5000;
this.OSRM_IP = process.env.OSRM_IP || '127.0.0.1';
this.HOST = `http://${this.OSRM_IP}:${this.OSRM_PORT}`;
this.HOST = 'http://127.0.0.1:' + this.OSRM_PORT;
this.OSRM_PROFILE = process.env.OSRM_PROFILE;
@@ -80,7 +78,7 @@ module.exports = function () {
// eslint-disable-next-line no-console
console.info(util.format('Node Version', process.version));
if (parseInt(process.version.match(/v(\d+)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
if (parseInt(process.version.match(/v(\d)/)[1]) < 4) throw new Error('*** Please upgrade to Node 4.+ to run OSRM cucumber tests');
fs.exists(this.TEST_PATH, (exists) => {
if (exists)
@@ -95,7 +93,7 @@ module.exports = function () {
};
this.verifyOSRMIsNotRunning = (callback) => {
tryConnect(this.OSRM_IP, this.OSRM_PORT, (err) => {
tryConnect(this.OSRM_PORT, (err) => {
if (!err) return callback(new Error('*** osrm-routed is already running.'));
else callback();
});
+1 -1
View File
@@ -51,7 +51,7 @@ module.exports = function () {
.defer(rimraf, this.scenarioLogFile)
.awaitAll(callback);
// uncomment to get path to logfile
// console.log(' Writing logging output to ' + this.scenarioLogFile);
// console.log(" Writing logging output to " + this.scenarioLogFile)
});
this.After((scenario, callback) => {
+2 -14
View File
@@ -199,26 +199,14 @@ module.exports = function () {
var merged = {};
instructions.legs.map(l => {
Object.keys(l.annotation).filter(a => !a.match(/metadata/)).forEach(a => {
Object.keys(l.annotation).forEach(a => {
if (!merged[a]) merged[a] = [];
merged[a].push(l.annotation[a].join(':'));
});
if (l.annotation.metadata) {
merged.metadata = {};
Object.keys(l.annotation.metadata).forEach(a => {
if (!merged.metadata[a]) merged.metadata[a] = [];
merged.metadata[a].push(l.annotation.metadata[a].join(':'));
});
}
});
Object.keys(merged).filter(k => !k.match(/metadata/)).map(a => {
Object.keys(merged).map(a => {
merged[a] = merged[a].join(',');
});
if (merged.metadata) {
Object.keys(merged.metadata).map(a => {
merged.metadata[a] = merged.metadata[a].join(',');
});
}
return merged;
};
+1 -9
View File
@@ -158,8 +158,7 @@ module.exports = function () {
// if header matches 'a:*', parse out the values for *
// and return in that header
headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed' ];
let metadata_whitelist = [ 'datasource_names' ];
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) {
let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1)
@@ -167,13 +166,6 @@ module.exports = function () {
if (annotation && !annotation[a_type])
return cb(new Error('Annotation not found in response', a_type));
got[k] = annotation && annotation[a_type] || '';
} else if (k.match(/^am:/)) {
let a_type = k.slice(3);
if (metadata_whitelist.indexOf(a_type) == -1)
return cb(new Error('Unrecognized annotation field', a_type));
if (annotation && (!annotation.metadata || !annotation.metadata[a_type]))
return cb(new Error('Annotation not found in response', a_type));
got[k] = (annotation && annotation.metadata && annotation.metadata[a_type]) || '';
}
});
-8
View File
@@ -4,14 +4,6 @@ Feature: Alternative route
Background:
Given the profile "testbot"
And a grid size of 200 meters
# Force data preparation to single-threaded to ensure consistent
# results for alternative generation during tests (alternative
# finding is highly sensitive to graph shape, which is in turn
# affected by parallelism during generation)
And the contract extra arguments "--threads 1"
And the extract extra arguments "--threads 1"
And the customize extra arguments "--threads 1"
And the partition extra arguments "--threads 1"
And the node map
"""
@@ -4,14 +4,6 @@ Feature: Alternative route
Background:
Given the profile "testbot"
Given a grid size of 200 meters
# Force data preparation to single-threaded to ensure consistent
# results for alternative generation during tests (alternative
# finding is highly sensitive to graph shape, which is in turn
# affected by parallelism during generation)
And the contract extra arguments "--threads 1"
And the extract extra arguments "--threads 1"
And the customize extra arguments "--threads 1"
And the partition extra arguments "--threads 1"
Scenario: Alternative Loop Paths
Given the node map
-33
View File
@@ -60,39 +60,6 @@ Feature: Annotations
| a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 |
| i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 |
Scenario: datasource name annotations
Given the profile "testbot"
And the node map
"""
a b c
"""
And the ways
| nodes |
| abc |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,180,1
2,1,180,1
"""
And the query options
| annotations | datasources |
# Note - the source names here are specific to how the tests are constructed,
# so if this test is moved around (changes line number) or support code
# changes how the filenames are generated, this test will need to be updated
When I route I should get
| from | to | route | am:datasource_names |
| a | c | abc,abc | lua profile:63_datasource_name_annotations_speeds |
| c | a | abc,abc | lua profile:63_datasource_name_annotations_speeds |
Scenario: Speed annotations should handle zero segments
Given the profile "testbot"
-88
View File
@@ -74,7 +74,6 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
###############
# Oneway Test #
###############
@@ -227,90 +226,3 @@ Feature: Approach parameter
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
#######################
# Left-side countries #
#######################
Scenario: [Left-hand-side] Start End same approach, option unrestricted for Start and End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: [Left-hand-side] Start End same approach, option unrestricted for Start and curb for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: [Left-hand-side] Start End opposite approach, option unrestricted for Start and End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: [Left-hand-side] Start End opposite approach, option unrestricted for Start and curb for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
+9 -9
View File
@@ -108,12 +108,12 @@ Feature: Bearing parameter
| ha | yes | ring |
When I route I should get
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,0->90,90->0 |
| 0 | a | 45 90 | jb,ring,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,0->90,90->0 |
| 0 | q | 90 90 | kc,ring,ring,ring,ring | 0->90,90->180,270->0,0->90,90->0 |
| 0 | a | 135 90 | ld,ring,ring,ring,ring | 0->135,135->270,270->0,0->90,90->0 |
| 0 | a | 180 90 | me,ring,ring,ring,ring | 0->180,180->270,270->0,0->90,90->0 |
| 0 | a | 225 90 | nf,ring,ring,ring | 0->225,225->0,0->90,90->0 |
| 0 | a | 270 90 | og,ring,ring,ring | 0->270,270->0,0->90,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
| from | to | bearings | route | bearing |
| 0 | q | 0 90 | ia,ring,ring,ring,ring | 0->0,0->90,180->270,270->0,90->0 |
| 0 | a | 45 90 | jb,ring,ring,ring,ring | 0->45,45->180,180->270,270->0,90->0 |
| 0 | q | 90 90 | kc,ring,ring,ring | 0->90,90->180,270->0,90->0 |
| 0 | a | 135 90 | ld,ring,ring,ring | 0->135,135->270,270->0,90->0 |
| 0 | a | 180 90 | me,ring,ring,ring | 0->180,180->270,270->0,90->0 |
| 0 | a | 225 90 | nf,ring,ring | 0->225,225->0,90->0 |
| 0 | a | 270 90 | og,ring,ring | 0->270,270->0,90->0 |
| 0 | a | 315 90 | ph,ring,ring | 0->315,315->90,90->0 |
-19
View File
@@ -226,22 +226,3 @@ Feature: Distance calculation
| x | v | xv,xv | 424m +-1 |
| x | w | xw,xw | 360m +-1 |
| x | y | xy,xy | 316m +-1 |
# Check rounding errors
Scenario: Distances Long distances
Given a grid size of 1000 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes |
| abcd |
When I route I should get
| from | to | distance |
| a | b | 1000m +-3 |
| a | c | 2000m +-3 |
| a | d | 3000m +-3 |
+180 -472
View File
@@ -1,142 +1,29 @@
@matrix @testbot
Feature: Basic Distance Matrix
# note that results of travel distance are in metres
# note that results are travel time, specified in 1/10th of seconds
# since testbot uses a default speed of 100m/10s, the result matches
# the number of meters as long as the way type is the default 'primary'
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel distance matrix of small grid
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
"""
a b c
d e f
a b
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
| ab |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network exact distances
Given the node map
"""
a z
b
c
d
"""
And the ways
| nodes |
| az |
| zbcd |
When I request a travel distance matrix I should get
| | a | z | b | c | d |
| a | 0 | 100.1 | 199.5 | 298.9 | 398.3 |
| z | 100.1 | 0 | 99.4 | 198.8 | 298.2 |
| b | 199.5 | 99.4 | 0 | 99.4 | 198.8 |
| c | 298.9 | 198.8 | 99.4 | 0 | 99.4 |
| d | 398.3 | 298.2 | 198.8 | 99.4 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network with toll exclude
Given the query options
| exclude | toll |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | primary | yes | not drivable for exclude=toll and exclude=motorway,toll |
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | | |
| b | 100.1 | 0 | | |
| c | | | 0 | 100.1 |
| d | | | 100.1 | 0 |
Scenario: Testbot - Travel distance matrix of minimal network with motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | # |
| ab | motorway | not drivable for exclude=motorway |
| cd | residential | |
| ac | residential | |
| bd | residential | |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 298.9 | 99.4 | 199.5 |
Scenario: Testbot - Travel distance matrix of minimal network disconnected motorway exclude
Given the query options
| exclude | motorway |
And the extract extra arguments "--small-component-size 4"
Given the node map
"""
ab efgh
cd
"""
And the ways
| nodes | highway | # |
| be | motorway | not drivable for exclude=motorway |
| abcd | residential | |
| efgh | residential | |
When I request a travel distance matrix I should get
| | a | b | e |
| a | 0 | 50.1 | |
Scenario: Testbot - Travel distance matrix of minimal network with motorway and toll excludes
Given the query options
| exclude | motorway,toll |
Given the node map
"""
a b e f
c d g h
"""
And the ways
| nodes | highway | toll | # |
| be | motorway | | not drivable for exclude=motorway |
| dg | primary | yes | not drivable for exclude=toll |
| abcd | residential | | |
| efgh | residential | | |
When I request a travel distance matrix I should get
| | a | b | e | g |
| a | 0 | 100.1 | | |
Scenario: Testbot - Travel distance matrix with different way speeds
Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a b c d
@@ -148,25 +35,40 @@ Feature: Basic Distance Matrix
| bc | secondary |
| cd | tertiary |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 |
| b | 100.1 | 0 | 100.1 | 200.1 |
| c | 200.1 | 100.1 | 0 | 100.1 |
| d | 300.2 | 200.1 | 100.1 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
| b | 10 | 0 | 20 | 50 |
| c | 30 | 20 | 0 | 30 |
| d | 60 | 50 | 30 | 0 |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 100.1 | 200.1 | 300.2 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 100.1 |
| c | 200.1 |
| d | 300.2 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| c | 30 |
| d | 60 |
Scenario: Testbot - Travel distance matrix of small grid
Scenario: Testbot - Travel time matrix with fuzzy match
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
Scenario: Testbot - Travel time matrix of small grid
Given the node map
"""
a b c
@@ -181,14 +83,14 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel distance matrix of network with unroutable parts
Scenario: Testbot - Travel time matrix of network with unroutable parts
Given the node map
"""
a b
@@ -198,12 +100,12 @@ Feature: Basic Distance Matrix
| nodes | oneway |
| ab | yes |
When I request a travel distance matrix I should get
| | a | b |
| a | 0 | 100.1 |
| b | | 0 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | | 0 |
Scenario: Testbot - Travel distance matrix of network with oneways
Scenario: Testbot - Travel time matrix of network with oneways
Given the node map
"""
x a b y
@@ -216,14 +118,14 @@ Feature: Basic Distance Matrix
| xa | |
| by | |
When I request a travel distance matrix I should get
| | x | y | d | e |
| x | 0 | 300.2 | 399.6 | 299.5 |
| y | 499 | 0 | 299.5 | 199.5 |
| d | 199.5 | 299.5 | 0 | 298.9 |
| e | 299.5 | 399.6 | 100.1 | 0 |
When I request a travel time matrix I should get
| | x | y | d | e |
| x | 0 | 30 | 40 | 30 |
| y | 50 | 0 | 30 | 20 |
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel distance matrix
Scenario: Testbot - Rectangular travel time matrix
Given the node map
"""
a b c
@@ -238,57 +140,51 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I route I should get
| from | to | distance |
| e | a | 200m |
| e | b | 100m |
| f | a | 299.9m |
| f | b | 200m |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 10 |
| e | 20 |
| f | 30 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 100.1 |
| e | 199.5 |
| f | 299.5 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel distance matrix I should get
| | a | b |
| a | 0 | 100.1 |
| b | 100.1 | 0 |
| e | 199.5 | 99.4 |
| f | 299.5 | 199.5 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 10 | 20 |
| b | 10 | 0 | 10 |
| e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel distance matrix I should get
| | a | b | e |
| a | 0 | 100.1 | 199.5 |
| b | 100.1 | 0 | 99.4 |
| e | 199.5 | 99.4 | 0 |
| f | 299.5 | 199.5 | 100.1 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
When I request a travel distance matrix I should get
| | a | b | e | f |
| a | 0 | 100.1 | 199.5 | 299.5 |
| b | 100.1 | 0 | 99.4 | 199.5 |
| e | 199.5 | 99.4 | 0 | 100.1 |
| f | 299.5 | 199.5 | 100.1 | 0 |
Scenario: Testbot - Travel distance 3x2 matrix
Scenario: Testbot - Travel time 3x2 matrix
Given the node map
"""
a b c
@@ -303,11 +199,10 @@ Feature: Basic Distance Matrix
| be |
| cf |
When I request a travel distance matrix I should get
| | b | e | f |
| a | 100.1 | 199.5 | 299.5 |
| b | 0 | 99.4 | 199.5 |
When I request a travel time matrix I should get
| | b | e | f |
| a | 10 | 20 | 30 |
| b | 0 | 10 | 20 |
Scenario: Testbot - All coordinates are from same small component
Given a grid size of 300 meters
@@ -326,10 +221,10 @@ Feature: Basic Distance Matrix
| da |
| fg |
When I request a travel distance matrix I should get
| | f | g |
| f | 0 | 298.2 |
| g | 298.2 | 0 |
When I request a travel time matrix I should get
| | f | g |
| f | 0 | 30 |
| g | 30 | 0 |
Scenario: Testbot - Coordinates are from different small component and snap to big CC
Given a grid size of 300 meters
@@ -349,25 +244,14 @@ Feature: Basic Distance Matrix
| fg |
| hi |
When I route I should get
| from | to | distance |
| f | g | 300m |
| f | i | 300m |
| g | f | 300m |
| g | h | 300m |
| h | g | 300m |
| h | i | 300m |
| i | f | 300m |
| i | h | 300m |
When I request a travel time matrix I should get
| | f | g | h | i |
| f | 0 | 30 | 0 | 30 |
| g | 30 | 0 | 30 | 0 |
| h | 0 | 30 | 0 | 30 |
| i | 30 | 0 | 30 | 0 |
When I request a travel distance matrix I should get
| | f | g | h | i |
| f | 0 | 298.2 | 0 | 298.2 |
| g | 298.2 | 0 | 298.2 | 0 |
| h | 0 | 298.2 | 0 | 298.2 |
| i | 298.2 | 0 | 298.2 | 0 |
Scenario: Testbot - Travel distance matrix with loops
Scenario: Testbot - Travel time matrix with loops
Given the node map
"""
a 1 2 b
@@ -381,15 +265,14 @@ Feature: Basic Distance Matrix
| cd | yes |
| da | yes |
When I request a travel distance matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 100.1 | 399.6 | 499.7 |
| 2 | 699.1 | 0 | 299.5 | 399.6 |
| 3 | 399.6 | 499.7 | 0 | 100.1 |
| 4 | 299.5 | 399.6 | 699.1 | 0 |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
Scenario: Testbot - Travel distance matrix based on segment durations
Scenario: Testbot - Travel time matrix based on segment durations
Given the profile file
"""
local functions = require('testbot')
@@ -418,19 +301,20 @@ Feature: Basic Distance Matrix
"""
And the ways
| nodes |
| abcd |
| ce |
| nodes |
| abcd |
| ce |
When I request a travel distance matrix I should get
| | a | b | c | d | e |
| a | 0 | 100.1 | 200.1 | 300.2 | 398.9 |
| b | 100.1 | 0 | 100.1 | 200.1 | 298.9 |
| c | 200.1 | 100.1 | 0 | 100.1 | 198.8 |
| d | 300.2 | 200.1 | 100.1 | 0 | 298.9 |
| e | 398.9 | 298.9 | 198.8 | 298.9 | 0 |
When I request a travel time matrix I should get
| | a | b | c | d | e |
| a | 0 | 11 | 22 | 33 | 33 |
| b | 11 | 0 | 11 | 22 | 22 |
| c | 22 | 11 | 0 | 11 | 11 |
| d | 33 | 22 | 11 | 0 | 22 |
| e | 33 | 22 | 11 | 22 | 0 |
Scenario: Testbot - Travel distance matrix for alternative loop paths
Scenario: Testbot - Travel time matrix for alternative loop paths
Given the profile file
"""
local functions = require('testbot')
@@ -466,238 +350,62 @@ Feature: Basic Distance Matrix
| dc | yes |
| ca | yes |
When I request a travel distance matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 1096.7 | 298.9 | 199.5 | 598.4 | 498.3 | 897.3 | 797.9 |
| 2 | 100.1 | 0 | 398.9 | 299.5 | 698.5 | 598.4 | 997.3 | 897.9 |
| 3 | 897.9 | 797.9 | 0 | 1097.4 | 299.5 | 199.5 | 598.4 | 499 |
| 4 | 997.3 | 897.3 | 99.4 | 0 | 398.9 | 298.9 | 697.8 | 598.4 |
| 5 | 598.4 | 498.3 | 897.3 | 797.9 | 0 | 1096.7 | 298.9 | 199.5 |
| 6 | 698.5 | 598.4 | 997.3 | 897.9 | 100.1 | 0 | 398.9 | 299.5 |
| 7 | 299.5 | 199.5 | 598.4 | 499 | 897.9 | 797.9 | 0 | 1097.4 |
| 8 | 398.9 | 298.9 | 697.8 | 598.4 | 997.3 | 897.3 | 99.4 | 0 |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 8 | 4.1 | 3.1 | 7.1 | 6.1 | 10.1 | 9.1 | 1 | 0 |
When I request a travel distance matrix I should get
| | 1 |
| 1 | 0 |
| 2 | 100.1 |
| 3 | 897.9 |
| 4 | 997.3 |
| 5 | 598.4 |
| 6 | 698.5 |
| 7 | 299.5 |
| 8 | 398.9 |
Scenario: Testbot - Travel distance matrix with ties
Given the node map
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
a b
c d
"""
And the ways
| nodes |
| ab |
| ac |
| bd |
| dc |
| nodes |
| ab |
| ac |
| bd |
| dc |
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 20s | 20 |
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
When I route I should get
| from | to | route | distance |
| a | b | ab,ab | 450m |
| a | c | ac,ac | 200m |
| a | d | ac,dc,dc | 499.9m |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 450.3 | 198.8 | 499 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 450.3 |
| c | 198.8 |
| d | 499 |
When I request a travel distance matrix I should get
| | a | c |
| a | 0 | 198.8 |
| c | 198.8 | 0 |
# Check rounding errors
Scenario: Testbot - Long distances in tables
Given a grid size of 1000 meters
Given the node map
"""
a b c d
"""
And the ways
| nodes |
| abcd |
When I request a travel distance matrix I should get
| | a | b | c | d |
| a | 0 | 1000.7 | 2001.4 | 3002.1 |
Scenario: Testbot - OneToMany vs ManyToOne
Given the node map
"""
a b
c
"""
And the ways
| nodes | oneway |
| ab | yes |
| ac | |
| bc | |
When I request a travel distance matrix I should get
| | a | b |
| b | 240.4 | 0 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 240.4 |
Scenario: Testbot - Varying distances between nodes
Given the node map
"""
a b c d
e
f
"""
And the ways
| nodes | oneway |
| feabcd | yes |
| ec | |
| fd | |
When I request a travel distance matrix I should get
| | a | b | c | d | e | f |
| a | 0 | 100.1 | 300.2 | 650.5 | 1930.6 | 1533 |
| b | 759 | 0 | 200.1 | 550.4 | 1830.5 | 1432.9 |
| c | 558.8 | 658.9 | 0 | 350.3 | 1630.4 | 1232.8 |
| d | 1478.9 | 1579 | 1779.1 | 0 | 1280.1 | 882.5 |
| e | 198.8 | 298.9 | 499 | 710.3 | 0 | 1592.8 |
| f | 596.4 | 696.5 | 896.6 | 1107.9 | 397.6 | 0 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1501.1 |
Scenario: Testbot - Fise input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
| b | 300.2 | 0 | 600.5 | 1200.9 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1501.1 | 1200.9 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1501.1 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1501.1 |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
| b | 300.2 | 0 | 600.5 | 900.7 |
| f | 900.7 | 600.5 | 0 | 302.2 |
| 1 | 1200.9 | 900.7 | 300.2 | 0 |
When I request a travel distance matrix I should get
| | a | b | f | 1 |
| a | 0 | 300.2 | 900.7 | 1200.9 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| b | 300.2 |
| f | 900.7 |
| 1 | 1200.9 |
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 |
-704
View File
@@ -1,704 +0,0 @@
@matrix @testbot
Feature: Basic Duration Matrix
# note that results of travel time are in seconds
Background:
Given the profile "testbot"
And the partition extra arguments "--small-component-size 1 --max-cell-sizes 2,4,8,16"
Scenario: Testbot - Travel time matrix of minimal network
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
@ch
Scenario: Testbot - Travel time matrix of minimal network with toll exclude
Given the query options
| exclude | toll |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | toll | # |
| ab | motorway | | not drivable for exclude=motorway |
| cd | primary | | always drivable |
| ac | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
| bd | motorway | yes | not drivable for exclude=toll and exclude=motorway,toll |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 15 | | |
| b | 15 | 0 | | |
| c | | | 0 | 10 |
| d | | | 10 | 0 |
@ch
Scenario: Testbot - Travel time matrix of minimal network with motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
a b
c d
"""
And the ways
| nodes | highway | # |
| ab | motorway | not drivable for exclude=motorway |
| cd | residential | |
| ac | residential | |
| bd | residential | |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 45 | 15 | 30 |
@ch
Scenario: Testbot - Travel time matrix of minimal network disconnected motorway exclude
Given the query options
| exclude | motorway |
Given the node map
"""
ab efgh
cd
"""
And the ways
| nodes | highway | # |
| be | motorway | not drivable for exclude=motorway |
| abcd | residential | |
| efgh | residential | |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 7.5 | |
@ch
Scenario: Testbot - Travel time matrix of minimal network with motorway and toll excludes
Given the query options
| exclude | motorway,toll |
Given the node map
"""
a b e f
c d g h
"""
And the ways
| nodes | highway | toll | # |
| be | motorway | | not drivable for exclude=motorway |
| dg | primary | yes | not drivable for exclude=toll |
| abcd | residential | | |
| efgh | residential | | |
When I request a travel time matrix I should get
| | a | b | e | g |
| a | 0 | 15 | | |
Scenario: Testbot - Travel time matrix with different way speeds
Given the node map
"""
a b c d
"""
And the ways
| nodes | highway |
| ab | primary |
| bc | secondary |
| cd | tertiary |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 10 | 30 | 60 |
| b | 10 | 0 | 20 | 50 |
| 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 of small grid
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel time matrix of network with unroutable parts
Given the node map
"""
a b
"""
And the ways
| nodes | oneway |
| ab | yes |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | | 0 |
Scenario: Testbot - Travel time matrix of network with oneways
Given the node map
"""
x a b y
d e
"""
And the ways
| nodes | oneway |
| abeda | yes |
| xa | |
| by | |
When I request a travel time matrix I should get
| | x | y | d | e |
| x | 0 | 30 | 40 | 30 |
| y | 50 | 0 | 30 | 20 |
| d | 20 | 30 | 0 | 30 |
| e | 30 | 40 | 10 | 0 |
Scenario: Testbot - Rectangular travel time matrix
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | 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 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 10 |
| b | 10 | 0 |
| e | 20 | 10 |
| f | 30 | 20 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
When I request a travel time matrix I should get
| | a | b | e |
| a | 0 | 10 | 20 |
| b | 10 | 0 | 10 |
| e | 20 | 10 | 0 |
| f | 30 | 20 | 10 |
When I request a travel time matrix I should get
| | a | b | e | f |
| a | 0 | 10 | 20 | 30 |
| b | 10 | 0 | 10 | 20 |
| e | 20 | 10 | 0 | 10 |
| f | 30 | 20 | 10 | 0 |
Scenario: Testbot - Travel time 3x2 matrix
Given the node map
"""
a b c
d e f
"""
And the ways
| nodes |
| abc |
| def |
| ad |
| be |
| cf |
When I request a travel time matrix I should get
| | b | e | f |
| a | 10 | 20 | 30 |
| b | 0 | 10 | 20 |
Scenario: Testbot - All coordinates are from same small component
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the node map
"""
a b f
d e g
"""
And the ways
| nodes |
| ab |
| be |
| ed |
| da |
| fg |
When I request a travel time matrix I should get
| | f | g |
| f | 0 | 30 |
| g | 30 | 0 |
Scenario: Testbot - Coordinates are from different small component and snap to big CC
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the node map
"""
a b f h
d e g i
"""
And the ways
| nodes |
| ab |
| be |
| ed |
| da |
| fg |
| hi |
When I request a travel time matrix I should get
| | f | g | h | i |
| f | 0 | 30 | 0 | 30 |
| g | 30 | 0 | 30 | 0 |
| h | 0 | 30 | 0 | 30 |
| i | 30 | 0 | 30 | 0 |
Scenario: Testbot - Travel time matrix with loops
Given the node map
"""
a 1 2 b
d 4 3 c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
| cd | yes |
| da | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 |
| 1 | 0 | 10 +-1 | 40 +-1 | 50 +-1 |
| 2 | 70 +-1 | 0 | 30 +-1 | 40 +-1 |
| 3 | 40 +-1 | 50 +-1 | 0 | 10 +-1 |
| 4 | 30 +-1 | 40 +-1 | 70 +-1 | 0 |
Scenario: Testbot - Travel time matrix based on segment durations
Given the profile file
"""
local functions = require('testbot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.traffic_signal_penalty = 0
profile.u_turn_penalty = 0
return profile
end
functions.process_segment = function(profile, segment)
segment.weight = 2
segment.duration = 11
end
return functions
"""
And the node map
"""
a-b-c-d
.
e
"""
And the ways
| nodes |
| abcd |
| ce |
When I request a travel time matrix I should get
| | a | b | c | d | e |
| a | 0 | 11 | 22 | 33 | 33 |
| b | 11 | 0 | 11 | 22 | 22 |
| c | 22 | 11 | 0 | 11 | 11 |
| d | 33 | 22 | 11 | 0 | 22 |
| e | 33 | 22 | 11 | 22 | 0 |
Scenario: Testbot - Travel time matrix for alternative loop paths
Given the profile file
"""
local functions = require('testbot')
functions.setup_testbot = functions.setup
functions.setup = function()
local profile = functions.setup_testbot()
profile.traffic_signal_penalty = 0
profile.u_turn_penalty = 0
profile.weight_precision = 3
return profile
end
functions.process_segment = function(profile, segment)
segment.weight = 777
segment.duration = 3
end
return functions
"""
And the node map
"""
a 2 1 b
7 4
8 3
c 5 6 d
"""
And the ways
| nodes | oneway |
| ab | yes |
| bd | yes |
| dc | yes |
| ca | yes |
When I request a travel time matrix I should get
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 1 | 0 | 11 | 3 | 2 | 6 | 5 | 8.9 | 7.9 |
| 2 | 1 | 0 | 4 | 3 | 7 | 6 | 9.9 | 8.9 |
| 3 | 9 | 8 | 0 | 11 | 3 | 2 | 5.9 | 4.9 |
| 4 | 10 | 9 | 1 | 0 | 4 | 3 | 6.9 | 5.9 |
| 5 | 6 | 5 | 9 | 8 | 0 | 11 | 2.9 | 1.9 |
| 6 | 7 | 6 | 10 | 9 | 1 | 0 | 3.9 | 2.9 |
| 7 | 3.1 | 2.1 | 6.1 | 5.1 | 9.1 | 8.1 | 0 | 11 |
| 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 |
Scenario: Testbot - OneToMany vs ManyToOne
Given the node map
"""
a b
c
"""
And the ways
| nodes | oneway |
| ab | yes |
| ac | |
| bc | |
When I request a travel time matrix I should get
| | a | b |
| b | 24.1 | 0 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 24.1 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 30 |
Scenario: Testbot - Filling in noroutes with estimates - use input coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | input |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
| b | 30 | 0 | 12 | 24 |
| f | 18 | 12 | 0 | 30 |
| 1 | 30 | 24 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 30 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 30 |
Scenario: Testbot - Filling in noroutes with estimates - use snapped coordinate
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 24 |
| b | 30 | 0 | 12 | 18 |
| f | 18 | 12 | 0 | 30 |
| 1 | 24 | 18 | 30 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 30 | 18 | 24 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 30 |
| f | 18 |
| 1 | 24 |
Scenario: Testbot - Travel time matrix of minimal network with scale factor
Given the query options
| scale_factor | 2 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 20 |
| b | 20 | 0 |
Scenario: Testbot - Test fallback speeds and scale factor
Given a grid size of 300 meters
Given the extract extra arguments "--small-component-size 4"
Given the query options
| scale_factor | 2 |
| fallback_speed | 5 |
| fallback_coordinate | snapped |
Given the node map
"""
a b f h 1
d e g i
"""
And the ways
| nodes |
| abeda |
| fhigf |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 60 | 36 | 48 |
| b | 60 | 0 | 24 | 36 |
| f | 36 | 24 | 0 | 60 |
| 1 | 48 | 36 | 60 | 0 |
When I request a travel time matrix I should get
| | a | b | f | 1 |
| a | 0 | 60 | 36 | 48 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 60 |
| f | 36 |
| 1 | 48 |
Scenario: Testbot - Travel time matrix of minimal network with overflow scale factor
Given the query options
| scale_factor | 2147483647 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 214748364.6 |
| b | 214748364.6 | 0 |
Scenario: Testbot - Travel time matrix of minimal network with fraction scale factor
Given the query options
| scale_factor | 0.5 |
Given the node map
"""
a b
"""
And the ways
| nodes |
| ab |
When I request a travel time matrix I should get
| | a | b |
| a | 0 | 5 |
| b | 5 | 0 |
+2 -61
View File
@@ -39,64 +39,5 @@ Feature: Fixed bugs, kept to check for regressions
| de | yes |
When I route I should get
| from | to | route |
| 1 | 2 | bcd,bcd |
#############################
# This test models the OSM map at the location for
# https://github.com/Project-OSRM/osrm-backend/issues/5039
#############################
Scenario: Mixed Entry and Exit and segregated
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
Given the node locations
| node | lon | lat |
| a | 171.12889297029 | -42.58425289548 |
| b | 171.1299357 | -42.5849295 |
| c | 171.1295427 | -42.5849385 |
| d | 171.1297356 | -42.5852029 |
| e | 171.1296909 | -42.5851986 |
| f | 171.1295097 | -42.585007 |
| g | 171.1298225 | -42.5851928 |
| h | 171.1300262 | -42.5859122 |
| i | 171.1292651 | -42.584698 |
| j | 171.1297209 | -42.5848569 |
| k | 171.1297188 | -42.5854056 |
| l | 171.1298326 | -42.5857266 |
| m | 171.1298871 | -42.5848922 |
| n | 171.1296505 | -42.585189 |
| o | 171.1295206 | -42.5850862 |
| p | 171.1296106 | -42.5848862 |
| q | 171.1299784 | -42.5850191 |
| r | 171.1298867 | -42.5851671 |
| s | 171.1306955 | -42.5845812 |
| t | 171.129525 | -42.584807 |
| u | 171.1299705 | -42.584984 |
| v | 171.1299067 | -42.5849073 |
| w | 171.1302061 | -42.5848173 |
| x | 171.12975 | -42.5855753 |
| y | 171.129969 | -42.585079 |
| 1 | 171.131511926651| -42.584306746421966 |
| 2 | 171.128743886947| -42.58414875714669 |
And the ways
| nodes | highway | maxspeed | name | ref | surface | junction | oneway |
| ws | primary | 100 | Taramakau Highway | SH 6 | asphalt | | |
| kxlh | trunk | | Otira Highway | SH 73 | | | |
| ai | primary | 100 | Kumara Junction Highway | SH 6 | asphalt | | |
| qyrgdenof | primary | 100 | Kumara Junction | | | roundabout | yes |
| ke | trunk | | Otira Highway | SH 73 | | | yes |
| itj | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
| gk | trunk | | Otira Highway | SH 73 | | | yes |
| fi | primary | 100 | Kumara Junction Highway | SH 6 | | | yes |
| wq | primary | 100 | Taramakau Highway | SH 6 | | | yes |
| vw | primary | 100 | Taramakau Highway | SH 6 | | | yes |
| vbuq | primary | 100 | Kumara Junction | | | roundabout | yes |
| jmv | primary | 100 | Kumara Junction | | | roundabout | yes |
| fcpj | primary | 100 | Kumara Junction | | | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| 1,2 | Taramakau Highway,Kumara Junction Highway,Kumara Junction Highway,Kumara Junction Highway | depart,Kumara Junction-exit-2,exit rotary slight left,arrive |
| from | to | route |
| 1 | 2 | bcd,bcd |
-75
View File
@@ -718,78 +718,3 @@ Feature: Basic Map Matching
| abe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok |
| ahd | 1,0.99973,1.00027,0.99973,1.00027,0.999461 | depart,turn right,arrive | Ok |
| ahe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok |
@match @testbot
Scenario: Regression test - add source phantoms properly (one phantom on one edge)
Given the profile "testbot"
Given a grid size of 10 meters
Given the node map
"""
a--1-b2-cd3--e
"""
And the ways
| nodes |
| ab |
| bcd |
| de |
Given the query options
| geometries | geojson |
| overview | full |
| steps | true |
| waypoints | 0;2 |
| annotations | duration,weight |
| generate_hints | false |
When I match I should get
| trace | geometry | a:duration | a:weight | duration |
| 123 | 1.000135,1,1.000225,1,1.00036,1,1.000405,1,1.00045,1 | 1:1.5:0.5:0.5 | 1:1.5:0.5:0.5 | 3.5 |
| 321 | 1.00045,1,1.000405,1,1.00036,1,1.000225,1,1.000135,1 | 0.5:0.5:1.5:1 | 0.5:0.5:1.5:1 | 3.5 |
@match @testbot
Scenario: Regression test - add source phantom properly (two phantoms on one edge)
Given the profile "testbot"
Given a grid size of 10 meters
Given the node map
"""
a--1-b23-c4--d
"""
And the ways
| nodes |
| ab |
| bc |
| cd |
Given the query options
| geometries | geojson |
| overview | full |
| steps | true |
| waypoints | 0;3 |
| annotations | duration,weight |
| generate_hints | false |
When I match I should get
| trace | geometry | a:duration | a:weight | duration |
| 1234 | 1.000135,1,1.000225,1,1.000405,1,1.00045,1 | 1:2:0.5 | 1:2:0.5 | 3.5 |
| 4321 | 1.00045,1,1.000405,1,1.000225,1,1.000135,1 | 0.5:2:1 | 0.5:2:1 | 3.5 |
@match @testbot
Scenario: Regression test - add source phantom properly (two phantoms on one edge)
Given the profile "testbot"
Given a grid size of 10 meters
Given the node map
"""
a--12345-b
"""
And the ways
| nodes |
| ab |
Given the query options
| geometries | geojson |
| overview | full |
| steps | true |
| waypoints | 0;3 |
| annotations | duration,weight,distance |
| generate_hints | false |
# These should have the same weights/duration in either direction
When I match I should get
| trace | geometry | a:distance | a:duration | a:weight | duration |
| 2345 | 1.00018,1,1.000315,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
| 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
+30 -62
View File
@@ -38,15 +38,15 @@ Feature: Multi level routing
Scenario: Testbot - Multi level routing
Given the node map
"""
ab ef
\ /
ab ef
dc hg
ij mn
/ \
lkpo
lkpo
"""
And the nodes
@@ -67,76 +67,44 @@ Feature: Multi level routing
When I route I should get
| from | to | route | time |
| a | b | abcda,abcda | 25s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 239.2s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 157.1s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 137.1s |
| f | l | efghe,hj,ijkli,ijkli | 136.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 162.1s |
| l | o | ijkli,kp,mnopm,mnopm | 80s |
| a | b | abcda,abcda | 20s |
| a | f | abcda,cm,mnopm,kp,ijkli,hj,efghe,efghe | 229.4s |
| a | l | abcda,cm,mnopm,kp,ijkli,ijkli | 144.7s |
| a | o | abcda,cm,mnopm,mnopm,mnopm | 124.7s |
| f | l | efghe,hj,ijkli,ijkli,ijkli | 124.7s |
| f | o | efghe,hj,ijkli,kp,mnopm,mnopm | 144.7s |
| l | o | ijkli,kp,mnopm,mnopm | 60s |
| c | m | cm,cm | 44.7s |
| f | a | efghe,hj,ijkli,kp,mnopm,cm,abcda,abcda | 239.2s |
| l | a | ijkli,kp,mnopm,cm,abcda,abcda | 157.1s |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
| f | 239.2 | 0 | 136.7 | 162.1 |
| l | 157.1 | 136.7 | 0 | 80 |
| o | 137.1 | 162.1 | 80 | 0 |
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| f | 229.4 | 0 | 124.7 | 144.7 |
| l | 144.7 | 124.7 | 0 | 60 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| f | 239.2 |
| l | 157.1 |
| o | 137.1 |
| | a |
| a | 0 |
| f | 229.4 |
| l | 144.7 |
| o | 124.7 |
When I request a travel time matrix I should get
| | a | f | l | o |
| a | 0 | 239.2 | 157.1 | 137.1 |
| o | 137.1 | 162.1 | 80 | 0 |
| | a | f | l | o |
| a | 0 | 229.4 | 144.7 | 124.7 |
| o | 124.7 | 144.7 | 60 | 0 |
When I request a travel time matrix I should get
| | a | o |
| a | 0 | 137.1 |
| f | 239.2 | 162.1 |
| l | 157.1 | 80 |
| o | 137.1 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
| l | 1618.3 | 1293.3 | 0 | 800.5 |
| o | 1418.2 | 1617.3 | 800.5 | 0 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
When I request a travel distance matrix I should get
| | a |
| a | 0 |
| f | 2339.9 |
| l | 1618.3 |
| o | 1418.2 |
When I request a travel distance matrix I should get
| | a | f | l | o |
| a | 0 | 2383.7 | 1566.9 | 1366.8 |
| f | 2339.9 | 0 | 1198.1 | 1522.1 |
When I request a travel distance matrix I should get
| | a | o |
| a | 0 | 1366.8 |
| f | 2339.9 | 1522.1 |
| l | 1618.3 | 800.5 |
| o | 1418.2 | 0 |
| a | 0 | 124.7 |
| f | 229.4 | 144.7 |
| l | 144.7 | 60 |
| o | 124.7 | 0 |
Scenario: Testbot - Multi level routing: horizontal road
Given the node map
+4 -4
View File
@@ -54,7 +54,7 @@ Feature: Traffic - speeds
| a | d | ad,ad | 27 km/h | 1275.7,0 | 1 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 |
| a | g | ad,df,fb,fb | 30 km/h | 1295.7,487.5,304.7,0 | 1:0:0 |
| a | g | ad,df,fb,fb | 30 km/h | 1275.7,487.5,304.7,0 | 1:0:0 |
Scenario: Weighting based on speed file weights, ETA based on file durations
@@ -136,13 +136,13 @@ Feature: Traffic - speeds
When I route I should get
| from | to | route | speed | weights | a:datasources | a:speed | a:nodes|
| a | b | fb,fb | 36 km/h | 329.4,0 | 0 | 10 | 6:2 |
| a | b | fb,fb | 36 km/h | 329.4,0 | 0 | 7 | 6:2 |
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | 0:1 | 10:7.5 | 6:2:3 |
| b | c | bc,bc | 27 km/h | 741.5,0 | 1 | 7.5 | 2:3 |
| a | d | fb,df,df | 36 km/h | 140,487.5,0 | 0:0 | 10:10 | 2:6:4 |
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 | 10 | 4:3 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 |
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 |
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 | 3.5 | 6:2 |
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 | 5.4 | 6:2 |
Scenario: Verify that negative values cause an error, they're not valid at all
+2 -2
View File
@@ -53,8 +53,8 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 |
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 |
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | 6.7 |
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | 6.5 |
| s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | 9.7:10 |
| e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | 10:9.7 |
-25
View File
@@ -1,25 +0,0 @@
#ifndef OSMR_CONTRACTOR_CONTRACTED_METRIC_HPP
#define OSMR_CONTRACTOR_CONTRACTED_METRIC_HPP
#include "contractor/query_graph.hpp"
namespace osrm
{
namespace contractor
{
namespace detail
{
template <storage::Ownership Ownership> struct ContractedMetric
{
detail::QueryGraph<Ownership> graph;
std::vector<util::ViewOrVector<bool, Ownership>> edge_filter;
};
}
using ContractedMetric = detail::ContractedMetric<storage::Ownership::Container>;
using ContractedMetricView = detail::ContractedMetric<storage::Ownership::View>;
}
}
#endif
+2 -5
View File
@@ -12,26 +12,23 @@ namespace contractor
struct ContractorEdgeData
{
ContractorEdgeData()
: weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0),
backward(0)
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
{
}
ContractorEdgeData(EdgeWeight weight,
EdgeWeight duration,
EdgeDistance distance,
unsigned original_edges,
unsigned id,
bool shortcut,
bool forward,
bool backward)
: weight(weight), duration(duration), distance(distance), id(id),
: weight(weight), duration(duration), id(id),
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
forward(forward), backward(backward)
{
}
EdgeWeight weight;
EdgeWeight duration;
EdgeDistance distance;
unsigned id;
unsigned originalEdges : 29;
bool shortcut : 1;
+42 -25
View File
@@ -1,9 +1,12 @@
#ifndef OSRM_CONTRACTOR_FILES_HPP
#define OSRM_CONTRACTOR_FILES_HPP
#include "contractor/serialization.hpp"
#include "contractor/query_graph.hpp"
#include <unordered_map>
#include "util/serialization.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
namespace osrm
{
@@ -12,45 +15,59 @@ namespace contractor
namespace files
{
// reads .osrm.hsgr file
template <typename ContractedMetricT>
template <typename QueryGraphT, typename EdgeFilterT>
inline void readGraph(const boost::filesystem::path &path,
std::unordered_map<std::string, ContractedMetricT> &metrics,
unsigned &checksum,
QueryGraphT &graph,
std::vector<EdgeFilterT> &edge_filter,
std::uint32_t &connectivity_checksum)
{
static_assert(std::is_same<ContractedMetric, ContractedMetricT>::value ||
std::is_same<ContractedMetricView, ContractedMetricT>::value,
"metric must be of type ContractedMetric<>");
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
"edge_filter must be a container of vector<bool> or vector_view<bool>");
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.ReadInto("/ch/connectivity_checksum", connectivity_checksum);
for (auto &pair : metrics)
reader.ReadInto(checksum);
util::serialization::read(reader, graph);
auto count = reader.ReadElementCount64();
edge_filter.resize(count);
for (const auto index : util::irange<std::size_t>(0, count))
{
serialization::read(reader, "/ch/metrics/" + pair.first, pair.second);
storage::serialization::read(reader, edge_filter[index]);
}
reader.ReadInto(connectivity_checksum);
}
// writes .osrm.hsgr file
template <typename ContractedMetricT>
template <typename QueryGraphT, typename EdgeFilterT>
inline void writeGraph(const boost::filesystem::path &path,
const std::unordered_map<std::string, ContractedMetricT> &metrics,
unsigned checksum,
const QueryGraphT &graph,
const std::vector<EdgeFilterT> &edge_filter,
const std::uint32_t connectivity_checksum)
{
static_assert(std::is_same<ContractedMetric, ContractedMetricT>::value ||
std::is_same<ContractedMetricView, ContractedMetricT>::value,
"metric must be of type ContractedMetric<>");
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
storage::tar::FileWriter writer{path, fingerprint};
static_assert(std::is_same<QueryGraphView, QueryGraphT>::value ||
std::is_same<QueryGraph, QueryGraphT>::value,
"graph must be of type QueryGraph<>");
static_assert(std::is_same<EdgeFilterT, std::vector<bool>>::value ||
std::is_same<EdgeFilterT, util::vector_view<bool>>::value,
"edge_filter must be a container of vector<bool> or vector_view<bool>");
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
writer.WriteElementCount64("/ch/connectivity_checksum", 1);
writer.WriteFrom("/ch/connectivity_checksum", connectivity_checksum);
for (const auto &pair : metrics)
writer.WriteOne(checksum);
util::serialization::write(writer, graph);
writer.WriteElementCount64(edge_filter.size());
for (const auto &filter : edge_filter)
{
serialization::write(writer, "/ch/metrics/" + pair.first, pair.second);
storage::serialization::write(writer, filter);
}
writer.WriteOne(connectivity_checksum);
}
}
}
@@ -41,7 +41,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.target,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
input_edge.data.distance,
1,
input_edge.data.turn_id,
false,
@@ -52,7 +51,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
input_edge.source,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
input_edge.data.distance,
1,
input_edge.data.turn_id,
false,
@@ -84,7 +82,6 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
// remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{
@@ -93,16 +90,12 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
forward_edge.data.duration =
std::min(edges[i].data.duration, forward_edge.data.duration);
forward_edge.data.distance =
std::min(edges[i].data.distance, forward_edge.data.distance);
}
if (edges[i].data.backward)
{
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
reverse_edge.data.duration =
std::min(edges[i].data.duration, reverse_edge.data.duration);
reverse_edge.data.distance =
std::min(edges[i].data.distance, reverse_edge.data.distance);
}
++i;
}
@@ -135,42 +128,44 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT graph)
{
util::Log() << "Converting contracted graph with " << graph.GetNumberOfEdges()
<< " to edge list (" << (graph.GetNumberOfEdges() * sizeof(Edge)) << " bytes)";
std::vector<Edge> edges(graph.GetNumberOfEdges());
std::vector<Edge> edges;
edges.reserve(graph.GetNumberOfEdges());
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, graph.GetNumberOfNodes());
const NodeID number_of_nodes = graph.GetNumberOfNodes();
if (graph.GetNumberOfNodes())
{
util::UnbufferedLog log;
log << "Getting edges of minimized graph ";
util::Percent p(log, graph.GetNumberOfNodes());
const NodeID number_of_nodes = graph.GetNumberOfNodes();
std::size_t edge_index = 0;
Edge new_edge;
for (const auto node : util::irange(0u, number_of_nodes))
{
p.PrintStatus(node);
for (auto edge : graph.GetAdjacentEdgeRange(node))
{
const NodeID target = graph.GetTarget(edge);
const auto &data = graph.GetEdgeData(edge);
auto &new_edge = edges[edge_index++];
const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge);
new_edge.source = node;
new_edge.target = target;
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
new_edge.data.weight = data.weight;
new_edge.data.duration = data.duration;
new_edge.data.distance = data.distance;
new_edge.data.shortcut = data.shortcut;
new_edge.data.turn_id = data.id;
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
"edge id invalid");
new_edge.data.forward = data.forward;
new_edge.data.backward = data.backward;
edges.push_back(new_edge);
}
}
BOOST_ASSERT(edge_index == edges.size());
}
// sort and remove duplicates
tbb::parallel_sort(edges.begin(), edges.end());
auto new_end = std::unique(edges.begin(), edges.end());
edges.resize(new_end - edges.begin());
edges.shrink_to_fit();
return edges;
}
+3 -8
View File
@@ -17,8 +17,7 @@ struct QueryEdge
struct EdgeData
{
explicit EdgeData()
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false),
distance(0)
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false)
{
}
@@ -26,11 +25,10 @@ struct QueryEdge
const bool shortcut,
const EdgeWeight weight,
const EdgeWeight duration,
const EdgeDistance distance,
const bool forward,
const bool backward)
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
forward(forward), backward(backward), distance(distance)
forward(forward), backward(backward)
{
}
@@ -42,7 +40,6 @@ struct QueryEdge
turn_id = other.id;
forward = other.forward;
backward = other.backward;
distance = other.distance;
}
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
@@ -53,7 +50,6 @@ struct QueryEdge
EdgeWeight duration : 30;
std::uint32_t forward : 1;
std::uint32_t backward : 1;
EdgeDistance distance;
} data;
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
@@ -73,8 +69,7 @@ struct QueryEdge
return (source == right.source && target == right.target &&
data.weight == right.data.weight && data.duration == right.data.duration &&
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
data.backward == right.data.backward && data.turn_id == right.data.turn_id &&
data.distance == right.data.distance);
data.backward == right.data.backward && data.turn_id == right.data.turn_id);
}
};
}
-53
View File
@@ -1,53 +0,0 @@
#ifndef OSRM_CONTRACTOR_SERIALIZATION_HPP
#define OSRM_CONTRACTOR_SERIALIZATION_HPP
#include "contractor/contracted_metric.hpp"
#include "util/serialization.hpp"
#include "storage/serialization.hpp"
#include "storage/tar.hpp"
namespace osrm
{
namespace contractor
{
namespace serialization
{
template <storage::Ownership Ownership>
void write(storage::tar::FileWriter &writer,
const std::string &name,
const detail::ContractedMetric<Ownership> &metric)
{
util::serialization::write(writer, name + "/contracted_graph", metric.graph);
writer.WriteElementCount64(name + "/exclude", metric.edge_filter.size());
for (const auto index : util::irange<std::size_t>(0, metric.edge_filter.size()))
{
storage::serialization::write(writer,
name + "/exclude/" + std::to_string(index) + "/edge_filter",
metric.edge_filter[index]);
}
}
template <storage::Ownership Ownership>
void read(storage::tar::FileReader &reader,
const std::string &name,
detail::ContractedMetric<Ownership> &metric)
{
util::serialization::read(reader, name + "/contracted_graph", metric.graph);
metric.edge_filter.resize(reader.ReadElementCount64(name + "/exclude"));
for (const auto index : util::irange<std::size_t>(0, metric.edge_filter.size()))
{
storage::serialization::read(reader,
name + "/exclude/" + std::to_string(index) + "/edge_filter",
metric.edge_filter[index]);
}
}
}
}
}
#endif
+11 -37
View File
@@ -22,7 +22,6 @@ class CellCustomizer
{
bool from_clique;
EdgeDuration duration;
EdgeDistance distance;
};
public:
@@ -61,7 +60,7 @@ class CellCustomizer
}
}
heap.Clear();
heap.Insert(source, 0, {false, 0, 0});
heap.Insert(source, 0, {false, 0});
// explore search space
while (!heap.Empty() && !destinations_set.empty())
@@ -69,18 +68,8 @@ class CellCustomizer
const NodeID node = heap.DeleteMin();
const EdgeWeight weight = heap.GetKey(node);
const EdgeDuration duration = heap.GetData(node).duration;
const EdgeDistance distance = heap.GetData(node).distance;
RelaxNode(graph,
cells,
allowed_nodes,
metric,
heap,
level,
node,
weight,
duration,
distance);
RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration);
destinations_set.erase(node);
}
@@ -88,27 +77,21 @@ class CellCustomizer
// fill a map of destination nodes to placeholder pointers
auto weights = cell.GetOutWeight(source);
auto durations = cell.GetOutDuration(source);
auto distances = cell.GetOutDistance(source);
for (auto &destination : destinations)
{
BOOST_ASSERT(!weights.empty());
BOOST_ASSERT(!durations.empty());
BOOST_ASSERT(!distances.empty());
const bool inserted = heap.WasInserted(destination);
weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT;
durations.front() =
inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION;
distances.front() =
inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE;
weights.advance_begin(1);
durations.advance_begin(1);
distances.advance_begin(1);
}
BOOST_ASSERT(weights.empty());
BOOST_ASSERT(durations.empty());
BOOST_ASSERT(distances.empty());
}
}
@@ -145,8 +128,7 @@ class CellCustomizer
LevelID level,
NodeID node,
EdgeWeight weight,
EdgeDuration duration,
EdgeDistance distance) const
EdgeDuration duration) const
{
auto first_level = level == 1;
BOOST_ASSERT(heap.WasInserted(node));
@@ -167,7 +149,6 @@ class CellCustomizer
auto subcell = cells.GetCell(metric, level - 1, subcell_id);
auto subcell_destination = subcell.GetDestinationNodes().begin();
auto subcell_duration = subcell.GetOutDuration(node).begin();
auto subcell_distance = subcell.GetOutDistance(node).begin();
for (auto subcell_weight : subcell.GetOutWeight(node))
{
if (subcell_weight != INVALID_EDGE_WEIGHT)
@@ -180,24 +161,20 @@ class CellCustomizer
const EdgeWeight to_weight = weight + subcell_weight;
const EdgeDuration to_duration = duration + *subcell_duration;
const EdgeDistance to_distance = distance + *subcell_distance;
if (!heap.WasInserted(to))
{
heap.Insert(to, to_weight, {true, to_duration, to_distance});
heap.Insert(to, to_weight, {true, to_duration});
}
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(heap.GetKey(to),
heap.GetData(to).duration,
heap.GetData(to).distance))
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, to_duration, to_distance};
heap.GetData(to) = {true, to_duration};
}
}
++subcell_destination;
++subcell_duration;
++subcell_distance;
}
}
}
@@ -218,18 +195,15 @@ class CellCustomizer
{
const EdgeWeight to_weight = weight + data.weight;
const EdgeDuration to_duration = duration + data.duration;
const EdgeDistance to_distance = distance + data.distance;
if (!heap.WasInserted(to))
{
heap.Insert(
to, to_weight, {false, duration + data.duration, distance + data.distance});
heap.Insert(to, to_weight, {false, duration + data.duration});
}
else if (std::tie(to_weight, to_duration, to_distance) <
std::tie(
heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance))
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, to_duration, to_distance};
heap.GetData(to) = {false, to_duration};
}
}
}
-1
View File
@@ -20,7 +20,6 @@ template <storage::Ownership Ownership> struct CellMetricImpl
Vector<EdgeWeight> weights;
Vector<EdgeDuration> durations;
Vector<EdgeDistance> distances;
};
}
+1 -2
View File
@@ -21,8 +21,7 @@ struct CustomizationConfig final : storage::IOConfig
".osrm.partition",
".osrm.cells",
".osrm.ebg_nodes",
".osrm.properties",
".osrm.enw"},
".osrm.properties"},
{},
{".osrm.cell_metrics", ".osrm.mldgr"}),
requested_num_threads(0)
+16 -104
View File
@@ -16,116 +16,28 @@ namespace osrm
namespace customizer
{
struct EdgeBasedGraphEdgeData
using EdgeBasedGraphEdgeData = partitioner::EdgeBasedGraphEdgeData;
struct MultiLevelEdgeBasedGraph
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>
{
NodeID turn_id; // ID of the edge based node (node based edge)
using Base =
partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using Base::Base;
};
template <typename EdgeDataT, storage::Ownership Ownership> class MultiLevelGraph;
namespace serialization
struct MultiLevelEdgeBasedGraphView
: public partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>
{
template <typename EdgeDataT, storage::Ownership Ownership>
void read(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph);
template <typename EdgeDataT, storage::Ownership Ownership>
void write(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
}
template <typename EdgeDataT, storage::Ownership Ownership>
class MultiLevelGraph : public partitioner::MultiLevelGraph<EdgeDataT, Ownership>
{
private:
using SuperT = partitioner::MultiLevelGraph<EdgeDataT, Ownership>;
using PartitionerGraphT = partitioner::MultiLevelGraph<partitioner::EdgeBasedGraphEdgeData,
storage::Ownership::Container>;
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
public:
using NodeArrayEntry = typename SuperT::NodeArrayEntry;
using EdgeArrayEntry = typename SuperT::EdgeArrayEntry;
using EdgeOffset = typename SuperT::EdgeOffset;
MultiLevelGraph() = default;
MultiLevelGraph(MultiLevelGraph &&) = default;
MultiLevelGraph(const MultiLevelGraph &) = default;
MultiLevelGraph &operator=(MultiLevelGraph &&) = default;
MultiLevelGraph &operator=(const MultiLevelGraph &) = default;
MultiLevelGraph(PartitionerGraphT &&graph,
Vector<EdgeWeight> node_weights_,
Vector<EdgeDuration> node_durations_,
Vector<EdgeDistance> node_distances_)
: node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
node_distances(std::move(node_distances_))
{
util::ViewOrVector<PartitionerGraphT::EdgeArrayEntry, storage::Ownership::Container>
original_edge_array;
std::tie(SuperT::node_array,
original_edge_array,
SuperT::node_to_edge_offset,
SuperT::connectivity_checksum) = std::move(graph).data();
SuperT::edge_array.reserve(original_edge_array.size());
for (const auto &edge : original_edge_array)
{
SuperT::edge_array.push_back({edge.target, {edge.data.turn_id}});
is_forward_edge.push_back(edge.data.forward);
is_backward_edge.push_back(edge.data.backward);
}
}
MultiLevelGraph(Vector<NodeArrayEntry> node_array_,
Vector<EdgeArrayEntry> edge_array_,
Vector<EdgeOffset> node_to_edge_offset_,
Vector<EdgeWeight> node_weights_,
Vector<EdgeDuration> node_durations_,
Vector<EdgeDistance> node_distances_,
Vector<bool> is_forward_edge_,
Vector<bool> is_backward_edge_)
: SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)),
node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)),
node_distances(std::move(node_distances_)), is_forward_edge(is_forward_edge_),
is_backward_edge(is_backward_edge_)
{
}
EdgeWeight GetNodeWeight(NodeID node) const { return node_weights[node]; }
EdgeWeight GetNodeDuration(NodeID node) const { return node_durations[node]; }
EdgeDistance GetNodeDistance(NodeID node) const { return node_distances[node]; }
bool IsForwardEdge(EdgeID edge) const { return is_forward_edge[edge]; }
bool IsBackwardEdge(EdgeID edge) const { return is_backward_edge[edge]; }
friend void
serialization::read<EdgeDataT, Ownership>(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph);
friend void
serialization::write<EdgeDataT, Ownership>(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph);
protected:
Vector<EdgeWeight> node_weights;
Vector<EdgeDuration> node_durations;
Vector<EdgeDistance> node_distances;
Vector<bool> is_forward_edge;
Vector<bool> is_backward_edge;
using Base = partitioner::MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
using Base::Base;
};
using MultiLevelEdgeBasedGraph =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::Container>;
using MultiLevelEdgeBasedGraphView =
MultiLevelGraph<EdgeBasedGraphEdgeData, storage::Ownership::View>;
struct StaticEdgeBasedGraphEdge : MultiLevelEdgeBasedGraph::InputEdge
{
using Base = MultiLevelEdgeBasedGraph::InputEdge;
using Base::Base;
};
}
}
+16 -70
View File
@@ -3,12 +3,10 @@
#include "customizer/serialization.hpp"
#include "storage/tar.hpp"
#include "storage/io.hpp"
#include "util/integer_range.hpp"
#include <unordered_map>
namespace osrm
{
namespace customizer
@@ -18,94 +16,42 @@ namespace files
// reads .osrm.cell_metrics file
template <typename CellMetricT>
inline void readCellMetrics(const boost::filesystem::path &path,
std::unordered_map<std::string, std::vector<CellMetricT>> &metrics)
inline void readCellMetrics(const boost::filesystem::path &path, std::vector<CellMetricT> &metrics)
{
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
std::is_same<CellMetric, CellMetricT>::value,
"");
const auto fingerprint = storage::tar::FileReader::VerifyFingerprint;
storage::tar::FileReader reader{path, fingerprint};
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
for (auto &pair : metrics)
auto num_metrics = reader.ReadElementCount64();
metrics.resize(num_metrics);
for (auto &metric : metrics)
{
const auto &metric_name = pair.first;
auto &metric_exclude_classes = pair.second;
auto prefix = "/mld/metrics/" + metric_name + "/exclude";
auto num_exclude_classes = reader.ReadElementCount64(prefix);
metric_exclude_classes.resize(num_exclude_classes);
auto id = 0;
for (auto &metric : metric_exclude_classes)
{
serialization::read(reader, prefix + "/" + std::to_string(id++), metric);
}
serialization::read(reader, metric);
}
}
// writes .osrm.cell_metrics file
template <typename CellMetricT>
inline void
writeCellMetrics(const boost::filesystem::path &path,
const std::unordered_map<std::string, std::vector<CellMetricT>> &metrics)
inline void writeCellMetrics(const boost::filesystem::path &path,
const std::vector<CellMetricT> &metrics)
{
static_assert(std::is_same<CellMetricView, CellMetricT>::value ||
std::is_same<CellMetric, CellMetricT>::value,
"");
const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint;
storage::tar::FileWriter writer{path, fingerprint};
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter writer{path, fingerprint};
for (const auto &pair : metrics)
writer.WriteElementCount64(metrics.size());
for (const auto &metric : metrics)
{
const auto &metric_name = pair.first;
const auto &metric_exclude_classes = pair.second;
auto prefix = "/mld/metrics/" + metric_name + "/exclude";
writer.WriteElementCount64(prefix, metric_exclude_classes.size());
auto id = 0;
for (auto &exclude_metric : metric_exclude_classes)
{
serialization::write(writer, prefix + "/" + std::to_string(id++), exclude_metric);
}
serialization::write(writer, metric);
}
}
// reads .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void readGraph(const boost::filesystem::path &path,
MultiLevelGraphT &graph,
std::uint32_t &connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileReader reader{path, storage::tar::FileReader::VerifyFingerprint};
reader.ReadInto("/mld/connectivity_checksum", connectivity_checksum);
serialization::read(reader, "/mld/multilevelgraph", graph);
}
// writes .osrm.mldgr file
template <typename MultiLevelGraphT>
inline void writeGraph(const boost::filesystem::path &path,
const MultiLevelGraphT &graph,
const std::uint32_t connectivity_checksum)
{
static_assert(std::is_same<customizer::MultiLevelEdgeBasedGraphView, MultiLevelGraphT>::value ||
std::is_same<customizer::MultiLevelEdgeBasedGraph, MultiLevelGraphT>::value,
"");
storage::tar::FileWriter writer{path, storage::tar::FileWriter::GenerateFingerprint};
writer.WriteElementCount64("/mld/connectivity_checksum", 1);
writer.WriteFrom("/mld/connectivity_checksum", connectivity_checksum);
serialization::write(writer, "/mld/multilevelgraph", graph);
}
}
}
}
+7 -45
View File
@@ -1,13 +1,11 @@
#ifndef OSRM_CUSTOMIZER_SERIALIZATION_HPP
#define OSRM_CUSTOMIZER_SERIALIZATION_HPP
#include "customizer/edge_based_graph.hpp"
#include "partitioner/cell_storage.hpp"
#include "storage/io.hpp"
#include "storage/serialization.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "storage/tar.hpp"
namespace osrm
{
@@ -17,53 +15,17 @@ namespace serialization
{
template <storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader,
const std::string &name,
detail::CellMetricImpl<Ownership> &metric)
inline void read(storage::io::FileReader &reader, detail::CellMetricImpl<Ownership> &metric)
{
storage::serialization::read(reader, name + "/weights", metric.weights);
storage::serialization::read(reader, name + "/durations", metric.durations);
storage::serialization::read(reader, name + "/distances", metric.distances);
storage::serialization::read(reader, metric.weights);
storage::serialization::read(reader, metric.durations);
}
template <storage::Ownership Ownership>
inline void write(storage::tar::FileWriter &writer,
const std::string &name,
const detail::CellMetricImpl<Ownership> &metric)
inline void write(storage::io::FileWriter &writer, const detail::CellMetricImpl<Ownership> &metric)
{
storage::serialization::write(writer, name + "/weights", metric.weights);
storage::serialization::write(writer, name + "/durations", metric.durations);
storage::serialization::write(writer, name + "/distances", metric.distances);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void read(storage::tar::FileReader &reader,
const std::string &name,
MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::read(reader, name + "/node_array", graph.node_array);
storage::serialization::read(reader, name + "/node_weights", graph.node_weights);
storage::serialization::read(reader, name + "/node_durations", graph.node_durations);
storage::serialization::read(reader, name + "/node_distances", graph.node_distances);
storage::serialization::read(reader, name + "/edge_array", graph.edge_array);
storage::serialization::read(reader, name + "/is_forward_edge", graph.is_forward_edge);
storage::serialization::read(reader, name + "/is_backward_edge", graph.is_backward_edge);
storage::serialization::read(reader, name + "/node_to_edge_offset", graph.node_to_edge_offset);
}
template <typename EdgeDataT, storage::Ownership Ownership>
inline void write(storage::tar::FileWriter &writer,
const std::string &name,
const MultiLevelGraph<EdgeDataT, Ownership> &graph)
{
storage::serialization::write(writer, name + "/node_array", graph.node_array);
storage::serialization::write(writer, name + "/node_weights", graph.node_weights);
storage::serialization::write(writer, name + "/node_durations", graph.node_durations);
storage::serialization::write(writer, name + "/node_distances", graph.node_distances);
storage::serialization::write(writer, name + "/edge_array", graph.edge_array);
storage::serialization::write(writer, name + "/is_forward_edge", graph.is_forward_edge);
storage::serialization::write(writer, name + "/is_backward_edge", graph.is_backward_edge);
storage::serialization::write(writer, name + "/node_to_edge_offset", graph.node_to_edge_offset);
storage::serialization::write(writer, metric.weights);
storage::serialization::write(writer, metric.durations);
}
}
}
-14
View File
@@ -30,11 +30,6 @@ template <typename AlgorithmT> const char *name();
template <> inline const char *name<ch::Algorithm>() { return "CH"; }
template <> inline const char *name<mld::Algorithm>() { return "MLD"; }
// Algorithm identifier
template <typename AlgorithmT> const char *identifier();
template <> inline const char *identifier<ch::Algorithm>() { return "ch"; }
template <> inline const char *identifier<mld::Algorithm>() { return "mld"; }
template <typename AlgorithmT> struct HasAlternativePathSearch final : std::false_type
{
};
@@ -50,9 +45,6 @@ template <typename AlgorithmT> struct HasMapMatching final : std::false_type
template <typename AlgorithmT> struct HasManyToManySearch final : std::false_type
{
};
template <typename AlgorithmT> struct SupportsDistanceAnnotationType final : std::false_type
{
};
template <typename AlgorithmT> struct HasGetTileTurns final : std::false_type
{
};
@@ -76,9 +68,6 @@ template <> struct HasMapMatching<ch::Algorithm> final : std::true_type
template <> struct HasManyToManySearch<ch::Algorithm> final : std::true_type
{
};
template <> struct SupportsDistanceAnnotationType<ch::Algorithm> final : std::true_type
{
};
template <> struct HasGetTileTurns<ch::Algorithm> final : std::true_type
{
};
@@ -102,9 +91,6 @@ template <> struct HasMapMatching<mld::Algorithm> final : std::true_type
template <> struct HasManyToManySearch<mld::Algorithm> final : std::true_type
{
};
template <> struct SupportsDistanceAnnotationType<mld::Algorithm> final : std::false_type
{
};
template <> struct HasGetTileTurns<mld::Algorithm> final : std::true_type
{
};
-5
View File
@@ -6,7 +6,6 @@
#include "engine/api/json_factory.hpp"
#include "engine/hint.hpp"
#include "util/coordinate_calculation.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
@@ -54,8 +53,6 @@ class BaseAPI
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
util::coordinate_calculation::fccApproximateDistance(phantom.location,
phantom.input_location),
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id)).to_string(),
Hint{phantom, facade.GetCheckSum()});
}
@@ -64,8 +61,6 @@ class BaseAPI
// TODO: check forward/reverse
return json::makeWaypoint(
phantom.location,
util::coordinate_calculation::fccApproximateDistance(phantom.location,
phantom.input_location),
facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))
.to_string());
}
+4 -7
View File
@@ -33,7 +33,7 @@ namespace json
namespace detail
{
util::json::Array coordinateToLonLat(const util::Coordinate &coordinate);
util::json::Array coordinateToLonLat(const util::Coordinate coordinate);
/**
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
@@ -86,14 +86,11 @@ util::json::Object makeRoute(const guidance::Route &route,
const char *weight_name);
// Creates a Waypoint without Hint, see the Hint overload below
util::json::Object
makeWaypoint(const util::Coordinate &location, const double &distance, std::string name);
util::json::Object makeWaypoint(const util::Coordinate location, std::string name);
// Creates a Waypoint with Hint, see the overload above when Hint is not needed
util::json::Object makeWaypoint(const util::Coordinate &location,
const double &distance,
std::string name,
const Hint &hint);
util::json::Object
makeWaypoint(const util::Coordinate location, std::string name, const Hint &hint);
util::json::Object makeRouteLeg(guidance::RouteLeg leg, util::json::Array steps);
+44 -42
View File
@@ -34,54 +34,56 @@ class NearestAPI final : public BaseAPI
util::json::Array waypoints;
waypoints.values.resize(phantom_nodes.front().size());
std::transform(
phantom_nodes.front().begin(),
phantom_nodes.front().end(),
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance) {
auto &phantom_node = phantom_with_distance.phantom_node;
auto waypoint = MakeWaypoint(phantom_node);
std::transform(phantom_nodes.front().begin(),
phantom_nodes.front().end(),
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance) {
auto &phantom_node = phantom_with_distance.phantom_node;
auto waypoint = MakeWaypoint(phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance;
util::json::Array nodes;
util::json::Array nodes;
std::uint64_t from_node = 0;
std::uint64_t to_node = 0;
std::uint64_t from_node = 0;
std::uint64_t to_node = 0;
datafacade::BaseDataFacade::NodeForwardRange forward_geometry;
if (phantom_node.forward_segment_id.enabled)
{
auto segment_id = phantom_node.forward_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
forward_geometry = facade.GetUncompressedForwardGeometry(geometry_id);
std::vector<NodeID> forward_geometry;
if (phantom_node.forward_segment_id.enabled)
{
auto segment_id = phantom_node.forward_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
forward_geometry =
facade.GetUncompressedForwardGeometry(geometry_id);
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry(phantom_node.fwd_segment_position));
to_node = static_cast<std::uint64_t>(osm_node_id);
}
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry[phantom_node.fwd_segment_position]);
to_node = static_cast<std::uint64_t>(osm_node_id);
}
if (phantom_node.reverse_segment_id.enabled)
{
auto segment_id = phantom_node.reverse_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
const auto geometry = facade.GetUncompressedForwardGeometry(geometry_id);
auto osm_node_id =
facade.GetOSMNodeIDOfNode(geometry(phantom_node.fwd_segment_position + 1));
from_node = static_cast<std::uint64_t>(osm_node_id);
}
else if (phantom_node.forward_segment_id.enabled &&
phantom_node.fwd_segment_position > 0)
{
// In the case of one way, rely on forward segment only
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry(phantom_node.fwd_segment_position - 1));
from_node = static_cast<std::uint64_t>(osm_node_id);
}
nodes.values.push_back(from_node);
nodes.values.push_back(to_node);
waypoint.values["nodes"] = std::move(nodes);
if (phantom_node.reverse_segment_id.enabled)
{
auto segment_id = phantom_node.reverse_segment_id.id;
const auto geometry_id = facade.GetGeometryIndex(segment_id).id;
std::vector<NodeID> geometry =
facade.GetUncompressedForwardGeometry(geometry_id);
auto osm_node_id = facade.GetOSMNodeIDOfNode(
geometry[phantom_node.fwd_segment_position + 1]);
from_node = static_cast<std::uint64_t>(osm_node_id);
}
else if (phantom_node.forward_segment_id.enabled &&
phantom_node.fwd_segment_position > 0)
{
// In the case of one way, rely on forward segment only
auto osm_node_id = facade.GetOSMNodeIDOfNode(
forward_geometry[phantom_node.fwd_segment_position - 1]);
from_node = static_cast<std::uint64_t>(osm_node_id);
}
nodes.values.push_back(from_node);
nodes.values.push_back(to_node);
waypoint.values["nodes"] = std::move(nodes);
return waypoint;
});
return waypoint;
});
response.values["code"] = "Ok";
response.values["waypoints"] = std::move(waypoints);
-20
View File
@@ -148,9 +148,6 @@ class RouteAPI : public BaseAPI
// processing is performed
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
// Collapse segregated steps before others
steps = guidance::collapseSegregatedTurnInstructions(std::move(steps));
/* Perform step-based post-processing.
*
* Using post-processing on basis of route-steps for a single leg at a time
@@ -324,23 +321,6 @@ class RouteAPI : public BaseAPI
}
annotation.values["nodes"] = std::move(nodes);
}
// Add any supporting metadata, if needed
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
const auto MAX_DATASOURCE_ID = 255u;
util::json::Object metadata;
util::json::Array datasource_names;
for (auto i = 0u; i < MAX_DATASOURCE_ID; i++)
{
const auto name = facade.GetDatasourceName(i);
// Length of 0 indicates the first empty name, so we can stop here
if (name.size() == 0)
break;
datasource_names.values.push_back(std::string(facade.GetDatasourceName(i)));
}
metadata.values["datasource_names"] = datasource_names;
annotation.values["metadata"] = metadata;
}
annotations.push_back(std::move(annotation));
}
+8 -48
View File
@@ -36,10 +36,9 @@ class TableAPI final : public BaseAPI
{
}
virtual void
MakeResponse(const std::pair<std::vector<EdgeDuration>, std::vector<EdgeDistance>> &tables,
const std::vector<PhantomNode> &phantoms,
util::json::Object &response) const
virtual void MakeResponse(const std::vector<EdgeWeight> &durations,
const std::vector<PhantomNode> &phantoms,
util::json::Object &response) const
{
auto number_of_sources = parameters.sources.size();
auto number_of_destinations = parameters.destinations.size();
@@ -65,18 +64,8 @@ class TableAPI final : public BaseAPI
response.values["destinations"] = MakeWaypoints(phantoms, parameters.destinations);
}
if (parameters.annotations & TableParameters::AnnotationsType::Duration)
{
response.values["durations"] =
MakeDurationTable(tables.first, number_of_sources, number_of_destinations);
}
if (parameters.annotations & TableParameters::AnnotationsType::Distance)
{
response.values["distances"] =
MakeDistanceTable(tables.second, number_of_sources, number_of_destinations);
}
response.values["durations"] =
MakeTable(durations, number_of_sources, number_of_destinations);
response.values["code"] = "Ok";
}
@@ -108,9 +97,9 @@ class TableAPI final : public BaseAPI
return json_waypoints;
}
virtual util::json::Array MakeDurationTable(const std::vector<EdgeWeight> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
virtual util::json::Array MakeTable(const std::vector<EdgeWeight> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
{
util::json::Array json_table;
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
@@ -127,7 +116,6 @@ class TableAPI final : public BaseAPI
{
return util::json::Value(util::json::Null());
}
// division by 10 because the duration is in deciseconds (10s)
return util::json::Value(util::json::Number(duration / 10.));
});
json_table.values.push_back(std::move(json_row));
@@ -135,34 +123,6 @@ class TableAPI final : public BaseAPI
return json_table;
}
virtual util::json::Array MakeDistanceTable(const std::vector<EdgeDistance> &values,
std::size_t number_of_rows,
std::size_t number_of_columns) const
{
util::json::Array json_table;
for (const auto row : util::irange<std::size_t>(0UL, number_of_rows))
{
util::json::Array json_row;
auto row_begin_iterator = values.begin() + (row * number_of_columns);
auto row_end_iterator = values.begin() + ((row + 1) * number_of_columns);
json_row.values.resize(number_of_columns);
std::transform(row_begin_iterator,
row_end_iterator,
json_row.values.begin(),
[](const EdgeDistance distance) {
if (distance == INVALID_EDGE_DISTANCE)
{
return util::json::Value(util::json::Null());
}
// round to single decimal place
return util::json::Value(
util::json::Number(std::round(distance * 10) / 10.));
});
json_table.values.push_back(std::move(json_row));
}
return json_table;
}
const TableParameters &parameters;
};
+9 -75
View File
@@ -59,27 +59,6 @@ struct TableParameters : public BaseParameters
{
std::vector<std::size_t> sources;
std::vector<std::size_t> destinations;
double fallback_speed = INVALID_FALLBACK_SPEED;
enum class FallbackCoordinateType
{
Input = 0,
Snapped = 1
};
FallbackCoordinateType fallback_coordinate_type = FallbackCoordinateType::Input;
enum class AnnotationsType
{
None = 0,
Duration = 0x01,
Distance = 0x02,
All = Duration | Distance
};
AnnotationsType annotations = AnnotationsType::Duration;
double scale_factor = 1;
TableParameters() = default;
template <typename... Args>
@@ -91,32 +70,6 @@ struct TableParameters : public BaseParameters
{
}
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, annotations{annotations_}
{
}
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
double fallback_speed_,
FallbackCoordinateType fallback_coordinate_type_,
double scale_factor_,
Args... args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
scale_factor{scale_factor_}
{
}
bool IsValid() const
{
if (!BaseParameters::IsValid())
@@ -126,9 +79,16 @@ struct TableParameters : public BaseParameters
if (coordinates.size() < 2)
return false;
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's their fault
// 1/ The user is able to specify duplicates in srcs and dsts, in that case it's her fault
// 2/ 0 <= index < len(locations)
// 2/ len(srcs) and len(dsts) smaller or equal to len(locations)
if (sources.size() > coordinates.size())
return false;
if (destinations.size() > coordinates.size())
return false;
// 3/ 0 <= index < len(locations)
const auto not_in_range = [this](const std::size_t x) { return x >= coordinates.size(); };
if (std::any_of(begin(sources), end(sources), not_in_range))
@@ -137,35 +97,9 @@ struct TableParameters : public BaseParameters
if (std::any_of(begin(destinations), end(destinations), not_in_range))
return false;
if (fallback_speed <= 0)
return false;
if (scale_factor <= 0)
return false;
return true;
}
};
inline bool operator&(TableParameters::AnnotationsType lhs, TableParameters::AnnotationsType rhs)
{
return static_cast<bool>(
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) &
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
}
inline TableParameters::AnnotationsType operator|(TableParameters::AnnotationsType lhs,
TableParameters::AnnotationsType rhs)
{
return (TableParameters::AnnotationsType)(
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(lhs) |
static_cast<std::underlying_type_t<TableParameters::AnnotationsType>>(rhs));
}
inline TableParameters::AnnotationsType &operator|=(TableParameters::AnnotationsType &lhs,
TableParameters::AnnotationsType rhs)
{
return lhs = lhs | rhs;
}
}
}
}
+2 -2
View File
@@ -87,7 +87,7 @@ inline std::string encodeBase64(const std::string &x) { return encodeBase64(x.da
// Encode any sufficiently trivial object to Base64.
template <typename T> std::string encodeBase64Bytewise(const T &x)
{
#if !defined(__GNUC__) || (__GNUC__ > 4)
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
@@ -124,7 +124,7 @@ inline std::string decodeBase64(const std::string &encoded)
// Decodes from Base 64 to any sufficiently trivial object.
template <typename T> T decodeBase64Bytewise(const std::string &encoded)
{
#if !defined(__GNUC__) || (__GNUC__ > 4)
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<T>::value, "requires a trivially copyable type");
#endif
+15 -46
View File
@@ -32,35 +32,20 @@ template <typename AlgorithmT, typename FacadeT> class DataWatchdogImpl;
template <typename AlgorithmT>
class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>> final
{
using mutex_type = typename storage::SharedMonitor<storage::SharedRegionRegister>::mutex_type;
using mutex_type = typename storage::SharedMonitor<storage::SharedDataTimestamp>::mutex_type;
using Facade = datafacade::ContiguousInternalMemoryDataFacade<AlgorithmT>;
public:
DataWatchdogImpl(const std::string &dataset_name) : dataset_name(dataset_name), active(true)
DataWatchdogImpl() : active(true), timestamp(0)
{
// create the initial facade before launching the watchdog thread
{
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
auto &shared_register = barrier.data();
auto static_region_id = shared_register.Find(dataset_name + "/static");
auto updatable_region_id = shared_register.Find(dataset_name + "/updatable");
if (static_region_id == storage::SharedRegionRegister::INVALID_REGION_ID ||
updatable_region_id == storage::SharedRegionRegister::INVALID_REGION_ID)
{
throw util::exception("Could not find shared memory region for \"" + dataset_name +
"/data\". Did you run osrm-datastore?");
}
static_shared_region = &shared_register.GetRegion(static_region_id);
updatable_shared_region = &shared_register.GetRegion(updatable_region_id);
static_region = *static_shared_region;
updatable_region = *updatable_shared_region;
facade_factory =
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
std::make_shared<datafacade::SharedMemoryAllocator>(
std::vector<storage::SharedRegionRegister::ShmKey>{
static_region.shm_key, updatable_region.shm_key}));
std::make_shared<datafacade::SharedMemoryAllocator>(barrier.data().region));
timestamp = barrier.data().timestamp;
}
watcher = std::thread(&DataWatchdogImpl::Run, this);
@@ -89,46 +74,30 @@ class DataWatchdogImpl<AlgorithmT, datafacade::ContiguousInternalMemoryDataFacad
{
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
while (active && static_region.timestamp == static_shared_region->timestamp &&
updatable_region.timestamp == updatable_shared_region->timestamp)
while (active && timestamp == barrier.data().timestamp)
{
barrier.wait(current_region_lock);
}
if (!active)
break;
if (static_region.timestamp != static_shared_region->timestamp)
if (timestamp != barrier.data().timestamp)
{
static_region = *static_shared_region;
auto region = barrier.data().region;
facade_factory =
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
std::make_shared<datafacade::SharedMemoryAllocator>(region));
timestamp = barrier.data().timestamp;
util::Log() << "updated facade to region " << region << " with timestamp "
<< timestamp;
}
if (updatable_region.timestamp != updatable_shared_region->timestamp)
{
updatable_region = *updatable_shared_region;
}
util::Log() << "updated facade to regions " << (int)static_region.shm_key << " and "
<< (int)updatable_region.shm_key << " with timestamps "
<< static_region.timestamp << " and " << updatable_region.timestamp;
facade_factory =
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT>(
std::make_shared<datafacade::SharedMemoryAllocator>(
std::vector<storage::SharedRegionRegister::ShmKey>{
static_region.shm_key, updatable_region.shm_key}));
}
util::Log() << "DataWatchdog thread stopped";
}
const std::string dataset_name;
storage::SharedMonitor<storage::SharedRegionRegister> barrier;
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
std::thread watcher;
bool active;
storage::SharedRegion static_region;
storage::SharedRegion updatable_region;
storage::SharedRegion *static_shared_region;
storage::SharedRegion *updatable_shared_region;
unsigned timestamp;
DataFacadeFactory<datafacade::ContiguousInternalMemoryDataFacade, AlgorithmT> facade_factory;
};
}
@@ -2,7 +2,6 @@
#define OSRM_ENGINE_DATAFACADE_ALGORITHM_DATAFACADE_HPP
#include "contractor/query_edge.hpp"
#include "customizer/edge_based_graph.hpp"
#include "extractor/edge_based_edge.hpp"
#include "engine/algorithm.hpp"
@@ -60,34 +59,22 @@ template <> class AlgorithmDataFacade<CH>
template <> class AlgorithmDataFacade<MLD>
{
public:
using EdgeData = customizer::EdgeBasedGraphEdgeData;
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
using EdgeRange = util::range<EdgeID>;
// search graph access
virtual unsigned GetNumberOfNodes() const = 0;
virtual unsigned GetMaxBorderNodeID() const = 0;
virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree(const NodeID n) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual EdgeWeight GetNodeWeight(const NodeID node) const = 0;
virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed
virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0;
virtual bool IsForwardEdge(EdgeID edge) const = 0;
virtual bool IsBackwardEdge(EdgeID edge) const = 0;
virtual NodeID GetTarget(const EdgeID e) const = 0;
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
virtual const partitioner::CellStorageView &GetCellStorage() const = 0;
@@ -1,7 +1,7 @@
#ifndef OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
#define OSRM_ENGINE_DATAFACADE_CONTIGUOUS_BLOCK_ALLOCATOR_HPP_
#include "storage/shared_data_index.hpp"
#include "storage/shared_datatype.hpp"
namespace osrm
{
@@ -16,7 +16,8 @@ class ContiguousBlockAllocator
virtual ~ContiguousBlockAllocator() = default;
// interface to give access to the datafacades
virtual const storage::SharedDataIndex &GetIndex() = 0;
virtual storage::DataLayout &GetLayout() = 0;
virtual char *GetMemory() = 0;
};
} // namespace datafacade
@@ -9,13 +9,44 @@
#include "engine/approach.hpp"
#include "engine/geospatial_query.hpp"
#include "customizer/edge_based_graph.hpp"
#include "extractor/datasources.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/intersection_bearings_container.hpp"
#include "extractor/maneuver_override.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/turn_lane_types.hpp"
#include "guidance/turn_bearing.hpp"
#include "guidance/turn_data_container.hpp"
#include "guidance/turn_instruction.hpp"
#include "contractor/query_graph.hpp"
#include "partitioner/cell_storage.hpp"
#include "partitioner/multi_level_partition.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory_ownership.hpp"
#include "storage/view_factory.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/filtered_graph.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/log.hpp"
#include "util/name_table.hpp"
#include "util/packed_vector.hpp"
#include "util/range_table.hpp"
#include "util/rectangle.hpp"
#include "util/static_graph.hpp"
#include "util/static_rtree.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
@@ -50,22 +81,44 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : public datafacade::Algor
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_,
const std::string &metric_name,
std::size_t exclude_index)
: allocator(std::move(allocator_))
void InitializeGraphPointer(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
memory_block, storage::DataLayout::CH_GRAPH_NODE_LIST);
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
memory_block, storage::DataLayout::CH_GRAPH_EDGE_LIST);
auto filter_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::CH_EDGE_FILTER_0 + exclude_index);
auto edge_filter_ptr = data_layout.GetBlockPtr<unsigned>(memory_block, filter_block_id);
util::vector_view<GraphNode> node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_NODE_LIST]);
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::CH_GRAPH_EDGE_LIST]);
util::vector_view<bool> edge_filter(edge_filter_ptr,
data_layout.num_entries[filter_block_id]);
m_query_graph = QueryGraph({node_list, edge_list}, edge_filter);
}
void InitializeInternalPointers(const storage::SharedDataIndex &index,
const std::string &metric_name,
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_, std::size_t exclude_index)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
}
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
m_query_graph =
make_filtered_graph_view(index, "/ch/metrics/" + metric_name, exclude_index);
InitializeGraphPointer(data_layout, memory_block, exclude_index);
}
// search graph access
@@ -133,10 +186,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
using RTreeNode = SharedRTree::TreeNode;
extractor::ClassData exclude_mask;
std::string m_timestamp;
extractor::ProfileProperties *m_profile_properties;
extractor::Datasources *m_datasources;
std::uint32_t m_check_sum;
unsigned m_check_sum;
util::vector_view<util::Coordinate> m_coordinate_list;
extractor::PackedOSMIDsView m_osmnodeid_list;
util::vector_view<std::uint32_t> m_lane_description_offsets;
@@ -155,13 +209,13 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
util::vector_view<extractor::StorageManeuverOverride> m_maneuver_overrides;
util::vector_view<NodeID> m_maneuver_override_node_sequences;
SharedRTree m_static_rtree;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path;
extractor::IntersectionBearingsView intersection_bearings_view;
extractor::NameTableView m_name_table;
util::NameTable m_name_table;
// the look-up table for entry classes. An entry class lists the possibility of entry for all
// available turns. Such a class id is stored with every edge.
util::vector_view<util::guidance::EntryClass> m_entry_class_table;
@@ -169,62 +223,328 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
// allocator that keeps the allocation data
std::shared_ptr<ContiguousBlockAllocator> allocator;
void InitializeInternalPointers(const storage::SharedDataIndex &index,
const std::string &metric_name,
const std::size_t exclude_index)
void InitializeProfilePropertiesPointer(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
// TODO: For multi-metric support we need to have separate exclude classes per metric
(void)metric_name;
m_profile_properties =
index.GetBlockPtr<extractor::ProfileProperties>("/common/properties");
m_profile_properties = data_layout.GetBlockPtr<extractor::ProfileProperties>(
memory_block, storage::DataLayout::PROPERTIES);
exclude_mask = m_profile_properties->excludable_classes[exclude_index];
}
m_check_sum = *index.GetBlockPtr<std::uint32_t>("/common/connectivity_checksum");
void InitializeTimestampPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto timestamp_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::TIMESTAMP);
m_timestamp.resize(data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP));
std::copy(timestamp_ptr,
timestamp_ptr + data_layout.GetBlockSize(storage::DataLayout::TIMESTAMP),
m_timestamp.begin());
}
std::tie(m_coordinate_list, m_osmnodeid_list) =
make_nbn_data_view(index, "/common/nbn_data");
void InitializeChecksumPointer(storage::DataLayout &data_layout, char *memory_block)
{
m_check_sum =
*data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::HSGR_CHECKSUM);
util::Log() << "set checksum: " << m_check_sum;
}
m_static_rtree = make_search_tree_view(index, "/common/rtree");
void InitializeRTreePointers(storage::DataLayout &data_layout, char *memory_block)
{
BOOST_ASSERT_MSG(!m_coordinate_list.empty(), "coordinates must be loaded before r-tree");
const auto file_index_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::FILE_INDEX_PATH);
file_index_path = boost::filesystem::path(file_index_ptr);
if (!boost::filesystem::exists(file_index_path))
{
util::Log(logDEBUG) << "Leaf file name " << file_index_path.string();
throw util::exception("Could not load " + file_index_path.string() +
"Is any data loaded into shared memory?" + SOURCE_REF);
}
auto tree_nodes_ptr =
data_layout.GetBlockPtr<RTreeNode>(memory_block, storage::DataLayout::R_SEARCH_TREE);
auto tree_level_sizes_ptr = data_layout.GetBlockPtr<std::uint64_t>(
memory_block, storage::DataLayout::R_SEARCH_TREE_LEVELS);
m_static_rtree.reset(
new SharedRTree(tree_nodes_ptr,
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE],
tree_level_sizes_ptr,
data_layout.num_entries[storage::DataLayout::R_SEARCH_TREE_LEVELS],
file_index_path,
m_coordinate_list));
m_geospatial_query.reset(
new SharedGeospatialQuery(m_static_rtree, m_coordinate_list, *this));
new SharedGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
edge_based_node_data = make_ebn_data_view(index, "/common/ebg_node_data");
void InitializeNodeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
{
const auto coordinate_list_ptr =
layout.GetBlockPtr<util::Coordinate>(memory_ptr, storage::DataLayout::COORDINATE_LIST);
m_coordinate_list.reset(coordinate_list_ptr,
layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
turn_data = make_turn_data_view(index, "/common/turn_data");
const auto osmnodeid_ptr = layout.GetBlockPtr<extractor::PackedOSMIDsView::block_type>(
memory_ptr, storage::DataLayout::OSM_NODE_ID_LIST);
m_osmnodeid_list = extractor::PackedOSMIDsView(
util::vector_view<extractor::PackedOSMIDsView::block_type>(
osmnodeid_ptr, layout.num_entries[storage::DataLayout::OSM_NODE_ID_LIST]),
// We (ab)use the number of coordinates here because we know we have the same amount of
// ids
layout.num_entries[storage::DataLayout::COORDINATE_LIST]);
}
m_name_table = make_name_table_view(index, "/common/names");
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr)
{
const auto edge_based_node_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode>(
memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
util::vector_view<extractor::EdgeBasedNode> edge_based_node_data_list(
edge_based_node_list_ptr,
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
std::tie(m_lane_description_offsets, m_lane_description_masks) =
make_turn_lane_description_views(index, "/common/turn_lanes");
m_lane_tupel_id_pairs = make_lane_data_view(index, "/common/turn_lanes");
const auto annotation_data_list_ptr =
layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation>(
memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
annotation_data_list_ptr,
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
m_turn_weight_penalties = make_turn_weight_view(index, "/common/turn_penalty");
m_turn_duration_penalties = make_turn_duration_view(index, "/common/turn_penalty");
edge_based_node_data = extractor::EdgeBasedNodeDataView(
std::move(edge_based_node_data_list), std::move(annotation_data));
}
segment_data = make_segment_data_view(index, "/common/segment_data");
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
{
const auto lane_data_id_ptr =
layout.GetBlockPtr<LaneDataID>(memory_ptr, storage::DataLayout::LANE_DATA_ID);
util::vector_view<LaneDataID> lane_data_ids(
lane_data_id_ptr, layout.num_entries[storage::DataLayout::LANE_DATA_ID]);
m_datasources = index.GetBlockPtr<extractor::Datasources>("/common/data_sources_names");
const auto turn_instruction_list_ptr = layout.GetBlockPtr<guidance::TurnInstruction>(
memory_ptr, storage::DataLayout::TURN_INSTRUCTION);
util::vector_view<guidance::TurnInstruction> turn_instructions(
turn_instruction_list_ptr, layout.num_entries[storage::DataLayout::TURN_INSTRUCTION]);
intersection_bearings_view =
make_intersection_bearings_view(index, "/common/intersection_bearings");
const auto entry_class_id_list_ptr =
layout.GetBlockPtr<EntryClassID>(memory_ptr, storage::DataLayout::ENTRY_CLASSID);
util::vector_view<EntryClassID> entry_class_ids(
entry_class_id_list_ptr, layout.num_entries[storage::DataLayout::ENTRY_CLASSID]);
m_entry_class_table = make_entry_classes_view(index, "/common/entry_classes");
const auto pre_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
memory_ptr, storage::DataLayout::PRE_TURN_BEARING);
util::vector_view<guidance::TurnBearing> pre_turn_bearings(
pre_turn_bearing_ptr, layout.num_entries[storage::DataLayout::PRE_TURN_BEARING]);
std::tie(m_maneuver_overrides, m_maneuver_override_node_sequences) =
make_maneuver_overrides_views(index, "/common/maneuver_overrides");
const auto post_turn_bearing_ptr = layout.GetBlockPtr<guidance::TurnBearing>(
memory_ptr, storage::DataLayout::POST_TURN_BEARING);
util::vector_view<guidance::TurnBearing> post_turn_bearings(
post_turn_bearing_ptr, layout.num_entries[storage::DataLayout::POST_TURN_BEARING]);
turn_data = guidance::TurnDataView(std::move(turn_instructions),
std::move(lane_data_ids),
std::move(entry_class_ids),
std::move(pre_turn_bearings),
std::move(post_turn_bearings));
}
void InitializeNamePointers(storage::DataLayout &data_layout, char *memory_block)
{
auto name_data_ptr =
data_layout.GetBlockPtr<char>(memory_block, storage::DataLayout::NAME_CHAR_DATA);
const auto name_data_size = data_layout.num_entries[storage::DataLayout::NAME_CHAR_DATA];
m_name_table.reset(name_data_ptr, name_data_ptr + name_data_size);
}
void InitializeTurnLaneDescriptionsPointers(storage::DataLayout &data_layout,
char *memory_block)
{
auto offsets_ptr = data_layout.GetBlockPtr<std::uint32_t>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_OFFSETS);
util::vector_view<std::uint32_t> offsets(
offsets_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_OFFSETS]);
m_lane_description_offsets = std::move(offsets);
auto masks_ptr = data_layout.GetBlockPtr<extractor::TurnLaneType::Mask>(
memory_block, storage::DataLayout::LANE_DESCRIPTION_MASKS);
util::vector_view<extractor::TurnLaneType::Mask> masks(
masks_ptr, data_layout.num_entries[storage::DataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
const auto lane_tupel_id_pair_ptr =
data_layout.GetBlockPtr<util::guidance::LaneTupleIdPair>(
memory_block, storage::DataLayout::TURN_LANE_DATA);
util::vector_view<util::guidance::LaneTupleIdPair> lane_tupel_id_pair(
lane_tupel_id_pair_ptr, data_layout.num_entries[storage::DataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
}
void InitializeTurnPenalties(storage::DataLayout &data_layout, char *memory_block)
{
auto turn_weight_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
memory_block, storage::DataLayout::TURN_WEIGHT_PENALTIES);
m_turn_weight_penalties = util::vector_view<TurnPenalty>(
turn_weight_penalties_ptr,
data_layout.num_entries[storage::DataLayout::TURN_WEIGHT_PENALTIES]);
auto turn_duration_penalties_ptr = data_layout.GetBlockPtr<TurnPenalty>(
memory_block, storage::DataLayout::TURN_DURATION_PENALTIES);
m_turn_duration_penalties = util::vector_view<TurnPenalty>(
turn_duration_penalties_ptr,
data_layout.num_entries[storage::DataLayout::TURN_DURATION_PENALTIES]);
}
void InitializeGeometryPointers(storage::DataLayout &data_layout, char *memory_block)
{
auto geometries_index_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::GEOMETRIES_INDEX);
util::vector_view<unsigned> geometry_begin_indices(
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST];
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries);
auto geometries_fwd_weight_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST);
extractor::SegmentDataView::SegmentWeightVector geometry_fwd_weight_list(
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
geometries_fwd_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_WEIGHT_LIST]),
num_entries);
auto geometries_rev_weight_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentWeightVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST);
extractor::SegmentDataView::SegmentWeightVector geometry_rev_weight_list(
util::vector_view<extractor::SegmentDataView::SegmentWeightVector::block_type>(
geometries_rev_weight_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_WEIGHT_LIST]),
num_entries);
auto geometries_fwd_duration_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST);
extractor::SegmentDataView::SegmentDurationVector geometry_fwd_duration_list(
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
geometries_fwd_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DURATION_LIST]),
num_entries);
auto geometries_rev_duration_list_ptr =
data_layout.GetBlockPtr<extractor::SegmentDataView::SegmentDurationVector::block_type>(
memory_block, storage::DataLayout::GEOMETRIES_REV_DURATION_LIST);
extractor::SegmentDataView::SegmentDurationVector geometry_rev_duration_list(
util::vector_view<extractor::SegmentDataView::SegmentDurationVector::block_type>(
geometries_rev_duration_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DURATION_LIST]),
num_entries);
auto geometries_fwd_datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
memory_block, storage::DataLayout::GEOMETRIES_FWD_DATASOURCES_LIST);
util::vector_view<DatasourceID> geometry_fwd_datasources_list(
geometries_fwd_datasources_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_FWD_DATASOURCES_LIST]);
auto geometries_rev_datasources_list_ptr = data_layout.GetBlockPtr<DatasourceID>(
memory_block, storage::DataLayout::GEOMETRIES_REV_DATASOURCES_LIST);
util::vector_view<DatasourceID> geometry_rev_datasources_list(
geometries_rev_datasources_list_ptr,
data_layout.num_entries[storage::DataLayout::GEOMETRIES_REV_DATASOURCES_LIST]);
segment_data = extractor::SegmentDataView{std::move(geometry_begin_indices),
std::move(geometry_node_list),
std::move(geometry_fwd_weight_list),
std::move(geometry_rev_weight_list),
std::move(geometry_fwd_duration_list),
std::move(geometry_rev_duration_list),
std::move(geometry_fwd_datasources_list),
std::move(geometry_rev_datasources_list)};
m_datasources = data_layout.GetBlockPtr<extractor::Datasources>(
memory_block, storage::DataLayout::DATASOURCES_NAMES);
}
void InitializeIntersectionClassPointers(storage::DataLayout &data_layout, char *memory_block)
{
auto bearing_class_id_ptr = data_layout.GetBlockPtr<BearingClassID>(
memory_block, storage::DataLayout::BEARING_CLASSID);
util::vector_view<BearingClassID> bearing_class_id(
bearing_class_id_ptr, data_layout.num_entries[storage::DataLayout::BEARING_CLASSID]);
auto bearing_values_ptr = data_layout.GetBlockPtr<DiscreteBearing>(
memory_block, storage::DataLayout::BEARING_VALUES);
util::vector_view<DiscreteBearing> bearing_values(
bearing_values_ptr, data_layout.num_entries[storage::DataLayout::BEARING_VALUES]);
auto offsets_ptr =
data_layout.GetBlockPtr<unsigned>(memory_block, storage::DataLayout::BEARING_OFFSETS);
auto blocks_ptr =
data_layout.GetBlockPtr<IndexBlock>(memory_block, storage::DataLayout::BEARING_BLOCKS);
util::vector_view<unsigned> bearing_offsets(
offsets_ptr, data_layout.num_entries[storage::DataLayout::BEARING_OFFSETS]);
util::vector_view<IndexBlock> bearing_blocks(
blocks_ptr, data_layout.num_entries[storage::DataLayout::BEARING_BLOCKS]);
util::RangeTable<16, storage::Ownership::View> bearing_range_table(
bearing_offsets, bearing_blocks, static_cast<unsigned>(bearing_values.size()));
intersection_bearings_view = extractor::IntersectionBearingsView{
std::move(bearing_values), std::move(bearing_class_id), std::move(bearing_range_table)};
auto entry_class_ptr = data_layout.GetBlockPtr<util::guidance::EntryClass>(
memory_block, storage::DataLayout::ENTRY_CLASS);
util::vector_view<util::guidance::EntryClass> entry_class_table(
entry_class_ptr, data_layout.num_entries[storage::DataLayout::ENTRY_CLASS]);
m_entry_class_table = std::move(entry_class_table);
}
void InitializeManeuverOverridePointers(storage::DataLayout &data_layout, char *memory_block)
{
auto maneuver_overrides_ptr = data_layout.GetBlockPtr<extractor::StorageManeuverOverride>(
memory_block, storage::DataLayout::MANEUVER_OVERRIDES);
m_maneuver_overrides = util::vector_view<extractor::StorageManeuverOverride>(
maneuver_overrides_ptr,
data_layout.num_entries[storage::DataLayout::MANEUVER_OVERRIDES]);
auto maneuver_override_node_sequences_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::MANEUVER_OVERRIDE_NODE_SEQUENCES);
m_maneuver_override_node_sequences = util::vector_view<NodeID>(
maneuver_override_node_sequences_ptr,
data_layout.num_entries[storage::DataLayout::MANEUVER_OVERRIDE_NODE_SEQUENCES]);
}
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
InitializeChecksumPointer(data_layout, memory_block);
InitializeNodeInformationPointers(data_layout, memory_block);
InitializeEdgeBasedNodeDataInformationPointers(data_layout, memory_block);
InitializeEdgeInformationPointers(data_layout, memory_block);
InitializeTurnPenalties(data_layout, memory_block);
InitializeGeometryPointers(data_layout, memory_block);
InitializeTimestampPointer(data_layout, memory_block);
InitializeNamePointers(data_layout, memory_block);
InitializeTurnLaneDescriptionsPointers(data_layout, memory_block);
InitializeProfilePropertiesPointer(data_layout, memory_block, exclude_index);
InitializeRTreePointers(data_layout, memory_block);
InitializeIntersectionClassPointers(data_layout, memory_block);
InitializeManeuverOverridePointers(data_layout, memory_block);
}
public:
// allows switching between process_memory/shared_memory datafacade, based on the type of
// allocator
ContiguousInternalMemoryDataFacadeBase(std::shared_ptr<ContiguousBlockAllocator> allocator_,
const std::string &metric_name,
const std::size_t exclude_index)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
}
// node and edge information access
@@ -238,57 +558,72 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_osmnodeid_list[id];
}
NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const override final
std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const override final
{
return segment_data.GetForwardGeometry(id);
auto range = segment_data.GetForwardGeometry(id);
return std::vector<NodeID>{range.begin(), range.end()};
}
NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const override final
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const override final
{
return segment_data.GetReverseGeometry(id);
auto range = segment_data.GetReverseGeometry(id);
return std::vector<NodeID>{range.begin(), range.end()};
}
DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const override final
virtual std::vector<EdgeWeight>
GetUncompressedForwardDurations(const EdgeID id) const override final
{
return segment_data.GetForwardDurations(id);
auto range = segment_data.GetForwardDurations(id);
return std::vector<EdgeWeight>{range.begin(), range.end()};
}
DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const override final
virtual std::vector<EdgeWeight>
GetUncompressedReverseDurations(const EdgeID id) const override final
{
return segment_data.GetReverseDurations(id);
auto range = segment_data.GetReverseDurations(id);
return std::vector<EdgeWeight>{range.begin(), range.end()};
}
WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const override final
virtual std::vector<EdgeWeight>
GetUncompressedForwardWeights(const EdgeID id) const override final
{
return segment_data.GetForwardWeights(id);
auto range = segment_data.GetForwardWeights(id);
return std::vector<EdgeWeight>{range.begin(), range.end()};
}
WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const override final
virtual std::vector<EdgeWeight>
GetUncompressedReverseWeights(const EdgeID id) const override final
{
return segment_data.GetReverseWeights(id);
auto range = segment_data.GetReverseWeights(id);
return std::vector<EdgeWeight>{range.begin(), range.end()};
}
// Returns the data source ids that were used to supply the edge
// weights.
DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const override final
virtual std::vector<DatasourceID>
GetUncompressedForwardDatasources(const EdgeID id) const override final
{
return segment_data.GetForwardDatasources(id);
auto range = segment_data.GetForwardDatasources(id);
return std::vector<DatasourceID>{range.begin(), range.end()};
}
// Returns the data source ids that were used to supply the edge
// weights.
DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const override final
virtual std::vector<DatasourceID>
GetUncompressedReverseDatasources(const EdgeID id) const override final
{
return segment_data.GetReverseDatasources(id);
auto range = segment_data.GetReverseDatasources(id);
return std::vector<DatasourceID>{range.begin(), range.end()};
}
TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const override final
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const override final
{
BOOST_ASSERT(m_turn_weight_penalties.size() > id);
return m_turn_weight_penalties[id];
}
TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const override final
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const override final
{
BOOST_ASSERT(m_turn_duration_penalties.size() > id);
return m_turn_duration_penalties[id];
@@ -428,7 +763,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
input_coordinate, bearing, bearing_range, approach);
}
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
unsigned GetCheckSum() const override final { return m_check_sum; }
GeometryID GetGeometryIndex(const NodeID id) const override final
{
@@ -501,6 +836,8 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
return m_datasources->GetSourceName(id);
}
std::string GetTimestamp() const override final { return m_timestamp; }
bool GetContinueStraightDefault() const override final
{
return m_profile_properties->continue_straight_at_waypoint;
@@ -617,10 +954,10 @@ class ContiguousInternalMemoryDataFacade<CH>
{
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
const std::string &metric_name,
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, metric_name, exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<CH>(allocator, exclude_index)
{
}
};
@@ -637,15 +974,122 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
QueryGraph query_graph;
void InitializeInternalPointers(const storage::SharedDataIndex &index,
const std::string &metric_name,
void InitializeInternalPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
mld_partition = make_partition_view(index, "/mld/multilevelpartition");
mld_cell_metric =
make_filtered_cell_metric_view(index, "/mld/metrics/" + metric_name, exclude_index);
mld_cell_storage = make_cell_storage_view(index, "/mld/cellstorage");
query_graph = make_multi_level_graph_view(index, "/mld/multilevelgraph");
InitializeMLDDataPointers(data_layout, memory_block, exclude_index);
InitializeGraphPointer(data_layout, memory_block);
}
void InitializeMLDDataPointers(storage::DataLayout &data_layout,
char *memory_block,
const std::size_t exclude_index)
{
if (data_layout.GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0)
{
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0);
BOOST_ASSERT(data_layout.GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0);
auto level_data =
data_layout.GetBlockPtr<partitioner::MultiLevelPartitionView::LevelData>(
memory_block, storage::DataLayout::MLD_LEVEL_DATA);
auto mld_partition_ptr = data_layout.GetBlockPtr<PartitionID>(
memory_block, storage::DataLayout::MLD_PARTITION);
auto partition_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_PARTITION);
util::vector_view<PartitionID> partition(mld_partition_ptr, partition_entries_count);
auto mld_chilren_ptr = data_layout.GetBlockPtr<CellID>(
memory_block, storage::DataLayout::MLD_CELL_TO_CHILDREN);
auto children_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_TO_CHILDREN);
util::vector_view<CellID> cell_to_children(mld_chilren_ptr, children_entries_count);
mld_partition =
partitioner::MultiLevelPartitionView{level_data, partition, cell_to_children};
}
const auto weights_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::MLD_CELL_WEIGHTS_0 + exclude_index);
const auto durations_block_id = static_cast<storage::DataLayout::BlockID>(
storage::DataLayout::MLD_CELL_DURATIONS_0 + exclude_index);
if (data_layout.GetBlockSize(weights_block_id) > 0)
{
auto mld_cell_weights_ptr =
data_layout.GetBlockPtr<EdgeWeight>(memory_block, weights_block_id);
auto mld_cell_durations_ptr =
data_layout.GetBlockPtr<EdgeDuration>(memory_block, durations_block_id);
auto weight_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_WEIGHTS_0);
auto duration_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DURATIONS_0);
BOOST_ASSERT(weight_entries_count == duration_entries_count);
util::vector_view<EdgeWeight> weights(mld_cell_weights_ptr, weight_entries_count);
util::vector_view<EdgeDuration> durations(mld_cell_durations_ptr,
duration_entries_count);
mld_cell_metric = customizer::CellMetricView{std::move(weights), std::move(durations)};
}
if (data_layout.GetBlockSize(storage::DataLayout::MLD_CELLS) > 0)
{
auto mld_source_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto mld_destination_boundary_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY);
auto mld_cells_ptr = data_layout.GetBlockPtr<partitioner::CellStorageView::CellData>(
memory_block, storage::DataLayout::MLD_CELLS);
auto mld_cell_level_offsets_ptr = data_layout.GetBlockPtr<std::uint64_t>(
memory_block, storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
auto source_boundary_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_SOURCE_BOUNDARY);
auto destination_boundary_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_DESTINATION_BOUNDARY);
auto cells_entries_counts = data_layout.GetBlockEntries(storage::DataLayout::MLD_CELLS);
auto cell_level_offsets_entries_count =
data_layout.GetBlockEntries(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS);
util::vector_view<NodeID> source_boundary(mld_source_boundary_ptr,
source_boundary_entries_count);
util::vector_view<NodeID> destination_boundary(mld_destination_boundary_ptr,
destination_boundary_entries_count);
util::vector_view<partitioner::CellStorageView::CellData> cells(mld_cells_ptr,
cells_entries_counts);
util::vector_view<std::uint64_t> level_offsets(mld_cell_level_offsets_ptr,
cell_level_offsets_entries_count);
mld_cell_storage = partitioner::CellStorageView{std::move(source_boundary),
std::move(destination_boundary),
std::move(cells),
std::move(level_offsets)};
}
}
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
memory_block, storage::DataLayout::MLD_GRAPH_NODE_LIST);
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
memory_block, storage::DataLayout::MLD_GRAPH_EDGE_LIST);
auto graph_node_to_offset_ptr = data_layout.GetBlockPtr<QueryGraph::EdgeOffset>(
memory_block, storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET);
util::vector_view<GraphNode> node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
util::vector_view<GraphEdge> edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
util::vector_view<QueryGraph::EdgeOffset> node_to_offset(
graph_node_to_offset_ptr,
data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET]);
query_graph =
QueryGraph(std::move(node_list), std::move(edge_list), std::move(node_to_offset));
}
// allocator that keeps the allocation data
@@ -653,12 +1097,10 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
public:
ContiguousInternalMemoryAlgorithmDataFacade(
std::shared_ptr<ContiguousBlockAllocator> allocator_,
const std::string &metric_name,
const std::size_t exclude_index)
std::shared_ptr<ContiguousBlockAllocator> allocator_, const std::size_t exclude_index)
: allocator(std::move(allocator_))
{
InitializeInternalPointers(allocator->GetIndex(), metric_name, exclude_index);
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory(), exclude_index);
}
const partitioner::MultiLevelPartitionView &GetMultiLevelPartition() const override
@@ -673,8 +1115,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
// search graph access
unsigned GetNumberOfNodes() const override final { return query_graph.GetNumberOfNodes(); }
unsigned GetMaxBorderNodeID() const override final { return query_graph.GetMaxBorderNodeID(); }
unsigned GetNumberOfEdges() const override final { return query_graph.GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final
@@ -682,36 +1122,6 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
return query_graph.GetOutDegree(n);
}
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return query_graph.GetAdjacentEdgeRange(node);
}
EdgeWeight GetNodeWeight(const NodeID node) const override final
{
return query_graph.GetNodeWeight(node);
}
EdgeDuration GetNodeDuration(const NodeID node) const override final
{
return query_graph.GetNodeDuration(node);
}
EdgeDistance GetNodeDistance(const NodeID node) const override final
{
return query_graph.GetNodeDistance(node);
}
bool IsForwardEdge(const NodeID node) const override final
{
return query_graph.IsForwardEdge(node);
}
bool IsBackwardEdge(const NodeID node) const override final
{
return query_graph.IsBackwardEdge(node);
}
NodeID GetTarget(const EdgeID e) const override final { return query_graph.GetTarget(e); }
const EdgeData &GetEdgeData(const EdgeID e) const override final
@@ -719,6 +1129,11 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade<MLD> : public Algo
return query_graph.GetEdgeData(e);
}
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return query_graph.GetAdjacentEdgeRange(node);
}
EdgeRange GetBorderEdgeRange(const LevelID level, const NodeID node) const override final
{
return query_graph.GetBorderEdgeRange(level, node);
@@ -739,10 +1154,10 @@ class ContiguousInternalMemoryDataFacade<MLD> final
private:
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator,
const std::string &metric_name,
const std::size_t exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, metric_name, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, metric_name, exclude_index)
: ContiguousInternalMemoryDataFacadeBase(allocator, exclude_index),
ContiguousInternalMemoryAlgorithmDataFacade<MLD>(allocator, exclude_index)
{
}
};
+16 -32
View File
@@ -10,9 +10,10 @@
#include "extractor/class_data.hpp"
#include "extractor/edge_based_node_segment.hpp"
//#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/maneuver_override.hpp"
//#include "extractor/original_edge_data.hpp"
#include "extractor/query_node.hpp"
#include "extractor/segment_data_container.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/turn_lane_types.hpp"
@@ -24,15 +25,12 @@
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/integer_range.hpp"
#include "util/packed_vector.hpp"
#include "util/string_util.hpp"
#include "util/string_view.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/any_range.hpp>
#include <cstddef>
#include <string>
@@ -52,27 +50,10 @@ class BaseDataFacade
{
public:
using RTreeLeaf = extractor::EdgeBasedNodeSegment;
using NodeForwardRange =
boost::iterator_range<extractor::SegmentDataView::SegmentNodeVector::const_iterator>;
using NodeReverseRange = boost::reversed_range<const NodeForwardRange>;
using WeightForwardRange =
boost::iterator_range<extractor::SegmentDataView::SegmentWeightVector::const_iterator>;
using WeightReverseRange = boost::reversed_range<const WeightForwardRange>;
using DurationForwardRange =
boost::iterator_range<extractor::SegmentDataView::SegmentDurationVector::const_iterator>;
using DurationReverseRange = boost::reversed_range<const DurationForwardRange>;
using DatasourceForwardRange =
boost::iterator_range<extractor::SegmentDataView::SegmentDatasourceVector::const_iterator>;
using DatasourceReverseRange = boost::reversed_range<const DatasourceForwardRange>;
BaseDataFacade() {}
virtual ~BaseDataFacade() {}
virtual std::uint32_t GetCheckSum() const = 0;
virtual unsigned GetCheckSum() const = 0;
// node and edge information access
virtual util::Coordinate GetCoordinateOfNode(const NodeID id) const = 0;
@@ -83,27 +64,28 @@ class BaseDataFacade
virtual ComponentID GetComponentID(const NodeID id) const = 0;
virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0;
virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0;
virtual std::vector<NodeID> GetUncompressedForwardGeometry(const EdgeID id) const = 0;
virtual TurnPenalty GetWeightPenaltyForEdgeID(const EdgeID id) const = 0;
virtual std::vector<NodeID> GetUncompressedReverseGeometry(const EdgeID id) const = 0;
virtual TurnPenalty GetDurationPenaltyForEdgeID(const EdgeID id) const = 0;
virtual TurnPenalty GetWeightPenaltyForEdgeID(const unsigned id) const = 0;
virtual TurnPenalty GetDurationPenaltyForEdgeID(const unsigned id) const = 0;
// Gets the weight values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry
virtual WeightForwardRange GetUncompressedForwardWeights(const EdgeID id) const = 0;
virtual WeightReverseRange GetUncompressedReverseWeights(const EdgeID id) const = 0;
virtual std::vector<EdgeWeight> GetUncompressedForwardWeights(const EdgeID id) const = 0;
virtual std::vector<EdgeWeight> GetUncompressedReverseWeights(const EdgeID id) const = 0;
// Gets the duration values for each segment in an uncompressed geometry.
// Should always be 1 shorter than GetUncompressedGeometry
virtual DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const = 0;
virtual DurationReverseRange GetUncompressedReverseDurations(const EdgeID id) const = 0;
virtual std::vector<EdgeWeight> GetUncompressedForwardDurations(const EdgeID id) const = 0;
virtual std::vector<EdgeWeight> GetUncompressedReverseDurations(const EdgeID id) const = 0;
// Returns the data source ids that were used to supply the edge
// weights. Will return an empty array when only the base profile is used.
virtual DatasourceForwardRange GetUncompressedForwardDatasources(const EdgeID id) const = 0;
virtual DatasourceReverseRange GetUncompressedReverseDatasources(const EdgeID id) const = 0;
virtual std::vector<DatasourceID> GetUncompressedForwardDatasources(const EdgeID id) const = 0;
virtual std::vector<DatasourceID> GetUncompressedReverseDatasources(const EdgeID id) const = 0;
// Gets the name of a datasource
virtual StringView GetDatasourceName(const DatasourceID id) const = 0;
@@ -191,6 +173,8 @@ class BaseDataFacade
virtual StringView GetExitsForID(const NameID id) const = 0;
virtual std::string GetTimestamp() const = 0;
virtual bool GetContinueStraightDefault() const = 0;
virtual double GetMapMatchingMaxSpeed() const = 0;
@@ -1,44 +0,0 @@
#ifndef OSRM_ENGINE_DATAFACADE_MMAP_MEMORY_ALLOCATOR_HPP_
#define OSRM_ENGINE_DATAFACADE_MMAP_MEMORY_ALLOCATOR_HPP_
#include "engine/datafacade/contiguous_block_allocator.hpp"
#include "storage/storage_config.hpp"
#include "util/vector_view.hpp"
#include <boost/iostreams/device/mapped_file.hpp>
#include <memory>
#include <string>
namespace osrm
{
namespace engine
{
namespace datafacade
{
/**
* This allocator uses file backed mmap memory block as the data location.
*/
class MMapMemoryAllocator : public ContiguousBlockAllocator
{
public:
explicit MMapMemoryAllocator(const storage::StorageConfig &config);
~MMapMemoryAllocator() override final;
// interface to give access to the datafacades
const storage::SharedDataIndex &GetIndex() override final;
private:
storage::SharedDataIndex index;
std::vector<boost::iostreams::mapped_file> mapped_memory_files;
std::string rtree_filename;
};
} // namespace datafacade
} // namespace engine
} // namespace osrm
#endif // OSRM_ENGINE_DATAFACADE_SHARED_MEMORY_ALLOCATOR_HPP_
@@ -27,11 +27,12 @@ class ProcessMemoryAllocator : public ContiguousBlockAllocator
~ProcessMemoryAllocator() override final;
// interface to give access to the datafacades
const storage::SharedDataIndex &GetIndex() override final;
storage::DataLayout &GetLayout() override final;
char *GetMemory() override final;
private:
storage::SharedDataIndex index;
std::unique_ptr<char[]> internal_memory;
std::unique_ptr<storage::DataLayout> internal_layout;
};
} // namespace datafacade
@@ -3,7 +3,7 @@
#include "engine/datafacade/contiguous_block_allocator.hpp"
#include "storage/shared_data_index.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include <memory>
@@ -23,16 +23,15 @@ namespace datafacade
class SharedMemoryAllocator : public ContiguousBlockAllocator
{
public:
explicit SharedMemoryAllocator(
const std::vector<storage::SharedRegionRegister::ShmKey> &shm_keys);
explicit SharedMemoryAllocator(storage::SharedDataType data_region);
~SharedMemoryAllocator() override final;
// interface to give access to the datafacades
const storage::SharedDataIndex &GetIndex() override final;
storage::DataLayout &GetLayout() override final;
char *GetMemory() override final;
private:
storage::SharedDataIndex index;
std::vector<std::unique_ptr<storage::SharedMemory>> memory_regions;
std::unique_ptr<storage::SharedMemory> m_large_memory;
};
} // namespace datafacade
+6 -30
View File
@@ -33,7 +33,6 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator)
: DataFacadeFactory(allocator, has_exclude_flags)
{
BOOST_ASSERT_MSG(facades.size() >= 1, "At least one datafacade is needed");
}
template <typename ParameterT> std::shared_ptr<const Facade> Get(const ParameterT &params) const
@@ -46,33 +45,13 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
template <typename AllocatorT>
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::true_type)
{
const auto &index = allocator->GetIndex();
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
const auto &metric_name = properties->GetWeightName();
std::vector<std::string> exclude_prefixes;
auto exclude_path = std::string("/") + routing_algorithms::identifier<AlgorithmT>() +
std::string("/metrics/") + metric_name + "/exclude/";
index.List(exclude_path, std::back_inserter(exclude_prefixes));
facades.resize(exclude_prefixes.size());
if (facades.empty())
for (const auto index : util::irange<std::size_t>(0, facades.size()))
{
throw util::exception(std::string("Could not find any metrics for ") +
routing_algorithms::name<AlgorithmT>() +
" in the data. Did you load the right dataset?");
facades[index] = std::make_shared<const Facade>(allocator, index);
}
for (const auto &exclude_prefix : exclude_prefixes)
{
auto index_begin = exclude_prefix.find_last_of("/");
BOOST_ASSERT_MSG(index_begin != std::string::npos,
"The exclude prefix needs to be a valid data path.");
std::size_t index =
std::stoi(exclude_prefix.substr(index_begin + 1, exclude_prefix.size()));
BOOST_ASSERT(index >= 0 && index < facades.size());
facades[index] = std::make_shared<const Facade>(allocator, metric_name, index);
}
properties = allocator->GetLayout().template GetBlockPtr<extractor::ProfileProperties>(
allocator->GetMemory(), storage::DataLayout::PROPERTIES);
for (const auto index : util::irange<std::size_t>(0, properties->class_names.size()))
{
@@ -88,10 +67,7 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
template <typename AllocatorT>
DataFacadeFactory(std::shared_ptr<AllocatorT> allocator, std::false_type)
{
const auto &index = allocator->GetIndex();
properties = index.template GetBlockPtr<extractor::ProfileProperties>("/common/properties");
const auto &metric_name = properties->GetWeightName();
facades.push_back(std::make_shared<const Facade>(allocator, metric_name, 0));
facades[0] = std::make_shared<const Facade>(allocator, 0);
}
std::shared_ptr<const Facade> Get(const api::TileParameters &, std::false_type) const
@@ -148,7 +124,7 @@ template <template <typename A> class FacadeT, typename AlgorithmT> class DataFa
return {};
}
std::vector<std::shared_ptr<const Facade>> facades;
std::array<std::shared_ptr<const Facade>, extractor::MAX_EXCLUDABLE_CLASSES> facades;
std::unordered_map<std::string, extractor::ClassData> name_to_class;
const extractor::ProfileProperties *properties = nullptr;
};
-29
View File
@@ -4,7 +4,6 @@
#include "engine/data_watchdog.hpp"
#include "engine/datafacade.hpp"
#include "engine/datafacade/contiguous_internalmem_datafacade.hpp"
#include "engine/datafacade/mmap_memory_allocator.hpp"
#include "engine/datafacade/process_memory_allocator.hpp"
#include "engine/datafacade_factory.hpp"
@@ -26,30 +25,6 @@ template <typename AlgorithmT, template <typename A> class FacadeT> class DataFa
virtual std::shared_ptr<const Facade> Get(const api::TileParameters &) const = 0;
};
template <typename AlgorithmT, template <typename A> class FacadeT>
class ExternalProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
{
public:
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
ExternalProvider(const storage::StorageConfig &config)
: facade_factory(std::make_shared<datafacade::MMapMemoryAllocator>(config))
{
}
std::shared_ptr<const Facade> Get(const api::TileParameters &params) const override final
{
return facade_factory.Get(params);
}
std::shared_ptr<const Facade> Get(const api::BaseParameters &params) const override final
{
return facade_factory.Get(params);
}
private:
DataFacadeFactory<FacadeT, AlgorithmT> facade_factory;
};
template <typename AlgorithmT, template <typename A> class FacadeT>
class ImmutableProvider final : public DataFacadeProvider<AlgorithmT, FacadeT>
{
@@ -82,8 +57,6 @@ class WatchingProvider : public DataFacadeProvider<AlgorithmT, FacadeT>
public:
using Facade = typename DataFacadeProvider<AlgorithmT, FacadeT>::Facade;
WatchingProvider(const std::string &dataset_name) : watchdog(dataset_name) {}
std::shared_ptr<const Facade> Get(const api::TileParameters &params) const override final
{
return watchdog.Get(params);
@@ -101,8 +74,6 @@ template <typename AlgorithmT>
using WatchingProvider = detail::WatchingProvider<AlgorithmT, DataFacade>;
template <typename AlgorithmT>
using ImmutableProvider = detail::ImmutableProvider<AlgorithmT, DataFacade>;
template <typename AlgorithmT>
using ExternalProvider = detail::ExternalProvider<AlgorithmT, DataFacade>;
}
}
+77 -14
View File
@@ -7,6 +7,8 @@
#include "engine/api/table_parameters.hpp"
#include "engine/api/tile_parameters.hpp"
#include "engine/api/trip_parameters.hpp"
#include "engine/data_watchdog.hpp"
#include "engine/datafacade/contiguous_block_allocator.hpp"
#include "engine/datafacade_provider.hpp"
#include "engine/engine_config.hpp"
#include "engine/plugins/match.hpp"
@@ -17,7 +19,9 @@
#include "engine/plugins/viaroute.hpp"
#include "engine/routing_algorithms.hpp"
#include "engine/status.hpp"
#include "util/exception.hpp"
#include "util/exception_utils.hpp"
#include "util/fingerprint.hpp"
#include "util/json_container.hpp"
#include <memory>
@@ -59,20 +63,9 @@ template <typename Algorithm> class Engine final : public EngineInterface
{
if (config.use_shared_memory)
{
util::Log(logDEBUG) << "Using shared memory with name \"" << config.dataset_name
<< "\" with algorithm " << routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name);
}
else if (!config.memory_file.empty() || config.use_mmap)
{
if (!config.memory_file.empty())
{
util::Log(logWARNING)
<< "The 'memory_file' option is DEPRECATED - using direct mmaping instead";
}
util::Log(logDEBUG) << "Using direct memory mapping with algorithm "
util::Log(logDEBUG) << "Using shared memory with algorithm "
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config);
facade_provider = std::make_unique<WatchingProvider<Algorithm>>();
}
else
{
@@ -123,6 +116,8 @@ template <typename Algorithm> class Engine final : public EngineInterface
return tile_plugin.HandleRequest(GetAlgorithms(params), params, result);
}
static bool CheckCompatibility(const EngineConfig &config);
private:
template <typename ParametersT> auto GetAlgorithms(const ParametersT &params) const
{
@@ -138,6 +133,74 @@ template <typename Algorithm> class Engine final : public EngineInterface
const plugins::MatchPlugin match_plugin;
const plugins::TilePlugin tile_plugin;
};
template <>
bool Engine<routing_algorithms::ch::Algorithm>::CheckCompatibility(const EngineConfig &config)
{
if (config.use_shared_memory)
{
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
using mutex_type = typename decltype(barrier)::mutex_type;
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
return layout->GetBlockSize(storage::DataLayout::CH_GRAPH_NODE_LIST) > 4 &&
layout->GetBlockSize(storage::DataLayout::CH_GRAPH_EDGE_LIST) > 4;
}
else
{
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.hsgr")))
return false;
storage::io::FileReader in(config.storage_config.GetPath(".osrm.hsgr"),
storage::io::FileReader::VerifyFingerprint);
auto size = in.GetSize();
return size > 0;
}
}
template <>
bool Engine<routing_algorithms::mld::Algorithm>::CheckCompatibility(const EngineConfig &config)
{
if (config.use_shared_memory)
{
storage::SharedMonitor<storage::SharedDataTimestamp> barrier;
using mutex_type = typename decltype(barrier)::mutex_type;
boost::interprocess::scoped_lock<mutex_type> current_region_lock(barrier.get_mutex());
auto mem = storage::makeSharedMemory(barrier.data().region);
auto layout = reinterpret_cast<storage::DataLayout *>(mem->Ptr());
// checks that all the needed memory blocks are populated
// DataLayout::MLD_CELL_SOURCE_BOUNDARY and DataLayout::MLD_CELL_DESTINATION_BOUNDARY
// are not checked, because in situations where there are so few nodes in the graph that
// they all fit into one cell, they can be empty.
bool empty_data = layout->GetBlockSize(storage::DataLayout::MLD_LEVEL_DATA) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_PARTITION) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_TO_CHILDREN) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELLS) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_LEVEL_OFFSETS) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_LIST) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_EDGE_LIST) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_WEIGHTS_0) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_CELL_DURATIONS_0) > 0 &&
layout->GetBlockSize(storage::DataLayout::MLD_GRAPH_NODE_TO_OFFSET) > 0;
return empty_data;
}
else
{
if (!boost::filesystem::exists(config.storage_config.GetPath(".osrm.partition")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cells")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.mldgr")) ||
!boost::filesystem::exists(config.storage_config.GetPath(".osrm.cell_metrics")))
return false;
storage::io::FileReader in(config.storage_config.GetPath(".osrm.partition"),
storage::io::FileReader::VerifyFingerprint);
auto size = in.GetSize();
return size > 0;
}
}
}
}
-3
View File
@@ -88,11 +88,8 @@ struct EngineConfig final
int max_results_nearest = -1;
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true;
boost::filesystem::path memory_file;
bool use_mmap = true;
Algorithm algorithm = Algorithm::CH;
std::string verbosity;
std::string dataset_name;
};
}
}
+40 -71
View File
@@ -13,7 +13,6 @@
#include <algorithm>
#include <cmath>
#include <iterator>
#include <memory>
#include <vector>
@@ -435,6 +434,11 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
// Find the node-based-edge that this belongs to, and directly
// calculate the forward_weight, forward_offset, reverse_weight, reverse_offset
EdgeWeight forward_weight_offset = 0, forward_weight = 0;
EdgeWeight reverse_weight_offset = 0, reverse_weight = 0;
EdgeDuration forward_duration_offset = 0, forward_duration = 0;
EdgeDuration reverse_duration_offset = 0, reverse_duration = 0;
BOOST_ASSERT(data.forward_segment_id.enabled || data.reverse_segment_id.enabled);
BOOST_ASSERT(!data.reverse_segment_id.enabled ||
datafacade.GetGeometryIndex(data.forward_segment_id.id).id ==
@@ -442,70 +446,35 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
const auto component_id = datafacade.GetComponentID(data.forward_segment_id.id);
const auto forward_weights = datafacade.GetUncompressedForwardWeights(geometry_id);
const auto reverse_weights = datafacade.GetUncompressedReverseWeights(geometry_id);
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(geometry_id);
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(geometry_id);
const std::vector<EdgeWeight> forward_duration_vector =
datafacade.GetUncompressedForwardDurations(geometry_id);
const std::vector<EdgeWeight> reverse_duration_vector =
datafacade.GetUncompressedReverseDurations(geometry_id);
const auto forward_durations = datafacade.GetUncompressedForwardDurations(geometry_id);
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
const auto forward_weight_offset =
std::accumulate(forward_weights.begin(),
forward_weights.begin() + data.fwd_segment_position,
EdgeWeight{0});
const auto forward_duration_offset =
std::accumulate(forward_durations.begin(),
forward_durations.begin() + data.fwd_segment_position,
EdgeDuration{0});
EdgeDistance forward_distance_offset = 0;
for (auto current = forward_geometry.begin();
current < forward_geometry.begin() + data.fwd_segment_position;
++current)
for (std::size_t i = 0; i < data.fwd_segment_position; i++)
{
forward_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
forward_weight_offset += forward_weight_vector[i];
forward_duration_offset += forward_duration_vector[i];
}
forward_weight = forward_weight_vector[data.fwd_segment_position];
forward_duration = forward_duration_vector[data.fwd_segment_position];
BOOST_ASSERT(data.fwd_segment_position <
std::distance(forward_durations.begin(), forward_durations.end()));
BOOST_ASSERT(data.fwd_segment_position < reverse_weight_vector.size());
EdgeWeight forward_weight = forward_weights[data.fwd_segment_position];
EdgeDuration forward_duration = forward_durations[data.fwd_segment_position];
EdgeDistance forward_distance = util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
point_on_segment);
const auto reverse_weight_offset =
std::accumulate(reverse_weights.begin(),
reverse_weights.end() - data.fwd_segment_position - 1,
EdgeWeight{0});
const auto reverse_duration_offset =
std::accumulate(reverse_durations.begin(),
reverse_durations.end() - data.fwd_segment_position - 1,
EdgeDuration{0});
EdgeDistance reverse_distance_offset = 0;
for (auto current = forward_geometry.begin();
current < forward_geometry.end() - data.fwd_segment_position - 2;
++current)
for (std::size_t i = 0; i < reverse_weight_vector.size() - data.fwd_segment_position - 1;
i++)
{
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
datafacade.GetCoordinateOfNode(*current),
datafacade.GetCoordinateOfNode(*std::next(current)));
reverse_weight_offset += reverse_weight_vector[i];
reverse_duration_offset += reverse_duration_vector[i];
}
EdgeWeight reverse_weight =
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
EdgeDuration reverse_duration =
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
point_on_segment,
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
reverse_weight =
reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1];
reverse_duration =
reverse_duration_vector[reverse_duration_vector.size() - data.fwd_segment_position - 1];
ratio = std::min(1.0, std::max(0.0, ratio));
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
@@ -524,13 +493,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
};
bool is_forward_valid_source =
areSegmentsValid(forward_weights.begin(), forward_weights.end());
bool is_forward_valid_target = areSegmentsValid(
forward_weights.begin(), forward_weights.begin() + data.fwd_segment_position + 1);
areSegmentsValid(forward_weight_vector.begin(), forward_weight_vector.end());
bool is_forward_valid_target =
areSegmentsValid(forward_weight_vector.begin(),
forward_weight_vector.begin() + data.fwd_segment_position + 1);
bool is_reverse_valid_source =
areSegmentsValid(reverse_weights.begin(), reverse_weights.end());
areSegmentsValid(reverse_weight_vector.begin(), reverse_weight_vector.end());
bool is_reverse_valid_target = areSegmentsValid(
reverse_weights.begin(), reverse_weights.end() - data.fwd_segment_position);
reverse_weight_vector.begin(), reverse_weight_vector.end() - data.fwd_segment_position);
auto transformed = PhantomNodeWithDistance{
PhantomNode{data,
@@ -539,10 +509,6 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_weight,
forward_weight_offset,
reverse_weight_offset,
forward_distance,
reverse_distance,
forward_distance_offset,
reverse_distance_offset,
forward_duration,
reverse_duration,
forward_duration_offset,
@@ -639,14 +605,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
BOOST_ASSERT(data.forward_segment_id.id != SPECIAL_NODEID);
const auto geometry_id = datafacade.GetGeometryIndex(data.forward_segment_id.id).id;
const auto forward_weights = datafacade.GetUncompressedForwardWeights(geometry_id);
if (forward_weights[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
const std::vector<EdgeWeight> forward_weight_vector =
datafacade.GetUncompressedForwardWeights(geometry_id);
if (forward_weight_vector[data.fwd_segment_position] != INVALID_SEGMENT_WEIGHT)
{
forward_edge_valid = data.forward_segment_id.enabled;
}
const auto reverse_weights = datafacade.GetUncompressedReverseWeights(geometry_id);
if (reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1] !=
const std::vector<EdgeWeight> reverse_weight_vector =
datafacade.GetUncompressedReverseWeights(geometry_id);
if (reverse_weight_vector[reverse_weight_vector.size() - data.fwd_segment_position - 1] !=
INVALID_SEGMENT_WEIGHT)
{
reverse_edge_valid = data.reverse_segment_id.enabled;
+16 -39
View File
@@ -12,7 +12,6 @@
#include "util/coordinate_calculation.hpp"
#include <algorithm>
#include <cmath>
#include <utility>
#include <vector>
@@ -55,10 +54,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto source_node_id =
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
std::vector<NodeID> source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate)));
facade.GetOSMNodeIDOfNode(source_geometry[source_segment_start_coordinate]));
auto cumulative_distance = 0.;
auto current_distance = 0.;
@@ -111,41 +110,18 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const auto target_node_id =
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
const auto forward_datasources = facade.GetUncompressedForwardDatasources(target_geometry_id);
const std::vector<DatasourceID> forward_datasources =
facade.GetUncompressedForwardDatasources(target_geometry_id);
// This happens when the source/target are on the same edge-based-node
// There will be no entries in the unpacked path, thus no annotations.
// We will need to calculate the lone annotation by looking at the position
// of the source/target nodes, and calculating their differences.
if (geometry.annotations.empty())
{
auto duration =
std::abs(
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) -
(reversed_source ? source_node.reverse_duration : source_node.forward_duration)) /
10.;
BOOST_ASSERT(duration >= 0);
auto weight =
std::abs((reversed_target ? target_node.reverse_weight : target_node.forward_weight) -
(reversed_source ? source_node.reverse_weight : source_node.forward_weight)) /
facade.GetWeightMultiplier();
BOOST_ASSERT(weight >= 0);
geometry.annotations.emplace_back(
LegGeometry::Annotation{current_distance,
duration,
weight,
forward_datasources(target_node.fwd_segment_position)});
}
else
{
geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance,
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
facade.GetWeightMultiplier(),
forward_datasources(target_node.fwd_segment_position)});
}
// FIXME if source and target phantoms are on the same segment then duration and weight
// will be from one projected point till end of segment
// testbot/weight.feature:Start and target on the same and adjacent edge
geometry.annotations.emplace_back(LegGeometry::Annotation{
current_distance,
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
facade.GetWeightMultiplier(),
forward_datasources[target_node.fwd_segment_position]});
geometry.segment_offsets.push_back(geometry.locations.size());
geometry.locations.push_back(target_node.location);
@@ -157,9 +133,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
// target node rev: 1 1 <- 2 <- 3
const auto target_segment_end_coordinate =
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id);
const std::vector<NodeID> target_geometry =
facade.GetUncompressedForwardGeometry(target_geometry_id);
geometry.osm_node_ids.push_back(
facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate)));
facade.GetOSMNodeIDOfNode(target_geometry[target_segment_end_coordinate]));
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
+2 -24
View File
@@ -13,19 +13,13 @@ namespace engine
namespace guidance
{
// Multiple possible reasons can result in unnecessary/confusing instructions
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
// Multiple possible reasons can result in unnecessary/confusing instructions
// A prime example would be a segregated intersection. Turning around at this
// intersection would result in two instructions to turn left.
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes.
// set of instructionst that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
// A combined turn is a set of two instructions that actually form a single turn, as far as we
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots
@@ -99,22 +93,6 @@ struct StaggeredTurnStrategy : CombineStrategy
const RouteStep &step_prior_to_intersection;
};
// Handling of consecutive segregated steps
struct CombineSegregatedStepsStrategy : CombineStrategy
{
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
};
// Handling of segregated intersections
struct SegregatedTurnStrategy : CombineStrategy
{
SegregatedTurnStrategy(const RouteStep &step_prior_to_intersection);
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
const RouteStep &step_prior_to_intersection;
};
// Signage Strategies
// Transfer the signage from the next step onto this step
@@ -23,7 +23,6 @@ const constexpr std::size_t MIN_END_OF_ROAD_INTERSECTIONS = std::size_t{2};
const constexpr double MAX_COLLAPSE_DISTANCE = 30.0;
// a bit larger than 100 to avoid oscillation in tests
const constexpr double NAME_SEGMENT_CUTOFF_LENGTH = 105.0;
const double constexpr STRAIGHT_ANGLE = 180.;
// check if a step is completely without turn type
inline bool hasTurnType(const RouteStep &step)
@@ -105,12 +104,6 @@ inline void setInstructionType(RouteStep &step, const osrm::guidance::TurnType::
step.maneuver.instruction.type = type;
}
// alias for readability
inline void setModifier(RouteStep &step, const osrm::guidance::DirectionModifier::Enum modifier)
{
step.maneuver.instruction.direction_modifier = modifier;
}
// alias for readability
inline bool haveSameMode(const RouteStep &lhs, const RouteStep &rhs)
{
@@ -222,86 +215,6 @@ inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_
return total_angle;
}
// check bearings for u-turns.
// since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to
// check if bearings `a` and `b` go in opposite directions. In general we accept some minor
// deviations for u-turns.
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
{
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
const double left_turn_angle = [&]() {
if (0 <= bearing_out && bearing_out <= bearing_in)
return bearing_in - bearing_out;
return bearing_in + 360 - bearing_out;
}();
return util::angularDeviation(left_turn_angle, 180) <= 35;
}
// Returns true if the specified step has only one intersection
inline bool hasSingleIntersection(const RouteStep &step)
{
return (step.intersections.size() == 1);
}
// Returns true if the specified angle is a wider straight turn
inline bool isWiderStraight(const double angle) { return (angle >= 125 && angle <= 235); }
// Returns the straightest intersecting edge turn for the specified step
inline double getStraightestIntersectingEdgeTurn(const RouteStep &step)
{
const auto &intersection = step.intersections.front();
const double bearing_in = util::bearing::reverse(intersection.bearings[intersection.in]);
double staightest_turn = 360.;
double staightest_delta = 360.;
for (std::size_t i = 0; i < intersection.bearings.size(); ++i)
{
// Skip the in, out, and non-traversable edges
if ((i == intersection.in) || (i == intersection.out) || !intersection.entry.at(i))
continue;
double intersecting_turn =
util::bearing::angleBetween(bearing_in, intersection.bearings.at(i));
double straight_delta = util::angularDeviation(intersecting_turn, STRAIGHT_ANGLE);
if (straight_delta < staightest_delta)
{
staightest_delta = straight_delta;
staightest_turn = intersecting_turn;
}
}
return staightest_turn;
}
// Returns true if the specified step has the straightest turn as compared to
// the intersecting edges
inline bool hasStraightestTurn(const RouteStep &step)
{
const auto &intersection = step.intersections.front();
const double path_turn =
util::bearing::angleBetween(util::bearing::reverse(intersection.bearings[intersection.in]),
intersection.bearings[intersection.out]);
// Path turn must be a wider straight
if (isWiderStraight(path_turn))
{
const double straightest_intersecting_turn = getStraightestIntersectingEdgeTurn(step);
const double path_straight_delta = util::angularDeviation(path_turn, STRAIGHT_ANGLE);
const double intersecting_straight_delta =
util::angularDeviation(straightest_intersecting_turn, STRAIGHT_ANGLE);
const double path_intersecting_delta =
util::angularDeviation(path_turn, straightest_intersecting_turn);
// Add some fuzz - the delta between the path and intersecting turn must be greater
// than 10 in order to consider using the intersecting turn as the straightest
return ((path_intersecting_delta > 10.)
? (path_straight_delta <= intersecting_straight_delta)
: true);
}
return false;
}
} /* namespace guidance */
} /* namespace engine */
} /* namespace osrm */
+2 -2
View File
@@ -63,8 +63,8 @@ struct Hint
friend std::ostream &operator<<(std::ostream &, const Hint &);
};
static_assert(sizeof(Hint) == 80 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 112;
static_assert(sizeof(Hint) == 64 + 4, "Hint is bigger than expected");
constexpr std::size_t ENCODED_HINT_SIZE = 92;
static_assert(ENCODED_HINT_SIZE / 4 * 3 >= sizeof(Hint),
"ENCODED_HINT_SIZE does not match size of Hint");
}
+3 -24
View File
@@ -145,32 +145,11 @@ inline InternalRouteResult CollapseInternalRouteResult(const InternalRouteResult
collapsed.target_traversed_in_reverse.back() =
leggy_result.target_traversed_in_reverse[i];
// copy path segments into current leg
if (!leggy_result.unpacked_path_segments[i].empty())
{
auto old_size = last_segment.size();
last_segment.insert(last_segment.end(),
leggy_result.unpacked_path_segments[i].begin(),
leggy_result.unpacked_path_segments[i].end());
// The first segment of the unpacked path is missing the weight of the
// source phantom. We need to add those values back so that the total
// edge weight is correct
last_segment[old_size].weight_until_turn +=
leggy_result.source_traversed_in_reverse[i]
? leggy_result.segment_end_coordinates[i].source_phantom.reverse_weight
: leggy_result.segment_end_coordinates[i].source_phantom.forward_weight;
last_segment[old_size].duration_until_turn +=
leggy_result.source_traversed_in_reverse[i]
? leggy_result.segment_end_coordinates[i].source_phantom.reverse_duration
: leggy_result.segment_end_coordinates[i].source_phantom.forward_duration;
}
last_segment.insert(last_segment.end(),
leggy_result.unpacked_path_segments[i].begin(),
leggy_result.unpacked_path_segments[i].end());
}
}
BOOST_ASSERT(collapsed.segment_end_coordinates.size() ==
collapsed.unpacked_path_segments.size());
return collapsed;
}
}
+3 -42
View File
@@ -47,13 +47,10 @@ struct PhantomNode
: forward_segment_id{SPECIAL_SEGMENTID, false},
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
forward_distance_offset(0), reverse_distance_offset(0),
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
is_valid_forward_source{false}, is_valid_forward_target{false},
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
{
}
@@ -81,30 +78,6 @@ struct PhantomNode
return reverse_duration + reverse_duration_offset;
}
// DO THIS FOR DISTANCE
EdgeDistance GetForwardDistance() const
{
// ..... <-- forward_distance
// .... <-- offset
// ......... <-- desired distance
// x <-- this is PhantomNode.location
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
BOOST_ASSERT(forward_segment_id.enabled);
return forward_distance + forward_distance_offset;
}
EdgeDistance GetReverseDistance() const
{
// .......... <-- reverse_distance
// ... <-- offset
// ............. <-- desired distance
// x <-- this is PhantomNode.location
// 0----1----2----3----4 <-- EdgeBasedGraph Node segments
BOOST_ASSERT(reverse_segment_id.enabled);
return reverse_distance + reverse_distance_offset;
}
bool IsBidirected() const { return forward_segment_id.enabled && reverse_segment_id.enabled; }
bool IsValid(const unsigned number_of_nodes) const
@@ -115,8 +88,6 @@ struct PhantomNode
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
((forward_duration != MAXIMAL_EDGE_DURATION) ||
(reverse_duration != MAXIMAL_EDGE_DURATION)) &&
((forward_distance != INVALID_EDGE_DISTANCE) ||
(reverse_distance != INVALID_EDGE_DISTANCE)) &&
(component.id != INVALID_COMPONENTID);
}
@@ -159,10 +130,6 @@ struct PhantomNode
EdgeWeight reverse_weight,
EdgeWeight forward_weight_offset,
EdgeWeight reverse_weight_offset,
EdgeDistance forward_distance,
EdgeDistance reverse_distance,
EdgeDistance forward_distance_offset,
EdgeDistance reverse_distance_offset,
EdgeWeight forward_duration,
EdgeWeight reverse_duration,
EdgeWeight forward_duration_offset,
@@ -177,9 +144,7 @@ struct PhantomNode
: forward_segment_id{other.forward_segment_id},
reverse_segment_id{other.reverse_segment_id}, forward_weight{forward_weight},
reverse_weight{reverse_weight}, forward_weight_offset{forward_weight_offset},
reverse_weight_offset{reverse_weight_offset}, forward_distance{forward_distance},
reverse_distance{reverse_distance}, forward_distance_offset{forward_distance_offset},
reverse_distance_offset{reverse_distance_offset}, forward_duration{forward_duration},
reverse_weight_offset{reverse_weight_offset}, forward_duration{forward_duration},
reverse_duration{reverse_duration}, forward_duration_offset{forward_duration_offset},
reverse_duration_offset{reverse_duration_offset},
component{component.id, component.is_tiny}, location{location},
@@ -197,17 +162,13 @@ struct PhantomNode
EdgeWeight reverse_weight;
EdgeWeight forward_weight_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight reverse_weight_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDistance forward_distance;
EdgeDistance reverse_distance;
EdgeDistance forward_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeDistance reverse_distance_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight forward_duration;
EdgeWeight reverse_duration;
EdgeWeight forward_duration_offset; // TODO: try to remove -> requires path unpacking changes
EdgeWeight reverse_duration_offset; // TODO: try to remove -> requires path unpacking changes
ComponentID component;
util::Coordinate location; // this is the coordinate of x
util::Coordinate location;
util::Coordinate input_location;
unsigned short fwd_segment_position;
// is phantom node valid to be used as source or target
@@ -219,7 +180,7 @@ struct PhantomNode
unsigned short bearing : 12;
};
static_assert(sizeof(PhantomNode) == 80, "PhantomNode has more padding then expected");
static_assert(sizeof(PhantomNode) == 64, "PhantomNode has more padding then expected");
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;

Some files were not shown because too many files have changed in this diff Show More