Expose driving_side as a property on RouteStep
This commit is contained in:
parent
5b79640b44
commit
5b58445535
@ -1,10 +1,14 @@
|
|||||||
# UNRELEASED
|
# 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:
|
- 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.
|
- 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:
|
- Bugfixes:
|
||||||
- Fixed #4670: Fix bug where merge instructions got the wrong direction modifier
|
- 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
|
# 5.13.0
|
||||||
- Changes from 5.12:
|
- Changes from 5.12:
|
||||||
|
1748
data/driving_side.geojson
Normal file
1748
data/driving_side.geojson
Normal file
File diff suppressed because it is too large
Load Diff
@ -594,6 +594,7 @@ step.
|
|||||||
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
|
||||||
- `rotary_name`: The name for the rotary. Optionally included, if the step is a rotary and a rotary name is available.
|
- `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.
|
- `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
|
#### Example
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ Feature: Testbot - side bias
|
|||||||
Scenario: Left-hand bias
|
Scenario: Left-hand bias
|
||||||
Given the profile file "car" initialized with
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
profile.left_hand_driving = true
|
profile.properties.left_hand_driving = true
|
||||||
profile.turn_bias = 1.075
|
profile.turn_bias = 1.075
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
@ -20,14 +20,14 @@ Feature: Testbot - side bias
|
|||||||
| bd |
|
| bd |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time | driving_side |
|
||||||
| d | a | bd,ab,ab | 24s +-1 |
|
| d | a | bd,ab,ab | 24s +-1 | left,left,left |
|
||||||
| d | c | bd,bc,bc | 27s +-1 |
|
| d | c | bd,bc,bc | 27s +-1 | left,left,left |
|
||||||
|
|
||||||
Scenario: Right-hand bias
|
Scenario: Right-hand bias
|
||||||
Given the profile file "car" initialized with
|
Given the profile file "car" initialized with
|
||||||
"""
|
"""
|
||||||
profile.left_hand_driving = true
|
profile.properties.left_hand_driving = true
|
||||||
profile.turn_bias = 1 / 1.075
|
profile.turn_bias = 1 / 1.075
|
||||||
"""
|
"""
|
||||||
And the node map
|
And the node map
|
||||||
@ -43,14 +43,14 @@ Feature: Testbot - side bias
|
|||||||
| bd |
|
| bd |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time | # |
|
| from | to | route | time | driving_side | # |
|
||||||
| d | a | bd,ab,ab | 27s +-1 | should be inverse of left hand bias |
|
| d | a | bd,ab,ab | 27s +-1 | left,left,left | should be inverse of left hand bias |
|
||||||
| d | c | bd,bc,bc | 24s +-1 | |
|
| d | c | bd,bc,bc | 24s +-1 | left,left,left | |
|
||||||
|
|
||||||
Scenario: Roundabout exit counting for left sided driving
|
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 a grid size of 10 meters
|
||||||
And the node map
|
And the node map
|
||||||
@ -70,10 +70,10 @@ Feature: Testbot - side bias
|
|||||||
| bcegb | roundabout |
|
| bcegb | roundabout |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | driving_side | turns |
|
||||||
| a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive |
|
| a,d | ab,cd,cd | left,left,left | depart,roundabout turn left exit-1,arrive |
|
||||||
| a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive |
|
| a,f | ab,ef,ef | left,left,left | depart,roundabout turn straight exit-2,arrive |
|
||||||
| a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive |
|
| a,h | ab,gh,gh | left,left,left | depart,roundabout turn right exit-3,arrive |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Left-hand bias via location-dependent tags
|
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"
|
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | driving_side | time |
|
||||||
| d | a | bd,ab,ab | 24s +-1 |
|
| d | a | bd,ab,ab | left,left,left | 24s +-1 |
|
||||||
| d | c | bd,bc,bc | 27s +-1 |
|
| d | c | bd,bc,bc | left,left,left | 27s +-1 |
|
||||||
|
|
||||||
|
|
||||||
Scenario: Left-hand bias via OSM tags
|
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"
|
And the extract extra arguments "--location-dependent-data test/data/regions/null-island.geojson"
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | driving_side | time |
|
||||||
| d | a | bd,ab,ab | 27s +-1 |
|
| d | a | bd,ab,ab | right,right,right | 27s +-1 |
|
||||||
| d | c | bd,bc,bc | 24s +-1 |
|
| d | c | bd,bc,bc | right,right,right | 24s +-1 |
|
||||||
|
@ -5,7 +5,7 @@ Feature: Basic Roundabout
|
|||||||
Given a grid size of 10 meters
|
Given a grid size of 10 meters
|
||||||
Given the profile file "car" initialized with
|
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
|
Scenario: Roundabout exit counting for left sided driving
|
||||||
|
@ -267,6 +267,10 @@ module.exports = function () {
|
|||||||
return this.extractInstructionList(instructions, s => s.mode);
|
return this.extractInstructionList(instructions, s => s.mode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.drivingSideList = (instructions) => {
|
||||||
|
return this.extractInstructionList(instructions, s => s.driving_side);
|
||||||
|
};
|
||||||
|
|
||||||
this.classesList = (instructions) => {
|
this.classesList = (instructions) => {
|
||||||
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
|
return this.extractInstructionList(instructions, s => '[' + s.intersections.map(i => '(' + (i.classes ? i.classes.join(',') : '') + ')').join(',') + ']');
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,8 @@ module.exports = function () {
|
|||||||
if (err) return cb(err);
|
if (err) return cb(err);
|
||||||
if (body && body.length) {
|
if (body && body.length) {
|
||||||
let destinations, exits, pronunciations, instructions, refs, bearings, turns, modes, times, classes,
|
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);
|
let json = JSON.parse(body);
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ module.exports = function () {
|
|||||||
turns = this.turnList(json.routes[0]);
|
turns = this.turnList(json.routes[0]);
|
||||||
intersections = this.intersectionList(json.routes[0]);
|
intersections = this.intersectionList(json.routes[0]);
|
||||||
modes = this.modeList(json.routes[0]);
|
modes = this.modeList(json.routes[0]);
|
||||||
|
driving_sides = this.drivingSideList(json.routes[0]);
|
||||||
classes = this.classesList(json.routes[0]);
|
classes = this.classesList(json.routes[0]);
|
||||||
times = this.timeList(json.routes[0]);
|
times = this.timeList(json.routes[0]);
|
||||||
distances = this.distanceList(json.routes[0]);
|
distances = this.distanceList(json.routes[0]);
|
||||||
@ -186,6 +188,10 @@ module.exports = function () {
|
|||||||
putValue('weight', weight);
|
putValue('weight', weight);
|
||||||
putValue('approach', approaches);
|
putValue('approach', approaches);
|
||||||
|
|
||||||
|
if (driving_sides) {
|
||||||
|
putValue('driving_side', driving_sides);
|
||||||
|
}
|
||||||
|
|
||||||
for (var key in row) {
|
for (var key in row) {
|
||||||
if (this.FuzzyMatch.match(got[key], row[key])) {
|
if (this.FuzzyMatch.match(got[key], row[key])) {
|
||||||
got[key] = row[key];
|
got[key] = row[key];
|
||||||
|
@ -141,7 +141,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
path_point.is_left_hand_driving});
|
||||||
|
|
||||||
if (leg_data_index + 1 < leg_data.size())
|
if (leg_data_index + 1 < leg_data.size())
|
||||||
{
|
{
|
||||||
@ -219,7 +220,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
maneuver,
|
maneuver,
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
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
|
// In this case the source + target are on the same edge segment
|
||||||
else
|
else
|
||||||
@ -261,7 +263,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.FrontIndex(segment_index),
|
leg_geometry.FrontIndex(segment_index),
|
||||||
leg_geometry.BackIndex(segment_index) + 1,
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
facade.IsLeftHandDriving(source_node_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||||
@ -301,7 +304,8 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
|
|||||||
std::move(maneuver),
|
std::move(maneuver),
|
||||||
leg_geometry.locations.size() - 1,
|
leg_geometry.locations.size() - 1,
|
||||||
leg_geometry.locations.size(),
|
leg_geometry.locations.size(),
|
||||||
{intersection}});
|
{intersection},
|
||||||
|
facade.IsLeftHandDriving(source_node_id)});
|
||||||
|
|
||||||
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);
|
||||||
|
@ -76,6 +76,7 @@ struct RouteStep
|
|||||||
std::size_t geometry_begin;
|
std::size_t geometry_begin;
|
||||||
std::size_t geometry_end;
|
std::size_t geometry_end;
|
||||||
std::vector<IntermediateIntersection> intersections;
|
std::vector<IntermediateIntersection> intersections;
|
||||||
|
bool is_left_hand_driving;
|
||||||
|
|
||||||
// remove all information from the route step, marking it as invalid (used to indicate empty
|
// remove all information from the route step, marking it as invalid (used to indicate empty
|
||||||
// steps to be removed).
|
// steps to be removed).
|
||||||
@ -129,6 +130,7 @@ inline void RouteStep::Invalidate()
|
|||||||
geometry_end = 0;
|
geometry_end = 0;
|
||||||
intersections.clear();
|
intersections.clear();
|
||||||
intersections.push_back(getInvalidIntersection());
|
intersections.push_back(getInvalidIntersection());
|
||||||
|
is_left_hand_driving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elongate by another step in front
|
// Elongate by another step in front
|
||||||
|
@ -57,6 +57,9 @@ struct PathData
|
|||||||
util::guidance::TurnBearing pre_turn_bearing;
|
util::guidance::TurnBearing pre_turn_bearing;
|
||||||
// bearing (as seen from the intersection) post-turn
|
// bearing (as seen from the intersection) post-turn
|
||||||
util::guidance::TurnBearing post_turn_bearing;
|
util::guidance::TurnBearing post_turn_bearing;
|
||||||
|
|
||||||
|
// Driving side of the turn
|
||||||
|
bool is_left_hand_driving;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InternalRouteResult
|
struct InternalRouteResult
|
||||||
|
@ -185,6 +185,8 @@ void annotatePath(const FacadeT &facade,
|
|||||||
: 0);
|
: 0);
|
||||||
const std::size_t end_index = weight_vector.size();
|
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 >= 0);
|
||||||
BOOST_ASSERT(start_index < end_index);
|
BOOST_ASSERT(start_index < end_index);
|
||||||
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
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,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
util::guidance::TurnBearing(0),
|
||||||
util::guidance::TurnBearing(0)});
|
util::guidance::TurnBearing(0),
|
||||||
|
is_left_hand_driving});
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(unpacked_path.size() > 0);
|
BOOST_ASSERT(unpacked_path.size() > 0);
|
||||||
if (facade.HasLaneData(turn_id))
|
if (facade.HasLaneData(turn_id))
|
||||||
@ -254,6 +257,7 @@ void annotatePath(const FacadeT &facade,
|
|||||||
// t: fwd_segment 3
|
// t: fwd_segment 3
|
||||||
// -> (U, v), (v, w), (w, x)
|
// -> (U, v), (v, w), (w, x)
|
||||||
// note that (x, t) is _not_ included but needs to be added later.
|
// 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;
|
for (std::size_t segment_idx = start_index; segment_idx != end_index;
|
||||||
(start_index < end_index ? ++segment_idx : --segment_idx))
|
(start_index < end_index ? ++segment_idx : --segment_idx))
|
||||||
{
|
{
|
||||||
@ -273,7 +277,8 @@ void annotatePath(const FacadeT &facade,
|
|||||||
EMPTY_ENTRY_CLASS,
|
EMPTY_ENTRY_CLASS,
|
||||||
datasource_vector[segment_idx],
|
datasource_vector[segment_idx],
|
||||||
util::guidance::TurnBearing(0),
|
util::guidance::TurnBearing(0),
|
||||||
util::guidance::TurnBearing(0)});
|
util::guidance::TurnBearing(0),
|
||||||
|
is_target_left_hand_driving});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unpacked_path.size() > 0)
|
if (unpacked_path.size() > 0)
|
||||||
|
@ -563,7 +563,7 @@ function WayHandlers.driving_side(profile, way, result, data)
|
|||||||
elseif driving_side == 'right' then
|
elseif driving_side == 'right' then
|
||||||
result.is_left_hand_driving = false
|
result.is_left_hand_driving = false
|
||||||
else
|
else
|
||||||
result.is_left_hand_driving = profile.left_hand_driving
|
result.is_left_hand_driving = profile.properties.left_hand_driving
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -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["mode"] = extractor::travelModeToString(std::move(step.mode));
|
||||||
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
|
route_step.values["maneuver"] = makeStepManeuver(std::move(step.maneuver));
|
||||||
route_step.values["geometry"] = std::move(geometry);
|
route_step.values["geometry"] = std::move(geometry);
|
||||||
|
route_step.values["driving_side"] = step.is_left_hand_driving ? "left" : "right";
|
||||||
|
|
||||||
util::json::Array intersections;
|
util::json::Array intersections;
|
||||||
intersections.values.reserve(step.intersections.size());
|
intersections.values.reserve(step.intersections.size());
|
||||||
|
@ -64,6 +64,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
|||||||
{"geometry", "yw_jGupkl@??"},
|
{"geometry", "yw_jGupkl@??"},
|
||||||
{"name", "Boulevard du Larvotto"},
|
{"name", "Boulevard du Larvotto"},
|
||||||
{"mode", "driving"},
|
{"mode", "driving"},
|
||||||
|
{"driving_side", "right"},
|
||||||
{"maneuver",
|
{"maneuver",
|
||||||
json::Object{{
|
json::Object{{
|
||||||
{"location", location},
|
{"location", location},
|
||||||
@ -84,6 +85,7 @@ BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
|
|||||||
{"geometry", "yw_jGupkl@"},
|
{"geometry", "yw_jGupkl@"},
|
||||||
{"name", "Boulevard du Larvotto"},
|
{"name", "Boulevard du Larvotto"},
|
||||||
{"mode", "driving"},
|
{"mode", "driving"},
|
||||||
|
{"driving_side", "right"},
|
||||||
{"maneuver",
|
{"maneuver",
|
||||||
json::Object{{{"location", location},
|
json::Object{{{"location", location},
|
||||||
{"bearing_before", 58},
|
{"bearing_before", 58},
|
||||||
|
Loading…
Reference in New Issue
Block a user