Compare commits
31 Commits
v5.3.0-rc.3
...
v5.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a22e7da2b | |||
| 40a86d43cd | |||
| 68d20c6ccc | |||
| fe491bf92c | |||
| 7b432b34bb | |||
| 6983cd0de2 | |||
| fe8177077c | |||
| 5f339f4ed6 | |||
| 3c0b52c637 | |||
| 877fc5b42c | |||
| e28785e399 | |||
| 2c4a54ce05 | |||
| a8afc74590 | |||
| d195eee7c4 | |||
| 9b737230d6 | |||
| ecbd709535 | |||
| 060ec99678 | |||
| 3601d1d262 | |||
| 41ba20ca9a | |||
| 57e3f173d3 | |||
| 92c298c7cf | |||
| b25011ee60 | |||
| 0e017a6ce5 | |||
| 2431e15ffa | |||
| 396add1e9d | |||
| 86241a2793 | |||
| ee47afbe17 | |||
| 8831ca2f32 | |||
| abde215bc3 | |||
| 130d5298fc | |||
| 50cbba1620 |
+5
-4
@@ -13,6 +13,7 @@ notifications:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- "5.3"
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
ccache: true
|
ccache: true
|
||||||
@@ -24,6 +25,7 @@ env:
|
|||||||
global:
|
global:
|
||||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||||
- CCACHE_COMPRESS=1
|
- CCACHE_COMPRESS=1
|
||||||
|
- CASHER_TIME_OUT=1000
|
||||||
- JOBS=4
|
- JOBS=4
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
@@ -75,10 +77,9 @@ matrix:
|
|||||||
compiler: "gcc-5-release-i686"
|
compiler: "gcc-5-release-i686"
|
||||||
env: TARGET_ARCH='i686' CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
|
env: TARGET_ARCH='i686' CCOMPILER='gcc-5' CXXCOMPILER='g++-5' BUILD_TYPE='Release'
|
||||||
|
|
||||||
# FIXME disabled until sourceforge fixes its packages for stxxl
|
- os: linux
|
||||||
#- os: linux
|
compiler: "gcc-4.8-release-armhf"
|
||||||
#- compiler: "gcc-4.8-release-armhf"
|
env: TARGET_ARCH='armhf' CCOMPILER='arm-linux-gnueabihf-gcc-4.8' CXXCOMPILER='arm-linux-gnueabihf-g++-4.8' BUILD_TYPE='Release'
|
||||||
#- env: TARGET_ARCH='armhf' CCOMPILER='arm-linux-gnueabihf-gcc-4.8' CXXCOMPILER='arm-linux-gnueabihf-g++-4.8' BUILD_TYPE='Release'
|
|
||||||
|
|
||||||
# Disabled because of CI slowness
|
# Disabled because of CI slowness
|
||||||
#- os: linux
|
#- os: linux
|
||||||
|
|||||||
@@ -1,3 +1,46 @@
|
|||||||
|
# 5.3.2
|
||||||
|
Changes from 5.3.1
|
||||||
|
- Bugfixes
|
||||||
|
- fixed a bug that occurred when trimming very short segments at the begin/end of a route (less than 1 meter)
|
||||||
|
|
||||||
|
# 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
|
# 5.3.0 RC3
|
||||||
Changes from 5.3.0-rc.2
|
Changes from 5.3.0-rc.2
|
||||||
- Guidance
|
- Guidance
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ endif()
|
|||||||
project(OSRM C CXX)
|
project(OSRM C CXX)
|
||||||
set(OSRM_VERSION_MAJOR 5)
|
set(OSRM_VERSION_MAJOR 5)
|
||||||
set(OSRM_VERSION_MINOR 3)
|
set(OSRM_VERSION_MINOR 3)
|
||||||
set(OSRM_VERSION_PATCH 0)
|
set(OSRM_VERSION_PATCH 2)
|
||||||
|
|
||||||
# these two functions build up custom variables:
|
# these two functions build up custom variables:
|
||||||
# OSRM_INCLUDE_PATHS and OSRM_DEFINES
|
# OSRM_INCLUDE_PATHS and OSRM_DEFINES
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ osrm-routed data.osrm
|
|||||||
Running a query on your local server:
|
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
|
### 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:
|
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
|
## References in publications
|
||||||
|
|||||||
+4
-13
@@ -1,18 +1,9 @@
|
|||||||
FROM ubuntu:14.04
|
FROM ubuntu:14.04
|
||||||
|
|
||||||
RUN apt-get update -y
|
RUN apt-get update -y && apt-get install -y software-properties-common
|
||||||
RUN apt-get install -y build-essential git-core python-pip python-software-properties 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 gcc-4.8 g++-4.8 libboost1.55-all-dev llvm-3.4
|
RUN apt-get -y install curl cmake cmake-curses-gui git
|
||||||
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
|
|
||||||
|
|
||||||
WORKDIR /opt
|
WORKDIR /opt
|
||||||
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
|
RUN git clone --depth 1 --branch v0.31.0 https://github.com/creationix/nvm.git
|
||||||
|
|||||||
+2
-1
@@ -5,7 +5,8 @@ set -o pipefail
|
|||||||
|
|
||||||
docker run \
|
docker run \
|
||||||
-i \
|
-i \
|
||||||
-e "CXX=g++" \
|
-e "CXX=g++-5" \
|
||||||
|
-e "CC=gcc-5" \
|
||||||
-v `pwd`:/home/mapbox/osrm-backend \
|
-v `pwd`:/home/mapbox/osrm-backend \
|
||||||
-t mapbox/osrm:linux \
|
-t mapbox/osrm:linux \
|
||||||
/bin/bash -lc "osrm-backend/docker/test.sh"
|
/bin/bash -lc "osrm-backend/docker/test.sh"
|
||||||
|
|||||||
+21
-12
@@ -453,24 +453,28 @@ step.
|
|||||||
"maneuver":{
|
"maneuver":{
|
||||||
"type":"turn",
|
"type":"turn",
|
||||||
"modifier":"right",
|
"modifier":"right",
|
||||||
"lanes":[
|
},
|
||||||
{"indications":["left","straight"], "valid":"false"},
|
|
||||||
{"indications":["right"], "valid":"true"}
|
|
||||||
]},
|
|
||||||
"geometry":"{lu_IypwpAVrAvAdI",
|
"geometry":"{lu_IypwpAVrAvAdI",
|
||||||
"mode":"driving",
|
"mode":"driving",
|
||||||
"intersections":[
|
"intersections":[
|
||||||
{"location":[13.39677,52.54366],
|
{"location":[13.39677,52.54366],
|
||||||
"in":3,
|
"in":3,
|
||||||
"out":1,
|
"out":2,
|
||||||
"bearings":[10,92,184,270],
|
"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],
|
{"location":[13.394718,52.543096],
|
||||||
"in":0,
|
"in":0,
|
||||||
"out":2,
|
"out":1,
|
||||||
"bearings":[60,150,240,330],
|
"bearings":[60,240,330],
|
||||||
"entry":["false","true","true","true"]
|
"entry":["false","true","true"]
|
||||||
}
|
"lanes":[
|
||||||
|
{"indications":["straight"], "valid":"true"},
|
||||||
|
{"indications":["right"], "valid":"false"}
|
||||||
|
]}
|
||||||
]}
|
]}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -536,8 +540,7 @@ step.
|
|||||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
|
| `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` |
|
| 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.
|
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
|
||||||
|
|
||||||
@@ -588,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.
|
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
|
- `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.
|
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
|
#### Example
|
||||||
```
|
```
|
||||||
@@ -597,6 +601,11 @@ location of the StepManeuver. Further intersections are listed for every cross-w
|
|||||||
"out":2,
|
"out":2,
|
||||||
"bearings":[60,150,240,330],
|
"bearings":[60,150,240,330],
|
||||||
"entry":["false","true","true","true"]
|
"entry":["false","true","true","true"]
|
||||||
|
"lanes":{
|
||||||
|
"indications": ["left", "straight"],
|
||||||
|
"valid": "false"
|
||||||
|
}
|
||||||
|
]}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -135,9 +135,9 @@ Feature: Turn Lane Guidance
|
|||||||
| cj | | 1 | motorway_link | yes | xbcj |
|
| cj | | 1 | motorway_link | yes | xbcj |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |
|
| 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, |
|
| a,j | ab,xbcj,xbcj | depart,merge slight left,arrive | ,, |
|
||||||
|
|
||||||
|
|
||||||
@anticipate
|
@anticipate
|
||||||
@@ -259,8 +259,8 @@ Feature: Turn Lane Guidance
|
|||||||
| waypoints | route | turns | lanes |
|
| 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, |
|
| 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
|
@anticipate @todo @bug @2661
|
||||||
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
|
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
|
||||||
Given the node map
|
Given the node map
|
||||||
| | | e | | |
|
| | | e | | |
|
||||||
| a | b | | d | f |
|
| a | b | | d | f |
|
||||||
@@ -365,6 +365,62 @@ Feature: Turn Lane Guidance
|
|||||||
| x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,slight right:true 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, |
|
| 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
|
@anticipate
|
||||||
Scenario: Anticipate Lanes for turns before and / or after roundabout
|
Scenario: Anticipate Lanes for turns before and / or after roundabout
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@@ -128,3 +128,36 @@ Feature: End Of Road Instructions
|
|||||||
| a,c | aeb,bc,bc | depart,on ramp left,arrive |
|
| a,c | aeb,bc,bc | depart,on ramp left,arrive |
|
||||||
| a,d | aeb,bd,bd | depart,on ramp right,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 |
|
||||||
|
|||||||
@@ -437,3 +437,42 @@ Feature: Basic Roundabout
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,k | massachusetts,massachusetts,massachusetts,massachusetts | depart,sheridan circle-exit-2,dupont circle-exit-1,arrive |
|
| 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 |
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
@routing @guidance @post-processing
|
||||||
|
Feature: General Post-Processing related features
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
Given a grid size of 0.1 meters
|
||||||
|
|
||||||
|
# this testcase used to crash geometry generation (at that time handled during intersection generation)
|
||||||
|
Scenario: Regression Test 2754
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | d | e | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | | | f | g | h | i | j |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abcde |
|
||||||
|
| ef |
|
||||||
|
| fghij |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route |
|
||||||
|
| a,j | ef,ef |
|
||||||
@@ -87,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
|
#this next test requires decision on how to announce lanes for going straight if there is no turn
|
||||||
@TODO
|
|
||||||
Scenario: Turn with Bus-Lane
|
Scenario: Turn with Bus-Lane
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | | b | | c |
|
| a | | b | | c |
|
||||||
@@ -101,9 +100,9 @@ Feature: Turn Lane Guidance
|
|||||||
| bd | turn | | |
|
| bd | turn | | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
|
| 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, |
|
| a,c | road,road | depart,arrive | , |
|
||||||
|
|
||||||
@PROFILE @LANES
|
@PROFILE @LANES
|
||||||
Scenario: Turn with Bus-Lane but without lanes
|
Scenario: Turn with Bus-Lane but without lanes
|
||||||
@@ -194,13 +193,13 @@ Feature: Turn Lane Guidance
|
|||||||
| fl | cross | | yes |
|
| fl | cross | | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
|
| 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, |
|
| 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, |
|
| 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,h | cross,road,road | depart,turn right,arrive | ,, |
|
||||||
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight:true, |
|
| i,j | cross,cross | depart,arrive | , |
|
||||||
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
|
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
|
||||||
|
|
||||||
Scenario: Turn Lanes at Segregated Road
|
Scenario: Turn Lanes at Segregated Road
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -238,9 +237,9 @@ Feature: Turn Lane Guidance
|
|||||||
| ce | turn | |
|
| ce | turn | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, |
|
| 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, |
|
| a,d | road,road | depart,arrive | , |
|
||||||
|
|
||||||
Scenario: Turn Lanes Given earlier than actual turn
|
Scenario: Turn Lanes Given earlier than actual turn
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -258,11 +257,11 @@ Feature: Turn Lane Guidance
|
|||||||
| hk | second-turn | | |
|
| hk | second-turn | | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, |
|
| 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, |
|
| a,i | road,road | depart,arrive | , |
|
||||||
| i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none: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, |
|
| i,a | road,road | depart,arrive | , |
|
||||||
|
|
||||||
Scenario: Passing a one-way street
|
Scenario: Passing a one-way street
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -358,9 +357,9 @@ Feature: Turn Lane Guidance
|
|||||||
| ce | turn | |
|
| ce | turn | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,d | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, |
|
| a,d | road,road | depart,arrive | , |
|
||||||
| a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
|
| a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
|
||||||
|
|
||||||
@bug @todo
|
@bug @todo
|
||||||
Scenario: Theodor Heuss Platz
|
Scenario: Theodor Heuss Platz
|
||||||
@@ -422,9 +421,9 @@ Feature: Turn Lane Guidance
|
|||||||
| restriction | bc | fdcg | c | no_right_turn |
|
| restriction | bc | fdcg | c | no_right_turn |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, |
|
| 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, |
|
| a,e | road,road | depart,arrive | , |
|
||||||
|
|
||||||
Scenario: U-Turn Road at Intersection
|
Scenario: U-Turn Road at Intersection
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -445,11 +444,11 @@ Feature: Turn Lane Guidance
|
|||||||
| gdeh | cross | | no | primary |
|
| gdeh | cross | | no | primary |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | bearings | route | turns | lanes |
|
| 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 | 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 | 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, |
|
| 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, |
|
| 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
|
Scenario: Segregated Intersection Merges With Lanes
|
||||||
Given the node map
|
Given the node map
|
||||||
@@ -519,7 +518,7 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| 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, |
|
| a,e | road,cross,cross | depart,turn slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
|
||||||
|
|
||||||
Scenario: Highway Ramp
|
Scenario: Highway Ramp
|
||||||
@@ -535,7 +534,7 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| 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, |
|
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
|
||||||
|
|
||||||
@bug @todo
|
@bug @todo
|
||||||
@@ -575,7 +574,7 @@ Feature: Turn Lane Guidance
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| 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, |
|
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false slight right:true, |
|
||||||
|
|
||||||
Scenario: Reverse Lane in Segregated Road
|
Scenario: Reverse Lane in Segregated Road
|
||||||
@@ -681,6 +680,169 @@ Feature: Turn Lane Guidance
|
|||||||
| ab | on | motorway_link | |
|
| ab | on | motorway_link | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | lanes |
|
| waypoints | route | turns | lanes |
|
||||||
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, |
|
| 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, |
|
| 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
|
||||||
|
|||||||
@@ -170,9 +170,9 @@ module.exports = function () {
|
|||||||
|
|
||||||
this.lanesList = (instructions) => {
|
this.lanesList = (instructions) => {
|
||||||
return this.extractInstructionList(instructions, instruction => {
|
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
|
} else
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ class RouteAPI : public BaseAPI
|
|||||||
phantoms.source_phantom,
|
phantoms.source_phantom,
|
||||||
phantoms.target_phantom);
|
phantoms.target_phantom);
|
||||||
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
|
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);
|
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;
|
std::vector<util::guidance::BearingClass> bearing_classes;
|
||||||
// and the actual bearing values
|
// and the actual bearing values
|
||||||
std::uint64_t num_bearings;
|
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);
|
m_bearing_values_table.resize(num_bearings);
|
||||||
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
|
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
|
||||||
sizeof(m_bearing_values_table[0]) * num_bearings);
|
sizeof(m_bearing_values_table[0]) * num_bearings);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
||||||
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
#include "extractor/travel_mode.hpp"
|
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
|
#include "extractor/travel_mode.hpp"
|
||||||
#include "engine/datafacade/datafacade_base.hpp"
|
#include "engine/datafacade/datafacade_base.hpp"
|
||||||
#include "engine/guidance/leg_geometry.hpp"
|
#include "engine/guidance/leg_geometry.hpp"
|
||||||
#include "engine/guidance/route_step.hpp"
|
#include "engine/guidance/route_step.hpp"
|
||||||
@@ -72,14 +72,15 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
bearings.second,
|
bearings.second,
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
WaypointType::Depart,
|
WaypointType::Depart,
|
||||||
0,
|
0};
|
||||||
util::guidance::LaneTupel(),
|
|
||||||
{}};
|
|
||||||
Intersection intersection{source_node.location,
|
Intersection intersection{source_node.location,
|
||||||
std::vector<short>({bearings.second}),
|
std::vector<short>({bearings.second}),
|
||||||
std::vector<bool>({true}),
|
std::vector<bool>({true}),
|
||||||
Intersection::NO_INDEX,
|
Intersection::NO_INDEX,
|
||||||
0};
|
0,
|
||||||
|
util::guidance::LaneTupel(),
|
||||||
|
{}};
|
||||||
|
|
||||||
if (leg_data.size() > 0)
|
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.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
||||||
intersection.bearings.clear();
|
intersection.bearings.clear();
|
||||||
intersection.bearings.reserve(bearing_class.getAvailableBearings().size());
|
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(),
|
std::copy(bearing_class.getAvailableBearings().begin(),
|
||||||
bearing_class.getAvailableBearings().end(),
|
bearing_class.getAvailableBearings().end(),
|
||||||
std::back_inserter(intersection.bearings));
|
std::back_inserter(intersection.bearings));
|
||||||
@@ -151,11 +157,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
bearings.second,
|
bearings.second,
|
||||||
path_point.turn_instruction,
|
path_point.turn_instruction,
|
||||||
WaypointType::None,
|
WaypointType::None,
|
||||||
0,
|
0};
|
||||||
path_point.lane_data.first,
|
|
||||||
(path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
|
|
||||||
? facade.GetTurnDescription(path_point.lane_data.second)
|
|
||||||
: extractor::guidance::TurnLaneDescription())};
|
|
||||||
segment_index++;
|
segment_index++;
|
||||||
segment_duration = 0;
|
segment_duration = 0;
|
||||||
}
|
}
|
||||||
@@ -210,15 +212,16 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
bearings.second,
|
bearings.second,
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
WaypointType::Arrive,
|
WaypointType::Arrive,
|
||||||
0,
|
0};
|
||||||
util::guidance::LaneTupel(),
|
|
||||||
{}};
|
|
||||||
intersection = {
|
intersection = {
|
||||||
target_node.location,
|
target_node.location,
|
||||||
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
|
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
|
||||||
std::vector<bool>({true}),
|
std::vector<bool>({true}),
|
||||||
0,
|
0,
|
||||||
Intersection::NO_INDEX};
|
Intersection::NO_INDEX,
|
||||||
|
util::guidance::LaneTupel(),
|
||||||
|
{}};
|
||||||
|
|
||||||
BOOST_ASSERT(!leg_geometry.locations.empty());
|
BOOST_ASSERT(!leg_geometry.locations.empty());
|
||||||
steps.push_back(RouteStep{target_node.name_id,
|
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().bearings.size() == 1);
|
||||||
BOOST_ASSERT(steps.back().intersections.front().entry.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.waypoint_type == WaypointType::Arrive);
|
||||||
BOOST_ASSERT(steps.back().maneuver.lanes.lanes_in_turn == 0);
|
BOOST_ASSERT(steps.back().intersections.front().lanes.lanes_in_turn == 0);
|
||||||
BOOST_ASSERT(steps.back().maneuver.lanes.first_lane_from_the_right == INVALID_LANEID);
|
BOOST_ASSERT(steps.back().intersections.front().lanes.first_lane_from_the_right == INVALID_LANEID);
|
||||||
BOOST_ASSERT(steps.back().maneuver.lane_description.empty());
|
BOOST_ASSERT(steps.back().intersections.front().lane_description.empty());
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ namespace guidance
|
|||||||
// Constrains lanes for multi-hop situations where lane changes depend on earlier ones.
|
// 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,
|
// Instead of forcing users to change lanes rapidly in a short amount of time,
|
||||||
// we anticipate lane changes emitting only matching lanes early on.
|
// 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 guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
|
|||||||
@@ -43,6 +43,15 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
|
|||||||
// remove steps invalidated by post-processing
|
// remove steps invalidated by post-processing
|
||||||
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
|
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
|
// postProcess will break the connection between the leg geometry
|
||||||
// for which a segment is supposed to represent exactly the coordinates
|
// for which a segment is supposed to represent exactly the coordinates
|
||||||
// between routing maneuvers and the route steps itself.
|
// between routing maneuvers and the route steps itself.
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include "util/guidance/bearing_class.hpp"
|
#include "util/guidance/bearing_class.hpp"
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
|
|
||||||
|
#include "extractor/guidance/turn_lane_types.hpp"
|
||||||
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -34,6 +37,10 @@ struct Intersection
|
|||||||
std::vector<bool> entry;
|
std::vector<bool> entry;
|
||||||
std::size_t in;
|
std::size_t in;
|
||||||
std::size_t out;
|
std::size_t out;
|
||||||
|
|
||||||
|
// turn lane information
|
||||||
|
util::guidance::LaneTupel lanes;
|
||||||
|
extractor::guidance::TurnLaneDescription lane_description;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Intersection getInvalidIntersection()
|
inline Intersection getInvalidIntersection()
|
||||||
@@ -42,7 +49,9 @@ inline Intersection getInvalidIntersection()
|
|||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
Intersection::NO_INDEX,
|
Intersection::NO_INDEX,
|
||||||
Intersection::NO_INDEX};
|
Intersection::NO_INDEX,
|
||||||
|
util::guidance::LaneTupel(),
|
||||||
|
{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RouteStep
|
struct RouteStep
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
|
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
|
||||||
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
#include "extractor/guidance/turn_lane_types.hpp"
|
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/guidance/turn_lanes.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -33,9 +31,6 @@ struct StepManeuver
|
|||||||
|
|
||||||
WaypointType waypoint_type;
|
WaypointType waypoint_type;
|
||||||
unsigned exit;
|
unsigned exit;
|
||||||
|
|
||||||
util::guidance::LaneTupel lanes;
|
|
||||||
extractor::guidance::TurnLaneDescription lane_description;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline StepManeuver getInvalidStepManeuver()
|
inline StepManeuver getInvalidStepManeuver()
|
||||||
@@ -45,9 +40,7 @@ inline StepManeuver getInvalidStepManeuver()
|
|||||||
0,
|
0,
|
||||||
extractor::guidance::TurnInstruction::NO_TURN(),
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
WaypointType::None,
|
WaypointType::None,
|
||||||
0,
|
0};
|
||||||
util::guidance::LaneTupel(),
|
|
||||||
{}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ class EntryClass
|
|||||||
friend std::size_t std::hash<EntryClass>::operator()(const EntryClass &) const;
|
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 guidance
|
||||||
} // namespace utilr
|
} // namespace utilr
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ class LaneTupel
|
|||||||
|
|
||||||
bool operator==(const LaneTupel other) const;
|
bool operator==(const LaneTupel other) const;
|
||||||
bool operator!=(const LaneTupel other) const;
|
bool operator!=(const LaneTupel other) const;
|
||||||
bool operator<(const LaneTupel other) const;
|
|
||||||
|
|
||||||
LaneID lanes_in_turn;
|
LaneID lanes_in_turn;
|
||||||
LaneID first_lane_from_the_right;
|
LaneID first_lane_from_the_right;
|
||||||
|
|||||||
@@ -72,6 +72,15 @@ namespace osrm
|
|||||||
namespace contractor
|
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()
|
int Contractor::Run()
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -573,12 +582,11 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
|
|||||||
find(segment_speed_lookup, Segment{u->node_id, v->node_id});
|
find(segment_speed_lookup, Segment{u->node_id, v->node_id});
|
||||||
if (forward_speed_iter != segment_speed_lookup.end())
|
if (forward_speed_iter != segment_speed_lookup.end())
|
||||||
{
|
{
|
||||||
int new_segment_weight =
|
auto new_segment_weight =
|
||||||
std::max(1,
|
(forward_speed_iter->speed_source.speed > 0)
|
||||||
static_cast<int>(std::floor(
|
? distanceAndSpeedToWeight(segment_length,
|
||||||
(segment_length * 10.) /
|
forward_speed_iter->speed_source.speed)
|
||||||
(forward_speed_iter->speed_source.speed / 3.6) +
|
: INVALID_EDGE_WEIGHT;
|
||||||
.5)));
|
|
||||||
m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight =
|
m_geometry_list[forward_begin + leaf_object.fwd_segment_position].weight =
|
||||||
new_segment_weight;
|
new_segment_weight;
|
||||||
m_geometry_datasource[forward_begin + leaf_object.fwd_segment_position] =
|
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});
|
find(segment_speed_lookup, Segment{u->node_id, v->node_id});
|
||||||
if (reverse_speed_iter != segment_speed_lookup.end())
|
if (reverse_speed_iter != segment_speed_lookup.end())
|
||||||
{
|
{
|
||||||
int new_segment_weight =
|
auto new_segment_weight =
|
||||||
std::max(1,
|
(reverse_speed_iter->speed_source.speed > 0)
|
||||||
static_cast<int>(std::floor(
|
? distanceAndSpeedToWeight(segment_length,
|
||||||
(segment_length * 10.) /
|
reverse_speed_iter->speed_source.speed)
|
||||||
(reverse_speed_iter->speed_source.speed / 3.6) +
|
: INVALID_EDGE_WEIGHT;
|
||||||
.5)));
|
|
||||||
m_geometry_list[reverse_begin + rev_segment_position].weight =
|
m_geometry_list[reverse_begin + rev_segment_position].weight =
|
||||||
new_segment_weight;
|
new_segment_weight;
|
||||||
m_geometry_datasource[reverse_begin + rev_segment_position] =
|
m_geometry_datasource[reverse_begin + rev_segment_position] =
|
||||||
@@ -763,21 +770,22 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
|
|||||||
const auto num_segments = header->num_osm_nodes - 1;
|
const auto num_segments = header->num_osm_nodes - 1;
|
||||||
for (auto i : util::irange<std::size_t>(0, num_segments))
|
for (auto i : util::irange<std::size_t>(0, num_segments))
|
||||||
{
|
{
|
||||||
|
|
||||||
auto speed_iter =
|
auto speed_iter =
|
||||||
find(segment_speed_lookup,
|
find(segment_speed_lookup,
|
||||||
Segment{previous_osm_node_id, segmentblocks[i].this_osm_node_id});
|
Segment{previous_osm_node_id, segmentblocks[i].this_osm_node_id});
|
||||||
if (speed_iter != segment_speed_lookup.end())
|
if (speed_iter != segment_speed_lookup.end())
|
||||||
{
|
{
|
||||||
// This sets the segment weight using the same formula as the
|
if (speed_iter->speed_source.speed > 0)
|
||||||
// EdgeBasedGraphFactory for consistency. The *why* of this formula
|
{
|
||||||
// is lost in the annals of time.
|
auto new_segment_weight = distanceAndSpeedToWeight(segmentblocks[i].segment_length, speed_iter->speed_source.speed);
|
||||||
int new_segment_weight = std::max(
|
new_weight += new_segment_weight;
|
||||||
1,
|
}
|
||||||
static_cast<int>(std::floor((segmentblocks[i].segment_length * 10.) /
|
else
|
||||||
(speed_iter->speed_source.speed / 3.6) +
|
{
|
||||||
.5)));
|
// This edge is blocked, we don't need to continue updating
|
||||||
new_weight += new_segment_weight;
|
new_weight = INVALID_EDGE_WEIGHT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
|
|||||||
maneuver.instruction.direction_modifier != DirectionModifier::UTurn);
|
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)
|
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)];
|
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;
|
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;
|
--lane_id;
|
||||||
util::json::Object lane;
|
util::json::Object lane;
|
||||||
lane.values["indications"] = extractor::guidance::TurnLaneType::toJsonArray(lane_desc);
|
lane.values["indications"] = extractor::guidance::TurnLaneType::toJsonArray(lane_desc);
|
||||||
if (lane_id >= maneuver.lanes.first_lane_from_the_right &&
|
if (lane_id >= intersection.lanes.first_lane_from_the_right &&
|
||||||
lane_id < maneuver.lanes.first_lane_from_the_right + maneuver.lanes.lanes_in_turn)
|
lane_id < intersection.lanes.first_lane_from_the_right + intersection.lanes.lanes_in_turn)
|
||||||
lane.values["valid"] = util::json::True();
|
lane.values["valid"] = util::json::True();
|
||||||
else
|
else
|
||||||
lane.values["valid"] = util::json::False();
|
lane.values["valid"] = util::json::False();
|
||||||
@@ -175,9 +175,6 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
|||||||
step_maneuver.values["modifier"] =
|
step_maneuver.values["modifier"] =
|
||||||
detail::instructionModifierToString(maneuver.instruction.direction_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["location"] = detail::coordinateToLonLat(maneuver.location);
|
||||||
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before);
|
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before);
|
||||||
step_maneuver.values["bearing_after"] = std::round(maneuver.bearing_after);
|
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)
|
if (intersection.out != guidance::Intersection::NO_INDEX)
|
||||||
result.values["out"] = intersection.out;
|
result.values["out"] = intersection.out;
|
||||||
|
|
||||||
|
if (detail::hasValidLanes(intersection))
|
||||||
|
result.values["lanes"] = detail::lanesFromIntersection(intersection);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,18 +20,17 @@ namespace engine
|
|||||||
namespace guidance
|
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
|
// Postprocessing does not strictly guarantee for only turns
|
||||||
const auto is_turn = [](const RouteStep &step) {
|
const auto is_turn = [](const RouteStep &step) {
|
||||||
return step.maneuver.instruction.type != TurnType::NewName &&
|
return step.maneuver.instruction.type != TurnType::NewName &&
|
||||||
step.maneuver.instruction.type != TurnType::Notification;
|
step.maneuver.instruction.type != TurnType::Notification;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto is_quick = [MIN_DURATION_NEEDED_FOR_LANE_CHANGE](const RouteStep &step) {
|
const auto is_quick = [min_duration_needed_for_lane_change](const RouteStep &step) {
|
||||||
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
|
return step.duration < min_duration_needed_for_lane_change;
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto is_quick_turn = [&](const RouteStep &step) {
|
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.
|
// the current turn lanes constrain the lanes we have to take in the previous turn.
|
||||||
util::for_each_pair(rev_first, rev_last, [](RouteStep ¤t, RouteStep &previous) {
|
util::for_each_pair(rev_first, rev_last, [](RouteStep ¤t, RouteStep &previous) {
|
||||||
const auto current_inst = current.maneuver.instruction;
|
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
|
// 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:
|
// 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
|
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
|
||||||
// otherwise nothing to constrain
|
// otherwise nothing to constrain
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include "engine/guidance/post_processing.hpp"
|
|
||||||
#include "extractor/guidance/turn_instruction.hpp"
|
#include "extractor/guidance/turn_instruction.hpp"
|
||||||
|
#include "engine/guidance/post_processing.hpp"
|
||||||
|
|
||||||
#include "engine/guidance/assemble_steps.hpp"
|
#include "engine/guidance/assemble_steps.hpp"
|
||||||
#include "engine/guidance/lane_processing.hpp"
|
#include "engine/guidance/lane_processing.hpp"
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "util/guidance/turn_lanes.hpp"
|
#include "util/guidance/turn_lanes.hpp"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/numeric/conversion/cast.hpp>
|
||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -524,7 +525,10 @@ std::vector<RouteStep> anticipateLaneChangeForRoundabouts(std::vector<RouteStep>
|
|||||||
enter.maneuver.instruction.direction_modifier =
|
enter.maneuver.instruction.direction_modifier =
|
||||||
mirrorDirectionModifier(enter_direction);
|
mirrorDirectionModifier(enter_direction);
|
||||||
|
|
||||||
auto enterAndLeave = anticipateLaneChange({enter, leave});
|
// 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.
|
// Undo flipping direction on a right turn in a right-sided counter-clockwise roundabout.
|
||||||
// FIXME: assumes right-side driving (counter-clockwise roundabout flow)
|
// FIXME: assumes right-side driving (counter-clockwise roundabout flow)
|
||||||
@@ -535,7 +539,6 @@ std::vector<RouteStep> anticipateLaneChangeForRoundabouts(std::vector<RouteStep>
|
|||||||
};
|
};
|
||||||
|
|
||||||
forEachRoundabout(begin(steps), end(steps), anticipate_lanes_in_roundabout);
|
forEachRoundabout(begin(steps), end(steps), anticipate_lanes_in_roundabout);
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -628,6 +631,10 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
|
|||||||
has_entered_roundabout = false;
|
has_entered_roundabout = false;
|
||||||
on_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
|
// unterminated roundabout
|
||||||
@@ -871,25 +878,34 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
geometry.locations[0], geometry.locations[1]) <= 1;
|
geometry.locations[0], geometry.locations[1]) <= 1;
|
||||||
if (zero_length_step || duplicated_coordinate)
|
if (zero_length_step || duplicated_coordinate)
|
||||||
{
|
{
|
||||||
// fixup the coordinate
|
|
||||||
geometry.locations.erase(geometry.locations.begin());
|
|
||||||
geometry.annotations.erase(geometry.annotations.begin());
|
|
||||||
geometry.osm_node_ids.erase(geometry.osm_node_ids.begin());
|
|
||||||
|
|
||||||
// remove the initial distance value
|
// remove the initial distance value
|
||||||
geometry.segment_distances.erase(geometry.segment_distances.begin());
|
geometry.segment_distances.erase(geometry.segment_distances.begin());
|
||||||
|
|
||||||
|
const auto offset = zero_length_step ? geometry.segment_offsets[1] : 1;
|
||||||
|
if (offset > 0)
|
||||||
|
{
|
||||||
|
// fixup the coordinates/annotations/ids
|
||||||
|
geometry.locations.erase(geometry.locations.begin(),
|
||||||
|
geometry.locations.begin() + offset);
|
||||||
|
geometry.annotations.erase(geometry.annotations.begin(),
|
||||||
|
geometry.annotations.begin() + offset);
|
||||||
|
geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(),
|
||||||
|
geometry.osm_node_ids.begin() + offset);
|
||||||
|
}
|
||||||
|
|
||||||
// We have to adjust the first step both for its name and the bearings
|
// We have to adjust the first step both for its name and the bearings
|
||||||
if (zero_length_step)
|
if (zero_length_step)
|
||||||
{
|
{
|
||||||
|
// since we are not only checking for epsilon but for a full meter, we can have multiple
|
||||||
|
// coordinates here.
|
||||||
// move offsets to front
|
// move offsets to front
|
||||||
BOOST_ASSERT(geometry.segment_offsets[1] == 1);
|
|
||||||
// geometry offsets have to be adjusted. Move all offsets to the front and reduce by
|
// geometry offsets have to be adjusted. Move all offsets to the front and reduce by
|
||||||
// one. (This is an inplace forward one and reduce by one)
|
// one. (This is an inplace forward one and reduce by one)
|
||||||
std::transform(geometry.segment_offsets.begin() + 1,
|
std::transform(geometry.segment_offsets.begin() + 1,
|
||||||
geometry.segment_offsets.end(),
|
geometry.segment_offsets.end(),
|
||||||
geometry.segment_offsets.begin(),
|
geometry.segment_offsets.begin(),
|
||||||
[](const std::size_t val) { return val - 1; });
|
[offset](const std::size_t val) { return val - offset; });
|
||||||
|
|
||||||
geometry.segment_offsets.pop_back();
|
geometry.segment_offsets.pop_back();
|
||||||
const auto ¤t_depart = steps.front();
|
const auto ¤t_depart = steps.front();
|
||||||
@@ -906,8 +922,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
|
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
// we need to make this conform with the intersection format for the first intersection
|
// we need to make this conform with the intersection format for the first intersection
|
||||||
auto &first_intersection = designated_depart.intersections.front();
|
auto &first_intersection = designated_depart.intersections.front();
|
||||||
designated_depart.maneuver.lanes = util::guidance::LaneTupel();
|
designated_depart.intersections.front().lanes = util::guidance::LaneTupel();
|
||||||
designated_depart.maneuver.lane_description.clear();
|
designated_depart.intersections.front().lane_description.clear();
|
||||||
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
|
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
|
||||||
first_intersection.entry = {true};
|
first_intersection.entry = {true};
|
||||||
first_intersection.in = Intersection::NO_INDEX;
|
first_intersection.in = Intersection::NO_INDEX;
|
||||||
@@ -930,9 +946,9 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// and update the leg geometry indices for the removed entry
|
// and update the leg geometry indices for the removed entry
|
||||||
std::for_each(steps.begin(), steps.end(), [](RouteStep &step) {
|
std::for_each(steps.begin(), steps.end(), [offset](RouteStep &step) {
|
||||||
--step.geometry_begin;
|
step.geometry_begin -= offset;
|
||||||
--step.geometry_end;
|
step.geometry_end -= offset;
|
||||||
});
|
});
|
||||||
|
|
||||||
auto &first_step = steps.front();
|
auto &first_step = steps.front();
|
||||||
@@ -964,18 +980,21 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
// all zero-length instructions
|
// all zero-length instructions
|
||||||
if (next_to_last_step.distance <= 1 && steps.size() > 2)
|
if (next_to_last_step.distance <= 1 && steps.size() > 2)
|
||||||
{
|
{
|
||||||
geometry.locations.pop_back();
|
|
||||||
geometry.annotations.pop_back();
|
|
||||||
geometry.osm_node_ids.pop_back();
|
|
||||||
geometry.segment_offsets.pop_back();
|
geometry.segment_offsets.pop_back();
|
||||||
|
// remove all the last coordinates from the geometry
|
||||||
|
geometry.locations.resize(geometry.segment_offsets.back() + 1);
|
||||||
|
geometry.annotations.resize(geometry.segment_offsets.back() + 1);
|
||||||
|
geometry.osm_node_ids.resize(geometry.segment_offsets.back() + 1);
|
||||||
|
|
||||||
BOOST_ASSERT(geometry.segment_distances.back() <= 1);
|
BOOST_ASSERT(geometry.segment_distances.back() <= 1);
|
||||||
geometry.segment_distances.pop_back();
|
geometry.segment_distances.pop_back();
|
||||||
|
|
||||||
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;
|
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;
|
||||||
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
|
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
|
||||||
next_to_last_step.maneuver.bearing_after = 0;
|
next_to_last_step.maneuver.bearing_after = 0;
|
||||||
next_to_last_step.maneuver.lanes = util::guidance::LaneTupel();
|
next_to_last_step.intersections.front().lanes = util::guidance::LaneTupel();
|
||||||
next_to_last_step.maneuver.lane_description.clear();
|
next_to_last_step.intersections.front().lane_description.clear();
|
||||||
|
next_to_last_step.geometry_end = next_to_last_step.geometry_begin + 1;
|
||||||
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
|
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
|
||||||
auto &last_intersection = next_to_last_step.intersections.back();
|
auto &last_intersection = next_to_last_step.intersections.back();
|
||||||
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
|
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
|
||||||
@@ -1023,6 +1042,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
|||||||
last_step.intersections.front().bearings.front() = util::bearing::reverseBearing(bearing);
|
last_step.intersections.front().bearings.front() = util::bearing::reverseBearing(bearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT(steps.back().geometry_end == geometry.locations.size());
|
||||||
|
|
||||||
BOOST_ASSERT(steps.front().intersections.size() >= 1);
|
BOOST_ASSERT(steps.front().intersections.size() >= 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
||||||
@@ -1143,6 +1164,60 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
|
|||||||
return removeNoTurnInstructions(std::move(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 guidance
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -507,8 +507,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
|
|||||||
|
|
||||||
std::vector<std::uint32_t> turn_lane_offsets;
|
std::vector<std::uint32_t> turn_lane_offsets;
|
||||||
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
|
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
|
||||||
if( !util::deserializeAdjacencyArray(
|
if (!util::deserializeAdjacencyArray(
|
||||||
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks) )
|
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks))
|
||||||
{
|
{
|
||||||
util::SimpleLogger().Write(logWARNING) << "Reading Turn Lane Masks failed.";
|
util::SimpleLogger().Write(logWARNING) << "Reading Turn Lane Masks failed.";
|
||||||
}
|
}
|
||||||
@@ -673,7 +673,7 @@ void Extractor::WriteIntersectionClassificationData(
|
|||||||
util::RangeTable<> bearing_class_range_table(bearing_counts);
|
util::RangeTable<> bearing_class_range_table(bearing_counts);
|
||||||
file_out_stream << bearing_class_range_table;
|
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)
|
for (const auto &bearing_class : bearing_classes)
|
||||||
{
|
{
|
||||||
const auto &bearings = bearing_class.getAvailableBearings();
|
const auto &bearings = bearing_class.getAvailableBearings();
|
||||||
@@ -681,17 +681,18 @@ void Extractor::WriteIntersectionClassificationData(
|
|||||||
sizeof(bearings[0]) * bearings.size());
|
sizeof(bearings[0]) * bearings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME
|
if (!static_cast<bool>(file_out_stream))
|
||||||
// This should be here, but g++4.8 does not have it...
|
{
|
||||||
// static_assert(std::is_trivially_copyable<util::guidance::EntryClass>::value,
|
throw util::exception("Failed to write to " + output_file_name + ".");
|
||||||
// "EntryClass Serialization requires trivial copyable entry classes");
|
}
|
||||||
|
|
||||||
util::serializeVector(file_out_stream, entry_classes);
|
util::serializeVector(file_out_stream, entry_classes);
|
||||||
TIMER_STOP(write_edges);
|
TIMER_STOP(write_edges);
|
||||||
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
|
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
|
||||||
<< node_based_intersection_classes.size() << " Indices into "
|
<< node_based_intersection_classes.size() << " Indices into "
|
||||||
<< bearing_classes.size() << " bearing classes and "
|
<< bearing_classes.size() << " bearing classes and "
|
||||||
<< entry_classes.size() << " entry classes";
|
<< entry_classes.size() << " entry classes and " << total_bearings
|
||||||
|
<< " bearing values." << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end();
|
||||||
++token_itr)
|
++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 =
|
const auto translated_mask =
|
||||||
masks_by_osm_string[std::distance(osm_lane_strings, position)];
|
masks_by_osm_string[std::distance(osm_lane_strings, position)];
|
||||||
if (translated_mask == TurnLaneType::empty)
|
if (translated_mask == TurnLaneType::empty)
|
||||||
@@ -203,7 +204,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
<< *token_itr << "\"";
|
<< *token_itr << "\"";
|
||||||
return {};
|
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;
|
lane_mask |= translated_mask;
|
||||||
}
|
}
|
||||||
// add the lane to the description
|
// add the lane to the description
|
||||||
@@ -265,8 +269,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
// name_offsets already has an offset of a new name, take the offset index as the name id
|
// 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;
|
name_id = external_memory.name_offsets.size() - 1;
|
||||||
|
|
||||||
external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length
|
external_memory.name_char_data.reserve(external_memory.name_char_data.size() + name_length +
|
||||||
+ destinations_length + pronunciation_length);
|
destinations_length + pronunciation_length);
|
||||||
|
|
||||||
std::copy(parsed_way.name.c_str(),
|
std::copy(parsed_way.name.c_str(),
|
||||||
parsed_way.name.c_str() + name_length,
|
parsed_way.name.c_str() + name_length,
|
||||||
@@ -306,7 +310,9 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
std::transform(input_way.nodes().begin(),
|
std::transform(input_way.nodes().begin(),
|
||||||
input_way.nodes().end(),
|
input_way.nodes().end(),
|
||||||
std::back_inserter(external_memory.used_node_id_list),
|
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;
|
const bool is_opposite_way = TRAVEL_MODE_INACCESSIBLE == parsed_way.forward_travel_mode;
|
||||||
|
|
||||||
@@ -338,7 +344,8 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
external_memory.way_start_end_id_list.push_back(
|
external_memory.way_start_end_id_list.push_back(
|
||||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
{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().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()[1].ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
|
||||||
}
|
}
|
||||||
@@ -372,27 +379,28 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
input_way.nodes().cbegin(),
|
input_way.nodes().cbegin(),
|
||||||
input_way.nodes().cend(),
|
input_way.nodes().cend(),
|
||||||
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
|
||||||
external_memory.all_edges_list.push_back(
|
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||||
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
name_id,
|
name_id,
|
||||||
backward_weight_data,
|
backward_weight_data,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
parsed_way.roundabout,
|
parsed_way.roundabout,
|
||||||
parsed_way.is_access_restricted,
|
parsed_way.is_access_restricted,
|
||||||
parsed_way.is_startpoint,
|
parsed_way.is_startpoint,
|
||||||
parsed_way.backward_travel_mode,
|
parsed_way.backward_travel_mode,
|
||||||
true,
|
true,
|
||||||
turn_lane_id_backward,
|
turn_lane_id_backward,
|
||||||
road_classification));
|
road_classification));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
external_memory.way_start_end_id_list.push_back(
|
external_memory.way_start_end_id_list.push_back(
|
||||||
{OSMWayID{static_cast<std::uint32_t>(input_way.id())},
|
{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().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()[1].ref())},
|
||||||
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].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 =
|
const auto valid_count =
|
||||||
boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; });
|
boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; });
|
||||||
if (0 == valid_count && uturn_could_be_valid)
|
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));
|
return mergeSegregatedRoads(std::move(intersection));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,14 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
|||||||
// a pgerequisite is simple turns. Larger differences should not end up here
|
// 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
|
// an additional line at the side is only reasonable if it is targeting public
|
||||||
// service vehicles. Otherwise, we should not have it
|
// 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));
|
lane_data = mergeNoneTag(none_index, std::move(lane_data));
|
||||||
}
|
}
|
||||||
@@ -292,6 +299,9 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
|
|||||||
{
|
{
|
||||||
lane_data = handleRenamingSituations(none_index, std::move(lane_data), intersection);
|
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
|
// finally make sure we are still sorted
|
||||||
std::sort(lane_data.begin(), lane_data.end());
|
std::sort(lane_data.begin(), lane_data.end());
|
||||||
return lane_data;
|
return lane_data;
|
||||||
|
|||||||
@@ -351,8 +351,14 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
|||||||
if (lane_data.back().tag == TurnLaneType::uturn)
|
if (lane_data.back().tag == TurnLaneType::uturn)
|
||||||
return findBestMatchForReverse(lane_data[lane_data.size() - 2].tag, intersection);
|
return findBestMatchForReverse(lane_data[lane_data.size() - 2].tag, intersection);
|
||||||
|
|
||||||
BOOST_ASSERT(lane_data.front().tag == TurnLaneType::uturn);
|
// TODO(mokob): #2730 have a look please
|
||||||
return findBestMatchForReverse(lane_data[1].tag, intersection);
|
// 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);
|
std::size_t match_index = std::distance(intersection.begin(), best_match);
|
||||||
all_simple &= (matched_indices.count(match_index) == 0);
|
all_simple &= (matched_indices.count(match_index) == 0);
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ int Storage::Run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::uint64_t num_bearings;
|
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);
|
std::vector<DiscreteBearing> bearing_class_table(num_bearings);
|
||||||
intersection_stream.read(reinterpret_cast<char *>(&bearing_class_table[0]),
|
intersection_stream.read(reinterpret_cast<char *>(&bearing_class_table[0]),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#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
|
// comparation based on interpretation as unsigned 32bit integer
|
||||||
bool LaneTupel::operator==(const LaneTupel other) const
|
bool LaneTupel::operator==(const LaneTupel other) const
|
||||||
{
|
{
|
||||||
static_assert(sizeof(LaneTupel) == sizeof(std::uint16_t),
|
return std::tie(lanes_in_turn, first_lane_from_the_right) ==
|
||||||
"Comparation requires LaneTupel to be the of size 16Bit");
|
std::tie(other.lanes_in_turn, other.first_lane_from_the_right);
|
||||||
return *reinterpret_cast<const std::uint16_t *>(this) ==
|
|
||||||
*reinterpret_cast<const std::uint16_t *>(&other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LaneTupel::operator!=(const LaneTupel other) const { return !(*this == other); }
|
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 guidance
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
Reference in New Issue
Block a user