Compare commits

...

66 Commits

Author SHA1 Message Date
Patrick Niklaus 2cc293ad16 [skip ci] Update changelog for RC3 2016-07-13 21:57:07 +02:00
Patrick Niklaus 6ac65a922f Disable ARM builds until sourceforge comes up again 2016-07-13 14:19:33 +02:00
Patrick Niklaus 3d80f989d0 Fix tests after cucumber update and changed escaping. 2016-07-13 11:48:53 +02:00
Patrick Niklaus 4fcb5d28a4 Merge pull request #2624 from oxidase/issues/2617
Fix ambiguous data issues
2016-07-13 11:20:40 +02:00
Patrick Niklaus 3ebdacf369 Merge pull request #2629 from ssuluh/master
Fix windows compilation with regard to struct/class packing
2016-07-13 11:08:34 +02:00
Moritz Kobitzsch 2ddc00c21e update cucumber to 1.2.1 and remove hack 2016-07-13 11:04:35 +02:00
Daniel J. Hofmann e76e39a398 Improves Lane Handling for Multi-Hop Roundabout Instruction
This changeset implements Lane Anticipation on roundabouts, delimited
by enter / leave step pairs. It does not handle lane anticipation
within a roundabout.

Lane anticipation happens on the granularity of a valid roundbaout:

We discard partial roundabout (enter without exit or exit without
enter) or data issues (no roundabout, exit before enter).

Related:

- https://github.com/Project-OSRM/osrm-backend/issues/2626 for lanes
  within a roundabout

- https://github.com/Project-OSRM/osrm-backend/issues/2625 for handling
  going straight in lane anticipation
2016-07-13 10:44:12 +02:00
Patrick Niklaus 04667f1ed8 Log incoming requests before they are processed 2016-07-11 16:50:09 +02:00
Surya Suluh 2091c3443b Fix windows compilation with regard to struct/class packing 2016-07-11 09:47:04 -04:00
Michael Krasnyk 2b466b2fb2 Fix ambiguity in edges by using names lexicographical order 2016-07-11 05:54:30 +02:00
Michael Krasnyk e17b306265 Fix ambiguity in edge weights by using minimal weight 2016-07-08 18:20:55 +02:00
Daniel J. Hofmann b00b15ab98 Manual modernize run with LLVM 3.8
More is blocked by:
- https://github.com/Project-OSRM/osrm-backend/issues/2631
2016-07-07 12:45:24 +02:00
Moritz Kobitzsch f4db79fe9b fix obvious turn collapsing for straight turns 2016-07-06 10:50:47 +02:00
Moritz Kobitzsch 0e4061f858 deduplicate code for roundabout handling 2016-07-01 11:34:44 +02:00
Moritz Kobitzsch 043a1446e1 adjust changelog (mention both files) and update a typo 2016-06-30 10:39:05 +02:00
Moritz Kobitzsch 49221995e8 add documentation on use lane type 2016-06-28 17:53:31 +02:00
Moritz Kobitzsch 247a7488b8 Adjusting Changelog 5.3.0-rc.2 to follow scheme 2016-06-28 13:25:35 +02:00
Moritz Kobitzsch 1806198971 Prepare Update to 5.3.0 RC2 2016-06-28 13:22:33 +02:00
Moritz Kobitzsch 375331b80c fixing lua issue in profile 2016-06-28 12:59:02 +02:00
Patrick Niklaus 8fdbe965cc [skip ci] Fix documentation 2016-06-28 11:08:37 +02:00
Patrick Niklaus dc77d02e8a Change OSRM version to 5.3.0 2016-06-28 10:35:45 +02:00
Moritz Kobitzsch 6265b8fa77 fix broken assertion 2016-06-28 10:30:02 +02:00
Moritz Kobitzsch 311b348d09 handle sliproads at traffic lights 2016-06-28 10:23:22 +02:00
Daniel Patterson ec02cdc4cc Use mmap instead of read - it's a lot faster here.
Also clean up construction of STRONG_TYPEDEF so that it can be
packed properly in structs (this explains all the () -> {}) changes
here.
2016-06-27 17:24:30 -07:00
Moritz Kobitzsch 5905708111 expose lanes as enums, adjusted for comments 2016-06-27 11:12:02 +02:00
Moritz Kobitzsch 5d91b759d1 Implement Turn Lane Api 2016-06-27 10:07:48 +02:00
Daniel J. Hofmann ec0a1a4ab1 Anticipate Lane Changes 2016-06-27 10:07:43 +02:00
Moritz Kobitzsch efa29edf09 basic turn lane handling 2016-06-27 10:07:41 +02:00
Moritz Kobitzsch 2a05b70dfc reduce number of end-of-road instructions in unnecessary cases 2016-06-26 16:40:15 +02:00
Patrick Niklaus 8693e68271 Merge pull request #2588 from Project-OSRM/fix/bike_surface_speeds
bike: surface should never increase speed
2016-06-26 16:37:12 +02:00
Emil Tin d21a9a514d bike: surface should never increase speed 2016-06-25 12:52:54 +02:00
Moritz Kobitzsch e03d132823 fix invalid circle centers 2016-06-24 15:12:51 +02:00
Daniel J. Hofmann 61ba985bc9 Prevent linker from discarding TBB symbols we need, fixes #2557
We build `osrm_contract` (the library) linking in libtbb. We then
build `osrm-contract` (the binary) linking in `osrm_contract` (the
library).

Because we're only using TBB's `parallel_invoke` in the code for the
binary, it seems like the linker discards some symbols in the library.

Therefore we have to link libtbb for the binary again. Even worse, the
order now matters: if we first link in `osrm_contract` and then libtbb,
we're still hitting the issue re. discarded symbols.

Therefore we first link in all dependencies (libtbb, libboost*), and
only then `osrm_contract`.

Strictly speaking, we probably have to do this for all of our binary
targets, or we will hit similar issues in the future.
2016-06-24 12:06:28 +02:00
Moritz Kobitzsch 4629a20fe4 improve handling of obvious for end-of-road situations 2016-06-24 12:05:42 +02:00
Patrick Niklaus a28125ee9a Merge pull request #2577 from noblige/noblige/compile-armv7
option to disable LTO
2016-06-24 12:04:02 +02:00
Daniel J. Hofmann df877aca1b Hard-abort on assertion and show detailed information, solves #2579
From

> [warn} oops

to

> [assert] /tmp/osrm-backend/src/extractor/extractor.cpp:79
> in: int osrm::extractor::Extractor::run(): false
> terminate called without an active exception
2016-06-23 18:57:35 +02:00
Aleksei Potov 05dc415aba option to disable LTO 2016-06-23 09:44:02 -07:00
Daniel Patterson 6dedd9cb72 Fix segfault when route includes very short segments. 2016-06-22 14:48:57 -07:00
Daniel J. Hofmann 256d39b572 Sync OSRM version in CMakeLists, fixes #2576 2016-06-22 17:03:31 +02:00
Patrick Niklaus d186ae1863 Fix semi-colon warnings 2016-06-22 13:20:55 +02:00
Patrick Niklaus fddc19e98d Fix regressed formating 2016-06-21 22:25:48 +02:00
Lauren Budorick 2592cd2e58 Update tests to catch 0-subtraction error 2016-06-21 19:31:46 +02:00
Patrick Niklaus 93b6438cea Fix fromTop and fromLeft calculation 2016-06-21 19:31:46 +02:00
Daniel J. Hofmann f6746d88b7 Removes unused -s from osrm-datastore, use osrm-springclean tool, closes #2561 2016-06-21 18:09:11 +02:00
Daniel J. Hofmann 34ace4dd4b Let Travis fail fast if CMake/Clang download fails, fixes #2433 2016-06-21 18:08:19 +02:00
Daniel J. Hofmann 41d0f42ddf Show user hint on wrong Node.js version, fixes #2435.
This is more of a hack but looks like the best we can do.

The reason for this is the following:

1/ we require strict mode for our v4 script

2/ v0.10 in strict mode marks 'let' as a reserved keyword,
   aborting before execution any code in the script. Thus,
   we can't assert e.g. on process.versions['node'] !== '4'.
2016-06-21 18:07:35 +02:00
Moritz Kobitzsch 2868f702a5 fix issues with roundabouts and intersections and sliproads 2016-06-21 16:56:57 +02:00
Patrick Niklaus ec4dcee8bd Merge pull request #2549 from oxidase/issue/2546
Fix omitting the last point's coordinates in the geometry field
2016-06-21 16:41:35 +02:00
Michael Krasnyk 8c378191df Fix omitting the last point's coordinates in the geometry field 2016-06-21 07:06:43 +02:00
Daniel J. Hofmann b98431e8e6 Use BaseDataFacades in guidance and prevent ODR violations with inline 2016-06-21 00:49:06 +02:00
Moritz Kobitzsch 3c8781855e handle steep off-ramps 2016-06-21 00:47:43 +02:00
Patrick Niklaus 27a94f3ca6 Merge pull request #2504 from oxidase/issue/2502
Fixes for i686 and armhf platforms
2016-06-20 22:01:09 +00:00
Michael Krasnyk 04e334e3e2 Make storage blocks aligned to 4 bytes for ARM NEON/VFP instructions
Aligned blocks prevent bus errors in NEON/VFP instructions.

Block pointers are aligned to 4 bytes, that is guaranteed
by aligned mmaped-pointers, the 4 bytes size of the CANARY block and
aligned sizes of blocks.
2016-06-20 22:45:40 +02:00
Michael Krasnyk 12d4832037 Fix platform-independent data in data files 2016-06-20 22:45:40 +02:00
Michael Krasnyk 6e4f6fec91 Added armhf Travis build 2016-06-20 22:45:40 +02:00
Michael Krasnyk 57c9525e5c Added i686 Travis build 2016-06-20 22:45:40 +02:00
Michael Krasnyk 543e4fb57d Fix rounding issue in query coordinates by using toFixed
that internally uses boost::numeric_cast<std::int32_t>
instead of static_cast<std::int32_t>
2016-06-20 22:45:40 +02:00
Michael Krasnyk 3881ead8e5 Fix rounding issue due to non-associative floating arithmetic
Failing test
features/car/traffic_turn_penalties.feature:33

Tables were not identical:
    from |     to |     route |     speed |     time
|     a |     h |     ad,dhk,dhk |     63 km/h |     11.5s +-1 |
|     i |     g |     fim,fg,fg |     59 km/h |     12s  +-1 |
| (-) a | (-) e | (-) ad,de,de | (-) 57 km/h | (-) 12.5s +-1 |
| (+) a | (+) e | (+) ad,de,de | (+) 58 km/h | (+) 12.5s +-1 |
|     c |     g |     cd,de,ef,fg,fg |     63 km/h |     23s +-1 |
|     p |     g |     mp,fim,fg,fg |     61 km/h |     23.5s +-1 |
|     a |     l |     ad,dhk,kl,kl |     60 km/h |     24s +-1 |
|     l |     e |     kl,dhk,de,de |     59 km/h |     24.5s +-1 |
|     g |     n |     fg,fim,mn,mn |     57 km/h |     25s +-1 |
2016-06-20 22:45:40 +02:00
Michael Krasnyk 911d1e81b6 Make explicit promotion to int64_t
to avoid incorrect promotions for 32 bit size_t
2016-06-20 22:45:40 +02:00
Michael Krasnyk ae06300c17 Fix unused variables warnings in crc32 2016-06-20 22:43:28 +02:00
Michael Krasnyk 26879ca91a Make build directory configurable via OSRM_BUILD_DIR in tests 2016-06-20 22:43:28 +02:00
Moritz Kobitzsch 306744e5cb fix roundabout-handling when name changes 2016-06-17 11:02:14 +02:00
Moritz Kobitzsch 3ca32898a1 move guidance decision into debug header 2016-06-15 11:30:30 +02:00
Patrick Niklaus 532fda267f [skip ci] Update changelog for 5.2.1
Conflicts:
	CHANGELOG.md
