diff --git a/features/testbot/weight.feature b/features/testbot/weight.feature index 39edffaeb..43acae992 100644 --- a/features/testbot/weight.feature +++ b/features/testbot/weight.feature @@ -260,3 +260,49 @@ Feature: Weight tests | e,a | ,, | 60m +-.1 | 0.211,2.22,0 | 10.1s,200s,0s | | e,d | ,, | 40m +-.1 | 2.009,1.11,0 | 189.9s,100s,0s | | d,e | ,, | 40m +-.1 | 0.211,1.11,0 | 10.1s,100s,0s | + + Scenario: Step weights -- segment_function with speed and turn updates + Given the profile file "testbot" extended with + """ + api_version = 1 + properties.traffic_signal_penalty = 0 + properties.u_turn_penalty = 0 + properties.weight_name = 'steps' + function way_function(way, result) + result.forward_mode = mode.driving + result.backward_mode = mode.driving + result.weight = 42 + result.duration = 3 + end + function segment_function (segment) + segment.weight = 10 + segment.duration = 11 + end + """ + + And the node map + """ + a---b---c---d + . + e + """ + And the ways + | nodes | + | abcd | + | ce | + And the speed file + """ + 1,2,36,42 + 2,1,36,42 + """ + And the turn penalty file + """ + 2,3,5,25.5,16.7 + """ + And the contract extra arguments "--segment-speed-file {speeds_file} --turn-penalty-file {penalties_file}" + + When I route I should get + | waypoints | route | distance | weights | times | + | a,d | , | 59.9m | 62,0 | 24s,0s | + | a,e | ,, | 60.1m | 68.7,10,0 | 38.5s,11s,0s | + | d,e | ,, | 39.9m | 10,10,0 | 11s,11s,0s | diff --git a/include/extractor/edge_based_graph_factory.hpp b/include/extractor/edge_based_graph_factory.hpp index c0049702a..e2a0a2cb1 100644 --- a/include/extractor/edge_based_graph_factory.hpp +++ b/include/extractor/edge_based_graph_factory.hpp @@ -61,10 +61,10 @@ struct SegmentBlock OSMNodeID this_osm_node_id; double segment_length; EdgeWeight segment_weight; - // TODO MKR add duration if needed + EdgeWeight segment_duration; }; #pragma pack(pop) -static_assert(sizeof(SegmentBlock) == 20, "SegmentBlock is not packed correctly"); +static_assert(sizeof(SegmentBlock) == 24, "SegmentBlock is not packed correctly"); #pragma pack(push, 1) struct TurnPenaltiesHeader diff --git a/src/contractor/contractor.cpp b/src/contractor/contractor.cpp index 72f7d4ad6..f677faca1 100644 --- a/src/contractor/contractor.cpp +++ b/src/contractor/contractor.cpp @@ -728,7 +728,7 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, }; const auto maybe_load_turn_duration_penalties = [&] { - if (!update_turn_penalties) + if (!update_edge_weights && !update_turn_penalties) return; using storage::io::FileReader; FileReader file(config.turn_duration_penalties_path, FileReader::HasNoFingerprint); @@ -737,7 +737,7 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, tbb::parallel_invoke(maybe_load_turn_weight_penalties, maybe_load_turn_duration_penalties); - if (update_turn_penalties && turn_duration_penalties.empty()) + if ((update_edge_weights || update_turn_penalties) && turn_duration_penalties.empty()) { // Copy-on-write for duration penalties as turn weight penalties turn_duration_penalties = turn_weight_penalties; } @@ -778,11 +778,12 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, // Find a segment with zero speed and simultaneously compute the new edge weight EdgeWeight new_weight = 0; - // TODO MKR add new_duration if needed + EdgeWeight new_duration = 0; auto osm_node_id = header->previous_osm_node_id; bool skip_edge = std::find_if(first, last, [&](const auto &segment) { auto segment_weight = segment.segment_weight; + auto segment_duration = segment.segment_duration; if (auto value = segment_speed_lookup({osm_node_id, segment.this_osm_node_id})) { // If we hit a 0-speed edge, then it's effectively not traversible. @@ -790,19 +791,17 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, if (value->speed == 0) return true; - // TODO MKR add new_duration = ConvertToDuration(segment.segment_length, - // value->speed) if needed + segment_duration = ConvertToDuration(segment.segment_length, value->speed); - segment_weight = - std::isfinite(value->weight) - ? std::round(value->weight * config.weight_multiplier) - : ConvertToDuration(segment.segment_length, value->speed); + segment_weight = std::isfinite(value->weight) + ? std::round(value->weight * config.weight_multiplier) + : segment_duration; } // Update the edge weight and the next OSM node ID osm_node_id = segment.this_osm_node_id; new_weight += segment_weight; - // TODO MKR new_duration += segment_duration; + new_duration += segment_duration; return false; }) != last; @@ -819,9 +818,10 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, // Get the turn penalty and update to the new value if required const auto &turn_index = turn_index_blocks[edge_index]; auto turn_weight_penalty = turn_weight_penalties[edge_index]; + auto turn_duration_penalty = turn_duration_penalties[edge_index]; if (auto value = turn_penalty_lookup(turn_index)) { - auto turn_duration_penalty = + turn_duration_penalty = boost::numeric_cast(std::round(value->duration * 10.)); turn_weight_penalty = std::isfinite(value->weight) ? boost::numeric_cast(std::round( @@ -849,7 +849,7 @@ Contractor::LoadEdgeExpandedGraph(const ContractorConfig &config, // Update edge weight inbuffer.weight = new_weight + turn_weight_penalty; - // TODO MKR inbuffer.duration = new_duration + turn_duration_penalty; + inbuffer.duration = new_duration + turn_duration_penalty; } edge_based_edge_list.emplace_back(std::move(inbuffer)); diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 797fd3891..d4ce0329c 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -599,8 +599,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const double segment_length = util::coordinate_calculation::greatCircleDistance(from, to); - lookup::SegmentBlock nodeblock = { - to.node_id, segment_length, target_node.weight}; + lookup::SegmentBlock nodeblock{to.node_id, + segment_length, + target_node.weight, + target_node.duration}; edge_segment_file.write(reinterpret_cast(&nodeblock), sizeof(nodeblock));