Expose driving_side as a property on RouteStep

This commit is contained in:
Daniel Patterson 2017-10-31 23:51:11 -04:00
parent 5b79640b44
commit 5b58445535
14 changed files with 1811 additions and 31 deletions

View File

@ -1,10 +1,14 @@
# UNRELEASED
- Changes from 5.13:
- Changes from 5.13
- API:
- new RouteStep property `driving_side` that has either "left" or "right" for that step
- Misc:
- Bundles a rough (please improve!) driving-side GeoJSON file for use with `osrm-extract --location-dependent-data data/driving_side.geojson`
- Profile:
- Remove dependency on turn types and turn modifier in the process_turn function in the `car.lua` profile. Guidance instruction types are not used to influence turn penalty anymore so this will break backward compatibility between profile version 3 and 4.
- Bugfixes:
- Fixed #4670: Fix bug where merge instructions got the wrong direction modifier
- Properly use the `profile.properties.left_hand_driving` property, there was a typo that meant it had no effect
# 5.13.0
- Changes from 5.12:

1748
data/driving_side.geojson Normal file

File diff suppressed because it is too large Load Diff

View File

@ -594,6 +594,7 @@ step.
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
- `rotary_pronunciation`: The pronunciation hint of the rotary name. Optionally included, if the step is a rotary and a rotary pronunciation is available.
- `driving_side`: The legal driving side at the location for this step. Either `left` or `right`.
#### Example

View File

