Compare commits

...

48 Commits

Author SHA1 Message Date
Daniel J. Hofmann fe491bf92c Allow Travis builds for this branch 2016-08-04 15:22:51 +02:00
Daniel J. Hofmann 7b432b34bb Update CMakeLists.txt version to 5.3.1 2016-08-04 15:12:48 +02:00
Daniel J. Hofmann 6983cd0de2 Adapt Changelog for v5.3.1 2016-08-04 15:06:44 +02:00
Daniel J. Hofmann fe8177077c Disable our added failing cucumber tests for now 2016-08-04 14:58:06 +02:00
Daniel J. Hofmann 5f339f4ed6 Fall back to generic match finding if not a reverse-lane 2016-08-04 14:57:59 +02:00
Daniel J. Hofmann 3c0b52c637 Skip handling none values for our edge cases for now..
Conflicts:
	src/extractor/guidance/turn_lane_augmentation.cpp
2016-08-04 14:57:53 +02:00
Daniel Patterson 877fc5b42c Add a minimal version of the failing test case. 2016-08-04 14:57:47 +02:00
Daniel J. Hofmann e28785e399 Reproducing breaking intersection in cucumber scenario
Conflicts:
	src/extractor/guidance/turn_lane_augmentation.cpp
2016-08-04 14:57:39 +02:00
Daniel J. Hofmann 2c4a54ce05 Try to come up with a small test case 2016-08-04 14:57:32 +02:00
Michael Krasnyk a8afc74590 Fix #2706 by using correct fallback u-turn
Regression is due to a combination of 08248e3853
and http://www.openstreetmap.org/changeset/40938983
where in ways http://www.openstreetmap.org/way/27292481
and http://www.openstreetmap.org/way/432488408
nodes
4315134884 (part of way 432488408)
4315134891 (part of way 432488408)
4315134886 (part of way 432488408)
form a u-turn that has index 0 after sorting and used as an allowed one
with a reversed edge.
A u-turn that corresponds to the condition uturn_could_be_valid == true has index 1
and ignored.
2016-07-31 22:46:10 +02:00
Daniel J. Hofmann d195eee7c4 Lane Handling for multiple indications per lane as in left;left|, fixes #2694
Before we asserted on unique lane indications per lane. Turns out the
OSM data contains lane strings such as:

    left;left|right

Which represents two lanes as in:

    <<     >
     ||    |

The two left indications _on a single lane_ look like data issue.
And we can't represent this with our enum-approach at the moment.

We don't want to crash there, so silently swallow this and
generate a single left|right for it.
2016-07-26 12:18:15 +02:00
Patrick Niklaus 9b737230d6 Reenable ARM builds 2016-07-22 13:57:57 +02:00
Patrick Niklaus ecbd709535 Update the changelog for 5.3.0 2016-07-22 13:57:28 +02:00
Patrick Niklaus 060ec99678 Fix devide by zero when updating speeds 2016-07-21 18:57:21 +02:00
Dane Springmeyer 3601d1d262 increase travis cacher timeout to ensure large caches are able to be uploaded and downloaded 2016-07-21 17:58:57 +02:00
Moritz Kobitzsch 41ba20ca9a switch api format to new structure 2016-07-21 17:42:10 +02:00
Patrick Niklaus 57e3f173d3 [skip ci] Update docker files to gcc 5 2016-07-21 17:19:35 +02:00
Patrick Niklaus 92c298c7cf [skip ci] Fix example URLs in readme 2016-07-21 17:08:39 +02:00
Moritz Kobitzsch b25011ee60 fix use-lane handling 2016-07-21 16:37:54 +02:00
Moritz Kobitzsch 0e017a6ce5 collapse use-lane instructions if possible 2016-07-20 10:23:26 +02:00
Moritz Kobitzsch 2431e15ffa mark second case as todo, see https://github.com/Project-OSRM/osrm-backend/issues/2661 2016-07-20 09:55:30 +02:00
Moritz Kobitzsch 396add1e9d make roundabout maneuvers continuous with respect to lane changes 2016-07-20 09:55:30 +02:00
Patrick Niklaus 86241a2793 [skip ci] Add docs for contributing 2016-07-19 17:38:03 +02:00
Moritz Kobitzsch ee47afbe17 fix 2672 2016-07-19 17:06:47 +02:00
Moritz Kobitzsch 8831ca2f32 fix roundabouts with traffic lights 2016-07-19 14:49:09 +02:00
Daniel J. Hofmann abde215bc3 Remove semantically wrong ordering for LaneTupel 2016-07-18 12:33:56 +02:00
Daniel J. Hofmann 130d5298fc Fixes Undefined Behavior in LaneTupel (Strict Aliasing), resolves 2665
It's complicated :sigh: read this please:
http://dbp-consulting.com/tutorials/StrictAliasing.html