2016-06-14 14:32:33 +02:00
Daniel Patterson 494845b160 Copy data to beginning of buffer, not end. (#2542)
Copy data to beginning of buffer, not end.
2016-06-13 12:59:42 -07:00
Patrick Niklaus 0fc823041e Removed debug code 2016-06-13 17:57:33 +02:00
157 changed files with 6445 additions and 1202 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
IncludeCategories:
- Regex: '^<'
Priority: 3
- Regex: '^"(osrm|util|engine|extract|contract)/'
+13 -2
View File
@@ -71,6 +71,15 @@ matrix:
packages: ['g++-5', 'libbz2-dev', 'libstxxl-dev', 'libstxxl1', 'libxml2-dev', 'libzip-dev', 'lua5.1', 'liblua5.1-0-dev', 'libtbb-dev', 'libgdal-dev', 'libluabind-dev', 'libboost-all-dev', 'ccache']
env: CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
- os: linux
compiler: "gcc-5-release-i686"
env: TARGET_ARCH='i686' CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
# FIXME disabled until sourceforge fixes its packages for stxxl
#- os: linux
#- compiler: "gcc-4.8-release-armhf"
#- env: TARGET_ARCH='armhf' CCOMPILER='arm-linux-gnueabihf-gcc-4.8' CXXCOMPILER='arm-linux-gnueabihf-g++-4.8' BUILD_TYPE='Release'
# Disabled because of CI slowness
#- os: linux
#- compiler: gcc
@@ -114,19 +123,20 @@ matrix:
#- env: CCOMPILER='clang-3.8' CXXCOMPILER='clang++-3.8' BUILD_TYPE='Release' BUILD_SHARED_LIBS=ON
before_install:
- if [[ ! -z $TARGET_ARCH ]] ; then source ./scripts/travis/before_install.$TARGET_ARCH.sh ; fi
- if [[ $(uname -s) == 'Darwin' ]]; then sudo mdutil -i off /; fi;
- source ./scripts/install_node.sh 4
- npm install
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
- export PATH=${DEPS_DIR}/bin:${PATH} && mkdir -p ${DEPS_DIR}
- CMAKE_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/cmake/3.5.2.tar.gz"
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR}
- travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
- |
if [[ ${CLANG_VERSION:-false} != false ]]; then
export CCOMPILER='clang'
export CXXCOMPILER='clang++'
CLANG_URL="https://mason-binaries.s3.amazonaws.com/${TRAVIS_OS_NAME}-x86_64/clang/${CLANG_VERSION}.tar.gz"
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR}
travis_retry wget --quiet -O - ${CLANG_URL} | tar --strip-components=1 -xz -C ${DEPS_DIR} || exit 1
fi
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
@@ -161,6 +171,7 @@ install:
- popd
script:
- if [[ $TARGET_ARCH == armhf ]] ; then echo "Skip tests for $TARGET_ARCH" && exit 0 ; fi
- echo "travis_fold:start:BENCHMARK"
- make -C test/data benchmark
- echo "travis_fold:end:BENCHMARK"
+45 -1
View File
@@ -1,5 +1,49 @@
# 5.3.0 RC3
Changes from 5.3.0-rc.2
- Guidance
- Improved detection of obvious turns
- Improved turn lane detection
- Bugfixes
- Fix bug that didn't chose minimal weights on overlapping edges
# 5.3.0 RC2
Changes from 5.3.0-rc.1
- Bugfixes
- Fixes invalid checks in the lane-extraction part of the car profile
# 5.3.0 RC1
- API
- Introduces new `TurnType` in the form of `use lane`. The type indicates that you have to stick to a lane without turning
- Introduces lanes to the route response. The lane data contains both the markings at the intersection and a flag indicating their involvement in the turn
- Infrastructure
- BREAKING: The new turn type changes the turn-type order. This breaks the **data format**.
- BREAKING: Turn lane data introduces two new files (osrm.tld,osrm.tls). This breaks the fileformat for older versions.
# 5.2.5
- Bugfixes
- Fixes a segfault caused by incorrect trimming logic for very short steps.
# 5.2.4
- Bugfixes:
- Fixed in issue that arised on roundabouts in combination with intermediate intersections and sliproads
# 5.2.3
- Bugfixes:
- Fixed an issue with name changes in roundabouts that could result in crashes
# 5.2.2
Changes from 5.2.1
- Bugfixes:
- Buffer overrun in tile plugin response handling
# 5.2.1
Changes from 5.2.0
- Bugfixes:
- Removed debug statement that was spamming the console
# 5.2.0
Changes form 5.2.0 RC2
Changes from 5.2.0 RC2
- Bugfixes:
- Fixed crash when loading shared memory caused by invalid OSM IDs segment size.
- Various small instructions handling fixes
+5 -4
View File
@@ -9,7 +9,7 @@ endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 2)
set(OSRM_VERSION_MINOR 3)
set(OSRM_VERSION_PATCH 0)
# these two functions build up custom variables:
@@ -39,7 +39,7 @@ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(bitness 64)
message(STATUS "Building on a 64 bit system")
else()
message(WARNING "Building on a 32 bit system is unsupported")
message(STATUS "Building on a 32 bit system")
endif()
if(WIN32 AND MSVC_VERSION LESS 1900)
@@ -53,6 +53,7 @@ option(BUILD_COMPONENTS "Build osrm-components" OFF)
option(ENABLE_ASSERTIONS OFF)
option(COVERAGE OFF)
option(SANITIZER OFF)
option(ENABLE_LTO "Use LTO if available" ON)
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
@@ -118,7 +119,7 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode")
# Check if LTO is available
check_cxx_compiler_flag("-flto" LTO_AVAILABLE)
if(LTO_AVAILABLE)
if(ENABLE_LTO AND LTO_AVAILABLE)
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# GCC in addition allows parallelizing LTO
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
@@ -319,7 +320,7 @@ include_directories(SYSTEM ${OSRM_INCLUDE_PATHS})
# Binaries
target_link_libraries(osrm-datastore osrm_store ${Boost_LIBRARIES})
target_link_libraries(osrm-extract osrm_extract ${Boost_LIBRARIES})
target_link_libraries(osrm-contract osrm_contract ${Boost_LIBRARIES})
target_link_libraries(osrm-contract ${Boost_LIBRARIES} ${TBB_LIBRARIES} osrm_contract)
target_link_libraries(osrm-routed osrm ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} ${ZLIB_LIBRARY})
set(EXTRACTOR_LIBRARIES
+76 -41
View File
@@ -357,7 +357,7 @@ Three input coordinates, `geometry=geojson`, `steps=false`:
{
"distance": 90.0,
"duration": 300.0,
"geometry": {"type": "LineString", "coordinates": [[120., 10.], [120.1, 10.], [120.2, 10.], [120.3, 10.]]},
"geometry": {"type": "LineString", "coordinates": [[120.0, 10.0], [120.1, 10.0], [120.2, 10.0], [120.3, 10.0]]},
"legs": [
{
"distance": 30.0,
@@ -410,7 +410,7 @@ With `steps=false` and `annotations=true`:
{
"distance": 30.0,
"duration": 100.0,
"steps": []
"steps": [],
"annotation": {
"distance": [5,5,10,5,5],
"duration": [15,15,40,15,15],
@@ -441,7 +441,7 @@ step.
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
- `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
#### Example
@@ -451,16 +451,20 @@ step.
"duration":15.6,
"name":"Lortzingstraße",
"maneuver":{
"type":"depart",
"modifier":"left"
},
"type":"turn",
"modifier":"right",
"lanes":[
{"indications":["left","straight"], "valid":"false"},
{"indications":["right"], "valid":"true"}
]},
"geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving",
"intersections":[
{"location":[13.39677,52.54366],
"in":3,
"out":1,
"bearings":[66,246],
"entry":["true","true"]},
"bearings":[10,92,184,270],
"entry":[false,"true","true"]},
{"location":[13.394718,52.543096],
"in":0,
"out":2,
@@ -482,51 +486,50 @@ step.
- `type` A string indicating the type of maneuver. **new identifiers might be introduced without API change**
Types unknown to the client should be handled like the `turn` type, the existance of correct `modifier` values is guranteed.
| `type` | Description |
|-------------------|--------------------------------------------------------------|
| turn | a basic turn into direction of the `modifier` |
| new name | no turn is taken/possible, but the road name changes. The road can take a turn itself, following `modifier`. |
| depart | indicates the departure of the leg |
| arrive | indicates the destination of the leg |
| merge | merge onto a street (e.g. getting on the highway from a ramp, the `modifier specifies the direction of the merge`) |
| ramp | **Deprecated**. Replaced by `on_ramp` and `off_ramp`. |
| on ramp | take a ramp to enter a highway (direction given my `modifier`) |
| off ramp | take a ramp to exit a highway (direction given my `modifier`) |
| fork | take the left/right side at a fork depending on `modifier` |
| end of road | road ends in a T intersection turn in direction of `modifier`|
| continue | Turn in direction of `modifier` to stay on the same road |
| roundabout | traverse roundabout, has additional field `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` |
| rotary | a larger version of a roundabout, can offer `rotary_name` in addition to the `exit` parameter. |
| roundabout turn | Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| notification | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
| `type` | Description |
|------------------|--------------------------------------------------------------|
| `turn` | a basic turn into direction of the `modifier` |
| `new name` | no turn is taken/possible, but the road name changes. The road can take a turn itself, following `modifier`. |
| `depart` | indicates the departure of the leg |
| `arrive` | indicates the destination of the leg |
| `merge` | merge onto a street (e.g. getting on the highway from a ramp, the `modifier specifies the direction of the merge`) |
| `ramp` | **Deprecated**. Replaced by `on_ramp` and `off_ramp`. |
| `on ramp` | take a ramp to enter a highway (direction given my `modifier`) |
| `off ramp` | take a ramp to exit a highway (direction given my `modifier`) |
| `fork` | take the left/right side at a fork depending on `modifier` |
| `end of road` | road ends in a T intersection turn in direction of `modifier`|
| `use lane` | going straight on a specific lane |
| `continue` | Turn in direction of `modifier` to stay on the same road |
| `roundabout` | traverse roundabout, has additional field `exit` with NR if the roundabout is left. `the modifier specifies the direction of entering the roundabout` |
| `rotary` | a larger version of a roundabout, can offer `rotary_name` in addition to the `exit` parameter. |
| `roundabout turn`| Describes a turn at a small roundabout that should be treated as normal turn. The `modifier` indicates the turn direciton. Example instruction: `At the roundabout turn left`. |
| `notification` | not an actual turn but a change in the driving conditions. For example the travel mode. If the road takes a turn itself, the `modifier` describes the direction |
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
between all instructions. They only offer a fallback in case nothing else is to report.
- `modifier` An optional `string` indicating the direction change of the maneuver.
| `modifier` | Description |
|-------------------|-------------------------------------------|
| uturn | indicates reversal of direction |
| sharp right | a sharp right turn |
| right | a normal turn to the right |
| slight right | a slight turn to the right |
| straight | no relevant change in direction |
| slight left | a slight turn to the left |
| left | a normal turn to the left |
| sharp left | a sharp turn to the left |
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
| `uturn` | indicates reversal of direction |
| `sharp right` | a sharp right turn |
| `right` | a normal turn to the right |
| `slight right` | a slight turn to the right |
| `straight` | no relevant change in direction |
| `slight left` | a slight turn to the left |
| `left` | a normal turn to the left |
| `sharp left` | a sharp turn to the left |
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
The meaning depends on the `type` field.
| `type` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `turn` | `modifier` indicates the change in direction accomplished through the turn |
| `depart`/`arrive` | `modifier` indicates the position of departure point and arrival point in relation to the current direction of travel |
- `exit` An optional `integer` indicating number of the exit to take. The field exists for the following `type` field:
| `type` | Description |
@@ -534,10 +537,42 @@ step.
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
| else | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
- `lanes`: Array of `Lane` objects that denote the available turn lanes at the turn location
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
### Intersections
### Lane
A `Lane` represents a turn lane at the corresponding turn location.
#### Properties
- `indications`: a indication (e.g. marking on the road) specifying the turn lane. A road can have multiple indications (e.g. an arrow pointing straight and left). The indications are given in an array, each containing one of the following types. Further indications might be added on without an API version change.
| `value` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `none` | No dedicated indication is shown. |
| `uturn` | An indication signaling the possibility to reverse (i.e. fully bend arrow). |
| `sharp right` | An indication indicating a sharp right turn (i.e. strongly bend arrow). |
| `right` | An indication indicating a right turn (i.e. bend arrow). |
| `slight right` | An indication indicating a slight right turn (i.e. slightly bend arrow). |
| `straight` | No dedicated indication is shown (i.e. straight arrow). |
| `slight left` | An indication indicating a slight left turn (i.e. slightly bend arrow). |
| `left` | An indication indicating a left turn (i.e. bend arrow). |
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend arrow). |
- `valid`: a boolean flag indicating whether the lane is a valid choice in the current maneuver
#### Example
```json
{
"indications": ["left", "straight"],
"valid": "false"
}
```
### Intersection
An intersection gives a full representation of any cross-way the path passes bay. For every step, the very first intersection (`intersections[0]`) corresponds to the
location of the StepManeuver. Further intersections are listed for every cross-way until the next turn instruction.
+2 -2
View File
@@ -40,8 +40,8 @@ int main(int argc, const char *argv[]) try
RouteParameters params;
// Route in monaco
params.coordinates.push_back({util::FloatLongitude(7.419758), util::FloatLatitude(43.731142)});
params.coordinates.push_back({util::FloatLongitude(7.419505), util::FloatLatitude(43.736825)});
params.coordinates.push_back({util::FloatLongitude{7.419758}, util::FloatLatitude{43.731142}});
params.coordinates.push_back({util::FloatLongitude{7.419505}, util::FloatLatitude{43.736825}});
// Response is in JSON format
json::Object result;
+5 -2
View File
@@ -46,14 +46,17 @@ Feature: Bike - Mode flag
Scenario: Bike - Mode when pushing bike against oneways
Given the node map
| a | b | |
| | c | d |
| a | b | e |
| f | c | d |
And the ways
| nodes | highway | oneway |
| ab | primary | |
| bc | primary | yes |
| cd | primary | |
| be | primary | |
| cf | primary | |
When I route I should get
| from | to | route | modes |
+4 -2
View File
@@ -18,8 +18,8 @@ Feature: Bike - Oneway streets
Scenario: Bike - Around the Block
Given the node map
| a | b |
| d | c |
| | a | b | |
| f | d | c | e |
And the ways
| nodes | oneway | foot |
@@ -27,6 +27,8 @@ Feature: Bike - Oneway streets
| bc | | no |
| cd | | no |
| da | | no |
| df | | no |
| ce | | no |
When I route I should get
| from | to | route |
+4 -2
View File
@@ -87,14 +87,16 @@ Feature: Bike - Accessability of different way types
Scenario: Bike - Instructions when pushing bike on oneways
Given the node map
| a | b | |
| | c | d |
| a | b | e |
| f | c | d |
And the ways
| nodes | highway | oneway |
| ab | primary | |
| bc | primary | yes |
| cd | primary | |
| be | primary | |
| cf | primary | |
When I route I should get
| from | to | route | modes |
+17
View File
@@ -38,3 +38,20 @@ Feature: Bike - Surfaces
| cycleway | | 48s |
| nosense | | |
| nosense | asphalt | |
Scenario: Bicycle - Surfaces should not increase speed when pushing bikes
Given the node map
| a | b |
| c | d |
And the ways
| nodes | highway | oneway | surface |
| ab | primary | yes | asphalt |
| cd | footway | | asphalt |
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 | 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 |
+4 -2
View File
@@ -35,8 +35,8 @@ Feature: Car - Oneway streets
Scenario: Car - Around the Block
Given the node map
| a | b |
| d | c |
| | a | b | |
| f | d | c | e |
And the ways
| nodes | oneway |
@@ -44,6 +44,8 @@ Feature: Car - Oneway streets
| bc | |
| cd | |
| da | |
| ce | |
| df | |
When I route I should get
| from | to | route |
+444
View File
@@ -0,0 +1,444 @@
@routing @guidance @turn-lanes
Feature: Turn Lane Guidance
Background:
Given the profile "car"
Given a grid size of 20 meters
@anticipate
Scenario: Anticipate Lane Change for subsequent multi-lane intersections
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | |
And the ways
| nodes | turn:lanes:forward |
| ab | through\|right\|right\|right |
| bx | |
| bc | left\|left\|through |
| cd | through\|right |
| cy | |
| dz | |
| de | |
When I route I should get
| waypoints | route | turns | lanes | # |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,straight:false right:true right:true right:false,left:true left:true straight:false, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true, | 3 hops |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, staying on the same street
Given the node map
| a | | b | x |
| | | | |
| | | c | |
| | | | |
| e | | d | y |
And the ways
| nodes | turn:lanes:forward | turn:lanes:backward | name |
| ab | through\|right\|right | | MySt |
| bx | | | XSt |
| bc | | left\|right | MySt |
| cd | left\|right | through\|through | MySt |
| de | | left\|left\|through | MySt |
| dy | | | YSt |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false right:false right:true,left:false right:true, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,turn left,arrive | ,left:true left:false straight:false,left:true right:false, |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, changing between streets
Given the node map
| a | | b | x |
| | | | |
| | | c | |
| | | | |
| e | | d | y |
And the ways
| nodes | turn:lanes:forward | turn:lanes:backward | name |
| ab | through\|right\|right | | AXSt |
| bx | | | AXSt |
| bc | | left\|right | BDSt |
| cd | left\|right | through\|through | BDSt |
| de | | left\|left\|through | EYSt |
| dy | | | EYSt |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,turn right,arrive | ,straight:false right:false right:true,left:false right:true, |
| e,a | EYSt,BDSt,AXSt,AXSt | depart,turn left,turn left,arrive | ,left:true left:false straight:false,left:true right:false, |
@anticipate
Scenario: Anticipate Lane Change for quick turns during a merge
Given the node map
| a | | | | |
| x | b | | c | y |
| | | | | d |
And the ways
| nodes | turn:lanes:forward | name | highway | oneway |
| ab | slight_left\|slight_left | On | motorway_link | yes |
| xb | | Hwy | motorway | |
| bc | through\|slight_right | Hwy | motorway | |
| cd | | Off | motorway_link | yes |
| cy | | Hwy | motorway | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight left:false slight left:true,straight:false slight right:true, |
@anticipate
Scenario: Schoenefelder Kreuz
# https://www.openstreetmap.org/way/264306388#map=16/52.3202/13.5568
Given the node map
| a | b | x | | | i |
| | | c | d | | |
| | | | | | j |
And the ways
| nodes | turn:lanes:forward | lanes | highway | oneway | name |
| ab | none\|none\|none\|slight_right\|slight_right | 5 | motorway | | abx |
| bx | | 3 | motorway | | abx |
| bc | | 2 | motorway_link | yes | bcd |
| cd | slight_left\|slight_left;slight_right\|slight_right | 3 | motorway_link | yes | bcd |
| di | slight_left\|slight_right | 2 | motorway_link | yes | di |
| dj | | 2 | motorway_link | yes | dj |
When I route I should get
| waypoints | route | turns | lanes |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,none:false none:false none:false slight right:true slight right:true,slight left:true slight left;slight right:true slight right:false, |
| a,j | abx,bcd,dj,dj | depart,off ramp right,fork slight right,arrive | ,none:false none:false none:false slight right:true slight right:true,slight left:false slight left;slight right:true slight right:true, |
@anticipate
Scenario: Kreuz Oranienburg
# https://www.openstreetmap.org/way/4484007#map=18/52.70439/13.20269
Given the node map
| i | | | | | a |
| j | | c | b | | x |
And the ways
| nodes | turn:lanes:forward | lanes | highway | oneway | name |
| ab | | 1 | motorway_link | yes | ab |
| xb | | 1 | motorway_link | yes | xbcj |
| bc | none\|slight_right | 2 | motorway_link | yes | xbcj |
| ci | | 1 | motorway_link | yes | ci |
| cj | | 1 | motorway_link | yes | xbcj |
When I route I should get
| waypoints | route | turns | lanes |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |
| a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, |
@anticipate
Scenario: Lane anticipation for fan-in
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | |
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|right\|right\|right | abx |
| bx | | abx |
| bc | left\|left\|through | bcy |
| cy | | bcy |
| cd | through\|right | cdz |
| dz | | cdz |
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true, |
@anticipate
Scenario: Lane anticipation for fan-out
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | |
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|right | abx |
| bx | | abx |
| bc | left\|left\|through | bcy |
| cy | | bcy |
| cd | through\|right\|right\|right | cdz |
| dz | | cdz |
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true,left:true left:true straight:false,straight:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-in followed by fan-out
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | |
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|right\|right\|right | abx |
| bx | | abx |
| bc | left\|left\|through | bcy |
| cy | | bcy |
| cd | through\|right\|right\|right | cdz |
| dz | | cdz |
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true right:true right:false,left:true left:true straight:false,straight:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-out followed by fan-in
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | |
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|right | abx |
| bx | | abx |
| bc | left\|left\|through | bcy |
| cy | | bcy |
| cd | through\|right | cdz |
| dz | | cdz |
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true,left:false left:true straight:false,straight:false right:true, |
@anticipate
Scenario: Lane anticipation for multiple hops with same number of lanes
Given the node map
| a | | b | | x | | |
| | | | | | | |
| | | c | | d | | z |
| | | | | | | |
| | | y | | e | | f |
| | | | | | | |
| | | | | w | | |
And the ways
| nodes | turn:lanes:forward | name |
| ab | through\|right\|right\|right | abx |
| bx | | abx |
| bc | left\|left\|through | bcy |
| cy | | bcy |
| cd | through\|right\|right | cdz |
| dz | | cdz |
| de | left\|through | dew |
| ew | | dew |
| ef | | ef |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true right:false,left:true straight:false, |
@anticipate
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
Given the node map
| | | e | | |
| a | b | | d | f |
| | | c | | |
| | | | | |
| | | g | | |
| k | h | | j | l |
| | | i | | |
And the ways
| nodes | turn:lanes:forward | highway | junction | # |
| ab | slight_right\|slight_right\|slight_right | primary | | |
| bc | slight_left\|slight_right\|slight_right | primary | roundabout | top |
| cd | | primary | roundabout | top |
| de | | primary | roundabout | top |
| eb | | primary | roundabout | top |
| df | | primary | | |
| cg | slight_right\|slight_right | primary | | |
| gh | slight_left\|slight_right | primary | roundabout | bot |
| hi | | primary | roundabout | bot |
| ij | slight_left\|slight_right | primary | roundabout | bot |
| jg | | primary | roundabout | bot |
| hk | | primary | | |
| jl | | primary | | |
When I route I should get
| # | waypoints | route | turns | lanes |
| right-right | a,k | ab,cg,hk,hk | depart,roundabout-exit-1,roundabout-exit-1,arrive | ,slight right:false slight right:false slight right:true,slight right:false slight right:true, |
| right-left | a,l | ab,cg,jl,jl | depart,roundabout-exit-1,roundabout-exit-2,arrive | ,slight right:false slight right:false slight right:true,slight right:false slight right:true, |
| todo exits | a,f | ab,df,df | depart,roundabout-exit-2,arrive | ,slight right:false slight right:false slight right:true, |
| todo exits | a,e | ab,bc,eb | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true slight right:true, |
@anticipate @todo
Scenario: Roundabout with lanes only tagged on exit
Given the node map
| | | e | | |
| a | b | | d | f |
| | | c | | |
And the ways
| nodes | turn:lanes:forward | highway | junction |
| ab | | primary | |
| bc | | primary | roundabout |
| cd | slight_left\|slight_left\|slight_right | primary | roundabout |
| de | | primary | roundabout |
| eb | | primary | roundabout |
| df | | primary | |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | ab,df,df | depart,roundabout-exit-1,use lane slight right,arrive | ,,slight left:false slight left:false slight right:true, |
@anticipate
Scenario: Anticipate with lanes in roundabout where we stay on the roundabout for multiple exits
Given the node map
| | | a | | |
| | | b | | |
| | c | | g | h |
| | | | | |
| | d | | f | |
| | | e | | |
| x | | | | y |
And the ways
| nodes | turn:lanes:forward | highway | junction |
| ab | slight_right\|slight_right | primary | |
| bc | | primary | roundabout |
| cd | | primary | roundabout |
| de | | primary | roundabout |
| ef | | primary | roundabout |
| fg | slight_right | primary | roundabout |
| gb | | primary | roundabout |
| gh | | primary | |
| cx | | primary | |
| dx | | primary | |
| ey | | primary | |
| fy | | primary | |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | ab,gh,gh | depart,roundabout-exit-5,arrive | ,slight right:false slight right:true, |
@anticipate
Scenario: Departing or arriving inside a roundabout does not yet anticipate lanes
Given the node map
| | | a | | |
| x | b | | d | y |
| | | c | | |
And the ways
| nodes | turn:lanes:forward | highway | junction | name |
| xb | slight_right\|slight_right | primary | | xb |
| dy | | primary | | dy |
| ab | | primary | roundabout | roundabout |
| bc | | primary | roundabout | roundabout |
| cd | left\|slight_right | primary | roundabout | roundabout |
| da | | primary | roundabout | roundabout |
When I route I should get
| waypoints | route | turns | lanes |
| x,y | xb,dy,dy | depart,roundabout-exit-1,arrive | ,slight right:false slight right:true, |
| x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, |
| x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true slight right:true, |
@anticipate
Scenario: Anticipate Lanes for turns before and / or after roundabout
Given the node map
| a | b | | | x |
| | c | | | |
| d | | f | g | z |
| | e | | h | |
| | | | | |
| | y | | | |
And the ways
| nodes | turn:lanes:forward | highway | junction | name |
| ab | through\|right\|right\|right\|right | primary | | abx |
| bx | | primary | | abx |
| bc | right\|right\|right\|right | primary | | bc |
| cd | | primary | roundabout | cdefc |
| de | slight_left\|slight_left&slight_left\|slight_right | primary | roundabout | cdefc |
| ef | left\|slight_right\|slight_right | primary | roundabout | cdefc |
| fc | | primary | roundabout | cdefc |
| ey | | primary | | ey |
| fg | through\|right | primary | | fg |
| gz | | primary | | gz |
| gh | | primary | | gh |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | abx,bc,fg,gh,gh | depart,turn right,cdefc-exit-2,turn right,arrive | ,straight:false right:false right:false right:false right:true,right:false right:false right:false right:true,straight:false right:true, |
@anticipate @bug @todo
Scenario: Tripple Right keeping Left
Given the node map
| a | | | | b | | i |
| | | | | | | |
| | | | | | | |
| f | | e | | | | g |
| | | | | | | |
| | | | | | | |
| | j | d | | c | | |
| | | | | h | | |
And the ways
| nodes | turn:lanes:forward | highway | name |
| abi | \|\|right\|right | primary | start |
| bch | \|\|right\|right | primary | first |
| cdj | \|\|right\|right | primary | second |
| de | left\|right\|right | secondary | third |
| feg | | tertiary | fourth |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road left,arrive | ,none:false none:true right:false right:false,none:false none:true right:false right:false,none:false none:true right:false right:false,left:true right:false right:false, |
| a,g | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road right,arrive | ,none:false none:false right:true right:true,none:false none:false right:true right:true,none:false none:false right:true right:true,left:false right:true right:true, |
@anticipate @bug @todo
Scenario: Tripple Left keeping Right
Given the node map
| i | | b | | | | a |
| | | | | | | |
| | | | | | | |
| g | | | | e | | f |
| | | | | | | |
| | | | | | | |
| | | c | | d | j | |
| | | h | | | | |
And the ways
| nodes | turn:lanes:forward | highway | name |
| abi | left\|left\|\| | primary | start |
| bch | left\|left\|\| | primary | first |
| cdj | left\|left\|\| | primary | second |
| de | left\|left\|right | secondary | third |
| feg | | tertiary | fourth |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road right,arrive | ,left:false left:false none:true none:false,left:false left:false none:true none:false,left:false left:false none:true none:false,left:false left:false right:true, |
| a,g | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road left,arrive | ,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true right:false, |
+9 -9
View File
@@ -525,9 +525,9 @@ Feature: Collapse
| cf | secondary | bottom |
When I route I should get
| waypoints | turns | route |
| a,d | depart,continue right,end of road right,arrive | road,road,road,road |
| d,a | depart,continue left,end of road left,arrive | road,road,road,road |
| waypoints | turns | route |
| a,d | depart,continue right,turn right,arrive | road,road,road,road |
| d,a | depart,continue left,turn left,arrive | road,road,road,road |
Scenario: Forking before a turn
Given the node map
@@ -606,13 +606,13 @@ Feature: Collapse
| restriction | bc | fdcg | c | no_right_turn |
When I route I should get
| waypoints | route | turns |
| a,g | road,cross,cross | depart,turn left,arrive |
| a,e | road,road,road | depart,continue slight right,arrive |
# We should discuss whether the next item should be collapsed to depart,turn right,arrive.
| a,f | road,road,cross,cross | depart,continue slight right,turn right,arrive |
| waypoints | route | turns |
| a,g | road,cross,cross | depart,turn left,arrive |
| a,e | road,road,road | depart,continue slight right,arrive |
# We should discuss whether the next item should be collapsed to depart,turn right,arrive.
| a,f | road,road,cross,cross | depart,continue slight right,turn right,arrive |
Scenario: On-Off on Highway
Scenario: On-Off on Highway
Given the node map
| f | | | |
| a | b | c | d |
+54 -10
View File
@@ -57,20 +57,21 @@ Feature: Slipways and Dedicated Turn Lanes
Scenario: Inner city expressway with on road
Given the node map
| a | b | | | | c |
| | | | | f | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | d |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | e |
| a | b | | | | c | g |
| | | | | f | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | d | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | e | |
And the ways
| nodes | highway | name |
| abc | primary | road |
| cg | primary | road |
| bfd | trunk_link | |
| cde | trunk | trunk |
@@ -123,3 +124,46 @@ Feature: Slipways and Dedicated Turn Lanes
When I route I should get
| waypoints | route | turns |
| a,f | road,road,road | depart,continue uturn,arrive |
Scenario: Schwarzwaldstrasse Autobahn
Given the node map
| | | | | i | | | | | | h | | | | | g |
| | | j | | | | | | | | | | | | | |
| a | | | | | | | k | | | | | | | | |
| | | | b | | r | c | | d | | e | | | | | f |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | l | | | | | | | | | | |
| | | | | | m | | | | | | | | | | |
| | | | | | | n | | q | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | |
| | | | | | | o | | p | | | | | | | |
And the nodes
# the traffic light at `l` is not actually in the data, but necessary for the test to check everything
# http://www.openstreetmap.org/#map=19/48.99211/8.40336
| node | highway |
| r | traffic_signals |
| l | traffic_signals |
And the ways
| nodes | highway | name | ref | oneway |
| abrcd | secondary | Schwarzwaldstrasse | L561 | yes |
| hija | secondary | Schwarzwaldstrasse | L561 | yes |
| def | secondary | Ettlinger Strasse | | yes |
| gh | secondary | Ettlinger Strasse | | yes |
| blmn | secondary_link | | L561 | yes |
| hkc | secondary_link | Ettlinger Strasse | | yes |
| qdki | secondary_link | Ettlinger Allee | | yes |
| cn | secondary_link | Ettlinger Allee | | yes |
| no | primary | Ettlinger Allee | | yes |
| pq | primary | Ettlinger Allee | | yes |
| qe | secondary_link | Ettlinger Allee | | yes |
When I route I should get
| waypoints | route | turns |
| a,o | Schwarzwaldstrasse (L561),Ettlinger Allee,Ettlinger Allee | depart,turn right,arrive |
+49 -42
View File
@@ -8,116 +8,123 @@ Feature: End Of Road Instructions
Scenario: End of Road with through street
Given the node map
| | | c |
| a | | b |
| | | d |
| a | e | b |
| | f | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| cbd | primary |
| ef | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
Scenario: End of Road with three streets
Given the node map
| | | c |
| a | | b |
| | | d |
| a | e | b |
| | f | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| cb | primary |
| bd | primary |
| ef | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cb,cb | depart,end of road left,arrive |
| a,d | ab,bd,bd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cb,cb | depart,end of road left,arrive |
| a,d | aeb,bd,bd | depart,end of road right,arrive |
Scenario: End of Road with three streets, slightly angled
Given the node map
| a | | | | | c |
| | | | | | b |
| a | e | | | | c |
| | f | | | | b |
| | | | | | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| cb | primary |
| bd | primary |
| ef | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cb,cb | depart,end of road left,arrive |
| a,d | ab,bd,bd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cb,cb | depart,end of road left,arrive |
| a,d | aeb,bd,bd | depart,end of road right,arrive |
Scenario: End of Road with three streets, slightly angled
Given the node map
| | | | | | c |
| | | | | | b |
| a | | | | | d |
| | f | | | | b |
| a | e | | | | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| ef | primary |
| cb | primary |
| bd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cb,cb | depart,end of road left,arrive |
| a,d | ab,bd,bd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cb,cb | depart,end of road left,arrive |
| a,d | aeb,bd,bd | depart,end of road right,arrive |
Scenario: End of Road with through street, slightly angled
Given the node map
| a | | | | | c |
| | | | | | b |
| a | e | | | | c |
| | f | | | | b |
| | | | | | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| ef | primary |
| cbd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
Scenario: End of Road with through street, slightly angled
Given the node map
| | | | | | c |
| | | | | | b |
| a | | | | | d |
| | f | | | | b |
| a | e | | | | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| ef | primary |
| cbd | primary |
When I route I should get
| waypoints | route | turns |
| a,c | ab,cbd,cbd | depart,end of road left,arrive |
| a,d | ab,cbd,cbd | depart,end of road right,arrive |
| waypoints | route | turns |
| a,c | aeb,cbd,cbd | depart,end of road left,arrive |
| a,d | aeb,cbd,cbd | depart,end of road right,arrive |
Scenario: End of Road with two ramps - prefer ramp over end of road
Given the node map
| | | c |
| a | | b |
| | | d |
| a | e | b |
| | f | d |
And the ways
| nodes | highway |
| ab | primary |
| aeb | primary |
| ef | primary |
| bc | motorway_link |
| bd | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,c | ab,bc,bc | depart,on ramp left,arrive |
| a,d | ab,bd,bd | depart,on ramp right,arrive |
| waypoints | route | turns |
| a,c | aeb,bc,bc | depart,on ramp left,arrive |
| a,d | aeb,bd,bd | depart,on ramp right,arrive |
+18
View File
@@ -296,3 +296,21 @@ Feature: Fork Instructions
| waypoints | route | turns |
| a,c | abc,abc | depart,arrive |
| a,d | abc,bd,bd | depart,turn slight right,arrive |
Scenario: Fork on motorway links - don't fork on through
Given the node map
| i | | | | | a |
| j | | c | b | | x |
And the ways
| nodes | name | highway |
| xb | xbcj | motorway_link |
| bc | xbcj | motorway_link |
| cj | xbcj | motorway_link |
| ci | off | motorway_link |
| ab | on | motorway_link |
When I route I should get
| waypoints | route | turns |
| a,j | on,xbcj,xbcj | depart,merge slight left,arrive |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive |
+20 -39
View File
@@ -17,8 +17,8 @@ Feature: Intersections Data
| bd | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:90 true:180 false:270;true:270 |
| waypoints | route | intersections |
| a,c | through,through | true:90,true:90 true:180 false:270;true:270 |
Scenario: Passing Three Way North
Given the node map
@@ -32,8 +32,8 @@ Feature: Intersections Data
| bd | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
| waypoints | route | intersections |
| a,c | through,through | true:90,true:0 true:90 false:270;true:270 |
Scenario: Passing Oneway Street In
Given the node map
@@ -47,8 +47,8 @@ Feature: Intersections Data
| db | corner | yes |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,false:0 true:90 false:270;true:270 |
| waypoints | route | intersections |
| a,c | through,through | true:90,false:0 true:90 false:270;true:270 |
Scenario: Passing Oneway Street Out
Given the node map
@@ -62,8 +62,8 @@ Feature: Intersections Data
| bd | corner | yes |
When I route I should get
| waypoints | route | turns | intersections |
| a,c | through,through | depart,arrive | true:90,true:0 true:90 false:270;true:270 |
| waypoints | route | intersections |
| a,c | through,through | true:90,true:0 true:90 false:270;true:270 |
Scenario: Passing Two Intersections
Given the node map
@@ -80,27 +80,8 @@ Feature: Intersections Data
| cf | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
Scenario: Regression test #2424
Given the node map
| | | e | | | | | | i | | | | |
| a | | b | | c | | d | | h | | k | | m |
| | | | | f | | | | | | l | | |
And the ways
| nodes | name |
| abcd | Fritz-Elsas-Straße |
| hkm | Fritz-Elsas-Straße |
| dhi | Martin-Luther-Straße |
| be | corner |
| kl | corner |
| cf | corner |
When I route I should get
| waypoints | route | turns |
| a,m | Fritz-Elsas-Straße,Fritz-Elsas-Straße| depart,arrive |
| waypoints | route | intersections |
| a,d | through,through | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
Scenario: Passing Two Intersections, Collapsing
Given the node map
@@ -117,9 +98,9 @@ Feature: Intersections Data
| cf | corner |
When I route I should get
| waypoints | route | turns | intersections |
| a,d | through,through | depart,arrive | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
| f,a | corner,through,through | depart,end of road left,arrive | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
| waypoints | route | intersections |
| a,d | through,through | true:90,true:0 true:90 false:270,true:90 true:180 false:270;true:270 |
| f,a | corner,through,through | true:0;true:90 false:180 true:270,true:0 false:90 true:270;true:90 |
Scenario: Roundabouts
Given the node map
@@ -144,10 +125,10 @@ Feature: Intersections Data
| hd | |
When I route I should get
| waypoints | route | turns | intersections |
| e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
| e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0|
| e,h | ea,hd,hd | depart,abcda-exit-3,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 |
| e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1|
| 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0|
| 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214|
| waypoints | route | intersections |
| e,f | ea,fb,fb | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
| e,g | ea,gc,gc | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
| e,h | ea,hd,hd | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 |
| e,2 | ea,abcda,abcda | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1 |
| 1,g | abcda,gc,gc | true:214;false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
| 1,3 | abcda,abcda | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214 |
+24
View File
@@ -50,3 +50,27 @@ Feature: Merging
| waypoints | route | turns |
| d,c | db,abc,abc | depart,merge slight left,arrive |
Scenario: Merge onto a turning road
Given the node map
| | | | | | | e |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | d | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | c | | |
| | | | b | | | |
| a | | | | | | f |
And the ways
| nodes | highway | name |
| abcde | primary | road |
| fd | residential | in |
When I route I should get
| waypoints | turns | route |
| f,e | depart,merge slight left,arrive | in,road,road |
| f,a | depart,turn sharp left,arrive | in,road,road |
+18
View File
@@ -216,3 +216,21 @@ Feature: Motorway Guidance
| waypoints | route | turns |
| d,c | db,abc,abc | depart,merge slight left,arrive |
| e,c | eb,abc,abc | depart,merge slight right,arrive |
Scenario: Handle 90 degree off ramps correctly
Given the node map
| a | | | | |
| x | b | | c | y |
| | | | d | |
And the ways
| nodes | name | highway | oneway |
| ab | On | motorway_link | yes |
| xb | Hwy | motorway | |
| bc | Hwy | motorway | |
| cd | Off | motorway_link | yes |
| cy | Hwy | motorway | |
When I route I should get
| waypoints | route | turns |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive |
+22
View File
@@ -0,0 +1,22 @@
@routing @guidance @post-processing
Feature: General Post-Processing related features
Background:
Given the profile "car"
Given a grid size of 10 meters
# this testcase used to crash geometry generation (at that time handled during intersection generation)
Scenario: Regression test #2424
Given the node map
| | | e | | | | | | i | | | | |
| a | | b | | c | | d | | h | | k | | m |
| | | | | f | | | | | | l | | |
And the ways
| nodes | name |
| abcd | Fritz-Elsas-Straße |
| hkm | Fritz-Elsas-Straße |
| dhi | Martin-Luther-Straße |
| be | corner |
| kl | corner |
| cf | corner |
+76
View File
@@ -361,3 +361,79 @@ Feature: Basic Roundabout
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive | 0->180,180->270,180->0 |
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive | 0->180,180->270,270->0 |
Scenario: Motorway Roundabout
#See 39.933742 -75.082345
Given the node map
| | | | | l | | | | a | | i |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | b | | | | |
| | | | c | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | h | | |
| n | | | | | | | | | | |
| | | | | | | | | | | |
| | | d | | | | | | | | j |
| | | | | | | | | | | |
| | | | | m | | | g | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | e | | f | | | | | | |
And the ways
| nodes | junction | name | highway | oneway | ref |
| ab | | crescent | trunk | yes | US 130 |
| bcd | roundabout | crescent | trunk | yes | US 130 |
| de | | crescent | trunk | yes | US 130 |
| fg | | crescent | trunk | yes | US 130 |
| gh | roundabout | crescent | trunk | yes | US 130 |
| hi | | crescent | trunk | yes | US 130 |
| jh | | | trunk_link | yes | NJ 38 |
| hb | roundabout | | trunk_link | yes | NJ 38 |
| bl | | | trunk_link | yes | NJ 38 |
| cnd | | kaighns | trunk_link | yes | |
| dmg | roundabout | | trunk_link | yes | |
When I route I should get
| waypoints | route | turns |
| a,e | crescent (US 130),crescent (US 130),crescent (US 130) | depart,roundabout-exit-3,arrive |
| j,l | NJ 38,NJ 38,NJ 38 | depart,roundabout-exit-2,arrive |
Scenario: Double Roundabout with through-lane
#http://map.project-osrm.org/?z=18&center=38.911752%2C-77.048667&loc=38.912003%2C-77.050831&loc=38.909277%2C-77.042516&hl=en&alt=0
Given the node map
| | | | | o | | | | | | | | | | | | n | | | | |
| | | | | e | | | | | | | | | | | | j | | | | |
| | | | | | | | | | | | | | | | | | | | | |
| | | | | | | q | | | | | | | | | | | | | | |
| a | | b | | | | | | s | | f | | | | g | | | | i | | k |
| | | | | | | r | | | | | | | | | | | p | | | |
| | | | | | | | | | | t | | | | | | | | | | |
| | | | | c | | d | | | | | | | | | | h | | | | |
| | | | | l | | | | | | | | | | | | m | | | | |
And the nodes
| node | highway |
| i | traffic_signals |
And the ways
| nodes | junction | name | oneway |
| bcdrqeb | roundabout | sheridan circle | yes |
| ghi | roundabout | dupont circle | yes |
| ijg | roundabout | dupont circle | yes |
| ab | | massachusetts | no |
| sfgpik | | massachusetts | no |
| cl | | 23rd street | no |
| oe | | r street | no |
| jn | | new hampshire | no |
| mh | | new hampshire | yes |
| rsq | | massachusetts | yes |
| ft | | suppressed | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sfgpik | ijg | i | no_left_turn |
When I route I should get
| waypoints | route | turns |
| a,k | massachusetts,massachusetts,massachusetts,massachusetts | depart,sheridan circle-exit-2,dupont circle-exit-1,arrive |
+686
View File
@@ -0,0 +1,686 @@
@routing @guidance @turn-lanes
Feature: Turn Lane Guidance
Background:
Given the profile "car"
Given a grid size of 20 meters
@bug
Scenario: Basic Turn Lane 3-way Turn with empty lanes
Given the node map
| a | | b | | c |
| | | d | | |
And the ways
| nodes | turn:lanes | turn:lanes:forward | turn:lanes:backward | name |
| ab | | through\|right | | in |
| bc | | | left\|through\|\| | straight |
| bd | | | left\|right | right |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,straight:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,straight:false right:true, |
| c,a | straight,in,in | depart,new name straight,arrive | ,left:false straight:true none:true none:true, |
| c,d | straight,right,right | depart,turn left,arrive | ,left:true straight:false none:false none:false, |
Scenario: Basic Turn Lane 4-Way Turn
Given the node map
| | | e | | |
| a | | b | | c |
| | | d | | |
And the ways
| nodes | turn:lanes | turn:lanes:forward | turn:lanes:backward | name |
| ab | | \|right | | in |
| bc | | | | straight |
| bd | | | left\| | right |
| be | | | | left |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
| d,a | right,in,in | depart,turn left,arrive | ,left:true none:false, |
| d,e | right,left,left | depart,new name straight,arrive | ,left:false none:true, |
| d,c | right,straight,straight | depart,turn right,arrive | ,left:false none:true, |
Scenario: Basic Turn Lane 4-Way Turn using none
Given the node map
| | | e | | |
| a | | b | | c |
| | | d | | |
And the ways
| nodes | turn:lanes | turn:lanes:forward | turn:lanes:backward | name |
| ab | | none\|right | | in |
| bc | | | | straight |
| bd | | | left\|none | right |
| be | | | | left |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
Scenario: Basic Turn Lane 4-Way With U-Turn Lane
Given the node map
| | | e | | |
| a | 1 | b | | c |
| | | d | | |
And the ways
| nodes | turn:lanes | turn:lanes:forward | name |
| ab | | reverse;left\|through;right | in |
| bc | | | straight |
| bd | | | right |
| be | | | left |
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,left;uturn:false straight;right:true, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,left;uturn:false straight;right:true, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,left;uturn:true straight;right:false, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,left;uturn:true straight;right:false, |
#this next test requires decision on how to announce lanes for going straight if there is no turn
@TODO
Scenario: Turn with Bus-Lane
Given the node map
| a | | b | | c |
| | | | | |
| | | d | | |
And the ways
| nodes | name | turn:lanes:forward | lanes:psv:forward |
| ab | road | through\|right\| | 1 |
| bc | road | | |
| bd | turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
| a,c | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, |
@PROFILE @LANES
Scenario: Turn with Bus-Lane but without lanes
Given the node map
| a | | b | | c |
| | | | | |
| | | d | | |
And the ways
| nodes | name | lanes:psv |
| ab | road | 1 |
| bc | road | yes |
| bd | turn | |
When I route I should get
| waypoints | route | turns |
| a,d | road,turn,turn | depart,turn right,arrive |
| a,c | road,road | depart,arrive |
#turn lanes are often drawn at the incoming road, even though the actual turn requires crossing the intersection first
@todo @bug
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | i | l | | |
| | | | | | |
| h | | g | f | | e |
| a | | b | c | | d |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through\|right | yes |
| bc | road | left\|through | yes |
| cd | road | | yes |
| ef | road | \|through\|through;right | yes |
| fg | road | left;through\|through\| | yes |
| gh | road | | yes |
| ig | cross | | yes |
| gb | cross | left\|through | yes |
| bj | cross | | yes |
| kc | cross | left\|through;right | yes |
| cf | cross | left\|through | yes |
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true |
| a,d | road,road,road | depart,use lane straight,arrive | ,left:false straight:true right:false, |
| a,l | road,cross,cross | depart,turn left,arrive | ,left:true straight:false right:false, |
| a,h | road,road,road | depart,continue uturn,arrive | ,left:true straight:false right:false, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight;right:true, |
| k,h | cross,road,road | depart,turn left,arrive | ,left:true straight;right:false, |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight;right:false, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
| e,h | road,road | depart,arrive | ,none:false straight:true straight;right:true |
| e,j | road,cross,cross | depart,turn left,arrive | ,none:true straight:false straight;right:false, |
| e,d | road,road,road | depart,continue uturn,arrive | ,none:true straight:false straight;right:false, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight:true, |
| i,d | cross,road,road | depart,turn left,arrive | ,left:true straight:false, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
#copy of former case to prevent further regression
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | i | l | | |
| | | | | | |
| h | | g | f | | e |
| a | | b | c | | d |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through\|right | yes |
| bc | road | left\|through | yes |
| cd | road | | yes |
| ef | road | \|through\|through;right | yes |
| fg | road | left;through\|through\| | yes |
| gh | road | | yes |
| ig | cross | | yes |
| gb | cross | left\|through | yes |
| bj | cross | | yes |
| kc | cross | left\|through;right | yes |
| cf | cross | left\|through | yes |
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, |
| 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,cross | depart,use lane straight,arrive | ,left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | g | f | | |
| a | | b | c | | d |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through\|right | yes |
| bc | road | | yes |
| cd | road | | yes |
| gb | cross | | yes |
| bj | cross | | yes |
| kc | cross | | yes |
| cf | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
#this can happen due to traffic lights / lanes not drawn up to the intersection itself
Scenario: Turn Lanes Given earlier than actual turn
Given the node map
| a | | b | c | | d |
| | | | | | |
| | | | e | | |
And the ways
| nodes | name | turn:lanes:forward |
| ab | road | \|right |
| bc | road | |
| cd | road | |
| ce | turn | |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, |
| a,d | road,road,road | depart,use lane straight,arrive | ,none:true right:false, |
Scenario: Turn Lanes Given earlier than actual turn
Given the node map
| a | | b | c | d | | e | | f | g | h | | i |
| | | j | | | | | | | | k | | |
And the ways
| nodes | name | turn:lanes:forward | turn:lanes:backward |
| abc | road | | |
| cd | road | | left\| |
| def | road | | |
| fg | road | \|right | |
| ghi | road | | |
| bj | first-turn | | |
| hk | second-turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, |
| a,i | road,road,road | depart,use lane straight,arrive | ,none:true right:false, |
| i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none:false, |
| i,a | road,road,road | depart,use lane straight,arrive | ,left:false none:true, |
Scenario: Passing a one-way street
Given the node map
| e | | | f | |
| a | | b | c | d |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through | no |
| bcd | road | | no |
| eb | owi | | yes |
| cf | turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight:false, |
Scenario: Passing a one-way street, partly pulled back lanes
Given the node map
| e | | | f | |
| a | | b | c | d |
| | | g | | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through;right | no |
| bcd | road | | no |
| eb | owi | | yes |
| cf | turn | | no |
| bg | right | | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight;right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false straight;right:true, |
Scenario: Passing a one-way street, partly pulled back lanes, no through
Given the node map
| e | | | f |
| a | | b | c |
| | | g | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|right | no |
| bc | road | | no |
| eb | owi | | yes |
| cf | turn | | no |
| bg | right | | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false right:true, |
@todo @bug
Scenario: Narrowing Turn Lanes
Given the node map
| | | | | g | |
| | | | | | |
| a | | b | c | d | e |
| | | | f | | |
And the ways
| nodes | name | turn:lanes:forward |
| ab | road | left\|through\|right |
| bc | road | |
| cd | road | left\|through |
| de | through | |
| dg | left | |
| cf | right | |
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,left,left | depart,turn left,arrive | ,left:true straight:false right:false, |
| a,e | road,through,through | depart,new name straight,arrive | ,left:false straight:true right:false, |
| a,f | road,right,right | depart,turn right,arrive | ,left:false straight:false right:true, |
Scenario: Turn at a traffic light
Given the node map
| a | b | c | d |
| | | e | |
And the nodes
| node | highway |
| b | traffic_signals |
And the ways
| nodes | name | turn:lanes:forward |
| ab | road | through\|right |
| bc | road | |
| cd | road | |
| ce | turn | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, |
| a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
@bug @todo
Scenario: Theodor Heuss Platz
Given the node map
| | | | i | o | | | l | |
| | | b | | | | a | | m |
| | c | | | | | | | |
| | | | | | | | h | |
| | | | | | | | | |
| j | | | | | | | | |
| | | | | | | | g | |
| | | | | | | | | |
| | d | | | | | | | |
| | | e | | | | f | | |
| | | | | k | | | | n |
And the nodes
| node | highway |
| g | traffic_signals |
And the ways
| nodes | name | turn:lanes:forward | junction | oneway | highway |
| abcdef | roundabout | | roundabout | yes | primary |
| gha | roundabout | | roundabout | yes | primary |
| fg | roundabout | slight_left\|slight_left;slight_right\|slight_right\|slight_right | roundabout | yes | primary |
| aoib | top | | | yes | primary |
| cjd | left | | | yes | primary |
| ekf | bottom | | | yes | primary |
| fng | bottom-right | | | yes | primary |
| hma | top-right | | | yes | primary |
| hl | top-right-out | | | yes | secondary |
When I route I should get
| waypoints | route | turns | lanes |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,slight left:false slight left;slight right:true slight right:true slight right:true, |
| i,l | top,top-right-out,top-right-out | depart,roundabout-exit-4,arrive | ,slight left:true slight left;slight right:true slight right:false slight right:false, |
| i,o | top,top,top | depart,roundabout-exit-5,arrive | ,, |
Scenario: Turn Lanes Breaking up
Given the node map
| | | | g | |
| | | | | |
| | | | c | |
| a | b | | d | e |
| | | | | |
| | | | f | |
And the ways
| nodes | name | turn:lanes:forward | oneway | highway |
| ab | road | left\|left\|through\|through | yes | primary |
| bd | road | through\|through | yes | primary |
| bc | road | left\|left | yes | primary |
| de | road | | yes | primary |
| fdcg | cross | | | secondary |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bd | fdcg | d | no_left_turn |
| restriction | bc | fdcg | c | no_right_turn |
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, |
| a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false straight:true straight:true, |
Scenario: U-Turn Road at Intersection
Given the node map
| | | | | | h | |
| | | | | f | e | j |
| a | b | | | | | |
| | | | | c | d | i |
| | | | | | g | |
And the ways
| nodes | name | turn:lanes:forward | oneway | highway |
| ab | road | | no | primary |
| di | road | | yes | primary |
| bc | road | \|through\|right | yes | primary |
| cd | road | \|through\|right | yes | primary |
| fc | road | | no | tertiary |
| jefb | road | | yes | primary |
| gdeh | cross | | no | primary |
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false straight:false right:true, |
| a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true straight:false right:false, |
| a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,none:true straight:true right:false, |
| b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true straight:false right:false, |
Scenario: Segregated Intersection Merges With Lanes
Given the node map
| | | | | | | f |
| | | | | | | |
| e | | | d | | | |
| | | | | | c | g |
| a | | | b | | | |
| | | | | | | |
| | | | | | h | |
And the ways
| nodes | name | turn:lanes:forward | oneway | highway |
| abc | road | left\|left\|left\|through\|through | yes | primary |
| cde | road | | yes | primary |
| hc | cross | | yes | secondary |
| cg | straight | | no | tertiary |
| cf | left | | yes | primary |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true straight:false straight:false, |
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false straight:true straight:true, |
@bug @todo
Scenario: Passing Through a Roundabout
Given the node map
| | | h | | g | | |
| | a | | | | f | k |
| i | | | | | | |
| | | | | | | |
| | b | | | | e | |
| | | c | | d | | |
| | | | | j | | |
And the ways
| nodes | name | turn:lanes:forward | oneway | highway | junction |
| efgha | round | | yes | primary | roundabout |
| ab | round | | yes | primary | roundabout |
| bc | round | slight_left\|slight_left\|slight_right | yes | primary | roundabout |
| cd | round | | yes | primary | roundabout |
| de | round | slight_left\|slight_right | yes | primary | roundabout |
| ib | left | slight_left\|slight_left\|slight_right | yes | primary | |
| cj | bottom | | yes | primary | |
| ek | right | | yes | primary | |
When I route I should get
| waypoints | route | turns | lanes |
| i,j | left,bottom,bottom | depart,round-exit-1,arrive | ,0, |
| i,k | left,right,right | depart,round-exit-2,arrive | ,1, |
Scenario: Crossing Traffic Light
Given the node map
| a | | b | | c | | d |
| | | | | | | e |
And the nodes
| node | highway |
| b | traffic_signals |
And the ways
| nodes | name | turn:lanes:forward | highway |
| abc | road | through\|through\|through;slight_right\|slight_right | primary |
| cd | road | | primary |
| ce | cross | | primary |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
Scenario: Highway Ramp
Given the node map
| a | | b | | c | | d |
| | | | | | | e |
And the ways
| nodes | name | turn:lanes:forward | highway |
| abc | hwy | through\|through\|through;slight_right\|slight_right | motorway |
| cd | hwy | | motorway |
| ce | ramp | | motorway_link |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
@bug @todo
Scenario: Turning Off Ramp
Given the node map
| | a | |
| d | c | b |
| e | f | g |
| | h | |
And the ways
| nodes | name | turn:lanes:forward | highway | oneway |
| ac | off | left\|right | motorway_link | yes |
| bcd | road | | primary | yes |
| cf | road | | primary | |
| efg | road | | primary | yes |
| fh | on | | motorway_link | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | off,road,road | depart,turn_right,arrive | ,left:false right:true, |
| a,g | off,road,road | depart,turn_left,arrive | ,left:true right:false, |
| a,h | | | |
Scenario: Off Ramp In a Turn
Given the node map
| a | | | | | | | | | | | |
| | | | | | | | | | | | |
| | | | | | b | | | | | | c |
| | | | | | | | | | | d | |
And the ways
| nodes | name | turn:lanes:forward | highway | oneway |
| ab | hwy | through\|through\|slight_right | motorway | yes |
| bc | hwy | | motorway | yes |
| bd | ramp | | motorway_link | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,straight:true straight:true slight right:false, |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false slight right:true, |
Scenario: Reverse Lane in Segregated Road
Given the node map
| h | | | | | g | | | | | | f |
| | | | | | | | e | | | | |
| | | | | | | | d | | | | |
| a | | | | | b | | | | | | c |
And the ways
| nodes | name | turn:lanes:forward | highway | oneway |
| ab | road | reverse\|through\|through | primary | yes |
| bc | road | | primary | yes |
| bdeg | road | | primary_link | yes |
| fgh | road | | primary | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false straight:false,|
Scenario: Reverse Lane in Segregated Road with none
Given the node map
| h | | | | | g | | | | | | f |
| | | | | | | | e | | | | |
| | | | | | | | d | | | | |
| a | | | | | b | | | | | | c |
And the ways
| nodes | name | turn:lanes:forward | highway | oneway |
| ab | road | reverse\|through\|none | primary | yes |
| bc | road | | primary | yes |
| bdeg | road | | primary_link | yes |
| fgh | road | | primary | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false none:false, |
Scenario: Reverse Lane in Segregated Road with none, Service Turn Prior
Given the node map
| h | | | | | g | | | | | | f |
| | | | | | | | e | | | | |
| | | | | | | | d | | | | |
| a | | j | | | b | | | | | | c |
| | | i | | | | | | | | | |
And the ways
| nodes | name | turn:lanes:forward | highway | oneway |
| ajb | road | reverse\|through\|none | primary | yes |
| bc | road | | primary | yes |
| bdeg | road | | primary_link | yes |
| fgh | road | | primary | yes |
| ji | park | | service | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false none:false, |
Scenario: Don't collapse everything to u-turn / too wide
Given the node map
| a | | b | | e |
| | | | | |
| d | | c | | f |
And the ways
| nodes | highway | name | turn:lanes:forward |
| ab | primary | road | through\|right |
| bc | primary | road | |
| dc | primary | road | left\|through |
| be | secondary | top | |
| cf | secondary | bottom | |
When I route I should get
| waypoints | turns | route | lanes |
| a,d | depart,continue right,turn right,arrive | road,road,road,road | ,straight:false right:true,, |
| d,a | depart,continue left,turn left,arrive | road,road,road,road | ,left:true straight:false,, |
Scenario: Merge Lanes Onto Freeway
Given the node map
| a | | | b | c |
| | d | | | |
And the ways
| nodes | highway | name | turn:lanes:forward |
| abc | motorway | Hwy | |
| db | motorway_link | ramp | slight_right\|slight_right |
When I route I should get
| waypoints | turns | route | lanes |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,slight right:true slight right:true, |
Scenario: Fork on motorway links - don't fork on through but use lane
Given the node map
| i | | | | | a |
| j | | c | b | | x |
And the ways
| nodes | name | highway | turn:lanes:forward |
| xb | xbcj | motorway_link | |
| bc | xbcj | motorway_link | none\|slight_right |
| cj | xbcj | motorway_link | |
| ci | off | motorway_link | |
| ab | on | motorway_link | |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |
+46
View File
@@ -833,3 +833,49 @@ Feature: Simple Turns
| a,d | road,road | depart,arrive |
| d,i | road,cross,cross | depart,turn left,arrive |
| d,g | road,road | depart,arrive |
Scenario: Go onto turning major road
Given the node map
| | | | c |
| | | | |
| | | | |
| a | | | b |
| | | | |
| | | | d |
And the ways
| nodes | highway | name |
| abc | primary | road |
| bd | residential | in |
When I route I should get
| waypoints | turns | route |
| a,c | depart,arrive | road,road |
| d,a | depart,turn left,arrive | in,road,road |
| d,c | depart,new name straight,arrive | in,road,road |
Scenario: Channing Street
Given the node map
| | | g | f | |
| | | | | |
| d | | c | b | a |
| | | | | |
| | | | | |
| | | h | e | |
And the nodes
| node | highway |
| c | traffic_signals |
| b | traffic_signals |
And the ways
| nodes | name | highway | oneway |
| ab | Channing Street Northeast | residential | no |
| bcd | Channing Street Northwest | residential | yes |
| ebf | North Capitol Street Northeast | primary | yes |
| gch | North Capitol Street Northeast | primary | yes |
When I route I should get
| waypoints | turns | route |
| a,d | depart,arrive | Channing Street Northeast,Channing Street Northwest |
| a,h | depart,turn left,arrive | Channing Street Northeast,North Capitol Street Northeast,North Capitol Street Northeast |
+1 -1
View File
@@ -17,7 +17,7 @@ module.exports = function () {
this.setContractArgs(args, callback);
});
this.Given(/^a grid size of (\d+) meters$/, (meters, callback) => {
this.Given(/^a grid size of ([0-9.]+) meters$/, (meters, callback) => {
this.setGridSize(meters);
callback();
});
-12
View File
@@ -15,16 +15,4 @@ module.exports = function () {
this.setOrigin(this.DEFAULT_ORIGIN);
callback();
});
this.Before('@ignore-platform-windows', () => {
this.skipThisScenario();
});
this.Before('@ignore-platform-unix', () => {
this.skipThisScenario();
});
this.Before('@ignore-platform-mac', () => {
this.skipThisScenario();
});
};
+14
View File
@@ -1,5 +1,6 @@
var util = require('util');
var d3 = require('d3-queue');
var polyline = require('polyline');
module.exports = function () {
this.When(/^I match I should get$/, (table, callback) => {
@@ -35,6 +36,7 @@ module.exports = function () {
route = '',
duration = '',
annotation = '',
geometry = '',
OSMIDs = '';
@@ -63,6 +65,11 @@ module.exports = function () {
annotation = this.annotationList(json.matchings[0]);
}
if (headers.has('geometry')) {
if (json.matchings.length != 1) throw new Error('*** Checking geometry only supported for matchings with one subtrace');
geometry = json.matchings[0].geometry;
}
if (headers.has('OSM IDs')) {
if (json.matchings.length != 1) throw new Error('*** CHecking annotation only supported for matchings with one subtrace');
OSMIDs = this.OSMIDList(json.matchings[0]);
@@ -85,6 +92,13 @@ module.exports = function () {
got.annotation = annotation.toString();
}
if (headers.has('geometry')) {
if (this.queryParams['geometries'] === 'polyline')
got.geometry = polyline.decode(geometry).toString();
else
got.geometry = geometry;
}
if (headers.has('OSM IDs')) {
got['OSM IDs'] = OSMIDs;
}
+2 -2
View File
@@ -223,7 +223,7 @@ module.exports = function () {
};
['osrm', 'osrm.ebg', 'osrm.edges', 'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.icd',
'osrm.names', 'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions'].forEach(file => {
'osrm.names', 'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach(file => {
q.defer(rename, file);
});
@@ -283,7 +283,7 @@ module.exports = function () {
['osrm', 'osrm.core', 'osrm.datasource_indexes', 'osrm.datasource_names', 'osrm.ebg','osrm.edges',
'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.hsgr', 'osrm.icd','osrm.level', 'osrm.names',
'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions'].forEach((file) => {
'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach((file) => {
q.defer(rename, file);
});
+1 -1
View File
@@ -21,7 +21,7 @@ module.exports = function () {
this.DEFAULT_GRID_SIZE = 100; // meters
this.PROFILES_PATH = path.resolve(this.ROOT_FOLDER, 'profiles');
this.FIXTURES_PATH = path.resolve(this.ROOT_FOLDER, 'unit_tests/fixtures');
this.BIN_PATH = path.resolve(this.ROOT_FOLDER, 'build');
this.BIN_PATH = process.env.OSRM_BUILD_DIR && process.env.OSRM_BUILD_DIR || path.resolve(this.ROOT_FOLDER, 'build');
this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_ORIGIN = [1,1];
this.DEFAULT_LOAD_METHOD = 'datastore';
-5
View File
@@ -33,9 +33,4 @@ module.exports = function () {
});
});
});
this.Around('@stress', (scenario, callback) => {
// TODO implement stress timeout? Around support is being dropped in cucumber-js anyway
callback();
});
};
+11
View File
@@ -168,6 +168,17 @@ module.exports = function () {
return instructions.legs.map(l => l.annotation.nodes.map(n => n.toString()).join(',')).join(',');
};
this.lanesList = (instructions) => {
return this.extractInstructionList(instructions, instruction => {
if( 'lanes' in instruction.maneuver )
{
return instruction.maneuver.lanes.map( p => { return (p.indications).join(';') + ':' + p.valid; } ).join(' ');
} else
{
return '';
}});
};
this.turnList = (instructions) => {
return instructions.legs.reduce((m, v) => m.concat(v.steps), [])
.map(v => {
+7 -1
View File
@@ -33,7 +33,8 @@ module.exports = function () {
var afterRequest = (err, res, body) => {
if (err) return cb(err);
if (body && body.length) {
let destinations, pronunciations, instructions, bearings, turns, modes, times, distances, summary, intersections;
let destinations, pronunciations, instructions, bearings, turns, modes, times,
distances, summary, intersections, lanes;
let json = JSON.parse(body);
@@ -49,6 +50,7 @@ module.exports = function () {
modes = this.modeList(json.routes[0]);
times = this.timeList(json.routes[0]);
distances = this.distanceList(json.routes[0]);
lanes = this.lanesList(json.routes[0]);
summary = this.summary(json.routes[0]);
}
@@ -102,6 +104,10 @@ module.exports = function () {
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))
+37 -1
View File
@@ -233,7 +233,7 @@ Feature: Basic Routing
| d | a | abcd,abcd |
| a | m | aeim,aeim |
| m | a | aeim,aeim |
Scenario: Testbot - Triangle challenge
Given the node map
| | | | d |
@@ -251,3 +251,39 @@ Feature: Basic Routing
| from | to | route |
| d | c | de,ce,ce |
| e | d | de,de |
Scenario: Ambiguous edge weights - Use minimal edge weight
Given the node map
| a | b |
And the ways
| nodes | highway | name |
| ab | tertiary | |
| ab | primary | |
| ab | secondary | |
When I route I should get
| from | to | route | time |
| a | b | , | 10s |
| b | a | , | 10s |
Scenario: Ambiguous edge names - Use lexicographically smallest name
Given the node map
| a | b | c |
And the ways
| nodes | highway | name |
| ab | primary | |
| ab | primary | Αβγ |
| ab | primary | |
| ab | primary | Abc |
| ab | primary | |
| ab | primary | Абв |
| bc | primary | Ηθι |
| bc | primary | Δεζ |
| bc | primary | Где |
When I route I should get
| from | to | route |
| a | c | Abc,Δεζ,Δεζ |
| c | a | Δεζ,Abc,Abc |
+18 -2
View File
@@ -59,10 +59,10 @@ Feature: Compass bearing
Scenario: Bearing in a roundabout
Given the node map
| | d | c | |
| k | d | c | j |
| e | | | b |
| f | | | a |
| | g | h | |
| l | g | h | i |
And the ways
| nodes | oneway |
@@ -74,6 +74,14 @@ Feature: Compass bearing
| fg | yes |
| gh | yes |
| ha | yes |
| dk | no |
| ke | no |
| fl | no |
| lg | no |
| hi | no |
| ia | no |
| bj | no |
| cj | no |
When I route I should get
| from | to | route | bearing |
@@ -82,8 +90,10 @@ Feature: Compass bearing
Scenario: Bearing should stay constant when zig-zagging
Given the node map
| i | j | k | |
| b | d | f | h |
| a | c | e | g |
| | m | n | o |
And the ways
| nodes |
@@ -94,6 +104,12 @@ Feature: Compass bearing
| ef |
| fg |
| gh |
| bi |
| cm |
| dj |
| en |
| fk |
| go |
When I route I should get
| from | to | route | bearing |
+19 -19
View File
@@ -14,11 +14,11 @@ Feature: Bearing parameter
| ad |
When I route I should get
| from | to | bearings | route | bearing |
| from | to | bearings | route | bearing |
| b | c | 90 90 | ad,ad | 0->90,90->0|
| b | c | 180 90 | | |
| b | c | 180 90 | | |
| b | c | 80 100 | ad,ad | 0->90,90->0|
| b | c | 79 100 | | |
| b | c | 79 100 | | |
| b | c | 79,11 100 | ad,ad | 0->90,90->0|
Scenario: Testbot - Intial bearing in simple case
@@ -33,13 +33,13 @@ Feature: Bearing parameter
| bc |
When I route I should get
| from | to | bearings | route | bearing |
| 0 | c | 0 0 | | |
| 0 | c | 45 45 | bc,bc | 0->44,44->0 +- 1|
| 0 | c | 85 85 | | |
| 0 | c | 95 95 | | |
| from | to | bearings | route | bearing |
| 0 | c | 0 0 | | |
| 0 | c | 45 45 | bc,bc | 0->44,44->0 +- 1 |
| 0 | c | 85 85 | | |
| 0 | c | 95 95 | | |
| 0 | c | 135 135 | ac,ac | 0->135,135->0 +- 1|
| 0 | c | 180 180 | | |
| 0 | c | 180 180 | | |
Scenario: Testbot - Initial bearing on split way
Given the node map
@@ -58,21 +58,21 @@ Feature: Bearing parameter
| ha | yes |
When I route I should get
| from | to | bearings | route | bearing |
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
| from | to | bearings | route | bearing |
| 0 | b | 10 10 | bc,bc | 0->0,0->0 |
| 0 | b | 90 90 | ab,ab | 0->90,90->0 |
# The returned bearing is wrong here, it's based on the snapped
# coordinates, not the acutal edge bearing. This should be
# fixed one day, but it's only a problem when we snap two vias
# to the same point - DP
#| 0 | b | 170 170 | da | 180 |
#| 0 | b | 189 189 | da | 180 |
| 0 | 1 | 90 270 | ab,bc,cd,cd | 0->90,90->0,0->270,270->0 |
| 1 | d | 10 10 | bc,bc | 0->0,0->0 |
#| 0 | b | 170 170 | da | 180 |
#| 0 | b | 189 189 | da | 180 |
| 0 | 1 | 90 270 | ab,bc,cd,cd | 0->90,90->0,0->270,270->0 |
| 1 | d | 10 10 | bc,bc | 0->0,0->0 |
| 1 | d | 90 90 | ab,bc,cd,da,da | 0->90,90->0,0->270,270->180,180->0 |
| 1 | 0 | 189 189 | da,da | 0->180,180->0 |
| 1 | d | 270 270 | cd,cd | 0->270,270->0 |
| 1 | d | 349 349 | | |
| 1 | 0 | 189 189 | da,da | 0->180,180->0 |
| 1 | d | 270 270 | cd,cd | 0->270,270->0 |
| 1 | d | 349 349 | | |
Scenario: Testbot - Initial bearing in all direction
Given the node map
+1 -1
View File
@@ -3,7 +3,7 @@ Feature: U-turns at via points
Background:
Given the profile "testbot"
Given a grid size of 100 meters
Given a grid size of 250 meters
Scenario: Continue straight at waypoints enabled by default
Given the node map
+15
View File
@@ -24,3 +24,18 @@ Feature: Fixed bugs, kept to check for regressions
When I route I should get
| from | to | route |
| x | y | abc,abc |
Scenario: Step trimming with very short segments
Given a grid size of 0.1 meters
Given the node map
| a | 1 | b | c | d | 2 | e |
Given the ways
| nodes | oneway |
| ab | yes |
| bcd | yes |
| de | yes |
When I route I should get
| from | to | route |
| 1 | 2 | bcd,bcd |
+5 -3
View File
@@ -75,12 +75,12 @@ Feature: Avoid weird loops caused by rounding errors
And the node map
| a | | |
| b | e | |
| | | 1 |
| h | | 1 |
| | | |
| | | 2 |
| | | |
| g | | |
| | c | f |
| | d | |
| d | | |
And the ways
| nodes | highway |
@@ -90,6 +90,8 @@ Feature: Avoid weird loops caused by rounding errors
| be | primary |
| ef | primary |
| cf | primary |
| cg | primary |
| bh | primary |
When I route I should get
| waypoints | route |
+18
View File
@@ -128,3 +128,21 @@ Feature: Basic Map Matching
| trace | matchings | OSM IDs |
| abeh | abcedgh | 1,2,3,2,3,4,5,4,5,6,7 |
| abci | abc,ci | 1,2,3,2,3,8,3,8 |
Scenario: Testbot - Geometry details
Given the query options
| overview | full |
| geometries | polyline |
Given the node map
| a | b | c |
| | d | |
And the ways
| nodes | oneway |
| abc | no |
| bd | no |
When I match I should get
| trace | matchings | geometry |
| abd | abd | 1,1,1,1.00009,1,1.00009,0.99991,1.00009 |
+5 -2
View File
@@ -3,6 +3,7 @@ Feature: Testbot - oneways
Background:
Given the profile "testbot"
Given a grid size of 250 meters
Scenario: Routing on a oneway roundabout
Given the node map
@@ -59,8 +60,8 @@ Feature: Testbot - oneways
Scenario: Testbot - Around the Block
Given the node map
| a | b |
| d | c |
| | a | b | |
| e | d | c | f |
And the ways
| nodes | oneway | foot |
@@ -68,6 +69,8 @@ Feature: Testbot - oneways
| bc | | no |
| cd | | no |
| da | | no |
| de | | no |
| cf | | no |
When I route I should get
| from | to | route |
+1 -1
View File
@@ -29,7 +29,7 @@ Feature: Basic Routing
Scenario: Check handling empty values
Given the node map
| a | b | | c | | d | f |
| | | | | | e |
| | | | | | e | |
And the ways
| nodes | name |
+4 -2
View File
@@ -145,14 +145,16 @@ Feature: Estimation of travel time
Scenario: Time of travel on a series of ways
Given the node map
| a | b | |
| | c | d |
| a | b | e |
| f | c | d |
And the ways
| nodes | highway |
| ab | primary |
| bc | primary |
| cd | primary |
| be | primary |
| cf | primary |
When I route I should get
| from | to | route | time |
+12 -6
View File
@@ -85,13 +85,16 @@ Feature: Via points
Scenario: Via points on ring of oneways
# xa it to avoid only having a single ring, which cna trigger edge cases
Given the node map
| x | | | | | | |
| a | 1 | b | 2 | c | 3 | d |
| f | | | | | | e |
| | x | | | | | | g | |
| | a | 1 | b | 2 | c | 3 | d | |
| i | f | | | | | | e | h |
And the ways
| nodes | oneway |
| xa | |
| if | |
| gd | |
| eh | |
| ab | yes |
| bc | yes |
| cd | yes |
@@ -110,13 +113,16 @@ Feature: Via points
Scenario: Via points on ring on the same oneway
# xa it to avoid only having a single ring, which cna trigger edge cases
Given the node map
| x | | | | |
| a | 1 | 2 | 3 | b |
| d | | | | c |
| | x | | | | e | |
| | a | 1 | 2 | 3 | b | |
| g | d | | | | c | f |
And the ways
| nodes | oneway |
| xa | |
| eb | |
| cf | |
| dg | |
| ab | yes |
| bc | yes |
| cd | yes |
+1 -1
View File
@@ -78,7 +78,7 @@ class Contractor
private:
ContractorConfig config;
std::size_t
EdgeID
LoadEdgeExpandedGraph(const std::string &edge_based_graph_path,
util::DeallocatingVector<extractor::EdgeBasedEdge> &edge_based_edge_list,
const std::string &edge_segment_lookup_path,
+8 -2
View File
@@ -82,6 +82,9 @@ class IteratorbasedCRC32
: "0"(crc), "c"(*str));
++str;
}
#else
(void)str;
(void)len;
#endif
return crc;
}
@@ -95,8 +98,11 @@ class IteratorbasedCRC32
}
#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__)
inline void
__get_cpuid(int param, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx) const
inline void __get_cpuid(int /*param*/,
unsigned * /*eax*/,
unsigned * /*ebx*/,
unsigned *ecx,
unsigned * /*edx*/) const
{
*ecx = 0;
}
+2
View File
@@ -12,6 +12,7 @@
#include "engine/guidance/assemble_overview.hpp"
#include "engine/guidance/assemble_route.hpp"
#include "engine/guidance/assemble_steps.hpp"
#include "engine/guidance/lane_processing.hpp"
#include "engine/guidance/post_processing.hpp"
#include "engine/internal_route_result.hpp"
@@ -149,6 +150,7 @@ class RouteAPI : public BaseAPI
leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom);
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
}
@@ -7,6 +7,7 @@
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "engine/phantom_node.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
@@ -138,6 +139,11 @@ class BaseDataFacade
const int bearing,
const int bearing_range) const = 0;
virtual bool hasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const = 0;
virtual extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
virtual unsigned GetCheckSum() const = 0;
virtual bool IsCoreNode(const NodeID id) const = 0;
@@ -16,6 +16,7 @@
#include "storage/storage_config.hpp"
#include "engine/geospatial_query.hpp"
#include "util/graph_loader.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/io.hpp"
#include "util/packed_vector.hpp"
#include "util/range_table.hpp"
@@ -78,6 +79,8 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<NodeID, false>::vector m_via_node_list;
util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
util::ShM<LaneDataID, false>::vector m_lane_data_id;
util::ShM<util::guidance::LaneTupelIdPair, false>::vector m_lane_tupel_id_pairs;
util::ShM<extractor::TravelMode, false>::vector m_travel_mode_list;
util::ShM<char, false>::vector m_names_char_list;
util::ShM<unsigned, false>::vector m_geometry_indices;
@@ -86,6 +89,8 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<unsigned, false>::vector m_segment_weights;
util::ShM<uint8_t, false>::vector m_datasource_list;
util::ShM<std::string, false>::vector m_datasource_names;
util::ShM<std::uint32_t, false>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, false>::vector m_lane_description_masks;
extractor::ProfileProperties m_profile_properties;
std::unique_ptr<InternalRTree> m_static_rtree;
@@ -118,6 +123,20 @@ class InternalDataFacade final : public BaseDataFacade
sizeof(m_profile_properties));
}
void LoadLaneTupelIdPairs(const boost::filesystem::path &lane_data_path)
{
boost::filesystem::ifstream in_stream(lane_data_path);
if (!in_stream)
{
throw util::exception("Could not open " + lane_data_path.string() + " for reading.");
}
std::uint64_t size;
in_stream.read(reinterpret_cast<char *>(&size), sizeof(size));
m_lane_tupel_id_pairs.resize(size);
in_stream.read(reinterpret_cast<char *>(&m_lane_tupel_id_pairs[0]),
sizeof(m_lane_tupel_id_pairs) * size);
}
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
{
util::SimpleLogger().Write() << "Loading Timestamp";
@@ -173,6 +192,7 @@ class InternalDataFacade final : public BaseDataFacade
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_lane_data_id.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
@@ -184,6 +204,7 @@ class InternalDataFacade final : public BaseDataFacade
m_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_lane_data_id[i] = current_edge_data.lane_data_id;
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid;
}
@@ -251,9 +272,9 @@ class InternalDataFacade final : public BaseDataFacade
}
BOOST_ASSERT(datasources_stream);
std::size_t number_of_datasources = 0;
std::uint64_t number_of_datasources = 0;
datasources_stream.read(reinterpret_cast<char *>(&number_of_datasources),
sizeof(std::size_t));
sizeof(number_of_datasources));
if (number_of_datasources > 0)
{
m_datasource_list.resize(number_of_datasources);
@@ -284,6 +305,15 @@ class InternalDataFacade final : public BaseDataFacade
new InternalGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadLaneDescriptions(const boost::filesystem::path &lane_description_file)
{
if (!util::deserializeAdjacencyArray(lane_description_file.string(),
m_lane_description_offsets,
m_lane_description_masks))
util::SimpleLogger().Write(logWARNING) << "Failed to read turn lane descriptions from "
<< lane_description_file.string();
}
void LoadStreetNames(const boost::filesystem::path &names_file)
{
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
@@ -386,11 +416,17 @@ class InternalDataFacade final : public BaseDataFacade
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading lane tags";
LoadLaneDescriptions(config.turn_lane_description_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path);
util::SimpleLogger().Write() << "Loading Lane Data Pairs";
LoadLaneTupelIdPairs(config.turn_lane_data_path);
}
// search graph access
@@ -741,6 +777,29 @@ class InternalDataFacade final : public BaseDataFacade
{
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return m_lane_data_id[id] != INVALID_LANE_DATAID;
}
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs[m_lane_data_id[id]];
}
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const override final
{
if (lane_description_id == INVALID_LANE_DESCRIPTIONID)
return {};
else
return extractor::guidance::TurnLaneDescription(
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id],
m_lane_description_masks.begin() +
m_lane_description_offsets[lane_description_id + 1]);
}
};
}
}
@@ -9,9 +9,11 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/profile_properties.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "engine/geospatial_query.hpp"
#include "util/make_unique.hpp"
@@ -79,6 +81,7 @@ class SharedDataFacade final : public BaseDataFacade
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
util::ShM<NodeID, true>::vector m_via_node_list;
util::ShM<unsigned, true>::vector m_name_ID_list;
util::ShM<LaneDataID, true>::vector m_lane_data_id;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
util::ShM<char, true>::vector m_names_char_list;
@@ -87,10 +90,13 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector m_geometry_list;
util::ShM<bool, true>::vector m_is_core_node;
util::ShM<uint8_t, true>::vector m_datasource_list;
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
util::ShM<char, true>::vector m_datasource_name_data;
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
util::ShM<util::guidance::LaneTupelIdPair, true>::vector m_lane_tupel_id_pairs;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
@@ -177,7 +183,8 @@ class SharedDataFacade final : public BaseDataFacade
osmnodeid_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::OSM_NODE_ID_LIST]);
// We (ab)use the number of coordinates here because we know we have the same amount of ids
m_osmnodeid_list.set_number_of_entries(data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
m_osmnodeid_list.set_number_of_entries(
data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]);
auto travel_mode_list_ptr = data_layout->GetBlockPtr<extractor::TravelMode>(
shared_memory, storage::SharedDataLayout::TRAVEL_MODE);
@@ -185,6 +192,19 @@ class SharedDataFacade final : public BaseDataFacade
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
auto lane_data_id_ptr = data_layout->GetBlockPtr<LaneDataID>(
shared_memory, storage::SharedDataLayout::LANE_DATA_ID);
util::ShM<LaneDataID, true>::vector lane_data_id(
lane_data_id_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DATA_ID]);
m_lane_data_id = std::move(lane_data_id);
auto lane_tupel_id_pair_ptr = data_layout->GetBlockPtr<util::guidance::LaneTupelIdPair>(
shared_memory, storage::SharedDataLayout::TURN_LANE_DATA);
util::ShM<util::guidance::LaneTupelIdPair, true>::vector lane_tupel_id_pair(
lane_tupel_id_pair_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
@@ -237,6 +257,23 @@ class SharedDataFacade final : public BaseDataFacade
m_names_char_list = std::move(names_char_list);
}
void LoadTurnLaneDescriptions()
{
auto offsets_ptr = data_layout->GetBlockPtr<std::uint32_t>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS);
util::ShM<std::uint32_t, true>::vector offsets(
offsets_ptr,
data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS]);
m_lane_description_offsets = std::move(offsets);
auto masks_ptr = data_layout->GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_MASKS);
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
masks_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
}
void LoadCoreInformation()
{
if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0)
@@ -415,6 +452,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadTimestamp();
LoadViaNodeList();
LoadNames();
LoadTurnLaneDescriptions();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
@@ -782,6 +820,28 @@ class SharedDataFacade final : public BaseDataFacade
{
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
}
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
}
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const override final
{
if (lane_description_id == INVALID_LANE_DESCRIPTIONID)
return {};
else
return extractor::guidance::TurnLaneDescription(
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id],
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id + 1]);
}
};
}
}
@@ -3,6 +3,7 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/toolkit.hpp"
@@ -31,11 +32,10 @@ namespace guidance
// |---| segment 1
// |---| segment 2
// |---| segment 3
template <typename DataFacadeT>
LegGeometry assembleGeometry(const DataFacadeT &facade,
const std::vector<PathData> &leg_data,
const PhantomNode &source_node,
const PhantomNode &target_node)
inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &leg_data,
const PhantomNode &source_node,
const PhantomNode &target_node)
{
LegGeometry geometry;
+24 -11
View File
@@ -3,6 +3,8 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/step_maneuver.hpp"
@@ -14,6 +16,7 @@
#include "util/coordinate_calculation.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
@@ -34,14 +37,13 @@ std::pair<short, short> getIntermediateBearings(const LegGeometry &leg_geometry,
const std::size_t segment_index);
} // ns detail
template <typename DataFacadeT>
std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const std::vector<PathData> &leg_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool source_traversed_in_reverse,
const bool target_traversed_in_reverse)
inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &facade,
const std::vector<PathData> &leg_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool source_traversed_in_reverse,
const bool target_traversed_in_reverse)
{
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.;
const constexpr char *NO_ROTARY_NAME = "";
@@ -70,7 +72,9 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Depart,
0};
0,
util::guidance::LaneTupel(),
{}};
Intersection intersection{source_node.location,
std::vector<short>({bearings.second}),
std::vector<bool>({true}),
@@ -147,7 +151,11 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
bearings.second,
path_point.turn_instruction,
WaypointType::None,
0};
0,
path_point.lane_data.first,
(path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::guidance::TurnLaneDescription())};
segment_index++;
segment_duration = 0;
}
@@ -202,7 +210,9 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Arrive,
0};
0,
util::guidance::LaneTupel(),
{}};
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
@@ -233,6 +243,9 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1);
BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1);
BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive);
BOOST_ASSERT(steps.back().maneuver.lanes.lanes_in_turn == 0);
BOOST_ASSERT(steps.back().maneuver.lanes.first_lane_from_the_right == INVALID_LANEID);
BOOST_ASSERT(steps.back().maneuver.lane_description.empty());
return steps;
}
@@ -0,0 +1,24 @@
#ifndef OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#define OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#include <vector>
#include "engine/guidance/route_step.hpp"
namespace osrm
{
namespace engine
{
namespace guidance
{
// Constrains lanes for multi-hop situations where lane changes depend on earlier ones.
// Instead of forcing users to change lanes rapidly in a short amount of time,
// we anticipate lane changes emitting only matching lanes early on.
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps);
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_ */
+10 -1
View File
@@ -2,9 +2,12 @@
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace osrm
@@ -27,8 +30,12 @@ struct StepManeuver
short bearing_before;
short bearing_after;
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
util::guidance::LaneTupel lanes;
extractor::guidance::TurnLaneDescription lane_description;
};
inline StepManeuver getInvalidStepManeuver()
@@ -38,7 +45,9 @@ inline StepManeuver getInvalidStepManeuver()
0,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::None,
0};
0,
util::guidance::LaneTupel(),
{}};
}
} // namespace guidance
+37 -31
View File
@@ -2,9 +2,13 @@
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include <algorithm>
#include <iterator>
#include <utility>
namespace osrm
{
@@ -13,6 +17,10 @@ namespace engine
namespace guidance
{
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
using util::guidance::staysOnRoundabout;
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
@@ -21,34 +29,6 @@ inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
}
inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
{
if (bearing < 135)
@@ -63,10 +43,36 @@ inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(con
return extractor::guidance::DirectionModifier::Left;
}
inline double angularDeviation(const double angle, const double from)
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
const double deviation = std::abs(angle - from);
return std::min(360 - deviation, deviation);
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
} // namespace guidance
+4 -2
View File
@@ -4,9 +4,9 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "engine/phantom_node.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <vector>
@@ -27,6 +27,8 @@ struct PathData
EdgeWeight duration_until_turn;
// instruction to execute at the turn
extractor::guidance::TurnInstruction turn_instruction;
// turn lane data
util::guidance::LaneTupelIdPair lane_data;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// entry class of the turn, indicating possibility of turns
@@ -546,8 +546,8 @@ class AlternativeRouting final
}
}
via_path_index = partially_unpacked_via_path.size() - 1;
shortest_path_index = partially_unpacked_shortest_path.size() - 1;
via_path_index = static_cast<int64_t>(partially_unpacked_via_path.size()) - 1;
shortest_path_index = static_cast<int64_t>(partially_unpacked_shortest_path.size()) - 1;
for (; via_path_index > 0 && shortest_path_index > 0;
--via_path_index, --shortest_path_index)
{
@@ -327,10 +327,14 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
name_index,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
INVALID_ENTRY_CLASSID});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade->hasLaneData(ed.id))
unpacked_path.back().lane_data = facade->GetLaneData(ed.id);
unpacked_path.back().entry_classid = facade->GetEntryClassID(ed.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
@@ -389,6 +393,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
phantom_node_pair.target_phantom.name_id,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID});
+51 -9
View File
@@ -13,6 +13,7 @@
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@@ -42,22 +43,60 @@ namespace osrm
namespace extractor
{
namespace lookup
{
// Set to 1 byte alignment
#pragma pack(push, 1)
struct SegmentHeaderBlock
{
std::uint32_t num_osm_nodes;
OSMNodeID previous_osm_node_id;
};
#pragma pack(pop)
static_assert(sizeof(SegmentHeaderBlock) == 12, "SegmentHeaderBlock is not packed correctly");
#pragma pack(push, 1)
struct SegmentBlock
{
OSMNodeID this_osm_node_id;
double segment_length;
std::int32_t segment_weight;
};
#pragma pack(pop)
static_assert(sizeof(SegmentBlock) == 20, "SegmentBlock is not packed correctly");
#pragma pack(push, 1)
struct PenaltyBlock
{
std::uint32_t fixed_penalty;
OSMNodeID from_id;
OSMNodeID via_id;
OSMNodeID to_id;
};
#pragma pack(pop)
static_assert(sizeof(PenaltyBlock) == 28, "PenaltyBlock is not packed correctly");
}
class EdgeBasedGraphFactory
{
public:
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table);
explicit EdgeBasedGraphFactory(
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks);
void Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_penalty_filename,
@@ -104,7 +143,7 @@ class EdgeBasedGraphFactory
//! list of edge based nodes (compressed segments)
std::vector<EdgeBasedNode> m_edge_based_node_list;
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
unsigned m_max_edge_id;
EdgeID m_max_edge_id;
const std::vector<QueryNode> &m_node_info_list;
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
@@ -117,11 +156,14 @@ class EdgeBasedGraphFactory
ProfileProperties profile_properties;
const util::NameTable &name_table;
const std::vector<std::uint32_t> &turn_lane_offsets;
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks;
void CompressGeometry();
unsigned RenumberEdges();
void GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_fixed_penalties_filename,
+5 -3
View File
@@ -5,6 +5,8 @@
#include "util/typedefs.hpp"
#include <cstdint>
namespace osrm
{
namespace extractor
@@ -26,13 +28,13 @@ struct ExternalMemoryNode : QueryNode
static ExternalMemoryNode min_value()
{
return ExternalMemoryNode(
util::FixedLongitude(0), util::FixedLatitude(0), MIN_OSM_NODEID, false, false);
util::FixedLongitude{0}, util::FixedLatitude{0}, MIN_OSM_NODEID, false, false);
}
static ExternalMemoryNode max_value()
{
return ExternalMemoryNode(util::FixedLongitude(std::numeric_limits<int>::max()),
util::FixedLatitude(std::numeric_limits<int>::max()),
return ExternalMemoryNode(util::FixedLongitude{std::numeric_limits<std::int32_t>::max()},
util::FixedLatitude{std::numeric_limits<std::int32_t>::max()},
MAX_OSM_NODEID,
false,
false);
+15 -3
View File
@@ -3,10 +3,12 @@
#include "extractor/external_memory_node.hpp"
#include "extractor/first_and_last_segment_of_way.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/restriction.hpp"
#include "extractor/scripting_environment.hpp"
#include <cstdint>
#include <stxxl/vector>
#include <unordered_map>
@@ -37,7 +39,11 @@ class ExtractionContainers
void WriteNodes(std::ofstream &file_out_stream) const;
void WriteRestrictions(const std::string &restrictions_file_name) const;
void WriteEdges(std::ofstream &file_out_stream) const;
void WriteNames(const std::string &names_file_name) const;
void WriteCharData(const std::string &file_name);
void
WriteTurnLaneMasks(const std::string &file_name,
const stxxl::vector<std::uint32_t> &turn_lane_offsets,
const stxxl::vector<guidance::TurnLaneType::Mask> &turn_lane_masks) const;
public:
using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
@@ -45,12 +51,17 @@ class ExtractionContainers
using STXXLEdgeVector = stxxl::vector<InternalExtractorEdge>;
using STXXLRestrictionsVector = stxxl::vector<InputRestrictionContainer>;
using STXXLWayIDStartEndVector = stxxl::vector<FirstAndLastSegmentOfWay>;
using STXXLNameCharData = stxxl::vector<unsigned char>;
using STXXLNameOffsets = stxxl::vector<unsigned>;
STXXLNodeIDVector used_node_id_list;
STXXLNodeVector all_nodes_list;
STXXLEdgeVector all_edges_list;
stxxl::vector<char> name_char_data;
stxxl::vector<unsigned> name_lengths;
STXXLNameCharData name_char_data;
STXXLNameOffsets name_offsets;
// an adjacency array containing all turn lane masks
stxxl::vector<std::uint32_t> turn_lane_offsets;
stxxl::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;
@@ -61,6 +72,7 @@ class ExtractionContainers
void PrepareData(const std::string &output_file_name,
const std::string &restrictions_file_name,
const std::string &names_file_name,
const std::string &turn_lane_file_name,
lua_State *segment_state);
};
}
@@ -7,6 +7,8 @@
#include <limits>
#include <string>
#include "extractor/guidance/toolkit.hpp"
namespace osrm
{
namespace extractor
@@ -98,6 +100,12 @@ inline unsigned parseDuration(const std::string &s)
return !s.empty() && iter == s.end() ? duration : std::numeric_limits<unsigned>::max();
}
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
return extractor::guidance::trimLaneString(std::move(lane_string), count_left, count_right);
}
}
}
+5
View File
@@ -2,6 +2,7 @@
#define EXTRACTION_WAY_HPP
#include "extractor/travel_mode.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <string>
@@ -35,6 +36,8 @@ struct ExtractionWay
destinations.clear();
forward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
backward_travel_mode = TRAVEL_MODE_INACCESSIBLE;
turn_lanes_forward.clear();
turn_lanes_backward.clear();
}
// These accessors exists because it's not possible to take the address of a bitfield,
@@ -50,6 +53,8 @@ struct ExtractionWay
std::string name;
std::string pronunciation;
std::string destinations;
std::string turn_lanes_forward;
std::string turn_lanes_backward;
bool roundabout;
bool is_access_restricted;
bool is_startpoint;
+2 -2
View File
@@ -54,7 +54,7 @@ class Extractor
private:
ExtractorConfig config;
std::pair<std::size_t, std::size_t>
std::pair<std::size_t, EdgeID>
BuildEdgeExpandedGraph(lua_State *lua_state,
const ProfileProperties &profile_properties,
std::vector<QueryNode> &internal_to_external_node_map,
@@ -79,7 +79,7 @@ class Extractor
std::vector<QueryNode> &internal_to_external_node_map);
void WriteEdgeBasedGraph(const std::string &output_file_filename,
const size_t max_edge_id,
const EdgeID max_edge_id,
util::DeallocatingVector<EdgeBasedEdge> const &edge_based_edge_list);
void WriteIntersectionClassificationData(
@@ -2,6 +2,8 @@
#define EXTRACTOR_CALLBACKS_HPP
#include "util/typedefs.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include <boost/functional/hash.hpp>
#include <boost/optional/optional_fwd.hpp>
@@ -38,6 +40,7 @@ class ExtractorCallbacks
using MapKey = std::pair<std::string, std::string>;
using MapVal = unsigned;
std::unordered_map<MapKey, MapVal, boost::hash<MapKey>> string_map;
std::unordered_map<guidance::TurnLaneDescription,LaneDescriptionID,guidance::TurnLaneDescription_hash> lane_description_map;
ExtractionContainers &external_memory;
public:
+4
View File
@@ -61,6 +61,8 @@ struct ExtractorConfig
output_file_name = basepath + ".osrm";
restriction_file_name = basepath + ".osrm.restrictions";
names_file_name = basepath + ".osrm.names";
turn_lane_descriptions_file_name = basepath + ".osrm.tls";
turn_lane_data_file_name = basepath + ".osrm.tld";
timestamp_file_name = basepath + ".osrm.timestamp";
geometry_output_path = basepath + ".osrm.geometry";
node_output_path = basepath + ".osrm.nodes";
@@ -82,6 +84,8 @@ struct ExtractorConfig
std::string output_file_name;
std::string restriction_file_name;
std::string names_file_name;
std::string turn_lane_data_file_name;
std::string turn_lane_descriptions_file_name;
std::string timestamp_file_name;
std::string geometry_output_path;
std::string edge_output_path;
@@ -58,6 +58,12 @@ inline bool isLinkClass(const FunctionalRoadClass road_class)
road_class == FunctionalRoadClass::TERTIARY_LINK;
}
// check wheter a class is a motorway like class
inline bool isMotorwayClass(const FunctionalRoadClass road_class)
{
return road_class == FunctionalRoadClass::MOTORWAY || road_class == FunctionalRoadClass::TRUNK;
}
// TODO augment this with all data required for guidance generation
struct RoadClassificationData
{
@@ -22,6 +22,7 @@ struct TurnOperation final
EdgeID eid;
double angle;
TurnInstruction instruction;
LaneDataID lane_data_id;
};
// A Connected Road is the internal representation of a potential turn. Internally, we require
@@ -59,6 +60,9 @@ std::string toString(const ConnectedRoad &road);
typedef std::vector<ConnectedRoad> Intersection;
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle);
Intersection::iterator findClosestTurn(Intersection &intersection, const double angle);
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -5,6 +5,7 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
@@ -2,7 +2,6 @@
#define OSRM_EXTRACTOR_GUIDANCE_MOTORWAY_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/query_node.hpp"
@@ -26,8 +25,7 @@ class MotorwayHandler : public IntersectionHandler
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
const SuffixTable &street_name_suffix_table);
~MotorwayHandler() override final;
// check whether the handler can actually handle the intersection
@@ -47,8 +45,6 @@ class MotorwayHandler : public IntersectionHandler
Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
Intersection fallback(Intersection intersection) const;
const IntersectionGenerator &intersection_generator;
};
} // namespace guidance
+81 -4
View File
@@ -5,6 +5,8 @@
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
@@ -20,10 +22,12 @@
#include <cstdint>
#include <map>
#include <string>
#include <unordered_map>
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/functional/hash.hpp>
namespace osrm
{
@@ -32,7 +36,12 @@ namespace extractor
namespace guidance
{
using util::guidance::LaneTupelIdPair;
using LaneDataIdMap = std::unordered_map<LaneTupelIdPair, LaneDataID, boost::hash<LaneTupelIdPair>>;
using util::guidance::angularDeviation;
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
namespace detail
{
@@ -405,10 +414,10 @@ inline bool requiresNameAnnounced(const std::string &from,
(from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos);
const auto ref_is_removed = !from_ref.empty() && to_ref.empty();
const auto obvious_change = (names_are_empty && refs_are_empty) ||
(names_are_equal && ref_is_contained) ||
(names_are_equal && refs_are_empty) || name_is_removed ||
ref_is_removed || is_suffix_change;
const auto obvious_change =
(names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) ||
(names_are_equal && refs_are_empty) || (ref_is_contained && name_is_removed) ||
(names_are_equal && ref_is_removed) || is_suffix_change;
return !obvious_change;
}
@@ -456,6 +465,74 @@ inline ConnectedRoad mirror(ConnectedRoad road)
return road;
}
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto valid_end = valid_types + 13;
return std::find(valid_types, valid_end, instruction.type) != valid_end;
}
// Public service vehicle lanes and similar can introduce additional lanes into the lane string that
// are not specifically marked for left/right turns. This function can be used from the profile to
// trim the lane string appropriately
//
// left|throught|
// in combination with lanes:psv:forward=1
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
{
bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
for (std::int32_t i = 0; i < count_left; ++i)
// this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
// pipes, the '&' part can be removed
if (lane_string[i] != '|' && lane_string[i] != '&')
{
sane = false;
break;
}
if (sane)
{
lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
}
}
if (count_right)
{
bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
for (auto itr = lane_string.rbegin();
itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
++itr)
{
if (*itr != '|' && *itr != '&')
{
sane = false;
break;
}
}
if (sane)
lane_string.resize(lane_string.size() - count_right);
}
return lane_string;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
+7 -3
View File
@@ -44,10 +44,14 @@ class TurnAnalysis
const SuffixTable &street_name_suffix_table);
// the entry into the turn analysis
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
// access to the intersection representation for classification purposes
Intersection getIntersection(const NodeID from_node, const EdgeID via_eid) const;
Intersection
assignTurnTypes(const NodeID from_node, const EdgeID via_eid, Intersection intersection) const;
std::vector<TurnOperation>
transformIntersectionIntoTurns(const Intersection &intersection) const;
const IntersectionGenerator &getGenerator() const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -0,0 +1,38 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_TURN_DISCOVERY_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_TURN_DISCOVERY_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "util/typedefs.hpp"
#include <string>
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace lanes
{
// OSRM processes edges by looking at a via_edge, coming into an intersection. For turn lanes, we
// might require to actually look back a turn. We do so in the hope that the turn lanes match up at
// the previous intersection for all incoming lanes.
bool findPreviousIntersection(
const NodeID node,
const EdgeID via_edge,
const Intersection intersection,
const TurnAnalysis &turn_analysis, // to generate other intersections
const util::NodeBasedDynamicGraph &node_based_graph, // query edge data
// output parameters, will be in an arbitrary state on failure
NodeID &result_node,
EdgeID &result_via_edge,
Intersection &result_intersection);
} // namespace lanes
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /*OSRM_EXTRACTOR_GUIDANCE_TURN_DISCOVERY_HPP_*/
+20 -21
View File
@@ -6,6 +6,8 @@
#include <boost/assert.hpp>
#include "extractor/guidance/roundabout_type.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
namespace osrm
{
@@ -53,48 +55,45 @@ const constexpr Enum EnterRotary = 12; // Enter a rotary
const constexpr Enum EnterAndExitRotary = 13; // Touching a rotary
const constexpr Enum EnterRoundaboutIntersection = 14; // Entering a small Roundabout
const constexpr Enum EnterAndExitRoundaboutIntersection = 15; // Touching a roundabout
const constexpr Enum UseLane = 16; // No Turn, but you need to stay on a given lane!
// Values below here are silent instructions
const constexpr Enum NoTurn = 16; // end of segment without turn/middle of a segment
const constexpr Enum Suppressed = 17; // location that suppresses a turn
const constexpr Enum EnterRoundaboutAtExit = 18; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundabout = 19; // Exiting a small Roundabout
const constexpr Enum EnterRotaryAtExit = 20; // Enter A Rotary at a countable exit
const constexpr Enum ExitRotary = 21; // Exit a rotary
const constexpr Enum NoTurn = 17; // end of segment without turn/middle of a segment
const constexpr Enum Suppressed = 18; // location that suppresses a turn
const constexpr Enum EnterRoundaboutAtExit = 19; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundabout = 20; // Exiting a small Roundabout
const constexpr Enum EnterRotaryAtExit = 21; // Enter A Rotary at a countable exit
const constexpr Enum ExitRotary = 22; // Exit a rotary
const constexpr Enum EnterRoundaboutIntersectionAtExit =
22; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundaboutIntersection = 23; // Exiting a small Roundabout
const constexpr Enum StayOnRoundabout = 24; // Continue on Either a small or a large Roundabout
23; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundaboutIntersection = 24; // Exiting a small Roundabout
const constexpr Enum StayOnRoundabout = 25; // Continue on Either a small or a large Roundabout
const constexpr Enum Sliproad =
25; // Something that looks like a ramp, but is actually just a small sliproad
26; // Something that looks like a ramp, but is actually just a small sliproad
}
// turn angle in 1.40625 degree -> 128 == 180 degree
struct TurnInstruction
{
using LaneTupel = util::guidance::LaneTupel;
TurnInstruction(const TurnType::Enum type = TurnType::Invalid,
const DirectionModifier::Enum direction_modifier = DirectionModifier::Straight)
const DirectionModifier::Enum direction_modifier = DirectionModifier::UTurn)
: type(type), direction_modifier(direction_modifier)
{
}
TurnType::Enum type : 5;
DirectionModifier::Enum direction_modifier : 3;
// the lane tupel that is used for the turn
static TurnInstruction INVALID()
{
return TurnInstruction(TurnType::Invalid, DirectionModifier::UTurn);
}
static TurnInstruction INVALID() { return {TurnType::Invalid, DirectionModifier::UTurn}; }
static TurnInstruction NO_TURN()
{
return TurnInstruction(TurnType::NoTurn, DirectionModifier::UTurn);
}
static TurnInstruction NO_TURN() { return {TurnType::NoTurn, DirectionModifier::UTurn}; }
static TurnInstruction REMAIN_ROUNDABOUT(const RoundaboutType,
const DirectionModifier::Enum modifier)
{
return TurnInstruction(TurnType::StayOnRoundabout, modifier);
return {TurnType::StayOnRoundabout, modifier};
}
static TurnInstruction ENTER_ROUNDABOUT(const RoundaboutType roundabout_type,
@@ -146,7 +145,7 @@ struct TurnInstruction
}
};
static_assert(sizeof(TurnInstruction) == 1, "TurnInstruction does not fit one byte");
static_assert(sizeof(TurnInstruction) == 1, "TurnInstruction does not fit a byte");
inline bool operator!=(const TurnInstruction lhs, const TurnInstruction rhs)
{
@@ -0,0 +1,24 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_AUGMENTATION_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_AUGMENTATION_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace lanes
{
LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const Intersection &intersection);
} // namespace lanes
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /* OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_AUGMENTATION_HPP_ */
@@ -0,0 +1,44 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_DATA_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_DATA_HPP_
#include "util/typedefs.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include <string>
#include <vector>
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace lanes
{
struct TurnLaneData
{
TurnLaneType::Mask tag;
LaneID from;
LaneID to;
bool operator<(const TurnLaneData &other) const;
};
typedef std::vector<TurnLaneData> LaneDataVector;
// convertes a string given in the OSM format into a TurnLaneData vector
LaneDataVector laneDataFromDescription(const TurnLaneDescription &turn_lane_description);
// Locate A Tag in a lane data vector (if multiple tags are set, the first one found is returned)
LaneDataVector::const_iterator findTag(const TurnLaneType::Mask tag, const LaneDataVector &data);
LaneDataVector::iterator findTag(const TurnLaneType::Mask tag, LaneDataVector &data);
// Returns true if any of the queried tags is contained
bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data);
} // namespace lane_data_generation
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /* OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_DATA_HPP_ */
@@ -0,0 +1,85 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/query_node.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <cstdint>
#include <map>
#include <string>
#include <utility>
#include <vector>
namespace osrm
{
namespace extractor
{
namespace guidance
{
// Given an Intersection, the graph to access the data and the turn lanes, the turn lane matcher
// assigns appropriate turn tupels to the different turns.
namespace lanes
{
class TurnLaneHandler
{
public:
typedef std::vector<TurnLaneData> LaneDataVector;
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<TurnLaneType::Mask> &turn_lane_masks,
const std::vector<QueryNode> &node_info_list,
const TurnAnalysis &turn_analysis);
Intersection assignTurnLanes(const NodeID at,
const EdgeID via_edge,
Intersection intersection,
LaneDataIdMap &id_map) const;
private:
// we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<std::uint32_t> &turn_lane_offsets;
const std::vector<TurnLaneType::Mask> &turn_lane_masks;
const std::vector<QueryNode> &node_info_list;
const TurnAnalysis &turn_analysis;
// check whether we can handle an intersection
bool isSimpleIntersection(const LaneDataVector &turn_lane_data,
const Intersection &intersection) const;
// in case of a simple intersection, assign the lane entries
Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &id_map) const;
// partition lane data into lane data relevant at current turn and at next turn
std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector> partitionLaneData(
const NodeID at, LaneDataVector turn_lane_data, const Intersection &intersection) const;
// if the current intersections turn string is empty, we check whether there is an incoming
// intersection whose turns might be related to this current intersection
Intersection handleTurnAtPreviousIntersection(const NodeID at,
const EdgeID via_edge,
Intersection intersection,
LaneDataIdMap &id_map) const;
};
} // namespace lanes
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
@@ -0,0 +1,51 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include <unordered_map>
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace lanes
{
// Translate Turn Lane Tags into a matching modifier
DirectionModifier::Enum getMatchingModifier(const TurnLaneType::Mask &tag);
// check whether a match of a given tag and a turn instruction can be seen as valid
bool isValidMatch(const TurnLaneType::Mask &tag, const TurnInstruction instruction);
// localisation of the best possible match for a tag
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask &tag,
const Intersection &intersection);
typename Intersection::const_iterator
findBestMatchForReverse(const TurnLaneType::Mask &leftmost_tag, const Intersection &intersection);
// a match is trivial if all turns can be associated with their best match in a valid way and the
// matches occur in order
bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data);
// perform a trivial match on the turn lanes
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &lane_data_to_id);
} // namespace lanes
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /*OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_*/
@@ -0,0 +1,102 @@
#ifndef OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_
#define OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include <boost/assert.hpp>
#include <boost/functional/hash_fwd.hpp>
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
#include "util/json_container.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace TurnLaneType
{
namespace detail
{
const constexpr std::size_t num_supported_lane_types = 11;
const constexpr char *translations[detail::num_supported_lane_types] = {"none",
"straight",
"sharp left",
"left",
"slight left",
"slight right",
"right",
"sharp right",
"uturn",
"merge to left",
"merge to right"};
} // namespace detail
typedef std::uint16_t Mask;
const constexpr Mask empty = 0u;
const constexpr Mask none = 1u << 0u;
const constexpr Mask straight = 1u << 1u;
const constexpr Mask sharp_left = 1u << 2u;
const constexpr Mask left = 1u << 3u;
const constexpr Mask slight_left = 1u << 4u;
const constexpr Mask slight_right = 1u << 5u;
const constexpr Mask right = 1u << 6u;
const constexpr Mask sharp_right = 1u << 7u;
const constexpr Mask uturn = 1u << 8u;
const constexpr Mask merge_to_left = 1u << 9u;
const constexpr Mask merge_to_right = 1u << 10u;
inline std::string toString(const Mask lane_type)
{
if (lane_type == 0)
return "none";
std::bitset<8 * sizeof(Mask)> mask(lane_type);
std::string result = "";
for (std::size_t lane_id_nr = 0; lane_id_nr < detail::num_supported_lane_types; ++lane_id_nr)
if (mask[lane_id_nr])
result += (result.empty() ? detail::translations[lane_id_nr]
: (std::string(";") + detail::translations[lane_id_nr]));
return result;
}
inline util::json::Array toJsonArray(const Mask lane_type)
{
util::json::Array result;
std::bitset<8 * sizeof(Mask)> mask(lane_type);
for (std::size_t lane_id_nr = 0; lane_id_nr < detail::num_supported_lane_types; ++lane_id_nr)
if (mask[lane_id_nr])
result.values.push_back(detail::translations[lane_id_nr]);
return result;
}
} // TurnLaneType
typedef std::vector<TurnLaneType::Mask> TurnLaneDescription;
// hash function for TurnLaneDescription
struct TurnLaneDescription_hash
{
std::size_t operator()(const TurnLaneDescription &lane_description) const
{
std::size_t seed = 0;
for (auto val : lane_description)
boost::hash_combine(seed, val);
return seed;
}
};
} // guidance
} // extractor
} // osrm
#endif /* OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_ */
+7 -40
View File
@@ -29,7 +29,6 @@ struct InternalExtractorEdge
struct WeightData
{
WeightData() : duration(0.0), type(WeightType::INVALID) {}
union {
@@ -51,6 +50,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
guidance::TurnLaneType::empty,
guidance::RoadClassificationData())
{
}
@@ -66,9 +66,10 @@ struct InternalExtractorEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
LaneDescriptionID lane_description,
guidance::RoadClassificationData road_classification)
: result(OSMNodeID(source),
OSMNodeID(target),
: result(source,
target,
name_id,
0,
forward,
@@ -78,6 +79,7 @@ struct InternalExtractorEdge
startpoint,
travel_mode,
is_split,
lane_description,
std::move(road_classification)),
weight_data(std::move(weight_data))
{
@@ -104,6 +106,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassificationData());
}
static InternalExtractorEdge max_osm_value()
@@ -119,6 +122,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassificationData());
}
@@ -138,43 +142,6 @@ struct InternalExtractorEdge
}
};
struct CmpEdgeByInternalStartThenInternalTargetID
{
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
return (lhs.result.source < rhs.result.source) ||
((lhs.result.source == rhs.result.source) &&
(lhs.result.target < rhs.result.target));
}
value_type max_value() { return InternalExtractorEdge::max_internal_value(); }
value_type min_value() { return InternalExtractorEdge::min_internal_value(); }
};
struct CmpEdgeByOSMStartID
{
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
return lhs.result.osm_source_id < rhs.result.osm_source_id;
}
value_type max_value() { return InternalExtractorEdge::max_osm_value(); }
value_type min_value() { return InternalExtractorEdge::min_osm_value(); }
};
struct CmpEdgeByOSMTargetID
{
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
return lhs.result.osm_target_id < rhs.result.osm_target_id;
}
value_type max_value() { return InternalExtractorEdge::max_osm_value(); }
value_type min_value() { return InternalExtractorEdge::min_osm_value(); }
};
}
}
+8 -2
View File
@@ -26,6 +26,7 @@ struct NodeBasedEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification);
bool operator<(const NodeBasedEdge &other) const;
@@ -41,6 +42,7 @@ struct NodeBasedEdge
bool startpoint : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
LaneDescriptionID lane_description_id;
guidance::RoadClassificationData road_classification;
};
@@ -57,6 +59,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification);
OSMNodeID osm_source_id;
@@ -68,7 +71,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
backward(false), roundabout(false), access_restricted(false), startpoint(true),
is_split(false), travel_mode(false)
is_split(false), travel_mode(false), lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@@ -83,11 +86,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
road_classification(std::move(road_classification))
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
{
}
@@ -120,6 +124,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification)
: NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID,
@@ -132,6 +137,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(
startpoint,
travel_mode,
is_split,
lane_description_id,
std::move(road_classification)),
osm_source_id(std::move(source)), osm_target_id(std::move(target))
{
+7 -2
View File
@@ -17,18 +17,19 @@ struct OriginalEdgeData
{
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
LaneDataID lane_data_id,
guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), entry_classid(entry_classid),
turn_instruction(turn_instruction), travel_mode(travel_mode)
lane_data_id(lane_data_id), turn_instruction(turn_instruction), travel_mode(travel_mode)
{
}
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID),
turn_instruction(guidance::TurnInstruction::INVALID()),
lane_data_id(INVALID_LANE_DATAID), turn_instruction(guidance::TurnInstruction::INVALID()),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@@ -36,9 +37,13 @@ struct OriginalEdgeData
NodeID via_node;
unsigned name_id;
EntryClassID entry_classid;
LaneDataID lane_data_id;
guidance::TurnInstruction turn_instruction;
TravelMode travel_mode;
};
static_assert(sizeof(OriginalEdgeData) == 16,
"Increasing the size of OriginalEdgeData increases memory consumption");
}
}
+9 -8
View File
@@ -6,6 +6,7 @@
#include "util/coordinate.hpp"
#include <limits>
#include <cstdint>
namespace osrm
{
@@ -15,16 +16,16 @@ namespace extractor
struct QueryNode
{
using key_type = OSMNodeID; // type of NodeID
using value_type = int; // type of lat,lons
using value_type = std::int32_t; // type of lat,lons
explicit QueryNode(const util::FixedLongitude lon_,
const util::FixedLatitude lat_,
key_type node_id)
: lon(lon_), lat(lat_), node_id(std::move(node_id))
const key_type node_id_)
: lon(lon_), lat(lat_), node_id(node_id_)
{
}
QueryNode()
: lon(std::numeric_limits<int>::max()), lat(std::numeric_limits<int>::max()),
: lon{std::numeric_limits<value_type>::max()}, lat{std::numeric_limits<value_type>::max()},
node_id(SPECIAL_OSM_NODEID)
{
}
@@ -35,15 +36,15 @@ struct QueryNode
static QueryNode min_value()
{
return QueryNode(util::FixedLongitude(-180 * COORDINATE_PRECISION),
util::FixedLatitude(-90 * COORDINATE_PRECISION),
return QueryNode(util::FixedLongitude{static_cast<value_type>(-180 * COORDINATE_PRECISION)},
util::FixedLatitude{static_cast<value_type>(-90 * COORDINATE_PRECISION)},
MIN_OSM_NODEID);
}
static QueryNode max_value()
{
return QueryNode(util::FixedLongitude(180 * COORDINATE_PRECISION),
util::FixedLatitude(90 * COORDINATE_PRECISION),
return QueryNode(util::FixedLongitude{static_cast<value_type>(180 * COORDINATE_PRECISION)},
util::FixedLatitude{static_cast<value_type>(90 * COORDINATE_PRECISION)},
MAX_OSM_NODEID);
}
};
@@ -111,15 +111,15 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
qi::_1,
qi::_2)];
location_rule = (double_ > qi::lit(',') >
double_)[qi::_val = ph::bind(
[](double lon, double lat) {
return util::Coordinate(
util::FixedLongitude(lon * COORDINATE_PRECISION),
util::FixedLatitude(lat * COORDINATE_PRECISION));
},
qi::_1,
qi::_2)];
location_rule =
(double_ > qi::lit(',') >
double_)[qi::_val = ph::bind(
[](double lon, double lat) {
return util::Coordinate(util::toFixed(util::FloatLongitude{lon}),
util::toFixed(util::FloatLatitude{lat}));
},
qi::_1,
qi::_2)];
polyline_rule = qi::as_string[qi::lit("polyline(") > +polyline_chars > ')']
[qi::_val = ph::bind(
+55 -7
View File
@@ -14,7 +14,41 @@ namespace storage
{
// Added at the start and end of each block as sanity check
const constexpr char CANARY[] = "OSRM";
const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'};
const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
"NAME_BLOCKS",
"NAME_CHAR_LIST",
"NAME_ID_LIST",
"VIA_NODE_LIST",
"GRAPH_NODE_LIST",
"GRAPH_EDGE_LIST",
"COORDINATE_LIST",
"OSM_NODE_ID_LIST",
"TURN_INSTRUCTION",
"TRAVEL_MODE",
"ENTRY_CLASSID",
"R_SEARCH_TREE",
"GEOMETRIES_INDEX",
"GEOMETRIES_LIST",
"HSGR_CHECKSUM",
"TIMESTAMP",
"FILE_INDEX_PATH",
"CORE_MARKER",
"DATASOURCES_LIST",
"DATASOURCE_NAME_DATA",
"DATASOURCE_NAME_OFFSETS",
"DATASOURCE_NAME_LENGTHS",
"PROPERTIES",
"BEARING_CLASSID",
"BEARING_OFFSETS",
"BEARING_BLOCKS",
"BEARING_VALUES",
"ENTRY_CLASS",
"LANE_DATA_ID",
"TURN_LANE_DATA",
"LANE_DESCRIPTION_OFFSETS",
"LANE_DESCRIPTION_MASKS"};
struct SharedDataLayout
{
@@ -30,8 +64,8 @@ struct SharedDataLayout
COORDINATE_LIST,
OSM_NODE_ID_LIST,
TURN_INSTRUCTION,
ENTRY_CLASSID,
TRAVEL_MODE,
ENTRY_CLASSID,
R_SEARCH_TREE,
GEOMETRIES_INDEX,
GEOMETRIES_LIST,
@@ -49,6 +83,10 @@ struct SharedDataLayout
BEARING_BLOCKS,
BEARING_VALUES,
ENTRY_CLASS,
LANE_DATA_ID,
TURN_LANE_DATA,
LANE_DESCRIPTION_OFFSETS,
LANE_DESCRIPTION_MASKS,
NUM_BLOCKS
};
@@ -63,15 +101,20 @@ struct SharedDataLayout
entry_size[bid] = sizeof(T);
}
inline uint64_t AlignBlockSize(uint64_t block_size) const
{
const uint64_t alignment = 4;
return (block_size + (alignment - 1)) & ~(alignment - 1);
}
inline uint64_t GetBlockSize(BlockID bid) const
{
// special bit encoding
if (bid == CORE_MARKER)
{
return (num_entries[bid] / 32 + 1) * entry_size[bid];
return AlignBlockSize((num_entries[bid] / 32 + 1) * entry_size[bid]);
}
return num_entries[bid] * entry_size[bid];
return AlignBlockSize(num_entries[bid] * entry_size[bid]);
}
inline uint64_t GetSizeOfLayout() const
@@ -108,11 +151,13 @@ struct SharedDataLayout
bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
if (!start_canary_alive)
{
throw util::exception("Start canary of block corrupted.");
throw util::exception(std::string("Start canary of block corrupted. (") +
block_id_to_name[bid] + ")");
}
if (!end_canary_alive)
{
throw util::exception("End canary of block corrupted.");
throw util::exception(std::string("End canary of block corrupted. (") +
block_id_to_name[bid] + ")");
}
}
@@ -137,6 +182,9 @@ struct SharedDataTimestamp
SharedDataType data;
unsigned timestamp;
};
static_assert(sizeof(block_id_to_name) / sizeof(*block_id_to_name) == SharedDataLayout::NUM_BLOCKS,
"Number of blocks needs to match the number of Block names.");
}
}
+2
View File
@@ -65,6 +65,8 @@ struct StorageConfig final
boost::filesystem::path names_data_path;
boost::filesystem::path properties_path;
boost::filesystem::path intersection_class_path;
boost::filesystem::path turn_lane_data_path;
boost::filesystem::path turn_lane_description_path;
};
}
}
-20
View File
@@ -1,20 +0,0 @@
#ifndef OSRM_ASSERT_HPP
#define OSRM_ASSERT_HPP
#include <boost/assert.hpp>
#include <stdexcept>
namespace osrm
{
namespace util
{
// Assertion type to be thrown for stack unwinding
struct assertionError final : std::logic_error
{
assertionError(const char *msg) : std::logic_error{msg} {}
};
}
}
#endif
+6 -6
View File
@@ -61,7 +61,7 @@ inline FixedLatitude toFixed(const FloatLatitude floating)
{
const auto latitude = static_cast<double>(floating);
const auto fixed = boost::numeric_cast<std::int32_t>(latitude * COORDINATE_PRECISION);
return FixedLatitude(fixed);
return FixedLatitude{fixed};
}
/**
@@ -75,7 +75,7 @@ inline FixedLongitude toFixed(const FloatLongitude floating)
{
const auto longitude = static_cast<double>(floating);
const auto fixed = boost::numeric_cast<std::int32_t>(longitude * COORDINATE_PRECISION);
return FixedLongitude(fixed);
return FixedLongitude{fixed};
}
/**
@@ -89,7 +89,7 @@ inline FloatLatitude toFloating(const FixedLatitude fixed)
{
const auto latitude = static_cast<std::int32_t>(fixed);
const auto floating = boost::numeric_cast<double>(latitude / COORDINATE_PRECISION);
return FloatLatitude(floating);
return FloatLatitude{floating};
}
/**
@@ -103,7 +103,7 @@ inline FloatLongitude toFloating(const FixedLongitude fixed)
{
const auto longitude = static_cast<std::int32_t>(fixed);
const auto floating = boost::numeric_cast<double>(longitude / COORDINATE_PRECISION);
return FloatLongitude(floating);
return FloatLongitude{floating};
}
// fwd. decl.
@@ -127,7 +127,7 @@ struct Coordinate
FixedLongitude lon;
FixedLatitude lat;
Coordinate() : lon(std::numeric_limits<int>::min()), lat(std::numeric_limits<int>::min()) {}
Coordinate() : lon{std::numeric_limits<int>::min()}, lat{std::numeric_limits<int>::min()} {}
Coordinate(const FloatCoordinate &other);
@@ -173,7 +173,7 @@ struct FloatCoordinate
FloatLatitude lat;
FloatCoordinate()
: lon(std::numeric_limits<double>::min()), lat(std::numeric_limits<double>::min())
: lon{std::numeric_limits<double>::min()}, lat{std::numeric_limits<double>::min()}
{
}
+4 -4
View File
@@ -61,10 +61,10 @@ inline std::pair<double, FloatCoordinate> projectPointOnSegment(const FloatCoord
return {clamped_ratio,
{
FloatLongitude(1.0 - clamped_ratio) * source.lon +
target.lon * FloatLongitude(clamped_ratio),
FloatLatitude(1.0 - clamped_ratio) * source.lat +
target.lat * FloatLatitude(clamped_ratio),
FloatLongitude{1.0 - clamped_ratio} * source.lon +
target.lon * FloatLongitude{clamped_ratio},
FloatLatitude{1.0 - clamped_ratio} * source.lat +
target.lat * FloatLatitude{clamped_ratio},
}};
}
+91
View File
@@ -0,0 +1,91 @@
#ifndef OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#define OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/query_node.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/typedefs.hpp"
#include <iomanip>
#include <iostream>
#include <vector>
namespace osrm
{
namespace util
{
namespace guidance
{
inline void print(const engine::guidance::RouteStep &step)
{
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
<< static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
<< static_cast<int>(step.maneuver.waypoint_type) << " "
<< " Lanes: (" << static_cast<int>(step.maneuver.lanes.lanes_in_turn) << ", "
<< static_cast<int>(step.maneuver.lanes.first_lane_from_the_right) << ")"
<< " Duration: " << step.duration << " Distance: " << step.distance
<< " Geometry: " << step.geometry_begin << " " << step.geometry_end
<< " exit: " << step.maneuver.exit << " Intersections: " << step.intersections.size()
<< " [";
for (const auto &intersection : step.intersections)
{
std::cout << "(bearings:";
for (auto bearing : intersection.bearings)
std::cout << " " << bearing;
std::cout << ", entry: ";
for (auto entry : intersection.entry)
std::cout << " " << (entry ? "true" : "false");
std::cout << ")";
}
std::cout << "] name[" << step.name_id << "]: " << step.name;
}
inline void print(const std::vector<engine::guidance::RouteStep> &steps)
{
std::cout << "Path\n";
int segment = 0;
for (const auto &step : steps)
{
std::cout << "\t[" << segment++ << "]: ";
print(step);
std::cout << std::endl;
}
}
inline void print(const extractor::guidance::lanes::LaneDataVector &turn_lane_data)
{
std::cout << " Tags:\n";
for (auto entry : turn_lane_data)
std::cout << "\t" << entry.tag << "("
<< extractor::guidance::TurnLaneType::toString(entry.tag)
<< ") from: " << static_cast<int>(entry.from)
<< " to: " << static_cast<int>(entry.to) << "\n";
std::cout << std::flush;
}
inline void
printTurnAssignmentData(const NodeID at,
const extractor::guidance::lanes::LaneDataVector &turn_lane_data,
const extractor::guidance::Intersection &intersection,
const std::vector<extractor::QueryNode> &node_info_list)
{
std::cout << "[Turn Assignment Progress]\nLocation:";
auto coordinate = node_info_list[at];
std::cout << std::setprecision(12) << toFloating(coordinate.lat) << " "
<< toFloating(coordinate.lon) << "\n";
std::cout << " Intersection:\n";
for (const auto &road : intersection)
std::cout << "\t" << toString(road) << "\n";
// flushes as well
print(turn_lane_data);
}
} // namespace guidance
} // namespace util
} // namespace osrm
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
+2 -2
View File
@@ -24,8 +24,8 @@ template <typename EdgeDataT> class DynamicGraph
{
public:
using EdgeData = EdgeDataT;
using NodeIterator = unsigned;
using EdgeIterator = unsigned;
using NodeIterator = std::uint32_t;
using EdgeIterator = std::uint32_t;
using EdgeRange = range<EdgeIterator>;
class InputEdge
+40
View File
@@ -0,0 +1,40 @@
#ifndef OSRM_GROUP_BY
#define OSRM_GROUP_BY
#include <algorithm>
#include <utility>
namespace osrm
{
namespace util
{
// Runs fn on consecutive items in sub-ranges determined by pred.
//
// Example:
// vector<int> v{1,2,2,2,3,4,4};
// group_by(first, last, even, print);
// >>> 2,2,2
// >>> 4,4
//
// Note: this mimics Python's itertools.groupby
template <typename Iter, typename Pred, typename Fn>
Fn group_by(Iter first, Iter last, Pred pred, Fn fn)
{
while (first != last)
{
first = std::find_if(first, last, pred);
auto next = std::find_if_not(first, last, pred);
(void)fn(std::make_pair(first, next));
first = next;
}
return fn;
}
} // ns util
} // ns osrm
#endif
+64
View File
@@ -65,6 +65,70 @@ mirrorDirectionModifier(const extractor::guidance::DirectionModifier::Enum modif
return results[modifier];
}
inline bool hasLeftModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpLeft ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Left ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightLeft;
}
inline bool hasRightModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpRight ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Right ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightRight;
}
inline bool isLeftTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case extractor::guidance::TurnType::Merge:
return hasRightModifier(instruction);
default:
return hasLeftModifier(instruction);
}
}
inline bool isRightTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case extractor::guidance::TurnType::Merge:
return hasLeftModifier(instruction);
default:
return hasRightModifier(instruction);
}
}
inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary);
}
inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
} // namespace guidance
} // namespace util
} // namespace osrm
+82
View File
@@ -0,0 +1,82 @@
#ifndef OSRM_UTIL_GUIDANCE_TURN_LANES_HPP
#define OSRM_UTIL_GUIDANCE_TURN_LANES_HPP
#include <cstddef>
#include <cstdint>
#include <functional>
#include <vector>
#include "util/typedefs.hpp"
#include <boost/functional/hash.hpp>
namespace osrm
{
namespace util
{
namespace guidance
{
class LaneTupel;
} // namespace guidance
} // namespace util
} // namespace osrm
namespace std
{
template <> struct hash<::osrm::util::guidance::LaneTupel>
{
inline std::size_t operator()(const ::osrm::util::guidance::LaneTupel &bearing_class) const;
};
} // namespace std
namespace osrm
{
namespace util
{
namespace guidance
{
// The mapping of turn lanes can be done two values. We describe every turn by the number of
// contributing lanes and the first lane from the right..
// Given a road like this:
// | | |
// | | |
// ----------- |
// -^ |
// ----------- -------------
// -^ ->
// --------------------------------
// -v |
// ---------- |
// | |
//
// we generate a set of tuples in the form of:
// (2,1), (1,1), (1,0) for left, through and right respectively
class LaneTupel
{
public:
LaneTupel();
LaneTupel(const LaneID lanes_in_turn, const LaneID first_lane_from_the_right);
bool operator==(const LaneTupel other) const;
bool operator!=(const LaneTupel other) const;
bool operator<(const LaneTupel other) const;
LaneID lanes_in_turn;
LaneID first_lane_from_the_right;
friend std::size_t hash_value(const LaneTupel &tup)
{
std::size_t seed{0};
boost::hash_combine(seed, tup.lanes_in_turn);
boost::hash_combine(seed, tup.first_lane_from_the_right);
return seed;
}
};
using LaneTupelIdPair = std::pair<util::guidance::LaneTupel, LaneDescriptionID>;
} // namespace guidance
} // namespace util
} // namespace osrm
#endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */
+80
View File
@@ -4,12 +4,14 @@
#include "util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <cstddef>
#include <cstdint>
#include <bitset>
#include <fstream>
#include <stxxl/vector>
#include <vector>
#include "util/fingerprint.hpp"
@@ -88,6 +90,84 @@ bool deserializeVector(std::istream &stream, std::vector<simple_type> &data)
return static_cast<bool>(stream);
}
// serializes a vector of vectors into an adjacency array (creates a copy of the data internally)
template <typename simple_type>
bool serializeVectorIntoAdjacencyArray(const std::string &filename,
const std::vector<std::vector<simple_type>> &data)
{
std::ofstream out_stream(filename, std::ios::binary);
std::vector<std::uint32_t> offsets;
offsets.reserve(data.size() + 1);
std::uint64_t current_offset = 0;
offsets.push_back(current_offset);
for (auto const &vec : data)
{
current_offset += vec.size();
offsets.push_back(boost::numeric_cast<std::uint32_t>(current_offset));
}
if (!serializeVector(out_stream, offsets))
return false;
std::vector<simple_type> all_data;
all_data.reserve(offsets.back());
for (auto const &vec : data)
all_data.insert(all_data.end(), vec.begin(), vec.end());
if (!serializeVector(out_stream, all_data))
return false;
return static_cast<bool>(out_stream);
}
template <typename simple_type, std::size_t WRITE_BLOCK_BUFFER_SIZE = 1024>
bool serializeVector(std::ofstream &out_stream, const stxxl::vector<simple_type> &data)
{
const std::uint64_t size = data.size();
out_stream.write(reinterpret_cast<const char *>(&size), sizeof(size));
simple_type write_buffer[WRITE_BLOCK_BUFFER_SIZE];
std::size_t buffer_len = 0;
for (const auto entry : data)
{
write_buffer[buffer_len++] = entry;
if (buffer_len >= WRITE_BLOCK_BUFFER_SIZE)
{
out_stream.write(reinterpret_cast<const char *>(write_buffer),
WRITE_BLOCK_BUFFER_SIZE * sizeof(simple_type));
buffer_len = 0;
}
}
// write remaining entries
if (buffer_len > 0)
out_stream.write(reinterpret_cast<const char *>(write_buffer),
buffer_len * sizeof(simple_type));
return static_cast<bool>(out_stream);
}
template <typename simple_type>
bool deserializeAdjacencyArray(const std::string &filename,
std::vector<std::uint32_t> &offsets,
std::vector<simple_type>& data)
{
std::ifstream in_stream(filename, std::ios::binary);
if (!deserializeVector(in_stream, offsets))
return false;
if (!deserializeVector(in_stream, data))
return false;
// offsets have to match up with the size of the data
if (offsets.empty() || (offsets.back() != boost::numeric_cast<std::uint32_t>(data.size())))
return false;
return static_cast<bool>(in_stream);
}
inline bool serializeFlags(const boost::filesystem::path &path, const std::vector<bool> &flags)
{
// TODO this should be replaced with a FILE-based write using error checking
+9 -6
View File
@@ -20,7 +20,8 @@ struct NodeBasedEdgeData
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false), reversed(false),
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE)
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@@ -31,10 +32,11 @@ struct NodeBasedEdgeData
bool reversed,
bool roundabout,
bool startpoint,
extractor::TravelMode travel_mode)
extractor::TravelMode travel_mode,
const LaneDescriptionID lane_description_id)
: distance(distance), edge_id(edge_id), name_id(name_id),
access_restricted(access_restricted), reversed(reversed), roundabout(roundabout),
startpoint(startpoint), travel_mode(travel_mode)
startpoint(startpoint), travel_mode(travel_mode), lane_description_id(lane_description_id)
{
}
@@ -46,6 +48,7 @@ struct NodeBasedEdgeData
bool roundabout : 1;
bool startpoint : 1;
extractor::TravelMode travel_mode : 4;
LaneDescriptionID lane_description_id;
extractor::guidance::RoadClassificationData road_classification;
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
@@ -64,7 +67,7 @@ using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
/// Since DynamicGraph expects directed edges, we need to insert
/// two edges for undirected edges.
inline std::shared_ptr<NodeBasedDynamicGraph>
NodeBasedDynamicGraphFromEdges(std::size_t number_of_nodes,
NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
const std::vector<extractor::NodeBasedEdge> &input_edge_list)
{
auto edges_list = directedEdgesFromCompressed<NodeBasedDynamicGraph::InputEdge>(
@@ -80,12 +83,12 @@ NodeBasedDynamicGraphFromEdges(std::size_t number_of_nodes,
output_edge.data.travel_mode = input_edge.travel_mode;
output_edge.data.startpoint = input_edge.startpoint;
output_edge.data.road_classification = input_edge.road_classification;
output_edge.data.lane_description_id = input_edge.lane_description_id;
});
tbb::parallel_sort(edges_list.begin(), edges_list.end());
auto graph = std::make_shared<NodeBasedDynamicGraph>(
static_cast<NodeBasedDynamicGraph::NodeIterator>(number_of_nodes), edges_list);
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list);
return graph;
}
+6 -7
View File
@@ -12,7 +12,6 @@ namespace osrm
namespace util
{
/**
* Since OSM node IDs are (at the time of writing) not quite yet overflowing 32 bits, and
* will predictably be containable within 33 bits for a long time, the following packs
@@ -21,16 +20,16 @@ namespace util
* NOTE: this type is templated for future use, but will require a slight refactor to
* configure BITSIZE and ELEMSIZE
*/
template <typename T, bool UseSharedMemory=false> class PackedVector
template <typename T, bool UseSharedMemory = false> class PackedVector
{
static const constexpr std::size_t BITSIZE = 33;
static const constexpr std::size_t ELEMSIZE = 64;
static const constexpr std::size_t PACKSIZE = BITSIZE * ELEMSIZE;
public:
/**
* Returns the size of the packed vector datastructure with `elements` packed elements (the size of
* Returns the size of the packed vector datastructure with `elements` packed elements (the size
* of
* its underlying uint64 vector)
*/
inline static std::size_t elements_to_blocks(std::size_t elements)
@@ -96,14 +95,14 @@ template <typename T, bool UseSharedMemory=false> class PackedVector
if (left_index == 0)
{
// ID is at the far left side of this element
return static_cast<T>(elem >> (ELEMSIZE - BITSIZE));
return T{elem >> (ELEMSIZE - BITSIZE)};
}
else if (left_index >= BITSIZE)
{
// ID is entirely contained within this element
const std::uint64_t at_right = elem >> (left_index - BITSIZE);
const std::uint64_t left_mask = static_cast<std::uint64_t>(pow(2, BITSIZE)) - 1;
return static_cast<T>(at_right & left_mask);
return T{at_right & left_mask};
}
else
{
@@ -115,7 +114,7 @@ template <typename T, bool UseSharedMemory=false> class PackedVector
const std::uint64_t next_elem = static_cast<std::uint64_t>(vec.at(index + 1));
const std::uint64_t right_side = next_elem >> (ELEMSIZE - (BITSIZE - left_index));
return static_cast<T>(left_side | right_side);
return T{left_side | right_side};
}
}
+14 -14
View File
@@ -23,10 +23,10 @@ namespace util
struct RectangleInt2D
{
RectangleInt2D()
: min_lon(std::numeric_limits<std::int32_t>::max()),
max_lon(std::numeric_limits<std::int32_t>::min()),
min_lat(std::numeric_limits<std::int32_t>::max()),
max_lat(std::numeric_limits<std::int32_t>::min())
: min_lon{std::numeric_limits<std::int32_t>::max()},
max_lon{std::numeric_limits<std::int32_t>::min()},
min_lat{std::numeric_limits<std::int32_t>::max()},
max_lat{std::numeric_limits<std::int32_t>::min()}
{
}
@@ -56,10 +56,10 @@ struct RectangleInt2D
max_lon = std::max(max_lon, other.max_lon);
min_lat = std::min(min_lat, other.min_lat);
max_lat = std::max(max_lat, other.max_lat);
BOOST_ASSERT(min_lon != FixedLongitude(std::numeric_limits<std::int32_t>::min()));
BOOST_ASSERT(min_lat != FixedLatitude(std::numeric_limits<std::int32_t>::min()));
BOOST_ASSERT(max_lon != FixedLongitude(std::numeric_limits<std::int32_t>::min()));
BOOST_ASSERT(max_lat != FixedLatitude(std::numeric_limits<std::int32_t>::min()));
BOOST_ASSERT(min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
BOOST_ASSERT(min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
BOOST_ASSERT(max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
BOOST_ASSERT(max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
}
Coordinate Centroid() const
@@ -67,8 +67,8 @@ struct RectangleInt2D
Coordinate centroid;
// The coordinates of the midpoints are given by:
// x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (min_lon + max_lon) / FixedLongitude(2);
centroid.lat = (min_lat + max_lat) / FixedLatitude(2);
centroid.lon = (min_lon + max_lon) / FixedLongitude{2};
centroid.lat = (min_lat + max_lat) / FixedLatitude{2};
return centroid;
}
@@ -169,10 +169,10 @@ struct RectangleInt2D
bool IsValid() const
{
return min_lon != FixedLongitude(std::numeric_limits<std::int32_t>::max()) &&
max_lon != FixedLongitude(std::numeric_limits<std::int32_t>::min()) &&
min_lat != FixedLatitude(std::numeric_limits<std::int32_t>::max()) &&
max_lat != FixedLatitude(std::numeric_limits<std::int32_t>::min());
return min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::max()} &&
max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()} &&
min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
}
friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect);
+2 -2
View File
@@ -193,8 +193,8 @@ class StaticRTree
Coordinate current_centroid = coordinate_calculation::centroid(
m_coordinate_list[current_element.u], m_coordinate_list[current_element.v]);
current_centroid.lat =
FixedLatitude(COORDINATE_PRECISION *
web_mercator::latToY(toFloating(current_centroid.lat)));
FixedLatitude{static_cast<std::int32_t>(COORDINATE_PRECISION *
web_mercator::latToY(toFloating(current_centroid.lat)))};
current_wrapper.m_hilbert_value = hilbertCode(current_centroid);
}
+26 -26
View File
@@ -40,32 +40,32 @@ namespace osrm
* etc. Also clarifies what this random "int" value is
* being used for.
*/
#define OSRM_STRONG_TYPEDEF(From, To) \
class To final \
{ \
static_assert(std::is_arithmetic<From>(), ""); \
From x; \
friend std::ostream &operator<<(std::ostream &stream, const To &inst); \
\
public: \
To() = default; \
explicit To(const From x_) : x(x_) {} \
explicit operator From &() { return x; } \
explicit operator From() const { return x; } \
To operator+(const To rhs_) const { return To(x + static_cast<const From>(rhs_)); } \
To operator-(const To rhs_) const { return To(x - static_cast<const From>(rhs_)); } \
To operator*(const To rhs_) const { return To(x * static_cast<const From>(rhs_)); } \
To operator/(const To rhs_) const { return To(x / static_cast<const From>(rhs_)); } \
bool operator<(const To z_) const { return x < static_cast<const From>(z_); } \
bool operator>(const To z_) const { return x > static_cast<const From>(z_); } \
bool operator<=(const To z_) const { return x <= static_cast<const From>(z_); } \
bool operator>=(const To z_) const { return x >= static_cast<const From>(z_); } \
bool operator==(const To z_) const { return x == static_cast<const From>(z_); } \
bool operator!=(const To z_) const { return x != static_cast<const From>(z_); } \
}; \
inline std::ostream &operator<<(std::ostream &stream, const To &inst) \
{ \
return stream << inst.x; \
#define OSRM_STRONG_TYPEDEF(From, To) \
struct To final \
{ \
static_assert(std::is_arithmetic<From>(), ""); \
From __value; \
friend std::ostream &operator<<(std::ostream &stream, const To &inst); \
\
explicit operator From &() { return __value; } \
explicit operator From() const { return __value; } \
To operator+(const To rhs_) const { return To{__value + static_cast<const From>(rhs_)}; } \
To operator-(const To rhs_) const { return To{__value - static_cast<const From>(rhs_)}; } \
To operator*(const To rhs_) const { return To{__value * static_cast<const From>(rhs_)}; } \
To operator/(const To rhs_) const { return To{__value / static_cast<const From>(rhs_)}; } \
bool operator<(const To z_) const { return __value < static_cast<const From>(z_); } \
bool operator>(const To z_) const { return __value > static_cast<const From>(z_); } \
bool operator<=(const To z_) const { return __value <= static_cast<const From>(z_); } \
bool operator>=(const To z_) const { return __value >= static_cast<const From>(z_); } \
bool operator==(const To z_) const { return __value == static_cast<const From>(z_); } \
bool operator!=(const To z_) const { return __value != static_cast<const From>(z_); } \
}; \
static_assert(std::is_trivial<To>(), #To " is not a trivial type"); \
static_assert(std::is_standard_layout<To>(), #To " is not a standart layout"); \
static_assert(std::is_pod<To>(), #To " is not a POD layout"); \
inline std::ostream &operator<<(std::ostream &stream, const To &inst) \
{ \
return stream << inst.__value; \
}
#define OSRM_STRONG_TYPEDEF_HASHABLE(From, To) \
+24 -17
View File
@@ -43,37 +43,44 @@ OSRM_STRONG_TYPEDEF_HASHABLE(std::uint64_t, OSMNodeID)
OSRM_STRONG_TYPEDEF(std::uint32_t, OSMWayID)
OSRM_STRONG_TYPEDEF_HASHABLE(std::uint32_t, OSMWayID)
static const OSMNodeID SPECIAL_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::max());
static const OSMWayID SPECIAL_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::max());
static const OSMNodeID SPECIAL_OSM_NODEID = OSMNodeID{std::numeric_limits<std::uint64_t>::max()};
static const OSMWayID SPECIAL_OSM_WAYID = OSMWayID{std::numeric_limits<std::uint32_t>::max()};
static const OSMNodeID MAX_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::max());
static const OSMNodeID MIN_OSM_NODEID = OSMNodeID(std::numeric_limits<std::uint64_t>::min());
static const OSMWayID MAX_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::max());
static const OSMWayID MIN_OSM_WAYID = OSMWayID(std::numeric_limits<std::uint32_t>::min());
static const OSMNodeID MAX_OSM_NODEID = OSMNodeID{std::numeric_limits<std::uint64_t>::max()};
static const OSMNodeID MIN_OSM_NODEID = OSMNodeID{std::numeric_limits<std::uint64_t>::min()};
static const OSMWayID MAX_OSM_WAYID = OSMWayID{std::numeric_limits<std::uint32_t>::max()};
static const OSMWayID MIN_OSM_WAYID = OSMWayID{std::numeric_limits<std::uint32_t>::min()};
using OSMNodeID_weak = std::uint64_t;
using OSMEdgeID_weak = std::uint64_t;
using NodeID = unsigned int;
using EdgeID = unsigned int;
using NodeID = std::uint32_t;
using EdgeID = std::uint32_t;
using NameID = std::uint32_t;
using EdgeWeight = int;
using EdgeWeight = std::int32_t;
using LaneID = std::uint8_t;
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
using LaneDataID = std::uint16_t;
static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits<LaneDataID>::max();
using LaneDescriptionID = std::uint16_t;
static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID = std::numeric_limits<LaneDescriptionID>::max();
using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<std::uint32_t>::max();
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();
using DiscreteBearing = std::uint16_t;
using EntryClassID = std::uint16_t;
static const EntryClassID INVALID_ENTRY_CLASSID = std::numeric_limits<std::uint16_t>::max();
static const EntryClassID INVALID_ENTRY_CLASSID = std::numeric_limits<EntryClassID>::max();
static const NodeID SPECIAL_NODEID = std::numeric_limits<unsigned>::max();
static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<int>::max();
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<unsigned>::max();
static const unsigned INVALID_NAMEID = std::numeric_limits<unsigned>::max();
static const unsigned EMPTY_NAMEID = 0;
static const NodeID SPECIAL_NODEID = std::numeric_limits<NodeID>::max();
static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<NodeID>::max() >> 1;
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<EdgeID>::max();
static const NameID INVALID_NAMEID = std::numeric_limits<NameID>::max();
static const NameID EMPTY_NAMEID = 0;
static const unsigned INVALID_COMPONENTID = 0;
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<int>::max();
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
struct SegmentID
{
+10 -10
View File
@@ -35,7 +35,7 @@ inline FloatLatitude yToLat(const double y)
const double normalized_lat =
detail::RAD_TO_DEGREE * 2. * std::atan(std::exp(clamped_y * detail::DEGREE_TO_RAD));
return FloatLatitude(normalized_lat - 90.);
return FloatLatitude{normalized_lat - 90.};
}
inline double latToY(const FloatLatitude latitude)
@@ -56,7 +56,7 @@ template <typename T, typename... U> constexpr double horner(double x, T an, U..
inline double latToYapprox(const FloatLatitude latitude)
{
if (latitude < FloatLatitude(-70.) || latitude > FloatLatitude(70.))
if (latitude < FloatLatitude{-70.} || latitude > FloatLatitude{70.})
return latToY(latitude);
// Approximate the inverse Gudermannian function with the Padé approximant [11/11]: deg → deg
@@ -93,14 +93,14 @@ inline double latToYapprox(const FloatLatitude latitude)
inline FloatLatitude clamp(const FloatLatitude lat)
{
return std::max(std::min(lat, FloatLatitude(detail::MAX_LATITUDE)),
FloatLatitude(-detail::MAX_LATITUDE));
return std::max(std::min(lat, FloatLatitude{detail::MAX_LATITUDE}),
FloatLatitude{-detail::MAX_LATITUDE});
}
inline FloatLongitude clamp(const FloatLongitude lon)
{
return std::max(std::min(lon, FloatLongitude(detail::MAX_LONGITUDE)),
FloatLongitude(-detail::MAX_LONGITUDE));
return std::max(std::min(lon, FloatLongitude{detail::MAX_LONGITUDE}),
FloatLongitude{-detail::MAX_LONGITUDE});
}
inline void pixelToDegree(const double shift, double &x, double &y)
@@ -159,10 +159,10 @@ inline void xyzToMercator(
{
xyzToWGS84(x, y, z, minx, miny, maxx, maxy);
minx = static_cast<double>(clamp(util::FloatLongitude(minx))) * DEGREE_TO_PX;
miny = latToY(clamp(util::FloatLatitude(miny))) * DEGREE_TO_PX;
maxx = static_cast<double>(clamp(util::FloatLongitude(maxx))) * DEGREE_TO_PX;
maxy = latToY(clamp(util::FloatLatitude(maxy))) * DEGREE_TO_PX;
minx = static_cast<double>(clamp(util::FloatLongitude{minx})) * DEGREE_TO_PX;
miny = latToY(clamp(util::FloatLatitude{miny})) * DEGREE_TO_PX;
maxx = static_cast<double>(clamp(util::FloatLongitude{maxx})) * DEGREE_TO_PX;
maxy = latToY(clamp(util::FloatLatitude{maxy})) * DEGREE_TO_PX;
}
}
}

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