diff --git a/docs/http.md b/docs/http.md index 936a624aa..956ea8e7d 100644 --- a/docs/http.md +++ b/docs/http.md @@ -539,10 +539,10 @@ Annotation of the whole route leg with fine-grained information about each segme **Properties** - `distance`: The distance, in metres, between each pair of coordinates -- `duration`: The duration between each pair of coordinates, in seconds +- `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns. - `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` - `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates -- `weight`: The weights between each pair of coordinates +- `weight`: The weights between each pair of coordinates. Does not include any turn costs. - `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place #### Example diff --git a/features/testbot/annotations.feature b/features/testbot/annotations.feature new file mode 100644 index 000000000..c82d9f8f6 --- /dev/null +++ b/features/testbot/annotations.feature @@ -0,0 +1,30 @@ +@routing @speed @annotations @turn_penalty +Feature: Annotations + + Background: + Given the profile "turnbot" + Given a grid size of 100 meters + + Scenario: Ensure that turn penalties aren't included in annotations + Given the node map + """ + h i + j k l m + """ + + And the query options + | annotations | duration,speed,weight | + + And the ways + | nodes | highway | + | hk | residential | + | il | residential | + | jk | residential | + | lk | residential | + | lm | residential | + + When I route I should get + | from | to | route | a:speed | a:weight | + | h | j | hk,jk,jk | 6.7:6.7 | 15:15 | + | i | m | il,lm,lm | 6.7:6.7 | 15:15 | + | j | m | jk,lm | 6.7:6.7:6.7 | 15:15:15 | \ No newline at end of file diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 761f4c637..a9f72ba84 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -78,11 +78,19 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, } prev_coordinate = coordinate; - geometry.annotations.emplace_back( - LegGeometry::Annotation{current_distance, - path_point.duration_until_turn / 10., - path_point.weight_until_turn / facade.GetWeightMultiplier(), - path_point.datasource_id}); + geometry.annotations.emplace_back(LegGeometry::Annotation{ + current_distance, + // NOTE: we want annotations to include only the duration/weight + // of the segment itself. For segments immediately before + // a turn, the duration_until_turn/weight_until_turn values + // include the turn cost. To counter this, we subtract + // the duration_of_turn/weight_of_turn value, which is 0 for + // non-preceeding-turn segments, but contains the turn value + // for segments before a turn. + (path_point.duration_until_turn - path_point.duration_of_turn) / 10., + (path_point.weight_until_turn - path_point.weight_of_turn) / + facade.GetWeightMultiplier(), + path_point.datasource_id}); geometry.locations.push_back(std::move(coordinate)); geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node)); } diff --git a/include/engine/guidance/leg_geometry.hpp b/include/engine/guidance/leg_geometry.hpp index 1c5fa54b2..a1ba56c81 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -38,8 +38,12 @@ struct LegGeometry struct Annotation { double distance; // distance in meters - double duration; // duration in seconds - double weight; // weight value + + // Total duration of a segment, in seconds, NOT including + // the turn penalty if the segment preceeds a turn + double duration; + double weight; // weight value, NOT including the turn weight + DatasourceID datasource; }; std::vector annotations; diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index 395a9a1f9..9e22d7617 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -24,9 +24,17 @@ struct PathData // name of the street that leads to the turn unsigned name_id; // weight that is traveled on the segment until the turn is reached + // including the turn weight, if one exists EdgeWeight weight_until_turn; - // duration that is traveled on the segment until the turn is reached + // If this segment immediately preceeds a turn, then duration_of_turn + // will contain the weight of the turn. Otherwise it will be 0. + EdgeWeight weight_of_turn; + // duration that is traveled on the segment until the turn is reached, + // including a turn if the segment preceeds one. EdgeWeight duration_until_turn; + // If this segment immediately preceeds a turn, then duration_of_turn + // will contain the duration of the turn. Otherwise it will be 0. + EdgeWeight duration_of_turn; // instruction to execute at the turn extractor::guidance::TurnInstruction turn_instruction; // turn lane data diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 3524adc8e..98f1ef8e4 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -186,7 +186,9 @@ void annotatePath(const FacadeT &facade, unpacked_path.push_back(PathData{id_vector[segment_idx + 1], name_index, weight_vector[segment_idx], + 0, duration_vector[segment_idx], + 0, extractor::guidance::TurnInstruction::NO_TURN(), {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, travel_mode, @@ -200,10 +202,15 @@ void annotatePath(const FacadeT &facade, if (facade.HasLaneData(turn_id)) unpacked_path.back().lane_data = facade.GetLaneData(turn_id); + const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id); + const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id); + unpacked_path.back().entry_class = facade.GetEntryClass(turn_id); unpacked_path.back().turn_instruction = turn_instruction; - unpacked_path.back().duration_until_turn += facade.GetDurationPenaltyForEdgeID(turn_id); - unpacked_path.back().weight_until_turn += facade.GetWeightPenaltyForEdgeID(turn_id); + unpacked_path.back().duration_until_turn += turn_duration; + unpacked_path.back().duration_of_turn = turn_duration; + unpacked_path.back().weight_until_turn += turn_weight; + unpacked_path.back().weight_of_turn = turn_weight; unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id); unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id); } @@ -262,7 +269,9 @@ void annotatePath(const FacadeT &facade, PathData{id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], facade.GetNameIndex(target_node_id), weight_vector[segment_idx], + 0, duration_vector[segment_idx], + 0, extractor::guidance::TurnInstruction::NO_TURN(), {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, facade.GetTravelMode(target_node_id),