tl;dr: has to go through a memcpy (in C++) as in:
https://github.com/WebAssembly/binaryen/blob/184cc11cee2a65d30c7696eb3284e132099e4acb/src/support/utilities.h#L29-L40
2016-07-18 12:32:25 +02:00
Moritz Kobitzsch 50cbba1620 adding a todo testscase / regression test-case 2016-07-15 10:35:25 +02:00
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
56 changed files with 1453 additions and 616 deletions
+2
View File
@@ -13,6 +13,7 @@ notifications:
branches:
only:
- master
- "5.3"
cache:
ccache: true
@@ -24,6 +25,7 @@ env:
global:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- CASHER_TIME_OUT=1000
- JOBS=4
matrix:
+52 -1
View File
@@ -1,11 +1,62 @@
# 5.3.1
Changes from 5.3.1
- Bugfixes:
- Disabled broken lane handling for complex uturn/oneway combinations for now (190 intersections affected on the planet)
- Fixed a bug with overlaping geometries, which broke OSRM on recent Egypt extracts with data-modelling issues
# 5.3.0
Changes from 5.3.0-rc.3
- Guidance
- Only announce `use lane` on required turns (not using all lanes to go straight)
- Moved `lanes` to the intersection objects. This is BREAKING in relation to other Release Candidates but not with respect to other releases.
- Bugfixes
- Fix BREAKING: bug that could result in failure to load 'osrm.icd' files. This breaks the dataformat
- Fix: bug that results in segfaults when `use lane` instructions are suppressed
Changes form 5.2.7
- 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 `Intersection` object. The lane data contains both the markings at the intersection and a flag indicating if they can be chosen for the next turn
- Removed unused `-s` from `osrm-datastore`
- Guidance
- Only announce `use lane` on required turns (not using all lanes to go straight)
- Improved detection of obvious turns
- Improved turn lane detection
- Reduce the number of end-of-road instructions in obvious cases
- Profile:
- bicycle.lua: Surface speeds never increase the actual speed
- Infrastructure
- Add 32bit support
- Add ARM NEON/VFP support
- Fix Windows builds
- Optimize speed file updates using mmap
- Add option to disable LTO for older compilers
- 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.
- Bugfixes:
- Fix devide by zero on updating speed data using osrm-contract
# 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 a new file (osrm.tld). This breaks the fileformat for older versions.
- BREAKING: Turn lane data introduces two new files (osrm.tld,osrm.tls). This breaks the fileformat for older versions.
# 5.2.5
- Bugfixes
+1 -1
View File
@@ -10,7 +10,7 @@ endif()
project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 3)
set(OSRM_VERSION_PATCH 0)
set(OSRM_VERSION_PATCH 1)
# these two functions build up custom variables:
# OSRM_INCLUDE_PATHS and OSRM_DEFINES
+55
View File
@@ -0,0 +1,55 @@
# User
Before you open a new issue, please search for older ones that cover the same issue.
In general "me too" comments/issues are frowned upon.
You can add a :+1: emoji to the issue if you want to express interest in this.
# Developer
We use `clang-format` version `3.8` to consistently format the code base. There is a helper script under `scripts/format.sh`.
In general changes that affect the API and/or increase the memory consumption need to be discussed first.
Often we don't include changes that would increase the memory consumption a lot if they are not generally usable (e.g. elevation data is a good example).
## Pull Request
Every pull-request that changes the API needs to update the docs in `docs/http.md` and add an entry to `CHANGELOG.md`.
Breaking changes need to have a BREAKING prefix. See the [releasing documentation](docs/releasing.md) on how this affects the version.
Early feedback is also important.
You will see that a lot of the PR have tags like `[not ready]` or `[wip]`.
We like to open PRs as soon as we are starting to work on something to make it visible to the rest of the team.
If your work is going in entirely the wrong direction, there is a good chance someone will pick up on this before it is too late.
Everyone is encouraged to read PRs of other people and give feedback.
For every significant code change we require a pull request review before it is merged.
If your pull request modifies the API this need to be signed of by a team discussion.
This means you will need to find another member of the team with commit access and request a review of your pull request.
Once your pull request is reviewed you can merge it! If you don't have commit access, ping someone that has commit access.
If you do have commit access there are in general two accepted styles to merging:
1. Make sure the branch is up to date with `master`. Run `git rebase master` to find out.
2. Once that is ensured you can either:
- Click the nice green merge button (for a non-fast-forward merge)
- Merge by hand using a fast-forward merge
Which merge you prefer is up to personal preference. In general it is recommended to use fast-forward merges because it creates a history that is sequential and easier to understand.
# Maintainer
## Doing a release
There is an in-depth guide around how to push out a release once it is ready [here](docs/releasing.md).
## The API
Changes to the API need to be discussed and signed off by the team. Breaking changes even more so than additive changes.
## Milestones
If a pull request or an issue is applicable for the current or next milestone, depends on the target version number.
Since we use semantic versioning we restrict breaking changes to major releases.
After a Release Candidate is released we usually don't change the API anymore if it is not critical.
Bigger code changes after a RC was released should also be avoided.
+2 -2
View File
@@ -46,7 +46,7 @@ osrm-routed data.osrm
Running a query on your local server:
```
curl http://127.0.0.1:5000/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
curl http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
```
### Running a request against the Demo Server
@@ -56,7 +56,7 @@ First read the [API usage policy](https://github.com/Project-OSRM/osrm-backend/w
Then run simple query with instructions and alternatives on Berlin:
```
curl https://router.project-osrm.org/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
curl https://router.project-osrm.org/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true&alternatives=true
```
## References in publications
+4 -13
View File
@@ -1,18 +1,9 @@
FROM ubuntu:14.04
RUN apt-get update -y
RUN apt-get install -y build-essential git-core python-pip python-software-properties software-properties-common
RUN apt-get -y install gcc-4.8 g++-4.8 libboost1.55-all-dev llvm-3.4
RUN apt-get -y install libbz2-dev libstxxl-dev libstxxl1 libxml2-dev
RUN apt-get -y install libzip-dev lua5.1 liblua5.1-0-dev libtbb-dev libgdal-dev
RUN apt-get -y install curl cmake cmake-curses-gui
RUN pip install awscli
# luabind
RUN curl https://gist.githubusercontent.com/DennisOSRM/f2eb7b948e6fe1ae319e/raw/install-luabind.sh | sudo bash
RUN apt-get update -y && apt-get install -y software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
RUN apt-get update -y && apt-get install -y 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
RUN apt-get -y install curl cmake cmake-curses-gui git
WORKDIR /opt
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
+2 -1
View File
@@ -5,7 +5,8 @@ set -o pipefail
docker run \
-i \
-e "CXX=g++" \
-e "CXX=g++-5" \
-e "CC=gcc-5" \
-v `pwd`:/home/mapbox/osrm-backend \
-t mapbox/osrm:linux \
/bin/bash -lc "osrm-backend/docker/test.sh"
+55 -45
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],
@@ -453,24 +453,28 @@ step.
"maneuver":{
"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,
"out":2,
"bearings":[10,92,184,270],
"entry":[false,"true","true"]},
"entry":["true","true","true","false"],
"lanes":[
{"indications":["left","straight"], "valid":"false"},
{"indications":["right"], "valid":"true"}
]},
{"location":[13.394718,52.543096],
"in":0,
"out":2,
"bearings":[60,150,240,330],
"entry":["false","true","true","true"]
}
"out":1,
"bearings":[60,240,330],
"entry":["false","true","true"]
"lanes":[
{"indications":["straight"], "valid":"true"},
{"indications":["right"], "valid":"false"}
]}
]}
```
@@ -486,23 +490,24 @@ 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.
@@ -511,14 +516,14 @@ step.
| `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 |
| `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.
@@ -535,14 +540,13 @@ 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.
### Lane
A lane give a representation of turn lane at the corresponding turn location.
A `Lane` represents a turn lane at the corresponding turn location.
#### Properties
@@ -551,14 +555,14 @@ A lane give a representation of turn lane at the corresponding turn location.
| `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). |
| `sharp right` | An indication indicating a slight right turn (i.e. slightly 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). |
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend 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 slight left turn (i.e. slightly bend arrow). |
| `uturn` | An indication signaling the possibility to reverse (i.e. fully 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
@@ -566,7 +570,7 @@ A lane give a representation of turn lane at the corresponding turn location.
```json
{
"indication": ["left", "straight"],
"indications": ["left", "straight"],
"valid": "false"
}
```
@@ -587,6 +591,7 @@ location of the StepManeuver. Further intersections are listed for every cross-w
in the direction of driving, the bearing has to be rotated by a value of 180. The value is not supplied for `depart` maneuvers.
- `out`: index into the bearings/entry array. Used to extract the bearing just after the turn. Namely, The clockwise angle from true north to the
direction of travel immediately after the maneuver/passing the intersection. The value is not supplied for `arrive` maneuvers.
- `lanes`: Array of `Lane` objects that denote the available turn lanes at the turn location
#### Example
```
@@ -596,6 +601,11 @@ location of the StepManeuver. Further intersections are listed for every cross-w
"out":2,
"bearings":[60,150,240,330],
"entry":["false","true","true","true"]
"lanes":{
"indications": ["left", "straight"],
"valid": "false"
}
]}
}
```
+272 -82
View File
@@ -15,14 +15,14 @@ Feature: Turn Lane Guidance
| | | 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 | |
| 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 | # |
@@ -39,13 +39,13 @@ Feature: Turn Lane Guidance
| 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 |
| 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 |
@@ -62,13 +62,13 @@ Feature: Turn Lane Guidance
| 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 |
| 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 |
@@ -105,13 +105,13 @@ Feature: Turn Lane Guidance
| | | | | | 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 |
| 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 |
@@ -135,9 +135,9 @@ Feature: Turn Lane Guidance
| 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, |
| 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 | depart,merge slight left,arrive | ,, |
@anticipate
@@ -150,14 +150,14 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -173,14 +173,14 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -196,14 +196,14 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -219,14 +219,14 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -244,21 +244,211 @@ Feature: Turn Lane Guidance
| | | | | 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 |
| 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 @todo @bug @2661
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: Departing or arriving inside a roundabout does not yet anticipate lanes (BIG version)
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
@@ -273,10 +463,10 @@ Feature: Turn Lane Guidance
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 |
| 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
@@ -298,10 +488,10 @@ Feature: Turn Lane Guidance
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 |
| 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
+6 -6
View File
@@ -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 |
+33
View File
@@ -128,3 +128,36 @@ Feature: End Of Road Instructions
| a,c | aeb,bc,bc | depart,on ramp left,arrive |
| a,d | aeb,bd,bd | depart,on ramp right,arrive |
# http://www.openstreetmap.org/#map=19/52.49907/13.41836
@end-of-road @negative
Scenario: Don't Handle Circles as End-Of-Road
Given the node map
| | r | | | | q | | | | | | |
| | | | | | a | s | | | | | |
| | | | b | | | | | | | | |
| | | | | | | | j | | | | |
| | | | | | | | | | | | |
| l | | c | | | | | i | | | | k |
| | | | | | | | | | | | |
| | | | | | | | h | | | | |
| m | | | | | | | | | | | |
| | | d | | | | | | | | | n |
| | | | e | | | g | | | | | |
| | | | | f | | | | | | | |
| | | | | o | | p | | | | | |
And the ways
| nodes | highway | name | oneway |
| abcdefghijsa | secondary | kotti | yes |
| ki | secondary | skal | yes |
| cl | secondary | skal | yes |
| md | secondary | skal | yes |
| gn | secondary | skal | yes |
| qa | tertiary | adal | no |
| br | residential | rei | yes |
| fo | secondary | kstr | yes |
| pg | secondary | kstr | yes |
When I route I should get
| waypoints | route | turns | # |
| k,l | skal,kotti,skal,skal | depart,turn right,turn right,arrive | # could be a case to find better turn instructions for |
+39
View File
@@ -437,3 +437,42 @@ Feature: Basic Roundabout
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 |
Scenario: Enter and Exit - Traffic Signals
Given the node map
| | | a | | |
| | i | b | l | |
| h | g | | c | d |
| | j | e | k | |
| | | f | | |
And the nodes
| node | highway |
| i | traffic_signals |
| j | traffic_signals |
| k | traffic_signals |
| l | traffic_signals |
And the ways
| nodes | junction |
| ab | |
| cd | |
| ef | |
| gh | |
| bigjekclb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout-exit-3,arrive |
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive |
| d,f | cd,ef,ef | depart,roundabout-exit-3,arrive |
| d,h | cd,gh,gh | depart,roundabout-exit-2,arrive |
| d,a | cd,ab,ab | depart,roundabout-exit-1,arrive |
| f,h | ef,gh,gh | depart,roundabout-exit-3,arrive |
| f,a | ef,ab,ab | depart,roundabout-exit-2,arrive |
| f,d | ef,cd,cd | depart,roundabout-exit-1,arrive |
| h,a | gh,ab,ab | depart,roundabout-exit-3,arrive |
| h,d | gh,cd,cd | depart,roundabout-exit-2,arrive |
| h,f | gh,ef,ef | depart,roundabout-exit-1,arrive |
+322 -144
View File
@@ -5,9 +5,7 @@ Feature: Turn Lane Guidance
Given the profile "car"
Given a grid size of 20 meters
#requires https://github.com/cucumber/cucumber-js/issues/417
#Due to this, we use & as a pipe character. Switch them out for \| when 417 is fixed
@bug @WORKAROUND-FIXME
@bug
Scenario: Basic Turn Lane 3-way Turn with empty lanes
Given the node map
| a | | b | | c |
@@ -16,7 +14,7 @@ Feature: Turn Lane Guidance
And the ways
| nodes | turn:lanes | turn:lanes:forward | turn:lanes:backward | name |
| ab | | through\|right | | in |
| bc | | | left\|through&& | straight |
| bc | | | left\|through\|\| | straight |
| bd | | | left\|right | right |
When I route I should get
@@ -89,7 +87,6 @@ Feature: Turn Lane Guidance
#this next test requires decision on how to announce lanes for going straight if there is no turn
@TODO @WORKAROUND-FIXME
Scenario: Turn with Bus-Lane
Given the node map
| a | | b | | c |
@@ -98,17 +95,35 @@ Feature: Turn Lane Guidance
And the ways
| nodes | name | turn:lanes:forward | lanes:psv:forward |
| ab | road | through\|right& | 1 |
| 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, |
| waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
| a,c | road,road | depart,arrive | , |
@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 @WORKAROUND-FIXME @bug
@todo @bug
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | i | l | | |
@@ -119,19 +134,19 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -163,28 +178,28 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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, |
| 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 | depart,arrive | , |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
Scenario: Turn Lanes at Segregated Road
Given the node map
@@ -194,14 +209,14 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -222,9 +237,9 @@ Feature: Turn Lane Guidance
| 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, |
| waypoints | route | turns | lanes |
| a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, |
| a,d | road,road | depart,arrive | , |
Scenario: Turn Lanes Given earlier than actual turn
Given the node map
@@ -242,11 +257,11 @@ Feature: Turn Lane Guidance
| 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, |
| waypoints | route | turns | lanes |
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, |
| a,i | road,road | depart,arrive | , |
| i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none:false, |
| i,a | road,road | depart,arrive | , |
Scenario: Passing a one-way street
Given the node map
@@ -311,13 +326,13 @@ Feature: Turn Lane Guidance
| | | | 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 | |
| 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 |
@@ -342,9 +357,9 @@ Feature: Turn Lane Guidance
| 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, |
| waypoints | route | turns | lanes |
| a,d | road,road | depart,arrive | , |
| a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
@bug @todo
Scenario: Theodor Heuss Platz
@@ -366,16 +381,16 @@ Feature: Turn Lane Guidance
| 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 |
| 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 |
@@ -393,12 +408,12 @@ Feature: Turn Lane Guidance
| | | | 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 |
| 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 |
@@ -406,9 +421,9 @@ Feature: Turn Lane Guidance
| 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, |
| 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 | depart,arrive | , |
Scenario: U-Turn Road at Intersection
Given the node map
@@ -422,18 +437,18 @@ Feature: Turn Lane Guidance
| 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 |
| 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, |
| 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 | depart,arrive | , |
| 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
@@ -446,12 +461,12 @@ Feature: Turn Lane Guidance
| | | | | | 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 |
| 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 |
@@ -471,15 +486,15 @@ Feature: Turn Lane Guidance
| | | | | 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 | |
| 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 |
@@ -496,14 +511,14 @@ Feature: Turn Lane Guidance
| 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 |
| 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,d | road,road | depart,arrive | , |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
Scenario: Highway Ramp
@@ -512,14 +527,14 @@ Feature: Turn Lane Guidance
| | | | | | | 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 |
| 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,d | hwy,hwy | depart,arrive | , |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
@bug @todo
@@ -552,14 +567,14 @@ Feature: Turn Lane Guidance
| | | | | | | | | | | 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 |
| 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,c | hwy,hwy | depart,arrive | , |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false slight right:true, |
Scenario: Reverse Lane in Segregated Road
@@ -570,11 +585,11 @@ Feature: Turn Lane Guidance
| 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 |
| 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 |
@@ -588,11 +603,11 @@ Feature: Turn Lane Guidance
| 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 |
| 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 |
@@ -607,12 +622,12 @@ Feature: Turn Lane Guidance
| | | 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 |
| 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 |
@@ -665,6 +680,169 @@ Feature: Turn Lane Guidance
| 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, |
| waypoints | route | turns | lanes |
| a,j | on,xbcj,xbcj | depart,merge slight left,arrive | ,, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |
#http://www.openstreetmap.org/#map=17/52.47414/13.35712
@todo @ramp @2645
Scenario: Kreuz Schoeneberg - Continue on ramp, don't merge
Given the node map
| i | | | | | j | | | | | | | | | | | |
| | | | | k | | | | | | | | | | | | |
| h | g | | l | | | f | | | | | | | | | | e |
| d | | | | | | | | c | | | | | b | | | a |
And the ways
| nodes | highway | name | oneway | lanes | turn:lanes |
| ab | motorway | A 100 | yes | 3 | |
| bc | motorway | A 100 | yes | 4 | \|\|\|slight_right |
| cd | motorway | A 100 | yes | 3 | |
| eb | motorway_link | | yes | 1 | |
| cf | motorway_link | | yes | 1 | |
| fj | motorway_link | | yes | 1 | |
| fl | motorway_link | | yes | 1 | |
| kl | motorway_link | | yes | 1 | |
| lg | motorway_link | | yes | 2 | through\|slight_right |
| gi | motorway_link | | yes | 1 | |
| gh | motorway_link | | yes | 1 | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | A 100,A 100 | depart,arrive | |
| a,i | A 100,,,, | depart,off ramp slight right,fork slight left,turn right,arrive | ,none:false none:false none:false slight right:true,,straight:false slight right:true, |
| e,j | ,,, | depart,off ramp slight right,fork slight right,arrive | ,none:false none:false none:false slight right:true,,, |
| e,i | ,,,, | depart,off ramp right,fork slight left,use lane straight,arrive | ,none:false none:false none:false slight right:true,,straight:false slight right:true, |
| e,d | ,A 100,A 100 | depart,merge slight left,arrive | ,, |
| e,h | ,,,, | depart,off ramp right,fork left,use lane straight,arrive | ,none:false none:false none:false slight right:true,,straight:true slight right:false, |
@collapse @use-lane
Scenario: Collapse Multiple Use Lanes
Given the node map
| x | a | | b | | | c | | | d |
| | | | e | | | f | | | |
And the ways
| nodes | name | highway | turn:lanes:forward |
| ab | road | primary | through,right |
| bc | road | primary | through,right |
| cd | road | primary | |
| xa | road | primary | |
| be | turn | primary | |
| cf | turn | primary | |
When I route I should get
| waypoints | route | turns | lanes |
| x,d | road,road | depart,arrive | , |
Scenario: Lane Parsing Issue #2694
Given the node map
| | c |
| a | b |
| | d |
And the ways
| nodes | highway | turn:lanes:forward |
| ab | primary | left;left\|right |
| bc | primary | |
| bd | primary | |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | ab,bc,bc | depart,turn left,arrive | ,left:true right:false, |
# http://www.openstreetmap.org/#map=19/47.97685/7.82933&layers=D
@bug @todo
Scenario: Lane Parsing Issue #2706: None Assignments I
Given the node map
| | f | | | j | |
| | | | | | |
| a | b | c | | d | e |
| | | | | | |
| | | | | i | |
| | g | | | h | |
And the nodes
| node | highway |
| a | traffic_signals |
| i | traffic_signals |
And the ways
| nodes | highway | name | oneway | turn:lanes:forward |
| ab | secondary | Wiesentalstr | | through;left\|right |
| bc | secondary | Wiesentalstr | | none\|left;through |
| cd | secondary | Wiesentalstr | | none\|left;through |
| de | residential | Wippertstr | | |
| fb | secondary | Merzhauser Str | yes | through\|through\|right |
| bg | secondary | Merzhauser Str | yes | |
| hi | secondary | Merzhauser Str | yes | left;reverse\|none\|none |
| ic | secondary_link | Merzhauser Str | yes | |
| id | secondary | Merzhauser Str | yes | through;right\|none |
| dj | secondary | Merzhauser Str | yes | |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | fb | fb | b | no_left_turn |
| restriction | ic | cb | c | only_left_turn |
| restriction | id | dc | d | no_left_turn |
When I route I should get
| waypoints | route | turns | lanes |
| h,a ||||
# Note: at the moment we don't care about routes, we care about the extract process triggering assertions
# https://www.openstreetmap.org/#map=19/47.99257/7.83276&layers=D
@bug @todo
Scenario: Lane Parsing Issue #2706: None Assignments II
Given the node map
| | k | l | |
| j | a | b | f |
| i | c | d | e |
| | h | g | |
And the ways
| nodes | highway | name | oneway | turn:lanes |
| ka | secondary | Eschholzstr | yes | left;reverse\|through\|through\|none |
| kj | unclassified | kj | yes | |
| ac | secondary | Eschholzstr | yes | left;reverse\|none\|none\|none |
| ch | secondary | Eschholzstr | yes | |
| gd | secondary | Eschholzstr | yes | left;reverse\|through\|through\|none |
| db | secondary | Eschholzstr | yes | left;reverse\|through\|through\|none |
| bl | secondary | Eschholzstr | yes | |
| fb | residential | Haslacher Str | yes | left;reverse\|left;through\|right |
| ba | secondary_link | Haslacher Str | yes | left;reverse\|left;through |
| aj | unclassified | Haslacher Str | yes | |
| ic | unclassified | Haslacher Str | yes | left;reverse\|left\|through |
| cd | secondary_link | Haslacher Str | yes | left;reverse\|left\|through |
| de | residential | Haslacher Str | yes | |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ka | ac | a | only_straight_on |
| restriction | ic | cd | c | only_straight_on |
| restriction | gd | db | d | only_straight_on |
When I route I should get
| waypoints | route | turns | lanes |
| i,e ||||
# Note: at the moment we don't care about routes, we care about the extract process triggering assertions
@bug @todo
Scenario: Lane Parsing Issue #2706: None Assignments III - Minimal reproduction recipe
Given the node map
| | | l | |
| | a | b | |
| | | d | |
| | | | |
And the ways
| nodes | highway | name | oneway | turn:lanes |
| db | secondary | Eschholzstr | yes | left;reverse\|through\|through\|none |
| bl | secondary | Eschholzstr | yes | |
| ba | secondary_link | Haslacher Str | yes | |
When I route I should get
| waypoints | route | turns | lanes |
| d,a ||||
# Note: at the moment we don't care about routes, we care about the extract process triggering assertions
+26
View File
@@ -853,3 +853,29 @@ Feature: Simple Turns
| 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 |
-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();
});
};
-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();
});
};
+2 -2
View File
@@ -170,9 +170,9 @@ module.exports = function () {
this.lanesList = (instructions) => {
return this.extractInstructionList(instructions, instruction => {
if( 'lanes' in instruction.maneuver )
if( 'lanes' in instruction.intersections[0] )
{
return instruction.maneuver.lanes.map( p => { return (p.indications).join(';') + ':' + p.valid; } ).join(' ');
return instruction.intersections[0].lanes.map( p => { return (p.indications).join(';') + ':' + p.valid; } ).join(' ');
} else
{
return '';
+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 |
+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 |
+1
View File
@@ -151,6 +151,7 @@ class RouteAPI : public BaseAPI
phantoms.source_phantom,
phantoms.target_phantom);
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
leg.steps = guidance::collapseUseLane(std::move(leg.steps));
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
}
@@ -360,7 +360,7 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<util::guidance::BearingClass> bearing_classes;
// and the actual bearing values
std::uint64_t num_bearings;
intersection_stream >> num_bearings;
intersection_stream.read(reinterpret_cast<char*>(&num_bearings),sizeof(num_bearings));
m_bearing_values_table.resize(num_bearings);
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
sizeof(m_bearing_values_table[0]) * num_bearings);
+20 -17
View File
@@ -2,8 +2,8 @@
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/travel_mode.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
@@ -72,14 +72,15 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Depart,
0,
util::guidance::LaneTupel(),
{}};
0};
Intersection intersection{source_node.location,
std::vector<short>({bearings.second}),
std::vector<bool>({true}),
Intersection::NO_INDEX,
0};
0,
util::guidance::LaneTupel(),
{}};
if (leg_data.size() > 0)
{
@@ -138,6 +139,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
intersection.bearings.clear();
intersection.bearings.reserve(bearing_class.getAvailableBearings().size());
intersection.lanes = path_point.lane_data.first;
intersection.lane_description =
path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::guidance::TurnLaneDescription();
std::copy(bearing_class.getAvailableBearings().begin(),
bearing_class.getAvailableBearings().end(),
std::back_inserter(intersection.bearings));
@@ -151,11 +157,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
path_point.turn_instruction,
WaypointType::None,
0,
path_point.lane_data.first,
(path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::guidance::TurnLaneDescription())};
0};
segment_index++;
segment_duration = 0;
}
@@ -210,15 +212,16 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Arrive,
0,
util::guidance::LaneTupel(),
{}};
0};
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
std::vector<bool>({true}),
0,
Intersection::NO_INDEX};
Intersection::NO_INDEX,
util::guidance::LaneTupel(),
{}};
BOOST_ASSERT(!leg_geometry.locations.empty());
steps.push_back(RouteStep{target_node.name_id,
@@ -243,9 +246,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
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());
BOOST_ASSERT(steps.back().intersections.front().lanes.lanes_in_turn == 0);
BOOST_ASSERT(steps.back().intersections.front().lanes.first_lane_from_the_right == INVALID_LANEID);
BOOST_ASSERT(steps.back().intersections.front().lane_description.empty());
return steps;
}
+4 -1
View File
@@ -15,7 +15,10 @@ 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);
// the second parameter describes the duration that we feel two segments need to be apart to count
// as separate maneuvers.
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const double min_duration_needed_for_lane_change = 15);
} // namespace guidance
} // namespace engine
@@ -43,6 +43,15 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
// remove steps invalidated by post-processing
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
// remove use lane information that is not actually a turn. For post-processing, we need to
// associate lanes with every turn. Some of these use-lane instructions are not required after lane
// anticipation anymore. This function removes all use lane instructions that are not actually used
// anymore since all lanes going straight are used anyhow.
// FIXME this is currently only a heuristic. We need knowledge on which lanes actually might become
// turn lanes. If a straight lane becomes a turn lane, this might be something to consider. Right
// now we bet on lane-anticipation to catch this.
std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.
+10 -1
View File
@@ -7,6 +7,9 @@
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <cstddef>
#include <string>
@@ -34,6 +37,10 @@ struct Intersection
std::vector<bool> entry;
std::size_t in;
std::size_t out;
// turn lane information
util::guidance::LaneTupel lanes;
extractor::guidance::TurnLaneDescription lane_description;
};
inline Intersection getInvalidIntersection()
@@ -42,7 +49,9 @@ inline Intersection getInvalidIntersection()
{},
{},
Intersection::NO_INDEX,
Intersection::NO_INDEX};
Intersection::NO_INDEX,
util::guidance::LaneTupel(),
{}};
}
struct RouteStep
+1 -8
View File
@@ -2,9 +2,7 @@
#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>
@@ -33,9 +31,6 @@ struct StepManeuver
WaypointType waypoint_type;
unsigned exit;
util::guidance::LaneTupel lanes;
extractor::guidance::TurnLaneDescription lane_description;
};
inline StepManeuver getInvalidStepManeuver()
@@ -45,9 +40,7 @@ inline StepManeuver getInvalidStepManeuver()
0,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::None,
0,
util::guidance::LaneTupel(),
{}};
0};
}
} // namespace guidance
+40 -28
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,6 +43,38 @@ inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(con
return extractor::guidance::DirectionModifier::Left;
}
// 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)
{
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
} // namespace engine
} // namespace osrm
@@ -46,28 +46,34 @@ 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;
} __attribute ((packed));
};
#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;
} __attribute ((packed));
};
#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;
} __attribute ((packed));
};
#pragma pack(pop)
static_assert(sizeof(PenaltyBlock) == 28, "PenaltyBlock is not packed correctly");
}
+10 -9
View File
@@ -8,9 +8,9 @@
#include "extractor/restriction.hpp"
#include "extractor/scripting_environment.hpp"
#include <cstdint>
#include <stxxl/vector>
#include <unordered_map>
#include <cstdint>
namespace osrm
{
@@ -39,12 +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 WriteCharData(const std::string &file_name,
const stxxl::vector<unsigned> &offests,
const stxxl::vector<char> &char_data) const;
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;
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>;
@@ -52,12 +51,14 @@ 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;
+2 -23
View File
@@ -40,6 +40,8 @@ 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
{
@@ -531,29 +533,6 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co
return lane_string;
}
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);
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -142,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(); }
};
}
}
+7 -4
View File
@@ -21,10 +21,13 @@ 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) << " Duration: " << step.duration
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
<< step.geometry_end << " exit: " << step.maneuver.exit
<< " Intersections: " << step.intersections.size() << " [";
<< 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)
{
+7
View File
@@ -62,6 +62,13 @@ class EntryClass
friend std::size_t std::hash<EntryClass>::operator()(const EntryClass &) const;
};
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<EntryClass>::value,
"Class is serialized trivially in "
"the datafacades. Bytewise writing "
"requires trivially copyable type");
#endif
} // namespace guidance
} // namespace utilr
} // namespace osrm
+28
View File
@@ -101,6 +101,34 @@ inline bool isRightTurn(const extractor::guidance::TurnInstruction 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
-1
View File
@@ -60,7 +60,6 @@ class LaneTupel
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;
+4 -4
View File
@@ -4,13 +4,13 @@
"private": true,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.",
"dependencies": {
"cucumber": "^0.9.4",
"chalk": "^1.1.3",
"cucumber": "^1.2.1",
"d3-queue": "^2.0.3",
"node-timeout": "0.0.4",
"polyline": "^0.2.0",
"request": "^2.69.0",
"xmlbuilder": "^4.2.1",
"chalk": "^1.1.3",
"polyline": "^0.2.0"
"xmlbuilder": "^4.2.1"
},
"bin": {
"cucumber": "./node_modules/cucumber/bin/cucumber.js"
+13 -7
View File
@@ -189,7 +189,7 @@ local function getPSVCounts(way)
if( psv_backward and psv_backward ~= "" ) then
bw = tonumber(psv_backward);
if( bw == nil ) then
fw = 0
bw = 0
end
end
return fw, bw
@@ -206,10 +206,16 @@ local function getTurnLanes(way)
local turn_lanes_bw = way:get_value_by_key("turn:lanes:backward")
if( fw_psv ~= 0 or bw_psv ~= 0 ) then
turn_lanes = trimLaneString(turn_lanes, bw_psv, fw_psv )
turn_lanes_fw = trimLaneString(turn_lanes_fw, bw_psv, fw_psv )
if turn_lanes and turn_lanes ~= "" then
turn_lanes = trimLaneString(turn_lanes, bw_psv, fw_psv )
end
if turn_lanes_fw and turn_lanes_fw ~= "" then
turn_lanes_fw = trimLaneString(turn_lanes_fw, bw_psv, fw_psv )
end
--backwards turn lanes need to treat bw_psv as fw_psv and vice versa
turn_lanes_bw = trimLaneString(turn_lanes_bw, fw_psv, bw_psv )
if turn_lanes_bw and turn_lanes_bw ~= "" then
turn_lanes_bw = trimLaneString(turn_lanes_bw, fw_psv, bw_psv )
end
end
return turn_lanes, turn_lanes_fw, turn_lanes_bw
@@ -427,15 +433,15 @@ function way_function (way, result)
local turn_lanes_backward = ""
turn_lanes, turn_lanes_forward, turn_lanes_backward = getTurnLanes(way)
if( turn_lanes ~= "" ) then
if turn_lanes and turn_lanes ~= "" then
result.turn_lanes_forward = turn_lanes;
result.turn_lanes_backward = turn_lanes;
else
if( turn_lanes_forward ~= "" ) then
if turn_lanes_forward and turn_lanes_forward ~= "" then
result.turn_lanes_forward = turn_lanes_forward;
end
if( turn_lanes_backward ~= "" ) then
if turn_lanes_backward and turn_lanes_backward ~= "" then
result.turn_lanes_backward = turn_lanes_backward;
end
end
+30 -22
View File
@@ -72,6 +72,15 @@ namespace osrm
namespace contractor
{
// Returns duration in deci-seconds
inline EdgeWeight distanceAndSpeedToWeight(double distance_in_meters, double speed_in_kmh)
{
BOOST_ASSERT(speed_in_kmh > 0);
const double speed_in_ms = speed_in_kmh / 3.6;
const double duration = distance_in_meters / speed_in_ms;
return std::max<EdgeWeight>(1, static_cast<EdgeWeight>(std::round(duration * 10)));
}
int Contractor::Run()
{
#ifdef WIN32
@@ -573,12 +582,11 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
find(segment_speed_lookup, Segment{u->node_id, v->node_id});
if (forward_speed_iter != segment_speed_lookup.end())
{
int new_segment_weight =
std::max(1,
static_cast<int>(std::floor(
(segment_length * 10.) /
(forward_speed_iter->speed_source.speed / 3.6) +
.5)));
auto new_segment_weight =
(forward_speed_iter->speed_source.speed > 0)
? distanceAndSpeedToWeight(segment_length,
forward_speed_iter->speed_source.speed)
: INVALID_EDGE_WEIGHT;
m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight =
new_segment_weight;
m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] =
@@ -624,12 +632,11 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
find(segment_speed_lookup, Segment{u->node_id, v->node_id});
if (reverse_speed_iter != segment_speed_lookup.end())
{
int new_segment_weight =
std::max(1,
static_cast<int>(std::floor(
(segment_length * 10.) /
(reverse_speed_iter->speed_source.speed / 3.6) +
.5)));
auto new_segment_weight =
(reverse_speed_iter->speed_source.speed > 0)
? distanceAndSpeedToWeight(segment_length,
reverse_speed_iter->speed_source.speed)
: INVALID_EDGE_WEIGHT;
m_geometry_list[reverse_begin + rev_segment_position].weight =
new_segment_weight;
m_geometry_datasource[reverse_begin + rev_segment_position] =
@@ -763,21 +770,22 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
const auto num_segments = header->num_osm_nodes - 1;
for (auto i : util::irange<std::size_t>(0, num_segments))
{
auto speed_iter =
find(segment_speed_lookup,
Segment{previous_osm_node_id, segmentblocks[i].this_osm_node_id});
if (speed_iter != segment_speed_lookup.end())
{
// This sets the segment weight using the same formula as the
// EdgeBasedGraphFactory for consistency. The *why* of this formula
// is lost in the annals of time.
int new_segment_weight = std::max(
1,
static_cast<int>(std::floor((segmentblocks[i].segment_length * 10.) /
(speed_iter->speed_source.speed / 3.6) +
.5)));
new_weight += new_segment_weight;
if (speed_iter->speed_source.speed > 0)
{
auto new_segment_weight = distanceAndSpeedToWeight(segmentblocks[i].segment_length, speed_iter->speed_source.speed);
new_weight += new_segment_weight;
}
else
{
// This edge is blocked, we don't need to continue updating
new_weight = INVALID_EDGE_WEIGHT;
break;
}
}
else
{
+11 -11
View File
@@ -61,9 +61,9 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
maneuver.instruction.direction_modifier != DirectionModifier::UTurn);
}
inline bool hasValidLanes(const guidance::StepManeuver maneuver)
inline bool hasValidLanes(const guidance::Intersection &intersection)
{
return maneuver.lanes.lanes_in_turn > 0;
return intersection.lanes.lanes_in_turn > 0;
}
std::string instructionTypeToString(const TurnType::Enum type)
@@ -71,19 +71,19 @@ std::string instructionTypeToString(const TurnType::Enum type)
return turn_type_names[static_cast<std::size_t>(type)];
}
util::json::Array lanesFromManeuver(const guidance::StepManeuver &maneuver)
util::json::Array lanesFromIntersection(const guidance::Intersection &intersection)
{
BOOST_ASSERT(maneuver.lanes.lanes_in_turn >= 1);
BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1);
util::json::Array result;
LaneID lane_id = maneuver.lane_description.size();
LaneID lane_id = intersection.lane_description.size();
for (const auto &lane_desc : maneuver.lane_description)
for (const auto &lane_desc : intersection.lane_description)
{
--lane_id;
util::json::Object lane;
lane.values["indications"] = extractor::guidance::TurnLaneType::toJsonArray(lane_desc);
if (lane_id >= maneuver.lanes.first_lane_from_the_right &&
lane_id < maneuver.lanes.first_lane_from_the_right + maneuver.lanes.lanes_in_turn)
if (lane_id >= intersection.lanes.first_lane_from_the_right &&
lane_id < intersection.lanes.first_lane_from_the_right + intersection.lanes.lanes_in_turn)
lane.values["valid"] = util::json::True();
else
lane.values["valid"] = util::json::False();
@@ -175,9 +175,6 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
step_maneuver.values["modifier"] =
detail::instructionModifierToString(maneuver.instruction.direction_modifier);
if (detail::hasValidLanes(maneuver))
step_maneuver.values["lanes"] = detail::lanesFromManeuver(maneuver);
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before);
step_maneuver.values["bearing_after"] = std::round(maneuver.bearing_after);
@@ -217,6 +214,9 @@ util::json::Object makeIntersection(const guidance::Intersection &intersection)
if (intersection.out != guidance::Intersection::NO_INDEX)
result.values["out"] = intersection.out;
if (detail::hasValidLanes(intersection))
result.values["lanes"] = detail::lanesFromIntersection(intersection);
return result;
}
+6 -7
View File
@@ -20,18 +20,17 @@ namespace engine
namespace guidance
{
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const double min_duration_needed_for_lane_change)
{
const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.;
// Postprocessing does not strictly guarantee for only turns
const auto is_turn = [](const RouteStep &step) {
return step.maneuver.instruction.type != TurnType::NewName &&
step.maneuver.instruction.type != TurnType::Notification;
};
const auto is_quick = [MIN_DURATION_NEEDED_FOR_LANE_CHANGE](const RouteStep &step) {
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
const auto is_quick = [min_duration_needed_for_lane_change](const RouteStep &step) {
return step.duration < min_duration_needed_for_lane_change;
};
const auto is_quick_turn = [&](const RouteStep &step) {
@@ -61,10 +60,10 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
// the current turn lanes constrain the lanes we have to take in the previous turn.
util::for_each_pair(rev_first, rev_last, [](RouteStep &current, RouteStep &previous) {
const auto current_inst = current.maneuver.instruction;
const auto current_lanes = current.maneuver.lanes;
const auto current_lanes = current.intersections.front().lanes;
// Constrain the previous turn's lanes
auto &previous_lanes = previous.maneuver.lanes;
auto &previous_lanes = previous.intersections.front().lanes;
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
// otherwise nothing to constrain
+118 -9
View File
@@ -2,12 +2,14 @@
#include "engine/guidance/post_processing.hpp"
#include "engine/guidance/assemble_steps.hpp"
#include "engine/guidance/lane_processing.hpp"
#include "engine/guidance/toolkit.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <algorithm>
@@ -385,7 +387,9 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
{
BOOST_ASSERT(!one_back_step.intersections.empty());
if (TurnType::Continue == current_step.maneuver.instruction.type ||
TurnType::Suppressed == current_step.maneuver.instruction.type)
(TurnType::Suppressed == current_step.maneuver.instruction.type &&
current_step.maneuver.instruction.direction_modifier !=
DirectionModifier::Straight))
steps[step_index].maneuver.instruction.type = TurnType::Turn;
else if (TurnType::Merge == current_step.maneuver.instruction.type)
{
@@ -399,6 +403,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
DirectionModifier::Straight &&
one_back_step.intersections.front().bearings.size() > 2)
steps[step_index].maneuver.instruction.type = TurnType::Turn;
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step);
// If the previous instruction asked to continue, the name change will have to
// be changed into a turn
@@ -416,9 +421,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
if ((TurnType::Continue == one_back_step.maneuver.instruction.type ||
TurnType::Suppressed == one_back_step.maneuver.instruction.type) &&
current_step.name_id != steps[two_back_index].name_id)
{
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
}
else if (TurnType::Turn == one_back_step.maneuver.instruction.type &&
current_step.name_id == steps[two_back_index].name_id)
{
@@ -497,11 +500,51 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
}
}
// Works on steps including silent and invalid instructions in order to do lane anticipation for
// roundabouts which later on get collapsed into a single multi-hop instruction.
std::vector<RouteStep> anticipateLaneChangeForRoundabouts(std::vector<RouteStep> steps)
{
using namespace util::guidance;
using StepIter = decltype(steps)::iterator;
using StepIterRange = std::pair<StepIter, StepIter>;
const auto anticipate_lanes_in_roundabout = [&](StepIterRange roundabout) {
// We do lane anticipation on the roundabout's enter and leave step only.
// TODO: This means, lanes _inside_ the roundabout are ignored at the moment.
auto enter = *roundabout.first;
const auto leave = *roundabout.second;
// Although the enter instruction may be a left/right turn, for right-sided driving the
// roundabout is counter-clockwise and therefore we need to always set it to a left turn.
// FIXME: assumes right-side driving (counter-clockwise roundabout flow)
const auto enter_direction = enter.maneuver.instruction.direction_modifier;
if (util::guidance::isRightTurn(enter.maneuver.instruction))
enter.maneuver.instruction.direction_modifier =
mirrorDirectionModifier(enter_direction);
// a roundabout is a continuous maneuver. We don't switch lanes within a roundabout, as long
// as it can be avoided.
auto enterAndLeave =
anticipateLaneChange({enter, leave}, std::numeric_limits<double>::max());
// Undo flipping direction on a right turn in a right-sided counter-clockwise roundabout.
// FIXME: assumes right-side driving (counter-clockwise roundabout flow)
enterAndLeave[0].maneuver.instruction.direction_modifier = enter_direction;
std::swap(*roundabout.first, enterAndLeave[0]);
std::swap(*roundabout.second, enterAndLeave[1]);
};
forEachRoundabout(begin(steps), end(steps), anticipate_lanes_in_roundabout);
return steps;
}
} // namespace
// Post processing can invalidate some instructions. For example StayOnRoundabout
// is turned into exit counts. These instructions are removed by the following function
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
{
// finally clean up the post-processed instructions.
@@ -517,6 +560,9 @@ std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
boost::remove_erase_if(steps, not_is_valid);
// the steps should still include depart and arrive at least
BOOST_ASSERT(steps.size() >= 2);
BOOST_ASSERT(steps.front().intersections.size() >= 1);
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
@@ -543,6 +589,11 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
if (steps.size() == 2)
return steps;
// Before we invalidate and remove silent instructions, we handle roundabouts (before they're
// getting collapsed into a single multi-hop instruction) by back-propagating exit lane
// constraints already to a roundabout's enter instruction.
steps = anticipateLaneChangeForRoundabouts(std::move(steps));
// Count Street Exits forward
bool on_roundabout = false;
bool has_entered_roundabout = false;
@@ -550,7 +601,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
// count the exits forward. if enter/exit roundabout happen both, no further treatment is
// required. We might end up with only one of them (e.g. starting within a roundabout)
// or having a via-point in the roundabout.
// In this case, exits are numbered from the start of the lag.
// In this case, exits are numbered from the start of the leg.
for (std::size_t step_index = 0; step_index < steps.size(); ++step_index)
{
auto &step = steps[step_index];
@@ -580,6 +631,10 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
has_entered_roundabout = false;
on_roundabout = false;
}
else if (on_roundabout && step_index + 1 < steps.size())
{
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
}
}
// unterminated roundabout
@@ -858,8 +913,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
// we need to make this conform with the intersection format for the first intersection
auto &first_intersection = designated_depart.intersections.front();
designated_depart.maneuver.lanes = util::guidance::LaneTupel();
designated_depart.maneuver.lane_description.clear();
designated_depart.intersections.front().lanes = util::guidance::LaneTupel();
designated_depart.intersections.front().lane_description.clear();
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
first_intersection.entry = {true};
first_intersection.in = Intersection::NO_INDEX;
@@ -926,8 +981,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
next_to_last_step.maneuver.bearing_after = 0;
next_to_last_step.maneuver.lanes = util::guidance::LaneTupel();
next_to_last_step.maneuver.lane_description.clear();
next_to_last_step.intersections.front().lanes = util::guidance::LaneTupel();
next_to_last_step.intersections.front().lane_description.clear();
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
auto &last_intersection = next_to_last_step.intersections.back();
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
@@ -1095,6 +1150,60 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
return removeNoTurnInstructions(std::move(steps));
}
std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps)
{
const auto containsTag = [](const extractor::guidance::TurnLaneType::Mask mask,
const extractor::guidance::TurnLaneType::Mask tag) {
return (mask & tag) != extractor::guidance::TurnLaneType::empty;
};
const auto getPreviousIndex = [&steps](std::size_t index) {
BOOST_ASSERT(index > 0);
BOOST_ASSERT(index < steps.size());
--index;
while (index > 0 && steps[index].maneuver.instruction.type == TurnType::NoTurn)
--index;
return index;
};
const auto canCollapeUseLane =
[containsTag](const util::guidance::LaneTupel lanes,
extractor::guidance::TurnLaneDescription lane_description) {
// the lane description is given left to right, lanes are counted from the right.
// Therefore we access the lane description yousing the reverse iterator
if (lanes.first_lane_from_the_right > 0 &&
containsTag(*(lane_description.rbegin() + (lanes.first_lane_from_the_right - 1)),
(extractor::guidance::TurnLaneType::straight |
extractor::guidance::TurnLaneType::none)))
return false;
const auto lane_to_the_right = lanes.first_lane_from_the_right + lanes.lanes_in_turn;
if (lane_to_the_right < boost::numeric_cast<int>(lane_description.size()) &&
containsTag(*(lane_description.rbegin() + lane_to_the_right),
(extractor::guidance::TurnLaneType::straight |
extractor::guidance::TurnLaneType::none)))
return false;
return true;
};
for (std::size_t step_index = 1; step_index < steps.size(); ++step_index)
{
const auto &step = steps[step_index];
if (step.maneuver.instruction.type == TurnType::UseLane &&
canCollapeUseLane(step.intersections.front().lanes,
step.intersections.front().lane_description))
{
const auto previous = getPreviousIndex(step_index);
steps[previous] = elongate(steps[previous], steps[step_index]);
//elongate(steps[step_index-1], steps[step_index]);
invalidateStep(steps[step_index]);
}
}
return removeNoTurnInstructions(std::move(steps));
}
} // namespace guidance
} // namespace engine
} // namespace osrm
+88 -15
View File
@@ -26,6 +26,8 @@
namespace
{
namespace oe = osrm::extractor;
// Needed for STXXL comparison - STXXL requires max_value(), min_value(), so we can not use
// std::less<OSMNodeId>{}. Anonymous namespace to keep translation unit local.
struct OSMNodeIDSTXXLLess
@@ -35,6 +37,69 @@ struct OSMNodeIDSTXXLLess
value_type max_value() { return MAX_OSM_NODEID; }
value_type min_value() { return MIN_OSM_NODEID; }
};
struct CmpEdgeByOSMStartID
{
using value_type = oe::InternalExtractorEdge;
bool operator()(const value_type &lhs, const value_type &rhs) const
{
return lhs.result.osm_source_id < rhs.result.osm_source_id;
}
value_type max_value() { return value_type::max_osm_value(); }
value_type min_value() { return value_type::min_osm_value(); }
};
struct CmpEdgeByOSMTargetID
{
using value_type = oe::InternalExtractorEdge;
bool operator()(const value_type &lhs, const value_type &rhs) const
{
return lhs.result.osm_target_id < rhs.result.osm_target_id;
}
value_type max_value() { return value_type::max_osm_value(); }
value_type min_value() { return value_type::min_osm_value(); }
};
struct CmpEdgeByInternalSourceTargetAndName
{
using value_type = oe::InternalExtractorEdge;
bool operator()(const value_type &lhs, const value_type &rhs) const
{
if (lhs.result.source != rhs.result.source)
return lhs.result.source < rhs.result.source;
if (lhs.result.target != rhs.result.target)
return lhs.result.target < rhs.result.target;
if (lhs.result.source == SPECIAL_NODEID)
return false;
if (lhs.result.name_id == rhs.result.name_id)
return false;
if (lhs.result.name_id == EMPTY_NAMEID)
return false;
if (rhs.result.name_id == EMPTY_NAMEID)
return true;
BOOST_ASSERT(!name_offsets.empty() && name_offsets.back() == name_data.size());
const oe::ExtractionContainers::STXXLNameCharData::const_iterator data = name_data.begin();
return std::lexicographical_compare(data + name_offsets[lhs.result.name_id],
data + name_offsets[lhs.result.name_id + 1],
data + name_offsets[rhs.result.name_id],
data + name_offsets[rhs.result.name_id + 1]);
}
value_type max_value() { return value_type::max_internal_value(); }
value_type min_value() { return value_type::min_internal_value(); }
const oe::ExtractionContainers::STXXLNameCharData &name_data;
const oe::ExtractionContainers::STXXLNameOffsets &name_offsets;
};
}
namespace osrm
@@ -48,10 +113,13 @@ ExtractionContainers::ExtractionContainers()
{
// Check if stxxl can be instantiated
stxxl::vector<unsigned> dummy_vector;
// Insert three empty strings for name, destination and pronunciation
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
// Insert three empty strings offsets for name, destination and pronunciation
name_offsets.push_back(0);
name_offsets.push_back(0);
name_offsets.push_back(0);
// Insert the total length sentinel (corresponds to the next name string offset)
name_offsets.push_back(0);
// the offsets have to be initialized with two values, since we have the empty turn string for
// the first id
@@ -90,7 +158,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
WriteCharData(name_file_name, name_lengths, name_char_data);
WriteCharData(name_file_name);
WriteTurnLaneMasks(turn_lane_file_name, turn_lane_offsets, turn_lane_masks);
}
catch (const std::exception &e)
@@ -125,23 +193,26 @@ void ExtractionContainers::WriteTurnLaneMasks(
util::SimpleLogger().Write() << "done (" << TIMER_SEC(turn_lane_timer) << ")";
}
void ExtractionContainers::WriteCharData(const std::string &file_name,
const stxxl::vector<unsigned> &offsets,
const stxxl::vector<char> &char_data) const
void ExtractionContainers::WriteCharData(const std::string &file_name)
{
std::cout << "[extractor] writing street name index ... " << std::flush;
TIMER_START(write_index);
boost::filesystem::ofstream file_stream(file_name, std::ios::binary);
unsigned total_length = 0;
for (const auto length : offsets)
// transforms in-place name offsets to name lengths
BOOST_ASSERT(!name_offsets.empty());
for (auto curr = name_offsets.begin(), next = name_offsets.begin() + 1;
next != name_offsets.end(); ++curr, ++next)
{
total_length += length;
*curr = *next - *curr;
}
// removes the total length sentinel
unsigned total_length = name_offsets.back();
name_offsets.pop_back();
// builds and writes the index
util::RangeTable<> index_range(offsets);
util::RangeTable<> index_range(name_offsets);
file_stream << index_range;
file_stream.write((char *)&total_length, sizeof(unsigned));
@@ -150,7 +221,7 @@ void ExtractionContainers::WriteCharData(const std::string &file_name,
char write_buffer[WRITE_BLOCK_BUFFER_SIZE];
unsigned buffer_len = 0;
for (const auto c : char_data)
for (const auto c : name_char_data)
{
write_buffer[buffer_len++] = c;
@@ -416,7 +487,7 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
TIMER_START(sort_edges_by_renumbered_start);
stxxl::sort(all_edges_list.begin(),
all_edges_list.end(),
CmpEdgeByInternalStartThenInternalTargetID(),
CmpEdgeByInternalSourceTargetAndName{name_char_data, name_offsets},
stxxl_memory);
TIMER_STOP(sort_edges_by_renumbered_start);
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s" << std::endl;
@@ -453,11 +524,13 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
all_edges_list[i].result.weight < min_forward_weight)
{
min_forward_idx = i;
min_forward_weight = all_edges_list[i].result.weight;
}
if (all_edges_list[i].result.backward &&
all_edges_list[i].result.weight < min_backward_weight)
{
min_backward_idx = i;
min_backward_weight = all_edges_list[i].result.weight;
}
// this also increments the outer loop counter!
+9 -8
View File
@@ -507,8 +507,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
std::vector<std::uint32_t> turn_lane_offsets;
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
if( !util::deserializeAdjacencyArray(
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks) )
if (!util::deserializeAdjacencyArray(
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks))
{
util::SimpleLogger().Write(logWARNING) << "Reading Turn Lane Masks failed.";
}
@@ -673,7 +673,7 @@ void Extractor::WriteIntersectionClassificationData(
util::RangeTable<> bearing_class_range_table(bearing_counts);
file_out_stream << bearing_class_range_table;
file_out_stream << total_bearings;
file_out_stream.write(reinterpret_cast<const char *>(&total_bearings), sizeof(total_bearings));
for (const auto &bearing_class : bearing_classes)
{
const auto &bearings = bearing_class.getAvailableBearings();
@@ -681,17 +681,18 @@ void Extractor::WriteIntersectionClassificationData(
sizeof(bearings[0]) * bearings.size());
}
// FIXME
// This should be here, but g++4.8 does not have it...
// static_assert(std::is_trivially_copyable<util::guidance::EntryClass>::value,
// "EntryClass Serialization requires trivial copyable entry classes");
if (!static_cast<bool>(file_out_stream))
{
throw util::exception("Failed to write to " + output_file_name + ".");
}
util::serializeVector(file_out_stream, entry_classes);
TIMER_STOP(write_edges);
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
<< node_based_intersection_classes.size() << " Indices into "
<< bearing_classes.size() << " bearing classes and "
<< entry_classes.size() << " entry classes";
<< entry_classes.size() << " entry classes and " << total_bearings
<< " bearing values." << std::endl;
}
}
}
+42 -32
View File
@@ -1,8 +1,8 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/restriction.hpp"
#include "util/for_each_pair.hpp"
@@ -154,7 +154,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
TurnLaneDescription lane_description;
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|&", "", boost::keep_empty_tokens);
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
boost::char_separator<char> inner_sep(";", "");
tokenizer tokens(lane_string, sep);
@@ -193,7 +193,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end();
++token_itr)
{
auto position = std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr);
auto position =
std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr);
const auto translated_mask =
masks_by_osm_string[std::distance(osm_lane_strings, position)];
if (translated_mask == TurnLaneType::empty)
@@ -203,7 +204,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
<< *token_itr << "\"";
return {};
}
BOOST_ASSERT((lane_mask & translated_mask) == 0); // make sure the mask is valid
// In case of multiple times the same lane indicators withn a lane, as in
// "left;left|.." or-ing the masks generates a single "left" enum.
// Which is fine since this is data issue and we can't represent it anyway.
lane_mask |= translated_mask;
}
// add the lane to the description
@@ -215,7 +219,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
// convert the lane description into an ID and, if necessary, remembr the description in the
// description_map
const auto requestId = [&](std::string lane_string) {
if( lane_string.empty() )
if (lane_string.empty())
return INVALID_LANE_DESCRIPTIONID;
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
@@ -253,33 +257,35 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
// Get the unique identifier for the street name
// Get the unique identifier for the street name and destination
const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations));
unsigned name_id = external_memory.name_lengths.size();
unsigned name_id = EMPTY_NAMEID;
if (string_map.end() == name_iterator)
{
auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size());
auto destinations_length =
const auto name_length = std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.name.size());
const auto destinations_length =
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.destinations.size());
auto pronunciation_length =
const auto pronunciation_length =
std::min<unsigned>(MAX_STRING_LENGTH, parsed_way.pronunciation.size());
external_memory.name_char_data.reserve(name_id + name_length + destinations_length +
pronunciation_length);
// name_offsets already has an offset of a new name, take the offset index as the name id
name_id = external_memory.name_offsets.size() - 1;
external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length +
destinations_length + pronunciation_length);
std::copy(parsed_way.name.c_str(),
parsed_way.name.c_str() + name_length,
std::back_inserter(external_memory.name_char_data));
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
std::copy(parsed_way.destinations.c_str(),
parsed_way.destinations.c_str() + destinations_length,
std::back_inserter(external_memory.name_char_data));
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
std::copy(parsed_way.pronunciation.c_str(),
parsed_way.pronunciation.c_str() + pronunciation_length,
std::back_inserter(external_memory.name_char_data));
external_memory.name_lengths.push_back(name_length);
external_memory.name_lengths.push_back(destinations_length);
external_memory.name_lengths.push_back(pronunciation_length);
external_memory.name_offsets.push_back(external_memory.name_char_data.size());
auto k = MapKey{parsed_way.name, parsed_way.destinations};
auto v = MapVal{name_id};
@@ -304,7 +310,9 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
std::transform(input_way.nodes().begin(),
input_way.nodes().end(),
std::back_inserter(external_memory.used_node_id_list),
[](const osmium::NodeRef &ref) { return OSMNodeID{static_cast<std::uint64_t>(ref.ref())}; });
[](const osmium::NodeRef &ref) {
return OSMNodeID{static_cast<std::uint64_t>(ref.ref())};
});
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
@@ -336,7 +344,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
external_memory.way_start_end_id_list.push_back(
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
OSMNodeID{
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
}
@@ -370,27 +379,28 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
input_way.nodes().cbegin(),
input_way.nodes().cend(),
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
external_memory.all_edges_list.push_back(
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
name_id,
backward_weight_data,
false,
true,
parsed_way.roundabout,
parsed_way.is_access_restricted,
parsed_way.is_startpoint,
parsed_way.backward_travel_mode,
true,
turn_lane_id_backward,
road_classification));
external_memory.all_edges_list.push_back(InternalExtractorEdge(
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
name_id,
backward_weight_data,
false,
true,
parsed_way.roundabout,
parsed_way.is_access_restricted,
parsed_way.is_startpoint,
parsed_way.backward_travel_mode,
true,
turn_lane_id_backward,
road_classification));
});
}
external_memory.way_start_end_id_list.push_back(
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes().back().ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
OSMNodeID{
static_cast<std::uint64_t>(input_way.nodes()[input_way.nodes().size() - 2].ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[1].ref())},
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
}
@@ -143,7 +143,20 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
const auto valid_count =
boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; });
if (0 == valid_count && uturn_could_be_valid)
intersection[0].entry_allowed = true;
{
// after intersections sorting by angles, find the u-turn with (from_node == to_node)
// that was inserted together with setting uturn_could_be_valid flag
std::size_t self_u_turn = 0;
while (self_u_turn < intersection.size()
&& intersection[self_u_turn].turn.angle < std::numeric_limits<double>::epsilon()
&& from_node != node_based_graph.GetTarget(intersection[self_u_turn].turn.eid))
{
++self_u_turn;
}
BOOST_ASSERT(from_node == node_based_graph.GetTarget(intersection[self_u_turn].turn.eid));
intersection[self_u_turn].entry_allowed = true;
}
return mergeSegregatedRoads(std::move(intersection));
}
@@ -34,7 +34,7 @@ IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node
{
}
IntersectionHandler::~IntersectionHandler() {}
IntersectionHandler::~IntersectionHandler() = default;
std::size_t IntersectionHandler::countValid(const Intersection &intersection) const
{
+1 -1
View File
@@ -47,7 +47,7 @@ MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_g
{
}
MotorwayHandler::~MotorwayHandler() {}
MotorwayHandler::~MotorwayHandler() = default;
bool MotorwayHandler::canProcess(const NodeID,
const EdgeID via_eid,
@@ -31,7 +31,7 @@ RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_bas
{
}
RoundaboutHandler::~RoundaboutHandler() {}
RoundaboutHandler::~RoundaboutHandler() = default;
bool RoundaboutHandler::canProcess(const NodeID from_nid,
const EdgeID via_eid,
+13 -8
View File
@@ -1,7 +1,7 @@
#include "extractor/guidance/turn_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_scenario_three_way.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_handler.hpp"
#include "util/guidance/toolkit.hpp"
@@ -29,7 +29,7 @@ TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
{
}
TurnHandler::~TurnHandler() {}
TurnHandler::~TurnHandler() = default;
bool TurnHandler::canProcess(const NodeID, const EdgeID, const Intersection &) const
{
@@ -88,18 +88,20 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
const bool is_ramp = isRampClass(first_class);
const bool is_obvious_by_road_class =
(!is_ramp && (2 * getPriority(first_class) < getPriority(second_class))) ||
(!is_ramp && (2 * getPriority(first_class) < getPriority(second_class)) &&
in_data.road_classification.road_class == first_class) ||
(!isLowPriorityRoadClass(first_class) && isLowPriorityRoadClass(second_class));
if (is_obvious_by_road_class)
return true;
const bool other_is_obvious_by_road_flass =
const bool other_is_obvious_by_road_class =
(!isRampClass(second_class) &&
(2 * getPriority(second_class) < getPriority(first_class))) ||
(2 * getPriority(second_class) < getPriority(first_class)) &&
in_data.road_classification.road_class == second_class) ||
(!isLowPriorityRoadClass(second_class) && isLowPriorityRoadClass(first_class));
if (other_is_obvious_by_road_flass)
if (other_is_obvious_by_road_class)
return false;
const bool turn_is_perfectly_straight = angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <
@@ -375,6 +377,7 @@ std::size_t TurnHandler::findObviousTurn(const EdgeID via_edge,
double best_continue_deviation = 180;
const EdgeData &in_data = node_based_graph.GetEdgeData(via_edge);
const auto in_class = in_data.road_classification.road_class;
for (std::size_t i = 1; i < intersection.size(); ++i)
{
const double deviation = angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
@@ -388,9 +391,11 @@ std::size_t TurnHandler::findObviousTurn(const EdgeID via_edge,
auto continue_class = node_based_graph.GetEdgeData(intersection[best_continue].turn.eid)
.road_classification.road_class;
if (intersection[i].entry_allowed && out_data.name_id == in_data.name_id &&
(best_continue == 0 || continue_class > out_data.road_classification.road_class ||
(best_continue == 0 || (continue_class > out_data.road_classification.road_class &&
in_class != continue_class) ||
(deviation < best_continue_deviation &&
out_data.road_classification.road_class == continue_class)))
(out_data.road_classification.road_class == continue_class ||
in_class == out_data.road_classification.road_class))))
{
best_continue_deviation = deviation;
best_continue = i;
@@ -120,7 +120,7 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
}
}
lane_data.erase(lane_data.begin() + none_index);
return std::move(lane_data);
return lane_data;
}
// Merging none-tag into its neighboring fields
@@ -146,7 +146,7 @@ LaneDataVector mergeNoneTag(const std::size_t none_index, LaneDataVector lane_da
lane_data.erase(lane_data.begin() + none_index);
}
return std::move(lane_data);
return lane_data;
}
LaneDataVector handleRenamingSituations(const std::size_t none_index,
@@ -222,7 +222,7 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
lane_data[none_index].tag = TurnLaneType::straight;
}
}
return std::move(lane_data);
return lane_data;
}
} // namespace
@@ -239,7 +239,7 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
(intersection.empty() || lane_data.empty() || !hasTag(TurnLaneType::none, lane_data));
if (needs_no_processing)
return std::move(lane_data);
return lane_data;
// FIXME all this needs to consider the number of lanes at the target to ensure that we
// augment lanes correctly, if the target lane allows for more turns
@@ -282,7 +282,14 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
// a pgerequisite is simple turns. Larger differences should not end up here
// an additional line at the side is only reasonable if it is targeting public
// service vehicles. Otherwise, we should not have it
BOOST_ASSERT(connection_count + 1 == lane_data.size());
//
// TODO(mokob): #2730 have a look please
// BOOST_ASSERT(connection_count + 1 == lane_data.size());
//
if (connection_count + 1 != lane_data.size())
{
goto these_intersections_are_clearly_broken_at_the_moment;
}
lane_data = mergeNoneTag(none_index, std::move(lane_data));
}
@@ -292,9 +299,12 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
{
lane_data = handleRenamingSituations(none_index, std::move(lane_data), intersection);
}
these_intersections_are_clearly_broken_at_the_moment:
// finally make sure we are still sorted
std::sort(lane_data.begin(), lane_data.end());
return std::move(lane_data);
return lane_data;
}
} // namespace lanes
@@ -45,11 +45,6 @@ bool TurnLaneData::operator<(const TurnLaneData &other) const
LaneDataVector laneDataFromDescription(const TurnLaneDescription &turn_lane_description)
{
typedef std::unordered_map<TurnLaneType::Mask, std::pair<LaneID, LaneID>> LaneMap;
// FIXME this is a workaround due to https://github.com/cucumber/cucumber-js/issues/417,
// need to switch statements when fixed
// const auto num_lanes = std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1;
// count the number of lanes
const auto num_lanes = boost::numeric_cast<LaneID>(turn_lane_description.size());
const auto setLaneData = [&](
LaneMap &map, TurnLaneType::Mask full_mask, const LaneID current_lane) {
+18 -12
View File
@@ -65,7 +65,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
{
//if only a uturn exists, there is nothing we can do
if( intersection.size() == 1 )
return std::move(intersection);
return intersection;
const auto &data = node_based_graph.GetEdgeData(via_edge);
// Extract a lane description for the ID
@@ -85,19 +85,19 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
data.lane_description_id ==
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_description_id) ||
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE))
return std::move(intersection);
return intersection;
auto lane_data = laneDataFromDescription(turn_lane_description);
// if we see an invalid conversion, we stop immediately
if (!turn_lane_description.empty() && lane_data.empty())
return std::move(intersection);
return intersection;
// might be reasonable to handle multiple turns, if we know of a sequence of lanes
// e.g. one direction per lane, if three lanes and right, through, left available
if (!turn_lane_description.empty() && lane_data.size() == 1 &&
lane_data[0].tag == TurnLaneType::none)
return std::move(intersection);
return intersection;
const std::size_t possible_entries = getNumberOfTurns(intersection);
@@ -114,7 +114,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
lane_data.size() + 1 == possible_entries);
if (has_merge_lane || has_non_usable_u_turn)
return std::move(intersection);
return intersection;
if (!lane_data.empty() && canMatchTrivially(intersection, lane_data) &&
lane_data.size() !=
@@ -165,7 +165,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection), id_map);
}
return std::move(intersection);
return intersection;
}
// At segregated intersections, turn lanes will often only be specified up until the first turn. To
@@ -221,11 +221,11 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
// no lane string, no problems
if (previous_lane_description.empty())
return std::move(intersection);
return intersection;
// stop on invalid lane data conversion
if (lane_data.empty())
return std::move(intersection);
return intersection;
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
const auto is_simple = isSimpleIntersection(lane_data, intersection);
@@ -257,7 +257,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
}
}
}
return std::move(intersection);
return intersection;
}
/* A simple intersection does not depend on the next intersection coming up. This is important
@@ -351,8 +351,14 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
if (lane_data.back().tag == TurnLaneType::uturn)
return findBestMatchForReverse(lane_data[lane_data.size() - 2].tag, intersection);
BOOST_ASSERT(lane_data.front().tag == TurnLaneType::uturn);
return findBestMatchForReverse(lane_data[1].tag, intersection);
// TODO(mokob): #2730 have a look please
// BOOST_ASSERT(lane_data.front().tag == TurnLaneType::uturn);
// return findBestMatchForReverse(lane_data[1].tag, intersection);
//
if (lane_data.front().tag == TurnLaneType::uturn)
return findBestMatchForReverse(lane_data[1].tag, intersection);
return findBestMatch(data.tag, intersection);
}();
std::size_t match_index = std::distance(intersection.begin(), best_match);
all_simple &= (matched_indices.count(match_index) == 0);
@@ -522,7 +528,7 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
LaneDataIdMap &id_map) const
{
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
return std::move(intersection);
return intersection;
BOOST_ASSERT(
!hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right,
+2 -2
View File
@@ -236,7 +236,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
DirectionModifier::SharpLeft)
{
// cannot match u-turn in a valid way
return std::move(intersection);
return intersection;
}
u_turn = intersection.size() - 1;
}
@@ -246,7 +246,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
matchRoad(intersection[u_turn], lane_data.back());
}
return std::move(intersection);
return intersection;
}
} // namespace lane_matching
+1
View File
@@ -49,6 +49,7 @@ void RequestHandler::HandleRequest(const http::request &current_request, http::r
{
std::string request_string;
util::URIDecode(current_request.uri, request_string);
util::SimpleLogger().Write(logDEBUG) << "req: " << request_string;
auto api_iterator = request_string.begin();
auto maybe_parsed_url = api::parseURL(api_iterator, request_string.end());
+2 -2
View File
@@ -152,7 +152,7 @@ int Storage::Run()
if (!util::deserializeAdjacencyArray(config.turn_lane_description_path.string(),
lane_description_offsets,
lane_description_masks))
throw util::exception("Could not open read lane descriptions from: " +
throw util::exception("Failed to read lane descriptions from: " +
config.turn_lane_description_path.string());
shared_layout_ptr->SetBlockSize<std::uint32_t>(SharedDataLayout::LANE_DESCRIPTION_OFFSETS,
lane_description_offsets.size());
@@ -375,7 +375,7 @@ int Storage::Run()
}
std::uint64_t num_bearings;
intersection_stream >> num_bearings;
intersection_stream.read(reinterpret_cast<char*>(&num_bearings),sizeof(num_bearings));
std::vector<DiscreteBearing> bearing_class_table(num_bearings);
intersection_stream.read(reinterpret_cast<char *>(&bearing_class_table[0]),
+3 -13
View File
@@ -2,6 +2,7 @@
#include <algorithm>
#include <iostream>
#include <tuple>
#include <boost/assert.hpp>
@@ -24,23 +25,12 @@ LaneTupel::LaneTupel(const LaneID lanes_in_turn, const LaneID first_lane_from_th
// comparation based on interpretation as unsigned 32bit integer
bool LaneTupel::operator==(const LaneTupel other) const
{
static_assert(sizeof(LaneTupel) == sizeof(std::uint16_t),
"Comparation requires LaneTupel to be the of size 16Bit");
return *reinterpret_cast<const std::uint16_t *>(this) ==
*reinterpret_cast<const std::uint16_t *>(&other);
return std::tie(lanes_in_turn, first_lane_from_the_right) ==
std::tie(other.lanes_in_turn, other.first_lane_from_the_right);
}
bool LaneTupel::operator!=(const LaneTupel other) const { return !(*this == other); }
// comparation based on interpretation as unsigned 32bit integer
bool LaneTupel::operator<(const LaneTupel other) const
{
static_assert(sizeof(LaneTupel) == sizeof(std::uint16_t),
"Comparation requires LaneTupel to be the of size 16Bit");
return *reinterpret_cast<const std::uint16_t *>(this) <
*reinterpret_cast<const std::uint16_t *>(&other);
}
} // namespace guidance
} // namespace util
} // namespace osrm