Support snapping to multiple ways at an input location (#5953)

This PR improves routing results by adding support for snapping to
multiple ways at input locations.

This means all edges at the snapped location can act as source/target
candidates for routing search, ensuring we always find the best route,
and not the one dependent on the edge selected.
This commit is contained in:
Michael Bell
2022-08-27 11:36:20 +01:00
committed by GitHub
parent bb18a2b428
commit d74e7b66bd
59 changed files with 2820 additions and 1964 deletions
+3 -3
View File
@@ -28,7 +28,7 @@ Feature: Bicycle - Route around alleys
When I route I should get
| from | to | a:nodes | weight | # |
| a | f | 1:2:3:6 | 200.4 | Avoids d,e,f |
| a | e | 1:2:5 | 176.4 | Take the alley b,e if neccessary |
| d | f | 4:1:2:3:6 | 252.6 | Avoids the alley d,e,f |
| a | f | 1:2:3:6 | 196.2 | Avoids d,e,f |
| a | e | 1:2:5 | 172.2 | Take the alley b,e if neccessary |
| d | f | 4:1:2:3:6 | 248.4 | Avoids the alley d,e,f |
+16 -15
View File
@@ -7,10 +7,10 @@ Feature: Car - Destination only, no passing through
Scenario: Car - Destination only street
Given the node map
"""
a e
b c d
a e
b1 c 2d
x y
x y
"""
And the ways
@@ -23,21 +23,21 @@ Feature: Car - Destination only, no passing through
When I route I should get
| from | to | route |
| a | b | ab,ab |
| a | c | ab,bcd |
| a | d | ab,bcd,bcd |
| a | c | ab,bcd,bcd |
| a | 2 | ab,bcd,bcd |
| a | e | axye,axye |
| e | d | de,de |
| e | c | de,bcd |
| e | b | de,bcd,bcd |
| e | c | de,bcd,bcd |
| e | 1 | de,bcd,bcd |
| e | a | axye,axye |
Scenario: Car - Destination only street
Given the node map
"""
a e
b c d
a e
b1 c 2d
x y
x y
"""
And the ways
@@ -51,12 +51,12 @@ Feature: Car - Destination only, no passing through
When I route I should get
| from | to | route |
| a | b | ab,ab |
| a | c | ab,bc |
| a | d | ab,cd |
| a | c | ab,bc,bc |
| a | 2 | ab,bc,cd |
| a | e | axye,axye |
| e | d | de,de |
| e | c | de,cd |
| e | b | de,bc |
| e | c | de,cd,cd |
| e | 1 | de,cd,bc |
| e | a | axye,axye |
Scenario: Car - Routing inside a destination only area
@@ -117,6 +117,7 @@ Feature: Car - Destination only, no passing through
+ \
+ |
d |
1 |
\___e
"""
@@ -129,7 +130,7 @@ Feature: Car - Destination only, no passing through
When I route I should get
| from | to | route |
| e | a | acbe,acbe |
| d | a | de,acbe,acbe |
| 1 | a | de,acbe,acbe |
| c | d | cd,cd |
Scenario: Car - Routing through a parking lot tagged access=destination,service
+2 -2
View File
@@ -411,7 +411,7 @@ Feature: Car - Turn restrictions
y
i j f b x a e g h
c d
c1 d
"""
And the ways
@@ -438,7 +438,7 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route |
| e | f | ae,xa,bx,fb,fb |
| c | f | dc,da,ae,ge,hg,hg,ge,ae,xa,bx,fb,fb |
| 1 | f | dc,da,ae,ge,hg,hg,ge,ae,xa,bx,fb,fb |
| d | f | da,ae,ge,hg,hg,ge,ae,xa,bx,fb,fb |
@except
@@ -332,10 +332,11 @@ Feature: Merge Segregated Roads
|
.b.
c h
1 |
| 4
| |
| |
1 2
| |
2 |
| 3
d g
'e'
|
@@ -354,13 +355,13 @@ Feature: Merge Segregated Roads
| hb | road | yes |
When I route I should get
| waypoints | turns | route | intersections |
| waypoints | turns | route | intersections |
| a,f | depart,arrive | road,road | true:180,false:0 true:180,false:0 true:180;true:0 |
| c,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| 1,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| 2,f | depart,arrive | bridge,road | true:180,false:0 true:180;true:0 |
| f,a | depart,arrive | road,road | true:0,true:0 false:180,true:0 false:180;true:180 |
| g,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
| 2,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
| 3,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
| 4,a | depart,arrive | bridge,road | true:0,true:0 false:180;true:180 |
@negative
Scenario: Traffic Circle
+6 -6
View File
@@ -67,10 +67,10 @@ Feature: Compass bearing
Scenario: Bearing in a roundabout
Given the node map
"""
k d c j
e b
f a
l g h i
k d 1c j
e b
f a
l g2 h i
"""
And the ways
@@ -94,8 +94,8 @@ Feature: Compass bearing
When I route I should get
| from | to | route | bearing |
| c | b | cd,de,ef,fg,gh,ha,ab,ab | 0->270,270->225,225->180,180->135,135->90,90->45,45->0,0->0 |
| g | f | gh,ha,ab,bc,cd,de,ef,ef | 0->90,90->45,45->0,0->315,315->270,270->225,225->180,180->0 |
| 1 | b | cd,de,ef,fg,gh,ha,ab,ab | 0->270,270->225,225->180,180->135,135->90,90->45,45->0,0->0 |
| 2 | f | gh,ha,ab,bc,cd,de,ef,ef | 0->90,90->45,45->0,0->315,315->270,270->225,225->180,180->0 |
Scenario: Bearing should stay constant when zig-zagging
Given the node map
+8 -9
View File
@@ -589,12 +589,12 @@ Feature: Basic Distance Matrix
When I request a travel distance matrix I should get
| | a | b | c | d | e | f |
| a | 0 | 100 | 300 | 650 | 1934.5 | 1534.6 |
| b | 760.6 | 0 | 200 | 550.1 | 1834.6 | 1434.6 |
| c | 560.6 | 660.5 | 0 | 350 | 1634.6 | 1234.6 |
| d | 1484.6 | 1584.5| 1784.5 | 0 | 1284.5 | 884.6 |
| e | 200 | 300 | 500 | 710.6 | 0 | 1595.2 |
| f | 600 | 699.9 | 899.9 | 1110.5 | 399.9 | 0 |
| a | 0 | 100 | 300 | 650 | 660.5 | 1534.6 |
| b | 760.6 | 0 | 200 | 550.1 | 560.6 | 1434.6 |
| c | 560.6 | 660.5 | 0 | 350 | 360.5 | 1234.6 |
| d | 1484.6 | 1584.5| 1645.1 | 0 | 1284.5 | 884.6 |
| e | 200 | 300 | 360.5 | 710.6 | 0 | 1595.2 |
| f | 600 | 699.9 | 760.5 | 884.6 | 399.9 | 0 |
Scenario: Testbot - Filling in noroutes with estimates (defaults to input coordinate location)
@@ -720,11 +720,10 @@ Feature: Basic Distance Matrix
| 1 | 2 | abcdef,fghij,fghij | 1000.1m |
| 1 | 3 | abcdef,fghij,fghij | 1400.1m |
| 2 | 3 | fghij,fghij | 400m |
When I request a travel distance matrix I should get
| | 1 | 2 | 3 |
| | 1 | 2 | 3 |
| 1 | 0 | 1000.1 | 1400.1 |
| 2 | 1000.1 | 0 | 400 |
| 3 | 1400.1 | 400 | 0 |
+5 -5
View File
@@ -491,18 +491,18 @@ Feature: Basic Duration Matrix
When I route I should get
| from | to | route | distance | time | weight |
| a | c | ac,ac | 200m | 5s | 5 |
| a | c | ac,ac | 200m | 1s | 1 |
When I request a travel time matrix I should get
| | a | b | c | d |
| a | 0 | 1 | 5 | 10 |
| | a | b | c | d |
| a | 0 | 1 | 1 | 6 |
When I request a travel time matrix I should get
| | a |
| a | 0 |
| b | 1 |
| c | 15 |
| d | 10 |
| c | 1 |
| d | 6 |
Scenario: Testbot - OneToMany vs ManyToOne
Given the node map
+629
View File
@@ -0,0 +1,629 @@
Feature: Snapping at intersections
Background:
# Use turnbot so that we can validate when we are
# snapping to one of many potential candidate ways
Given the profile "turnbot"
# https://github.com/Project-OSRM/osrm-backend/issues/4465
Scenario: Snapping source to intersection with one-way roads
Given the node map
"""
a e c
\ | /
d
1
"""
And the ways
| nodes | oneway |
| da | yes |
| dc | yes |
| de | yes |
When I route I should get
| from | to | route | time |
| 1 | e | de,de | 20s |
| 1 | a | da,da | 28.3s |
| 1 | c | dc,dc | 28.3s |
When I request a travel time matrix I should get
| | a | c | e |
| 1 | 28.3 | 28.3 | 20 |
Scenario: Snapping destination to intersection with one-way roads
Given the node map
"""
a e c
\ | /
d
1
"""
And the ways
| nodes | oneway |
| da | -1 |
| dc | -1 |
| de | -1 |
When I route I should get
| from | to | route | time |
| e | 1 | de,de | 20s |
| a | 1 | da,da | 28.3s |
| c | 1 | dc,dc | 28.3s |
When I request a travel time matrix I should get
| | 1 |
| a | 28.3 |
| c | 28.3 |
| e | 20 |
Scenario: Snapping to intersection with bi-directional roads
Given the node map
"""
a e
| /
d---c
1
"""
And the ways
| nodes |
| ad |
| ed |
| dc |
When I route I should get
| from | to | route | time | weight |
| 1 | c | dc,dc | 20s | 20 |
| 1 | a | ad,ad | 20s | 20 |
| 1 | e | ed,ed | 28.3s | 28.3 |
| c | 1 | dc,dc | 20s | 20 |
| a | 1 | ad,ad | 20s | 20 |
| e | 1 | ed,ed | 28.3s | 28.3 |
When I request a travel time matrix I should get
| | a | c | e |
| 1 | 20 | 20 | 28.3 |
When I request a travel time matrix I should get
| | 1 |
| a | 20 |
| c | 20 |
| e | 28.3 |
Scenario: Snapping at compressible node
Given the node map
"""
a---b---c
"""
And the ways
| nodes |
| abc |
When I route I should get
| from | to | route | time | weight |
| b | c | abc,abc | 20s | 20 |
| b | a | abc,abc | 20s | 20 |
| a | b | abc,abc | 20s | 20 |
| c | b | abc,abc | 20s | 20 |
Scenario: Snapping at compressible node with traffic lights
Given the node map
"""
a---b---c
"""
And the ways
| nodes |
| abc |
# Turnbot will use the turn penalty instead of traffic penalty.
# We do this to induce a penalty between two edges of the same
# segment.
And the nodes
| node | highway |
| b | traffic_signals |
# Snaps to first edge in forward direction
When I route I should get
| from | to | route | time | weight |
| b | c | abc,abc | 40s | 40 |
| b | a | abc,abc | 20s | 20 |
| a | b | abc,abc | 20s | 20 |
| c | b | abc,abc | 40s | 40 |
Scenario: Snapping at compressible node traffic lights, one-way
Given the node map
"""
a-->b-->c
"""
And the ways
| nodes | oneway |
| abc | yes |
# Turnbot will use the turn penalty instead of traffic penalty.
# We do this to induce a penalty between two edges of the same
# segment.
And the nodes
| node | highway |
| b | traffic_signals |
# Snaps to first edge in forward direction
When I route I should get
| from | to | route | time | weight |
| b | c | abc,abc | 40s | 40 |
| a | b | abc,abc | 20s | 20 |
When I route I should get
| from | to | code |
| b | a | NoRoute |
| c | b | NoRoute |
Scenario: Snapping at compressible node traffic lights, reverse one-way
Given the node map
"""
a<--b<--c
"""
And the ways
| nodes | oneway |
| abc | -1 |
# Turnbot will use the turn penalty instead of traffic penalty.
# We do this to induce a penalty between two edges of the same
# segment.
And the nodes
| node | highway |
| b | traffic_signals |
# Snaps to first edge in forward direction - as this is one-way,
# the forward direction has changed.
When I route I should get
| from | to | route | time | weight |
| b | a | abc,abc | 40s | 40 |
| c | b | abc,abc | 20s | 20 |
When I route I should get
| from | to | code |
| b | c | NoRoute |
| a | b | NoRoute |
Scenario: Snapping at traffic lights, reverse disabled
Given the node map
"""
a-->b-->c
"""
And the ways
| nodes |
| abc |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,1,0
3,2,0
"""
# Turnbot will use the turn penalty instead of traffic penalty.
# We do this to induce a penalty between two edges of the same
# segment.
And the nodes
| node | highway |
| b | traffic_signals |
# Snaps to first edge in forward direction.
When I route I should get
| from | to | route | time | weight |
| b | c | abc,abc | 40s | 40 |
| a | b | abc,abc | 20s | 20 |
When I route I should get
| from | to | code |
| b | a | NoRoute |
| c | b | NoRoute |
Scenario: Snapping at traffic lights, forward disabled
Given the node map
"""
a<--b<--c
"""
And the ways
| nodes |
| abc |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
2,3,0
"""
# Turnbot will use the turn penalty instead of traffic penalty.
# We do this to induce a penalty between two edges of the same
# segment.
And the nodes
| node | highway |
| b | traffic_signals |
# Forward direction is disabled, still snaps to first edge in forward direction
When I route I should get
| from | to | route | time | weight |
| b | a | abc,abc | 20s | 20 |
| c | b | abc,abc | 40s | 40 |
When I route I should get
| from | to | code |
| b | c | NoRoute |
| a | b | NoRoute |
Scenario: Snap to target node with next section of segment blocked
Given the node map
"""
a-->b---c---d<--e
"""
And the ways
| nodes |
| abc |
| cde |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
2,1,0
4,5,0
"""
When I route I should get
| from | to | route | time | weight |
| a | d | abc,cde,cde | 60s | 60 |
| e | b | cde,abc,abc | 60s | 60 |
When I route I should get
| from | to | code |
| a | e | NoRoute |
| e | a | NoRoute |
Scenario: Snapping to source node with previous section of segment blocked
Given the node map
"""
a<--b---c---d-->e
"""
And the ways
| nodes |
| abc |
| cde |
And the contract extra arguments "--segment-speed-file {speeds_file}"
And the customize extra arguments "--segment-speed-file {speeds_file}"
And the speed file
"""
1,2,0
5,4,0
"""
When I route I should get
| from | to | code |
| a | e | NoRoute |
| b | e | NoRoute |
| e | a | NoRoute |
| d | a | NoRoute |
Scenario: Only snaps to one of many equidistant nearest locations
Given the node map
"""
b-------c
| |
| |
a 1 d
"""
And the ways
| nodes |
| ab |
| bc |
| cd |
When I route I should get
| from | to | route | time | weight |
| 1 | b | ab,ab | 30s | 30 |
| 1 | c | ab,bc,bc | 80s +-1 | 80 +-1 |
Scenario: Snaps to alternative big SCC candidate if nearest candidates are not strongly connected
Given the node map
"""
1
g---h---i
a-----b-----c
|
f-----e-----d
j---k---l
2
"""
Given the extract extra arguments "--small-component-size=4"
And the ways
| nodes |
| abc |
| cd |
| fed |
| ghi |
| jkl |
# As forward direction is disabled...
When I route I should get
| from | to | route | time | weight | locations |
| 1 | 2 | abc,cd,fed,fed | 100s +-1 | 100 +-1 | b,c,d,e |
Scenario: Can use big or small SCC nearest candidates if at same location
Given the node map
"""
1
a-----b-----c
| |
g |
|
f-----e-----d
"""
Given the extract extra arguments "--small-component-size=4"
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cd | no |
| fed | no |
| bg | yes | # small SCC
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ab | bg | b | no_right_turn |
| restriction | bc | bg | b | no_left_turn |
When I route I should get
| from | to | route | time | weight | locations |
| 1 | g | bg,bg | 20s | 20 | b,g |
| 1 | e | bc,cd,fed,fed | 120s +-1 | 120 +-1 | b,c,d,e |
Scenario: Using small SCC candidates when at same location as big SCC alternatives is not supported
Given the node map
"""
1
g---h---i
a-----b-----c
| |
| |
m |
f-----e-----d
j---k---l
2
"""
Given the extract extra arguments "--small-component-size=4"
And the ways
| nodes | oneway |
| ab | no |
| bc | no |
| cd | no |
| fed | no |
| ghi | no |
| jkl | no |
| bm | yes | # small SCC
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ab | bm | b | no_right_turn |
| restriction | bc | bm | b | no_left_turn |
When I route I should get
| from | to | route | time | weight | locations |
| 1 | 2 | bc,cd,fed,fed | 120s +-1 | 120 +-1 | b,c,d,e |
| 1 | m | bc,cd,fed,fed | 120s +-1 | 120 +-1 | b,c,d,e |
Scenario: Shortest via path with continuation, simple loop
Given the node map
"""
a---b
"""
And the ways
| nodes |
| ab |
When I route I should get
| waypoints | route | time | weight |
| a,b,a | ab,ab,ab,ab | 60s | 60 |
Scenario: Shortest via path with uturns, simple loop
Given the node map
"""
a---b
"""
Given the query options
| continue_straight | false |
And the ways
| nodes |
| ab |
# Does not pay the cost of the turn
When I route I should get
| waypoints | route | time | weight |
| a,b,a | ab,ab,ab,ab | 40s | 40 |
Scenario: Shortest path with multiple endpoint snapping candidates
Given the node map
"""
b
c
a d f
e
"""
And the ways
| nodes | oneway |
| ab | no |
| ac | no |
| ad | no |
| ae | no |
| bf | no |
| cf | yes |
| df | yes |
| ef | no |
When I route I should get
| from | to | route | time | weight |
| a | f | ad,df,df | 40s | 40 |
| f | a | ef,ae,ae | 66.6s | 66.6 |
When I request a travel time matrix I should get
| | a | f |
| a | 0 | 40 |
| f | 66.6 | 0 |
Scenario: Shortest via path with continuation, multiple waypoint snapping candidates
Given the node map
"""
b g
c h
a d f i
k
e j
"""
And the ways
| nodes | oneway |
| ab | no |
| ac | no |
| ad | no |
| ae | no |
| bf | no |
| cf | yes |
| df | yes |
| ef | no |
| fg | no |
| fh | -1 |
| fi | -1 |
| fj | no |
| gk | no |
| hk | no |
| ik | no |
| kj | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | df | fg | f | only_left_turn |
| restriction | fi | bf | f | only_right_turn |
# Longer routes can take different paths from sub-routes
When I route I should get
| waypoints | route | time | weight |
| a,f | ad,df,df | 40s | 40 |
| f,k | fj,kj,kj | 65.6s | 65.6 |
| a,f,k | ac,cf,cf,fj,kj,kj | 132.8s | 132.8 |
| k,f | ik,fi,fi | 54.3s | 54.3 |
| f,a | ef,ae,ae | 66.6s | 66.6 |
| k,f,a | kj,fj,fj,ef,ae,ae | 141.4s | 141.4 |
When I request a travel time matrix I should get
| | a | f | k |
| a | 0 | 40 | 132.8 |
| f | 66.6 | 0 | 65.6 |
| k | 141.4 | 54.3 | 0 |
Scenario: Shortest via path with uturns, multiple waypoint snapping candidates
Given the node map
"""
b g
c h
a d f i
k
e j
"""
Given the query options
| continue_straight | false |
And the ways
| nodes | oneway |
| ab | no |
| ac | no |
| ad | no |
| ae | no |
| bf | no |
| cf | yes |
| df | yes |
| ef | no |
| fg | no |
| fh | -1 |
| fi | -1 |
| fj | no |
| gk | no |
| hk | no |
| ik | no |
| kj | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | df | fg | f | only_left_turn |
| restriction | fi | bf | f | only_right_turn |
# Longer routes use same path as sub-routes
When I route I should get
| waypoints | route | time | weight |
| a,f | ad,df,df | 40s | 40 |
| f,k | fj,kj,kj | 65.6s | 65.6 |
| a,f,k | ad,df,df,fj,kj,kj | 105.6s | 105.6 |
| k,f | ik,fi,fi | 54.3s | 54.3 |
| f,a | ef,ae,ae | 66.6s | 66.6 |
| k,f,a | ik,fi,fi,ef,ae,ae | 120.9s | 120.9 |
@@ -47,7 +47,7 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
| 1 | e | ab,be,be | 36 km/h | 30s +-1 |
| b | f | bc,cf,cf | 36 km/h | 40s +-1 |
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 |
| c | g | cd,dg,dg | 144 km/h | 10s +-1 |
| c | g | cd,dg,dg | 72 km/h | 20s +-1 |
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 |
Scenario: Weighting based on turn penalty file with weights
@@ -65,5 +65,5 @@ Feature: Traffic - turn penalties applied to turn onto which a phantom node snap
| 1 | e | ab,be,be | 36 km/h | 30s +-1 | 6.8,20,0 |
| b | f | bc,cf,cf | 36 km/h | 40s +-1 | 20,20,0 |
| 2 | f | bc,cf,cf | 36 km/h | 30s +-1 | 10.1,20,0 |
| c | g | cd,dg,dg | 144 km/h | 10s +-1 | 120.8,20,0 |
| c | g | cd,dg,dg | 72 km/h | 20s +-1 | 120.8,20,0 |
| 3 | g | cd,dg,dg | 54 km/h | 20s +-1 | 110.9,20,0 |
+1 -1
View File
@@ -281,7 +281,7 @@ Feature: Weight tests
When I route I should get
| waypoints | route | distance | weights | times |
| a,c | , | 40m +-.1 | 5.12,0 | 290s,0s |
| a,c | , | 40m +-.1 | 2.22,0 | 200s,0s |
| a,e | ,, | 60m +-.1 | 5.12,1.11,0 | 290s,100s,0s |
| e,a | ,, | 60m +-.1 | 2.21,2.22,0 | 10s,200s,0s |
| e,d | ,, | 40m +-.1 | 4.01,1.11,0 | 190s,100s,0s |