-
Notifications
You must be signed in to change notification settings - Fork 53
/
RoadModel.java
510 lines (472 loc) · 22.8 KB
/
RoadModel.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
/*
* Copyright (C) 2011-2018 Rinde R.S. van Lon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.rinde.rinsim.core.model.road;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import javax.annotation.Nullable;
import javax.measure.Measure;
import javax.measure.quantity.Duration;
import javax.measure.quantity.Length;
import javax.measure.quantity.Velocity;
import javax.measure.unit.Unit;
import org.apache.commons.math3.random.RandomGenerator;
import com.github.rinde.rinsim.core.model.Model;
import com.github.rinde.rinsim.core.model.time.TimeLapse;
import com.github.rinde.rinsim.event.EventAPI;
import com.github.rinde.rinsim.geom.GeomHeuristic;
import com.github.rinde.rinsim.geom.GeomHeuristics;
import com.github.rinde.rinsim.geom.Point;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
/**
* RoadModel is a model that manages a fleet of vehicles ({@link RoadUser}s) on
* top of a <i>space</i>. The space that is used depends on the specific
* implementation of {@link RoadModel}. {@link RoadUser}s have a position which
* is represented by a {@link Point}. Generally, RoadModels are responsible for:
* <ul>
* <li>adding and removing objects</li>
* <li>moving objects around</li>
* </ul>
* Additionally, the RoadModel provides several methods for retrieving objects
* and finding the shortest path. More utilities for working with
* {@link RoadModel}s are defined in {@link RoadModels}.
* @author Rinde van Lon
*/
public interface RoadModel extends Model<RoadUser> {
/**
* Moves the specified {@link MovingRoadUser} towards the specified
* <code>destination</code> following the path returned by
* {@link #getPathTo(MovingRoadUser, Point, Unit, Measure, GeomHeuristic)}.
* The {@link GeomHeuristic} that is used by default is
* {@link GeomHeuristics#euclidean()}. There must be time left in the provided
* {@link TimeLapse}. The {@link #getDestination(MovingRoadUser)} method will
* return the destination point as specified in the most recent invocation of
* this method.
* <p>
* <b>Speed</b><br>
* The {@link MovingRoadUser} has to define a speed with which it wants to
* travel. This method uses the {@link MovingRoadUser}s speed as an
* <i>upper</i> bound, it gives no guarantee about the lower bound (i.e. the
* object could stand still). The actual speed of the object depends on the
* model implementation. A model can define constraints such as speed limits
* or traffic jams which can slow down a {@link MovingRoadUser}.
* <p>
* <b>Time</b><br>
* The time that is specified as indicated by the {@link TimeLapse} object may
* or may not be consumed completely. Normally, this method will try to
* consume all time in the {@link TimeLapse} object. In case the destination
* is reached before all time is consumed (which depends on the object's
* <i>speed</i>, the distance to the <code>destination</code> and any speed
* constraints if available) there will be some time left in the
* {@link TimeLapse}.
* @param object The object that is moved.
* @param destination The destination position.
* @param time The time that is available for travel.
* @return A {@link MoveProgress} instance which details: the distance
* traveled, the actual time spent traveling and the nodes which where
* traveled.
* @see #moveTo(MovingRoadUser, RoadUser, TimeLapse)
* @see #followPath(MovingRoadUser, Queue, TimeLapse)
*/
MoveProgress moveTo(MovingRoadUser object, Point destination, TimeLapse time);
/**
* Moves the specified {@link MovingRoadUser} towards the specified
* <code>destination</code> following the path returned by
* {@link #getPathTo(MovingRoadUser, Point, Unit, Measure, GeomHeuristic)}.
* The {@link GeomHeuristic} that is used by default is
* {@link GeomHeuristics#euclidean()}. The
* {@link #getDestination(MovingRoadUser)} method will return the destination
* point as specified in the most recent invocation of this method.
* <p>
* <b>Speed</b><br>
* The {@link MovingRoadUser} has to define a speed with which it wants to
* travel. This method uses the {@link MovingRoadUser}s speed as an
* <i>upper</i> bound, it gives no guarantee about the lower bound (i.e. the
* object could stand still). The actual speed of the object depends on the
* model implementation. A model can define constraints such as speed limits
* or traffic jams which can slow down a {@link MovingRoadUser}.
* <p>
* <b>Time</b><br>
* The time that is specified as indicated by the {@link TimeLapse} object may
* or may not be consumed completely. Normally, this method will try to
* consume all time in the {@link TimeLapse} object. In case the destination
* is reached before all time is consumed (which depends on the object's
* <i>speed</i>, the distance to the <code>destination</code> and any speed
* constraints if available) there will be some time left in the
* {@link TimeLapse}.
* @param object The object that is moved.
* @param destination The destination position.
* @param time The time that is available for travel.
* @return A {@link MoveProgress} instance which details: the distance
* traveled, the actual time spent traveling and the nodes which where
* traveled.
* @see #moveTo(MovingRoadUser, Point, TimeLapse)
* @see #followPath(MovingRoadUser, Queue, TimeLapse)
*/
MoveProgress moveTo(MovingRoadUser object, RoadUser destination,
TimeLapse time);
/**
* Moves the specified {@link MovingRoadUser} towards the specified
* <code>destination</code> following the path returned by
* {@link #getPathTo(MovingRoadUser, Point, Unit, Measure, GeomHeuristic)}.
* The {@link GeomHeuristic} that is used can be specified via
* <code>heuristic</code>. There must be time left in the provided
* {@link TimeLapse}. The {@link #getDestination(MovingRoadUser)} method will
* return the destination point as specified in the most recent invocation of
* this method.
* <p>
* <b>Speed</b><br>
* The {@link MovingRoadUser} has to define a speed with which it wants to
* travel. This method uses the {@link MovingRoadUser}s speed as an
* <i>upper</i> bound, it gives no guarantee about the lower bound (i.e. the
* object could stand still). The actual speed of the object depends on the
* model implementation. A model can define constraints such as speed limits
* or traffic jams which can slow down a {@link MovingRoadUser}.
* <p>
* <b>Time</b><br>
* The time that is specified as indicated by the {@link TimeLapse} object may
* or may not be consumed completely. Normally, this method will try to
* consume all time in the {@link TimeLapse} object. In case the destination
* is reached before all time is consumed (which depends on the object's
* <i>speed</i>, the distance to the <code>destination</code> and any speed
* constraints if available) there will be some time left in the
* {@link TimeLapse}.
* @param object The object that is moved.
* @param destination The destination position.
* @param time The time that is available for travel.
* @param heuristic The heuristic to use for path resolution.
* @return A {@link MoveProgress} instance which details: the distance
* traveled, the actual time spent traveling and the nodes which where
* traveled.
* @see #moveTo(MovingRoadUser, Point, TimeLapse)
* @see #followPath(MovingRoadUser, Queue, TimeLapse)
*/
MoveProgress moveTo(MovingRoadUser object, RoadUser destination,
TimeLapse time, GeomHeuristic heuristic);
/**
* Moves the specified {@link MovingRoadUser} towards the specified
* <code>destination</code> following the path returned by
* {@link #getPathTo(MovingRoadUser, Point, Unit, Measure, GeomHeuristic)}.
* The {@link GeomHeuristic} that is used can be specified via
* <code>heuristic</code>. There must be time left in the provided
* {@link TimeLapse}. The {@link #getDestination(MovingRoadUser)} method will
* return the destination point as specified in the most recent invocation of
* this method.
* <p>
* <b>Speed</b><br>
* The {@link MovingRoadUser} has to define a speed with which it wants to
* travel. This method uses the {@link MovingRoadUser}s speed as an
* <i>upper</i> bound, it gives no guarantee about the lower bound (i.e. the
* object could stand still). The actual speed of the object depends on the
* model implementation. A model can define constraints such as speed limits
* or traffic jams which can slow down a {@link MovingRoadUser}.
* <p>
* <b>Time</b><br>
* The time that is specified as indicated by the {@link TimeLapse} object may
* or may not be consumed completely. Normally, this method will try to
* consume all time in the {@link TimeLapse} object. In case the destination
* is reached before all time is consumed (which depends on the object's
* <i>speed</i>, the distance to the <code>destination</code> and any speed
* constraints if available) there will be some time left in the
* {@link TimeLapse}.
* @param object The object that is moved.
* @param destination The destination position.
* @param time The time that is available for travel.
* @param heuristic The heuristic to use for path resolution.
* @return A {@link MoveProgress} instance which details: the distance
* traveled, the actual time spent traveling and the nodes which where
* traveled.
* @see #moveTo(MovingRoadUser, RoadUser, TimeLapse)
* @see #followPath(MovingRoadUser, Queue, TimeLapse)
*/
MoveProgress moveTo(MovingRoadUser object, Point destination, TimeLapse time,
GeomHeuristic heuristic);
/**
* Moves the specified {@link MovingRoadUser} following the specified path and
* with the specified time. The provided <code>path</code> can not be empty
* and there must be time left in the provided {@link TimeLapse}.
* <p>
* <b>Speed</b><br>
* The {@link MovingRoadUser} has to define a speed with which it wants to
* travel. This method uses the {@link MovingRoadUser}s speed as an
* <i>upper</i> bound, it gives no guarantee about the lower bound (i.e. the
* object could stand still). The actual speed of the object depends on the
* model implementation. A model can define constraints such as speed limits
* or traffic jams which can slow down a {@link MovingRoadUser}.
* <p>
* <b>Path</b><br>
* The {@link MovingRoadUser} follows the path that is specified by the
* provided {@link Queue}. This path is composed of a number of {@link Point}
* s, which will be traveled in order as they appear. For example: consider
* that the path contains three points: <code>A, B, C</code>. The
* {@link MovingRoadUser} will first travel to {@link Point} <code>A</code>,
* once it has reached this point it will be <i>removed</i> out of the
* {@link Queue}. This means that after this method is finished the provided
* {@link Queue} will contain only <code>B, C</code>. By storing the reference
* to the queue, users of this method can repeatedly call this method using
* the same path object instance. The {@link #getDestination(MovingRoadUser)}
* method will return the last point of the path specified in the most recent
* invocation of this method.
* <p>
* Note that when an invalid path is supplied this method will throw an
* {@link IllegalArgumentException}. This method guarantees that the road
* model will not be in an invalid state when this happens. The path that is
* supplied may not be in a valid state. This means that it is safe to put
* invocations of this method in a try/catch block but that it is not safe to
* reuse the supplied path.
* <p>
* <b>Time</b><br>
* The time that is specified as indicated by the {@link TimeLapse} object may
* or may not be consumed completely. Normally, this method will try to
* consume all time in the {@link TimeLapse} object. In case the end of the
* path is reached before all time is consumed (which depends on the object's
* <i>speed</i>, the length of the <code>path</code> and any speed constraints
* if available) there will be some time left in the {@link TimeLapse}.
*
* @param object The object that is moved.
* @param path The path that is followed.
* @param time The time that is available for travel.
* @return A {@link MoveProgress} instance which details: the distance
* traveled, the actual time spent traveling and the nodes which were
* traveled.
* @see #moveTo(MovingRoadUser, Point, TimeLapse)
* @see #moveTo(MovingRoadUser, RoadUser, TimeLapse)
*/
MoveProgress followPath(MovingRoadUser object, Queue<Point> path,
TimeLapse time);
/**
* Adds a new object to the model at the specified position.
* @param newObj The object to be added to the model. It can not be an already
* added object.
* @param pos The position on which the object is to be added. This must be a
* node which already exists in the model.
*/
void addObjectAt(RoadUser newObj, Point pos);
/**
* Adds an object at the same position as the existing object.
* @param newObj The new object to be added to the model. It can not be an
* already added object.
* @param existingObj The existing object which location is used for the
* target of the <code>newObj</code>. This object
* <strong>must</strong> already exist in the model.
*/
void addObjectAtSamePosition(RoadUser newObj, RoadUser existingObj);
/**
* Removes the specified {@link RoadUser} from this model.
* @param roadUser the object to be removed.
*/
void removeObject(RoadUser roadUser);
/**
* Removes all objects from this road model.
*/
void clear();
/**
* Checks if the specified {@link RoadUser} exists in the model.
* @param obj The {@link RoadUser} to check for existence, may not be
* <code>null</code>.
* @return <code>true</code> if <code>obj</code> exists in the model,
* <code>false</code> otherwise.
*/
boolean containsObject(RoadUser obj);
/**
* Checks if the specified {@link RoadUser} exists at the specified position.
* @param obj The {@link RoadUser} to check.
* @param p The position to check.
* @return <code>true</code> if <code>obj</code> exists at position
* <code>p</code>, <code>false</code> otherwise.
*/
boolean containsObjectAt(RoadUser obj, Point p);
/**
* Checks if the positions of the <code>obj1</code> and <code>obj2</code> are
* equal.
* @param obj1 A {@link RoadUser}.
* @param obj2 A {@link RoadUser}.
* @return <code>true</code> if the positions are equal, <code>false</code>
* otherwise.
*/
boolean equalPosition(RoadUser obj1, RoadUser obj2);
/**
* This method returns a mapping of {@link RoadUser} to {@link Point} objects
* which exist in this model. The returned map is not a live view on this
* model, but a new created copy.
* @return A map of {@link RoadUser} to {@link Point} objects.
*/
// TODO add tests to check that this map really is not a live view
Map<RoadUser, Point> getObjectsAndPositions();
/**
* Method to retrieve the location of an object.
* @param roadUser The object for which the position is examined.
* @return The position (as a {@link Point} object) for the specified
* <code>obj</code> object.
*/
Point getPosition(RoadUser roadUser);
/**
* Finds the destination of the road user if it has a destination. A road user
* has a destination if it has moved previously using either of the following
* methods:
* <ul>
* <li>{@link #followPath(MovingRoadUser, Queue, TimeLapse)}, in this case the
* destination is the last point in the supplied path.</li>
* <li>{@link #moveTo(MovingRoadUser, Point, TimeLapse)}, in this case the
* destination is the supplied point.</li>
* <li>{@link #moveTo(MovingRoadUser, RoadUser, TimeLapse)}, in this case the
* destination is the position of the target road user.</li>
* </ul>
* @param roadUser The road user to look up.
* @return The destination of the specified road user or <code>null</code> if
* the road user has no destination.
*/
@Nullable
Point getDestination(MovingRoadUser roadUser);
/**
* Searches a random position in the space which is defined by this model.
* @param rnd The {@link RandomGenerator} which is used for obtaining a random
* number.
* @return A random position in this model.
*/
Point getRandomPosition(RandomGenerator rnd);
/**
* This method returns a collection of {@link Point} objects which are the
* positions of the objects that exist in this model. The returned collection
* is not a live view on the set, but a new created copy.
* @return The collection of {@link Point} objects.
*/
Collection<Point> getObjectPositions();
/**
* This method returns the set of {@link RoadUser} objects which exist in this
* model. The returned set is not a live view on the set, but a new created
* copy.
* @return The set of {@link RoadUser} objects.
*/
Set<RoadUser> getObjects();
/**
* This method returns a set of {@link RoadUser} objects which exist in this
* model and satisfy the given {@link Predicate}. The returned set is not a
* live view on this model, but a new created copy.
* @param predicate The predicate that decides which objects to return.
* @return A set of {@link RoadUser} objects.
*/
Set<RoadUser> getObjects(Predicate<RoadUser> predicate);
/**
* Returns all objects of the given type located in the same position as the
* given {@link RoadUser}.
* @param roadUser The object which location is checked for other objects.
* @param type The type of the objects to be returned.
* @param <Y> The type of the objects in the returned set.
* @return A set of objects of type <code>type</code>.
*/
<Y extends RoadUser> Set<Y> getObjectsAt(RoadUser roadUser, Class<Y> type);
/**
* This method returns a set of {@link RoadUser} objects which exist in this
* model and are instances of the specified {@link Class}. The returned set is
* not a live view on the set, but a new created copy.
* @param type The type of returned objects.
* @param <Y> The type of the objects in the returned set.
* @return A set of {@link RoadUser} objects.
*/
<Y extends RoadUser> Set<Y> getObjectsOfType(Class<Y> type);
/**
* Convenience method for {@link #getShortestPathTo(Point, Point)}.
* @param fromObj The object which is used as the path origin
* @param toObj The object which is used as the path destination
* @return The shortest path from 'fromObj' to 'toObj'.
*/
List<Point> getShortestPathTo(RoadUser fromObj, RoadUser toObj);
/**
* Convenience method for {@link #getShortestPathTo(Point, Point)}.
* @param fromObj The object which is used as the path origin
* @param to The path destination
* @return The shortest path from 'fromObj' to 'to'
*/
List<Point> getShortestPathTo(RoadUser fromObj, Point to);
/**
* Finds the shortest path between <code>from</code> and <code>to</code>. The
* definition of a <i>shortest</i> path is defined by the specific
* implementation, possibilities include the shortest travel time and the
* shortest distance.
* @param from The start point of the path.
* @param to The end point of the path.
* @return The shortest path.
*/
List<Point> getShortestPathTo(Point from, Point to);
/**
* Finds a path between <code>from</code> and <code>to</code>. The path
* finding is directed by the specified {@link GeomHeuristic}, this heuristic
* determines the property of the path that is minimized (e.g. travel time,
* distance traveled, etc.).
* @param from The starting point.
* @param to The ending point.
* @param timeUnit The time unit to use for the calculations.
* @param maxSpeed The speed of the {@link RoadUser} that requests the path.
* @param heuristic The heuristic to use to determine the optimal path.
* @return The path following the heuristic decorated with the heuristic value
* for the path as well as its travel time with the given speed in the
* given time unit.
*/
RoadPath getPathTo(Point from, Point to, Unit<Duration> timeUnit,
Measure<Double, Velocity> maxSpeed, GeomHeuristic heuristic);
/**
* Finds a path between <code>object</code> and <code>destination</code>. The
* path finding is directed by the specified {@link GeomHeuristic}, this
* heuristic determines the property of the path that is minimized (e.g.
* travel time, distance traveled, etc.).
* @param object The road user.
* @param destination The ending point.
* @param timeUnit The time unit to use for the calculations.
* @param maxSpeed The speed of the {@link RoadUser} that requests the path.
* @param heuristic The heuristic to use to determine the optimal path.
* @return The path following the heuristic decorated with the heuristic value
* for the path as well as its travel time with the given speed in the
* given time unit.
*/
RoadPath getPathTo(MovingRoadUser object, Point destination,
Unit<Duration> timeUnit, Measure<Double, Velocity> maxSpeed,
GeomHeuristic heuristic);
/**
* Determines the distance of the given path, indicated by a list of
* connecting points.
* @param path The path to find the distance of.
* @return The length of the given path in the distance unit of the model.
* @throws IllegalArgumentException If the path contains less than two points.
*/
Measure<Double, Length> getDistanceOfPath(Iterable<Point> path)
throws IllegalArgumentException;
/**
* @return The {@link EventAPI} for this road model.
*/
EventAPI getEventAPI();
/**
* @return Should return exactly two points. The first point contains the
* minimum x and y value, the second point contains the maximum x and
* y value.
*/
ImmutableList<Point> getBounds();
/**
* @return The distance unit as used in this model to represent distances.
*/
Unit<Length> getDistanceUnit();
/**
* @return The speed unit as used in this model to represent speeds.
*/
Unit<Velocity> getSpeedUnit();
/**
* @return A snapshot of the current state of this road model.
*/
RoadModelSnapshot getSnapshot();
}