Skip to content

Commit

Permalink
Support maneuver relations (#4676)
Browse files Browse the repository at this point in the history
  • Loading branch information
danpat authored Feb 9, 2018
1 parent 1aed135 commit 5531cac
Show file tree
Hide file tree
Showing 46 changed files with 1,474 additions and 89 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# UNRELEASED
- Changes from 5.15.1:
- Guidance
- ADDED #4676: Support for maneuver override relation, allowing data-driven overrides for turn-by-turn instructions [#4676](https://github.com/Project-OSRM/osrm-backend/pull/4676)
- CHANGED #4830: Announce reference change if names are empty
- CHANGED #4835: MAXIMAL_ALLOWED_SEPARATION_WIDTH increased to 12 meters
- Profile:
Expand Down
25 changes: 25 additions & 0 deletions features/car/restrictions.feature
Original file line number Diff line number Diff line change
Expand Up @@ -1061,3 +1061,28 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route |
| a | d | ab,bc,bc,bge,de,de |


Scenario: Ambiguous ways
Given the node map
"""
x---a----b-----c---z
|
d
"""

And the ways
| nodes |
| abc |
| bd |
| xa |
| cz |

And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bd | abc | b | no_left_turn |

When I route I should get
| from | to | route |
| d | x | bd,abc,xa,xa |
| d | z | bd,abc,cz,cz |
208 changes: 208 additions & 0 deletions features/guidance/maneuver-tag.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# The route results with #original are what the result should be if the maneuver tag is removed
@routing @guidance @maneuver
Feature: Maneuver tag support

Background:
Given the profile "car"
Given a grid size of 5 meters

Scenario: simple override #1
Given the node map
"""
a--b---c----d---e
|
g
|
h------i--------j
"""
And the ways
| nodes | name | oneway |
| abc | A Street | no |
| cde | B Street | no |
| cgi | C Street | no |
| hij | J Street | no |

And the relations
| type | way:from | node:via | way:to | maneuver | direction |
| maneuver | abc | c | cgi | turn | sharp_right |
| maneuver | hij | i | cde | turn | sharp_left |
| maneuver | abc | c | cde | turn | slight_left |

When I route I should get
| waypoints | route | turns |
# Testing directly connected from/to
| a,j | A Street,C Street,J Street,J Street | depart,turn sharp right,turn left,arrive |
| b,g | A Street,C Street,C Street | depart,turn sharp right,arrive |
# Testing re-awakening suppressed turns
| a,e | A Street,B Street,B Street | depart,turn slight left,arrive |

Scenario: single via-way
Given the node map
""""
a--b---c----d---e
|
g
|
h------i--------j
"""

And the ways
| nodes | name | oneway |
| abc | A Street | no |
| cde | B Street | no |
| cgi | C Street | no |
| hi | J Street | no |
| ij | J Street | no |

And the relations
| type | way:from | way:via | way:to | node:via | maneuver | direction |
| maneuver | abc | cgi | ij | c | turn | sharp_right |

When I route I should get
| waypoints | route | turns |
| a,j | A Street,C Street,J Street,J Street | depart,turn sharp right,turn left,arrive |


Scenario: multiple via-way
Given the node map
""""
a--b---c----d---e
|
g-----k
|
h------i--------j
"""

And the ways
| nodes | name | oneway |
| abc | A Street | no |
| cde | B Street | no |
| cg | C Street | no |
| gi | C Street | no |
| hi | J Street | no |
| ij | J Street | no |
| gk | G Street | no |

And the relations
| type | way:from | way:via | way:via | way:to | node:via | maneuver | direction |
| maneuver | abc | cg | gi | ij | c | turn | sharp_right |

When I route I should get
| waypoints | route | turns |
| a,j | A Street,C Street,J Street,J Street | depart,turn sharp right,end of road left,arrive |


Scenario: Use maneuver tag to announce a particular turn type
Given the node map
"""
f
*
*
*
*
*
*
*
*
*
t. .. * h
.. ....m** *
/ * *
/ * * *
/
/
|
|
\
\
o
"""

And the ways
| nodes | name | oneway | highway |
| fm | CA-120 | no | secondary |
| mh | CA-120 | no | secondary |
| mt | Priest Rd | no | unclassified |
| mo | | no | service |

And the relations
| type | way:from | node:via | way:to | maneuver | direction |
| maneuver | mh | m | mt | turn | left |

When I route I should get
| waypoints | route | turns |
| h,t | CA-120,Priest Rd,Priest Rd | depart,turn left,arrive |
#original | h,t | CA-120,Priest Rd,Priest Rd | depart,turn straight,arrive |

Scenario: Use maneuver tag to announce lane guidance
Given a grid size of 10 meters
Given the node map
"""
ad
/ \
/ \
/ \
| |
| |
| |
b-----c------e
| |
| |
| |
| |
r w
"""

And the ways
| nodes | name | oneway | highway |
| ab | Marsh Rd | yes | secondary |
| br | Marsh Rd | yes | secondary |
| cd | Marsh Rd | yes | secondary |
| cw | Marsh Rd | yes | secondary |
| bc | service | no | service |
| ce | service | no | service |

And the relations
| type | way:from | node:via | way:via | way:to | maneuver |
| maneuver | ab | c | bc | cd | uturn |
| maneuver | ab | b | bc | cd | suppress |

When I route I should get
| waypoints | route | turns |
| a,d | Marsh Rd,Marsh Rd,Marsh Rd | depart,turn uturn,arrive |
#original | a,d | Marsh Rd,service,Marsh Rd,Marsh Rd | depart,turn left,turn left,arrive |

Scenario: Use maneuver tag to suppress a turn
Given the node map
"""
c
|
|
v---y----------z
|
n---p----------k
|\
| \
b t
"""

And the ways
| nodes | name | oneway | highway |
| zy | NY Ave | yes | primary |
| yv | NY Ave | yes | primary |
| np | NY Ave | yes | primary |
| pk | NY Ave | yes | primary |
| cp | 4th St | no | tertiary |
| yp | | no | motorway_link |
| pb | 4th St | no | primary |
| pt | 395 | no | primary |

And the relations
| type | way:from | node:via | way:via | way:to | maneuver |
| maneuver | zy | p | yp | pt | suppress |

When I route I should get
| waypoints | route | turns |
| z,t | NY Ave,395,395 | depart,on ramp left,arrive |
#original | z,t | NY Ave,,395,395 | depart,on ramp left,fork slight left,arrive |

20 changes: 12 additions & 8 deletions features/step_definitions/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,40 +185,43 @@ module.exports = function () {

let q = d3.queue();

let addRelation = (row, cb) => {
let addRelation = (headers, row, cb) => {
let relation = new OSM.Relation(this.makeOSMId(), this.OSM_USER, this.OSM_TIMESTAMP, this.OSM_UID);


var name = null;
for (let key in row) {
for (let index in row) {

var key = headers[index];
var value = row[index];
let isNode = key.match(/^node:?(.*)/),
isWay = key.match(/^way:?(.*)/),
isRelation = key.match(/^relation:?(.*)/),
isColonSeparated = key.match(/^(.*):(.*)/);
if (isNode) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
value.split(',').map(function(v) { return v.trim(); }).forEach((nodeName) => {
if (nodeName.length !== 1) throw new Error(util.format('*** invalid relation node member "%s"', nodeName));
let node = this.findNodeByName(nodeName);
if (!node) throw new Error(util.format('*** unknown relation node member "%s"', nodeName));
relation.addMember('node', node.id, isNode[1]);
});
} else if (isWay) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((wayName) => {
value.split(',').map(function(v) { return v.trim(); }).forEach((wayName) => {
let way = this.findWayByName(wayName);
if (!way) throw new Error(util.format('*** unknown relation way member "%s"', wayName));
relation.addMember('way', way.id, isWay[1]);
});
} else if (isRelation) {
row[key].split(',').map(function(v) { return v.trim(); }).forEach((relName) => {
value.split(',').map(function(v) { return v.trim(); }).forEach((relName) => {
let otherrelation = this.findRelationByName(relName);
if (!otherrelation) throw new Error(util.format('*** unknown relation relation member "%s"', relName));
relation.addMember('relation', otherrelation.id, isRelation[1]);
});
} else if (isColonSeparated && isColonSeparated[1] !== 'restriction') {
throw new Error(util.format('*** unknown relation member type "%s:%s", must be either "node" or "way"', isColonSeparated[1], isColonSeparated[2]));
} else {
relation.addTag(key, row[key]);
if (key.match(/name/)) name = row[key];
relation.addTag(key, value);
if (key.match(/name/)) name = value;
}
}
relation.uid = this.OSM_UID;
Expand All @@ -233,7 +236,8 @@ module.exports = function () {
cb();
};

table.hashes().forEach((row) => q.defer(addRelation, row));
var headers = table.raw()[0];
table.rows().forEach((row) => q.defer(addRelation, headers, row));

q.awaitAll(callback);
});
Expand Down
8 changes: 8 additions & 0 deletions include/engine/api/route_api.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef ENGINE_API_ROUTE_HPP
#define ENGINE_API_ROUTE_HPP

#include "extractor/maneuver_override.hpp"
#include "engine/api/base_api.hpp"
#include "engine/api/json_factory.hpp"
#include "engine/api/route_parameters.hpp"
Expand All @@ -19,6 +20,8 @@

#include "engine/internal_route_result.hpp"

#include "guidance/turn_instruction.hpp"

#include "util/coordinate.hpp"
#include "util/integer_range.hpp"
#include "util/json_util.hpp"
Expand Down Expand Up @@ -130,6 +133,7 @@ class RouteAPI : public BaseAPI
reversed_target,
parameters.steps);

util::Log(logDEBUG) << "Assembling steps " << std::endl;
if (parameters.steps)
{
auto steps = guidance::assembleSteps(BaseAPI::facade,
Expand All @@ -140,6 +144,10 @@ class RouteAPI : public BaseAPI
reversed_source,
reversed_target);

// Apply maneuver overrides before any other post
// processing is performed
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);

/* Perform step-based post-processing.
*
* Using post-processing on basis of route-steps for a single leg at a time
Expand Down
Loading

0 comments on commit 5531cac

Please sign in to comment.