@ -4,7 +4,7 @@ Feature: Testbot - side bias
Scenario: Left-hand bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.properties.left_hand_driving = true
profile.turn_bias = 1.075
"""
And the node map
@ -20,14 +20,14 @@ Feature: Testbot - side bias
| bd |
When I route I should get
| from | to | route | time |
| d | a | bd,ab,ab | 24s +-1 |
| d | c | bd,bc,bc | 27s +-1 |
| from | to | route | time | driving_side |
| d | a | bd,ab,ab | 24s +-1 | left,left,left |
| d | c | bd,bc,bc | 27s +-1 | left,left,left |
Scenario: Right-hand bias
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.properties.left_hand_driving = true
profile.turn_bias = 1 / 1.075
"""
And the node map
@ -43,14 +43,14 @@ Feature: Testbot - side bias
| bd |
When I route I should get
| from | to | route | time | # |
| d | a | bd,ab,ab | 27s +-1 | should be inverse of left hand bias |
| d | c | bd,bc,bc | 24s +-1 | |
| from | to | route | time | driving_side | # |
| d | a | bd,ab,ab | 27s +-1 | left,left,left | should be inverse of left hand bias |
| d | c | bd,bc,bc | 24s +-1 | left,left,left | |
Scenario: Roundabout exit counting for left sided driving
Given the profile file "testbot" initialized with
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.properties.left_hand_driving = true
"""
And a grid size of 10 meters
And the node map
@ -70,10 +70,10 @@ Feature: Testbot - side bias
| bcegb | roundabout |
When I route I should get
| waypoints | route | turns |
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
| waypoints | route | driving_side | turns |
| a,d | ab,cd,cd | left,left,left | depart,roundabout turn left exit-1,arrive |
| a,f | ab,ef,ef | left,left,left | depart,roundabout turn straight exit-2,arrive |
| a,h | ab,gh,gh | left,left,left | depart,roundabout turn right exit-3,arrive |
Scenario: Left-hand bias via location-dependent tags
@ -92,9 +92,9 @@ Feature: Testbot - side bias
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | time |
| d | a | bd,ab,ab | 24s +-1 |
| d | c | bd,bc,bc | 27s +-1 |
| from | to | route | driving_side | time |
| d | a | bd,ab,ab | left,left,left | 24s +-1 |
| d | c | bd,bc,bc | left,left,left | 27s +-1 |
Scenario: Left-hand bias via OSM tags
@ -113,6 +113,6 @@ Feature: Testbot - side bias
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
When I route I should get
| from | to | route | time |
| d | a | bd,ab,ab | 27s +-1 |
| d | c | bd,bc,bc | 24s +-1 |
| from | to | route | driving_side | time |
| d | a | bd,ab,ab | right,right,right | 27s +-1 |
| d | c | bd,bc,bc | right,right,right | 24s +-1 |

View File

@ -5,7 +5,7 @@ Feature: Basic Roundabout
Given a grid size of 10 meters
Given the profile file "car" initialized with
"""
profile.left_hand_driving = true
profile.properties.left_hand_driving = true
"""
Scenario: Roundabout exit counting for left sided driving

View File

@ -267,6 +267,10 @@ module.exports = function () {
return this.extractInstructionList(instructions, s => s.mode);
};
this.drivingSideList = (instructions) => {
return this.extractInstructionList(instructions, s => s.driving_side);
};
this.classesList = (instructions) => {
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
};

View File

@ -35,7 +35,8 @@ module.exports = function () {
if (err) return cb(err);
if (body && body.length) {
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches;
distances, summary, intersections, lanes, locations, annotation, weight_name, weights, approaches,
driving_sides;
let json = JSON.parse(body);
@ -53,6 +54,7 @@ module.exports = function () {
turns = this.turnList(json.routes[0]);
intersections = this.intersectionList(json.routes[0]);
modes = this.modeList(json.routes[0]);
driving_sides = this.drivingSideList(json.routes[0]);
classes = this.classesList(json.routes[0]);
times = this.timeList(json.routes[0]);
distances = this.distanceList(json.routes[0]);
@ -186,6 +188,10 @@ module.exports = function () {
putValue('weight', weight);
putValue('approach', approaches);
if (driving_sides) {
putValue('driving_side', driving_sides);
}
for (var key in row) {
if (this.FuzzyMatch.match(got[key], row[key])) {
got[key] = row[key];

View File

@ -141,7 +141,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection}});
{intersection},
path_point.is_left_hand_driving});
if (leg_data_index + 1 < leg_data.size())
{
@ -219,7 +220,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
maneuver,
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection}});
{intersection},
facade.IsLeftHandDriving(target_node_id)});
}
// In this case the source + target are on the same edge segment
else
@ -261,7 +263,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
std::move(maneuver),
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1,
{intersection}});
{intersection},
facade.IsLeftHandDriving(source_node_id)});
}
BOOST_ASSERT(segment_index == number_of_segments - 1);
@ -301,7 +304,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
std::move(maneuver),
leg_geometry.locations.size() - 1,
leg_geometry.locations.size(),
{intersection}});
{intersection},
facade.IsLeftHandDriving(source_node_id)});
BOOST_ASSERT(steps.front().intersections.size() == 1);
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);

View File

@ -76,6 +76,7 @@ struct RouteStep
std::size_t geometry_begin;
std::size_t geometry_end;
std::vector<IntermediateIntersection> intersections;
bool is_left_hand_driving;
// remove all information from the route step, marking it as invalid (used to indicate empty
// steps to be removed).
@ -129,6 +130,7 @@ inline void RouteStep::Invalidate()
geometry_end = 0;
intersections.clear();
intersections.push_back(getInvalidIntersection());
is_left_hand_driving = false;
}
// Elongate by another step in front

View File

@ -57,6 +57,9 @@ struct PathData
util::guidance::TurnBearing pre_turn_bearing;
// bearing (as seen from the intersection) post-turn
util::guidance::TurnBearing post_turn_bearing;
// Driving side of the turn
bool is_left_hand_driving;
};
struct InternalRouteResult

View File

@ -185,6 +185,8 @@ void annotatePath(const FacadeT &facade,
: 0);
const std::size_t end_index = weight_vector.size();
bool is_left_hand_driving = facade.IsLeftHandDriving(node_id);
BOOST_ASSERT(start_index >= 0);
BOOST_ASSERT(start_index < end_index);
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
@ -202,7 +204,8 @@ void annotatePath(const FacadeT &facade,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
util::guidance::TurnBearing(0),
is_left_hand_driving});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade.HasLaneData(turn_id))
@ -254,6 +257,7 @@ void annotatePath(const FacadeT &facade,
// t: fwd_segment 3
// -> (U, v), (v, w), (w, x)
// note that (x, t) is _not_ included but needs to be added later.
bool is_target_left_hand_driving = facade.IsLeftHandDriving(target_node_id);
for (std::size_t segment_idx = start_index; segment_idx != end_index;
(start_index < end_index ? ++segment_idx : --segment_idx))
{
@ -273,7 +277,8 @@ void annotatePath(const FacadeT &facade,
EMPTY_ENTRY_CLASS,
datasource_vector[segment_idx],
util::guidance::TurnBearing(0),
util::guidance::TurnBearing(0)});
util::guidance::TurnBearing(0),
is_target_left_hand_driving});
}
if (unpacked_path.size() > 0)

View File

@ -563,7 +563,7 @@ function WayHandlers.driving_side(profile, way, result, data)
elseif driving_side == 'right' then
result.is_left_hand_driving = false
else
result.is_left_hand_driving = profile.left_hand_driving
result.is_left_hand_driving = profile.properties.left_hand_driving
end
end

View File

@ -195,6 +195,7 @@ util::json::Object makeRouteStep(guidance::RouteStep step, util::json::Value geo
route_step.values["mode"] = extractor::travelModeToString(std::move(step.mode));
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
route_step.values["geometry"] = std::move(geometry);
route_step.values["driving_side"] = step.is_left_hand_driving ? "left" : "right";
util::json::Array intersections;
intersections.values.reserve(step.intersections.size());

View File

@ -64,6 +64,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{"geometry", "yw_jGupkl@??"},
{"name", "Boulevard du Larvotto"},
{"mode", "driving"},
{"driving_side", "right"},
{"maneuver",
json::Object{{
{"location", location},
@ -84,6 +85,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{"geometry", "yw_jGupkl@"},
{"name", "Boulevard du Larvotto"},
{"mode", "driving"},
{"driving_side", "right"},
{"maneuver",
json::Object{{{"location", location},
{"bearing_before", 58},