Skip to content

Commit 1d367cc

Browse files
committed
Add source phantom weight to first segment when merging legs (#4949)
Fix annotation values for annotations on edges where phantom nodes are snapped.
1 parent 860c452 commit 1d367cc

File tree

7 files changed

+152
-18
lines changed

7 files changed

+152
-18
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 5.16.4
2+
- Changes from 5.16.3:
3+
- Bugfixes:
4+
- FIXED: Properly calculate annotations for speeds, durations and distances when waypoints are used with mapmatching [#4949](https://github.com/Project-OSRM/osrm-backend/pull/4949)
5+
16
# 5.16.3
27
- Changes from 5.16.2:
38
- FIXED: Remove the last short annotation segment in `trimShortSegments` [#4946](https://github.com/Project-OSRM/osrm-backend/pull/4946)

features/testbot/matching.feature

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,3 +718,78 @@ Feature: Basic Map Matching
718718
| abe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok |
719719
| ahd | 1,0.99973,1.00027,0.99973,1.00027,0.999461 | depart,turn right,arrive | Ok |
720720
| ahe | 1,0.99973,1.00027,0.99973,1.00027,1 | depart,turn left,arrive | Ok |
721+
722+
@match @testbot
723+
Scenario: Regression test - add source phantoms properly (one phantom on one edge)
724+
Given the profile "testbot"
725+
Given a grid size of 10 meters
726+
Given the node map
727+
"""
728+
a--1-b2-cd3--e
729+
"""
730+
And the ways
731+
| nodes |
732+
| ab |
733+
| bcd |
734+
| de |
735+
Given the query options
736+
| geometries | geojson |
737+
| overview | full |
738+
| steps | true |
739+
| waypoints | 0;2 |
740+
| annotations | duration,weight |
741+
| generate_hints | false |
742+
When I match I should get
743+
| trace | geometry | a:duration | a:weight | duration |
744+
| 123 | 1.000135,1,1.000225,1,1.00036,1,1.000405,1,1.00045,1 | 1:1.5:0.5:0.5 | 1:1.5:0.5:0.5 | 3.5 |
745+
| 321 | 1.00045,1,1.000405,1,1.00036,1,1.000225,1,1.000135,1 | 0.5:0.5:1.5:1 | 0.5:0.5:1.5:1 | 3.5 |
746+
747+
@match @testbot
748+
Scenario: Regression test - add source phantom properly (two phantoms on one edge)
749+
Given the profile "testbot"
750+
Given a grid size of 10 meters
751+
Given the node map
752+
"""
753+
a--1-b23-c4--d
754+
"""
755+
And the ways
756+
| nodes |
757+
| ab |
758+
| bc |
759+
| cd |
760+
Given the query options
761+
| geometries | geojson |
762+
| overview | full |
763+
| steps | true |
764+
| waypoints | 0;3 |
765+
| annotations | duration,weight |
766+
| generate_hints | false |
767+
When I match I should get
768+
| trace | geometry | a:duration | a:weight | duration |
769+
| 1234 | 1.000135,1,1.000225,1,1.000405,1,1.00045,1 | 1:2:0.5 | 1:2:0.5 | 3.5 |
770+
| 4321 | 1.00045,1,1.000405,1,1.000225,1,1.000135,1 | 0.5:2:1 | 0.5:2:1 | 3.5 |
771+
772+
@match @testbot
773+
Scenario: Regression test - add source phantom properly (two phantoms on one edge)
774+
Given the profile "testbot"
775+
Given a grid size of 10 meters
776+
Given the node map
777+
"""
778+
a--12345-b
779+
"""
780+
And the ways
781+
| nodes |
782+
| ab |
783+
Given the query options
784+
| geometries | geojson |
785+
| overview | full |
786+
| steps | true |
787+
| waypoints | 0;3 |
788+
| annotations | duration,weight,distance |
789+
| generate_hints | false |
790+
791+
# These should have the same weights/duration in either direction
792+
When I match I should get
793+
| trace | geometry | a:distance | a:duration | a:weight | duration |
794+
| 2345 | 1.00018,1,1.000315,1 | 15.013264 | 1.5 | 1.5 | 1.5 |
795+
| 4321 | 1.00027,1,1.000135,1 | 15.013264 | 1.5 | 1.5 | 1.5 |

features/testbot/traffic_speeds.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ Feature: Traffic - speeds
136136

137137
When I route I should get
138138
| from | to | route | speed | weights | a:datasources | a:speed | a:nodes|
139-
| a | b | fb,fb | 36 km/h | 329.4,0 | 0 | 7 | 6:2 |
139+
| a | b | fb,fb | 36 km/h | 329.4,0 | 0 | 10 | 6:2 |
140140
| a | c | fb,bc,bc | 30 km/h | 329.4,741.5,0 | 0:1 | 10:7.5 | 6:2:3 |
141141
| b | c | bc,bc | 27 km/h | 741.5,0 | 1 | 7.5 | 2:3 |
142142
| a | d | fb,df,df | 36 km/h | 140,487.5,0 | 0:0 | 10:10 | 2:6:4 |
143143
| d | c | dc,dc | 36 km/h | 956.8,0 | 0 | 10 | 4:3 |
144-
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 | 3.5 | 6:2 |
145-
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 | 5.4 | 6:2 |
144+
| g | b | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 |
145+
| a | g | fb,fb | 36 km/h | 164.7,0 | 0 | 10 | 6:2 |
146146

147147

148148
Scenario: Verify that negative values cause an error, they're not valid at all

features/testbot/weight.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ Feature: Weight tests
5353

5454
When I route I should get
5555
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
56-
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | 6.7 |
57-
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | 6.5 |
56+
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 |
57+
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 2.1 | 2.1 | 9.5 |
5858
| s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | 9.7:10 |
5959
| e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | 10:9.7 |
6060

include/engine/guidance/assemble_geometry.hpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "util/coordinate_calculation.hpp"
1313

1414
#include <algorithm>
15+
#include <cmath>
1516
#include <utility>
1617
#include <vector>
1718

@@ -113,15 +114,39 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
113114
const std::vector<DatasourceID> forward_datasources =
114115
facade.GetUncompressedForwardDatasources(target_geometry_id);
115116

116-
// FIXME if source and target phantoms are on the same segment then duration and weight
117-
// will be from one projected point till end of segment
118-
// testbot/weight.feature:Start and target on the same and adjacent edge
119-
geometry.annotations.emplace_back(LegGeometry::Annotation{
120-
current_distance,
121-
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
122-
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
123-
facade.GetWeightMultiplier(),
124-
forward_datasources[target_node.fwd_segment_position]});
117+
// This happens when the source/target are on the same edge-based-node
118+
// There will be no entries in the unpacked path, thus no annotations.
119+
// We will need to calculate the lone annotation by looking at the position
120+
// of the source/target nodes, and calculating their differences.
121+
if (geometry.annotations.empty())
122+
{
123+
auto duration =
124+
std::abs(
125+
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) -
126+
(reversed_source ? source_node.reverse_duration : source_node.forward_duration)) /
127+
10.;
128+
BOOST_ASSERT(duration >= 0);
129+
auto weight =
130+
std::abs((reversed_target ? target_node.reverse_weight : target_node.forward_weight) -
131+
(reversed_source ? source_node.reverse_weight : source_node.forward_weight)) /
132+
facade.GetWeightMultiplier();
133+
BOOST_ASSERT(weight >= 0);
134+
135+
geometry.annotations.emplace_back(
136+
LegGeometry::Annotation{current_distance,
137+
duration,
138+
weight,
139+
forward_datasources[target_node.fwd_segment_position]});
140+
}
141+
else
142+
{
143+
geometry.annotations.emplace_back(LegGeometry::Annotation{
144+
current_distance,
145+
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
146+
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
147+
facade.GetWeightMultiplier(),
148+
forward_datasources[target_node.fwd_segment_position]});
149+
}
125150

126151
geometry.segment_offsets.push_back(geometry.locations.size());
127152
geometry.locations.push_back(target_node.location);

include/engine/internal_route_result.hpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,32 @@ inline InternalRouteResult CollapseInternalRouteResult(const InternalRouteResult
145145
collapsed.target_traversed_in_reverse.back() =
146146
leggy_result.target_traversed_in_reverse[i];
147147
// copy path segments into current leg
148-
last_segment.insert(last_segment.end(),
149-
leggy_result.unpacked_path_segments[i].begin(),
150-
leggy_result.unpacked_path_segments[i].end());
148+
if (!leggy_result.unpacked_path_segments[i].empty())
149+
{
150+
auto old_size = last_segment.size();
151+
last_segment.insert(last_segment.end(),
152+
leggy_result.unpacked_path_segments[i].begin(),
153+
leggy_result.unpacked_path_segments[i].end());
154+
155+
// The first segment of the unpacked path is missing the weight of the
156+
// source phantom. We need to add those values back so that the total
157+
// edge weight is correct
158+
last_segment[old_size].weight_until_turn +=
159+
160+
leggy_result.source_traversed_in_reverse[i]
161+
? leggy_result.segment_end_coordinates[i].source_phantom.reverse_weight
162+
: leggy_result.segment_end_coordinates[i].source_phantom.forward_weight;
163+
164+
last_segment[old_size].duration_until_turn +=
165+
leggy_result.source_traversed_in_reverse[i]
166+
? leggy_result.segment_end_coordinates[i].source_phantom.reverse_duration
167+
: leggy_result.segment_end_coordinates[i].source_phantom.forward_duration;
168+
}
151169
}
152170
}
171+
172+
BOOST_ASSERT(collapsed.segment_end_coordinates.size() ==
173+
collapsed.unpacked_path_segments.size());
153174
return collapsed;
154175
}
155176
}

unit_tests/library/route.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,20 @@ BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance)
407407
const auto &durations = annotation.values.at("duration").get<json::Array>().values;
408408
const auto &distances = annotation.values.at("distance").get<json::Array>().values;
409409
int length = speeds.size();
410+
411+
BOOST_CHECK_EQUAL(length, 1);
410412
for (int i = 0; i < length; i++)
411413
{
412414
auto speed = speeds[i].get<json::Number>().value;
413415
auto duration = durations[i].get<json::Number>().value;
414416
auto distance = distances[i].get<json::Number>().value;
415-
BOOST_CHECK_EQUAL(speed, std::round(distance / duration * 10.) / 10.);
417+
auto calc = std::round(distance / duration * 10.) / 10.;
418+
BOOST_CHECK_EQUAL(speed, std::isnan(calc) ? 0 : calc);
419+
420+
// Because we route from/to the same location, all annotations should be 0;
421+
BOOST_CHECK_EQUAL(speed, 0);
422+
BOOST_CHECK_EQUAL(distance, 0);
423+
BOOST_CHECK_EQUAL(duration, 0);
416424
}
417425
}
418426

0 commit comments

Comments
 (0)