19
19
20
20
import com .graphhopper .config .CHProfile ;
21
21
import com .graphhopper .config .Profile ;
22
+ import com .graphhopper .json .Statement ;
22
23
import com .graphhopper .routing .ev .RoadClass ;
23
24
import com .graphhopper .speeds .SpeedKmByHour ;
24
25
import com .graphhopper .speeds .WaySpeedsProvider ;
@@ -41,7 +42,7 @@ public class GraphHopperCustomSpeedsTest {
41
42
public static final String DIR = "../core/files" ;
42
43
43
44
// map locations
44
- private static final String MONACO = DIR + "/monaco .osm.gz" ;
45
+ private static final String MONACO = DIR + "/monaco2024 .osm.gz" ;
45
46
46
47
// when creating GH instances make sure to use this as the GH location such that it will be cleaned between tests
47
48
private static final String GH_LOCATION = "target/graphhopper-test-gh" ;
@@ -55,21 +56,22 @@ public void setup() {
55
56
Helper .removeDir (new File (GH_LOCATION_CUSTOM_SPEEDS ));
56
57
}
57
58
58
- class CustomWaySpeedProvider implements WaySpeedsProvider {
59
+ @ Test
60
+ public void testDynamicSpeedProvider () {
59
61
60
- @ Override
61
- public Optional <SpeedKmByHour > speedForWay (long osmWayId ) {
62
- return Optional .of (new SpeedKmByHour (10.10 ));
63
- }
62
+ class CustomWaySpeedProvider implements WaySpeedsProvider {
64
63
65
- @ Override
66
- public Optional <SpeedKmByHour > speedForRoadClass (RoadClass roadClass ) {
67
- return Optional .of (new SpeedKmByHour (10.1 ));
64
+ @ Override
65
+ public Optional <SpeedKmByHour > speedForWay (long osmWayId ) {
66
+ return Optional .of (new SpeedKmByHour (10.10 ));
67
+ }
68
+
69
+ @ Override
70
+ public Optional <SpeedKmByHour > speedForRoadClass (RoadClass roadClass ) {
71
+ return Optional .of (new SpeedKmByHour (10.1 ));
72
+ }
68
73
}
69
- }
70
74
71
- @ Test
72
- public void testDynamicSpeedProvider () {
73
75
final String bikeProfile = "bike_profile" ;
74
76
final String carProfile = "car_profile" ;
75
77
List <Profile > profiles = asList (
@@ -101,36 +103,174 @@ public void testDynamicSpeedProvider() {
101
103
hopper .importOrLoad ();
102
104
hopperCustomSpeeds .importOrLoad ();
103
105
104
- GHResponse rsp = hopper .route (new GHRequest (43.73005 , 7.415707 , 43.741522 , 7.42826 )
105
- .setProfile (carProfile ));
106
+ GHRequest request = new GHRequest (43.73005 , 7.415707 , 43.741522 , 7.42826 );
107
+
108
+ GHResponse rsp = hopper .route (request .setProfile (carProfile ));
106
109
ResponsePath res = rsp .getBest ();
107
110
assertFalse (rsp .hasErrors (), rsp .getErrors ().toString ());
108
- assertEquals (205 , res .getTime () / 1000f , 1 );
109
- assertEquals (2837 , res .getDistance (), 1 );
111
+ assertEquals (208 , res .getTime () / 1000f , 1 ); // 50kmh = 13.8 m/s
112
+ assertEquals (2750 , res .getDistance (), 1 );
110
113
111
- GHResponse rspSpeeds = hopperCustomSpeeds .route (new GHRequest ( 43.73005 , 7.415707 , 43.741522 , 7.42826 )
114
+ GHResponse rspSpeeds = hopperCustomSpeeds .route (request
112
115
.setProfile (carProfile ));
113
116
ResponsePath resSpeeds = rspSpeeds .getBest ();
114
117
assertFalse (rspSpeeds .hasErrors (), rspSpeeds .getErrors ().toString ());
115
- assertEquals (893 , resSpeeds .getTime () / 1000f , 1 );
116
- assertEquals (2481 , resSpeeds .getDistance (), 1 );
118
+ assertEquals (893 , resSpeeds .getTime () / 1000f , 1 ); // 10kmh = 2.7m/s
119
+ assertEquals (2478 , resSpeeds .getDistance (), 1 );
117
120
118
121
119
- GHResponse rspBike = hopper .route (new GHRequest ( 43.73005 , 7.415707 , 43.741522 , 7.42826 )
122
+ GHResponse rspBike = hopper .route (request
120
123
.setProfile (bikeProfile ));
121
124
ResponsePath resBike = rspBike .getBest ();
122
125
assertFalse (rspBike .hasErrors (), rspBike .getErrors ().toString ());
123
- assertEquals (536 , resBike .getTime () / 1000f , 1 );
124
- assertEquals (2521 , resBike .getDistance (), 1 );
126
+ assertEquals (544 , resBike .getTime () / 1000f , 1 ); // 17kmh = 4.7 m/s
127
+ assertEquals (2764 , resBike .getDistance (), 1 );
125
128
126
- GHResponse rspBikeSpeeds = hopperCustomSpeeds .route (new GHRequest ( 43.73005 , 7.415707 , 43.741522 , 7.42826 )
129
+ GHResponse rspBikeSpeeds = hopperCustomSpeeds .route (request
127
130
.setProfile (bikeProfile ));
128
131
ResponsePath resBikeSpeeds = rspBikeSpeeds .getBest ();
129
132
assertFalse (rspBikeSpeeds .hasErrors (), rspBikeSpeeds .getErrors ().toString ());
130
- assertEquals (834 , resBikeSpeeds .getTime () / 1000f , 1 );
131
- assertEquals (2318 , resBikeSpeeds .getDistance (), 1 );
133
+ assertEquals (784 , resBikeSpeeds .getTime () / 1000f , 1 ); // 10kmh = 2.7m/s
134
+ assertEquals (2178 , resBikeSpeeds .getDistance (), 1 );
135
+
136
+ }
137
+
138
+ @ Test
139
+ public void testDynamicSpeedProviderUsesMaxSpeedWhenInputSpeedIsTooHigh () {
140
+
141
+ class SpeedsTooHighSpeedProvider implements WaySpeedsProvider {
142
+
143
+ @ Override
144
+ public Optional <SpeedKmByHour > speedForWay (long osmWayId ) {
145
+ return Optional .of (new SpeedKmByHour (100 ));
146
+ }
147
+
148
+ @ Override
149
+ public Optional <SpeedKmByHour > speedForRoadClass (RoadClass roadClass ) {
150
+ return Optional .of (new SpeedKmByHour (80.1 ));
151
+ }
152
+ }
153
+
154
+ final String carProfile = "car_profile" ;
155
+
156
+ List <Profile > profiles = asList (
157
+ new Profile (carProfile ).setVehicle ("car" )
158
+ .setCustomModel (
159
+ new CustomModel ()
160
+ .addToSpeed (
161
+ Statement .If ("road_class == SECONDARY" , Statement .Op .LIMIT , "20" )))
162
+ );
163
+
164
+ GraphHopper hopper = new GraphHopper ().
165
+ setGraphHopperLocation (GH_LOCATION ).
166
+ setOSMFile (MONACO ).
167
+ setProfiles (profiles ).
168
+ setStoreOnFlush (true );
169
+ hopper .getCHPreparationHandler ().setCHProfiles (
170
+ new CHProfile (carProfile )
171
+ );
172
+
173
+ GraphHopper hopperCustomSpeeds = new GraphHopperCustomSpeeds (new SpeedsTooHighSpeedProvider ()).
174
+ setGraphHopperLocation (GH_LOCATION_CUSTOM_SPEEDS ).
175
+ setOSMFile (MONACO ).
176
+ setProfiles (profiles ).
177
+ setStoreOnFlush (true )
178
+ .setEncodedValuesString ("roundabout, road_class, road_class_link, road_environment, max_speed, road_access, ferry_speed, bike_network, get_off_bike, smoothness, osm_way_id" );
179
+ hopperCustomSpeeds .getCHPreparationHandler ().setCHProfiles (
180
+ new CHProfile (carProfile )
181
+ );
182
+
183
+ hopper .importOrLoad ();
184
+ hopperCustomSpeeds .importOrLoad ();
185
+
186
+ // requests uses osm way 166009792 (secondary road, that has max speed = 50km)
187
+ // in the request we set a custom model with max speed of 20kmh for secondary roads
188
+ GHRequest request = new GHRequest (43.73887 , 7.42074 , 43.73992 , 7.42386 );
189
+
190
+ GHResponse rsp = hopper .route (request .setProfile (carProfile ));
191
+ ResponsePath res = rsp .getBest ();
192
+ assertFalse (rsp .hasErrors (), rsp .getErrors ().toString ());
193
+ assertEquals (49 , res .getTime () / 1000f , 1 ); // 20kmh = 5.7m/s
194
+ assertEquals (277 , res .getDistance (), 1 );
195
+
196
+ GHResponse rspSpeeds = hopperCustomSpeeds .route (request
197
+ .setProfile (carProfile ));
198
+ ResponsePath resSpeeds = rspSpeeds .getBest ();
199
+ assertFalse (rspSpeeds .hasErrors (), rspSpeeds .getErrors ().toString ());
200
+ assertEquals (21 , resSpeeds .getTime () / 1000f , 1 ); // 50kmh = 13.8 m/s
201
+ assertEquals (277 , resSpeeds .getDistance (), 1 );
132
202
133
203
}
134
204
205
+ @ Test
206
+ public void testDynamicSpeedProviderDiscardCustomSpeedIfHigherThanMaxEncoderSpeed () {
207
+
208
+ // For bike, the max encoder speed is 30kmh
209
+ // For car, the max encoder speed is 254 kmh
210
+ // We are trying to set a custom speed for bike > 30kmh, that is the limit for the bike
211
+ // encoder, so we expect it to be discarded, and we expect that the default speed
212
+ // for those roads will be used
213
+
214
+ class SpeedsTooHighSpeedProvider implements WaySpeedsProvider {
215
+
216
+ @ Override
217
+ public Optional <SpeedKmByHour > speedForWay (long osmWayId ) {
218
+ return Optional .of (new SpeedKmByHour (100 ));
219
+ }
220
+
221
+ @ Override
222
+ public Optional <SpeedKmByHour > speedForRoadClass (RoadClass roadClass ) {
223
+ return Optional .of (new SpeedKmByHour (80.1 ));
224
+ }
225
+ }
226
+
227
+ final String bikeProfile = "bike_profile" ;
228
+
229
+ List <Profile > profiles = asList (
230
+ new Profile (bikeProfile ).setVehicle ("bike" )
231
+ );
232
+
233
+ GraphHopper hopper = new GraphHopper ().
234
+ setGraphHopperLocation (GH_LOCATION ).
235
+ setOSMFile (MONACO ).
236
+ setProfiles (profiles ).
237
+ setStoreOnFlush (true );
238
+ hopper .getCHPreparationHandler ().setCHProfiles (
239
+ new CHProfile (bikeProfile )
240
+ );
241
+
242
+ GraphHopper hopperCustomSpeeds = new GraphHopperCustomSpeeds (new SpeedsTooHighSpeedProvider ()).
243
+ setGraphHopperLocation (GH_LOCATION_CUSTOM_SPEEDS ).
244
+ setOSMFile (MONACO ).
245
+ setProfiles (profiles ).
246
+ setStoreOnFlush (true )
247
+ .setEncodedValuesString ("roundabout, road_class, road_class_link, road_environment, max_speed, road_access, ferry_speed, bike_network, get_off_bike, smoothness, osm_way_id" );
248
+ hopperCustomSpeeds .getCHPreparationHandler ().setCHProfiles (
249
+ new CHProfile (bikeProfile )
250
+ );
251
+
252
+ hopper .importOrLoad ();
253
+ hopperCustomSpeeds .importOrLoad ();
254
+
255
+ GHRequest request = new GHRequest (43.73887 , 7.42074 , 43.73992 , 7.42386 );
256
+
257
+ GHResponse rspBike = hopper .route (request
258
+ .setProfile (bikeProfile ));
259
+ ResponsePath resBike = rspBike .getBest ();
260
+ assertFalse (rspBike .hasErrors (), rspBike .getErrors ().toString ());
261
+ assertEquals (55 , resBike .getTime () / 1000f , 1 ); // 18kmh = 5 m/s
262
+ assertEquals (277 , resBike .getDistance (), 1 );
263
+
264
+ GHResponse rspBikeSpeeds = hopperCustomSpeeds .route (request
265
+ .setProfile (bikeProfile ));
266
+ ResponsePath resBikeSpeeds = rspBikeSpeeds .getBest ();
267
+ assertFalse (rspBikeSpeeds .hasErrors (), rspBikeSpeeds .getErrors ().toString ());
268
+ assertEquals (55 , resBikeSpeeds .getTime () / 1000f , 1 ); // 17kmh = 4.7 m/s
269
+ assertEquals (277 , resBikeSpeeds .getDistance (), 1 );
270
+
271
+ // the result with and without custom speeds should be the same when the custom speed is > than the encoder limit
272
+ assertEquals (resBike .getTime () / 1000f , resBikeSpeeds .getTime () / 1000f , 1 );
273
+
274
+ }
135
275
}
136
276
0 commit comments