1
2
3
4
5
6
7
8
9
10
11 package nl.tudelft.simulation.traffic.track;
12
13 import java.rmi.RemoteException;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17
18 import nl.tudelft.simulation.dsol.animation.LocatableInterface;
19 import nl.tudelft.simulation.language.d3.DirectedPoint;
20 import nl.tudelft.simulation.logger.Logger;
21 import nl.tudelft.simulation.traffic.controlpoint.ControlPointInterface;
22 import nl.tudelft.simulation.traffic.controlpoint.util.ControlPointsList;
23 import nl.tudelft.simulation.traffic.track.util.TrackList;
24 import nl.tudelft.simulation.traffic.track.util.TrackProgression;
25 import nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface;
26
27 /***
28 * This class implements the TrackInterface. <br>
29 *
30 * @author <a
31 * href="http://www.tbm.tudelft.nl/webstaf/alexandv/index.htm">Alexander
32 * Verbraeck </a> <br>
33 *
34 * Original authors: J.H. Kwakkel and H.W.G. Phaff
35 */
36 public abstract class Track implements TrackInterface, LocatableInterface
37 {
38 /*** the name (id) of the track */
39 protected String name;
40
41 /*** the start link */
42 protected TrackLinkInterface startLink;
43
44 /*** the end link */
45 protected TrackLinkInterface endLink;
46
47 /*** the control points on the track */
48 private ControlPointsList controlPoints;
49
50 /*** the vehicles on the track */
51 protected List vehicles = new ArrayList();
52
53 /*** all routes from a certain point */
54 protected static final int TRACK_ROUTE_ALL = 0;
55
56 /*** active route from a certain point */
57 protected static final int TRACK_ROUTE_ACTIVE = 1;
58
59 /*** line route from a certain point */
60 protected static final int TRACK_ROUTE_LINE = 2;
61
62 /***
63 * @param name
64 * @param startLink
65 * @param endLink
66 */
67 public Track(final String name, final TrackLinkInterface startLink,
68 final TrackLinkInterface endLink)
69 {
70 this.name = name;
71 this.controlPoints = new ControlPointsList();
72 this.startLink = startLink;
73 this.endLink = endLink;
74 startLink.addSuccessor(this);
75 endLink.addPredecessor(this);
76 }
77
78 /***
79 * @see nl.tudelft.simulation.traffic.track.TrackInterface#getStartLink()
80 */
81 public TrackLinkInterface getStartLink()
82 {
83 return this.startLink;
84 }
85
86 /***
87 * @see nl.tudelft.simulation.traffic.track.TrackInterface#getEndLink()
88 */
89 public TrackLinkInterface getEndLink()
90 {
91 return this.endLink;
92 }
93
94 /***
95 * @see nl.tudelft.simulation.traffic.track.TrackInterface#getControlPoints()
96 */
97 public ControlPointsList getControlPoints()
98 {
99 return this.controlPoints;
100 }
101
102 /***
103 * @see nl.tudelft.simulation.traffic.track.TrackInterface#addControlPoint(nl.tudelft.simulation.traffic.controlpoint.ControlPointInterface)
104 */
105 public void addControlPoint(final ControlPointInterface cp)
106 {
107 this.controlPoints.add(cp);
108 }
109
110 /***
111 * @see nl.tudelft.simulation.traffic.track.TrackInterface#getCpsOnInterval(
112 * double, double)
113 */
114 public ControlPointsList getCpsOnInterval(final double progression,
115 final double lengthOfInterval)
116 {
117 ControlPointsList list = new ControlPointsList();
118 Iterator it = this.controlPoints.iterator();
119 while (it.hasNext())
120 {
121 ControlPointInterface cp = (ControlPointInterface) it.next();
122 double cpProg = cp.getProgression();
123 if (cpProg >= progression
124 && cpProg <= progression + lengthOfInterval)
125 {
126 list.add(cp);
127 }
128 }
129 return list;
130 }
131
132 /***
133 * @return dx
134 */
135 public double getdx()
136 {
137 return (this.endLink.getPosition().x)
138 - (this.startLink.getPosition().x);
139 }
140
141 /***
142 * @return dy
143 */
144 public double getdy()
145 {
146 return (this.endLink.getPosition().y)
147 - (this.startLink.getPosition().y);
148 }
149
150 /***
151 * @see nl.tudelft.simulation.dsol.animation.LocatableInterface#getLocation()
152 */
153 public DirectedPoint getLocation() throws RemoteException
154 {
155 return (DirectedPoint) this.startLink;
156 }
157
158 /***
159 * @see nl.tudelft.simulation.traffic.track.TrackInterface#removeControlPoint(nl.tudelft.simulation.traffic.controlpoint.ControlPointInterface)
160 */
161 public void removeControlPoint(final ControlPointInterface cp)
162 {
163 this.controlPoints.remove(cp);
164 }
165
166 /***
167 * @return Returns the name.
168 */
169 public String toString()
170 {
171 return this.name;
172 }
173
174 /***
175 * @see nl.tudelft.simulation.traffic.track.TrackInterface#addVehicle(nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface)
176 */
177 public void addVehicle(VehiclePhysicalInterface vehicle)
178 {
179 if (this.vehicles.contains(vehicle))
180 Logger.warning(this, "addVehicle", "vehicle already on track");
181 this.vehicles.add(vehicle);
182 }
183
184 /***
185 * @see nl.tudelft.simulation.traffic.track.TrackInterface#removeVehicle(nl.tudelft.simulation.traffic.vehicle.VehiclePhysicalInterface)
186 */
187 public void removeVehicle(VehiclePhysicalInterface vehicle)
188 {
189 if (!this.vehicles.contains(vehicle))
190 Logger.warning(this, "removeVehicle", "vehicle not on track "
191 + this);
192 else if (this.vehicles.indexOf(vehicle) != 0)
193 Logger.warning(this, "removeVehicle", "vehicle not first on track "
194 + this);
195 else
196 this.vehicles.remove(vehicle);
197 }
198
199 /***
200 * @see nl.tudelft.simulation.traffic.track.TrackInterface#getVehiclesOnTrack()
201 */
202 public List getVehiclesOnTrack()
203 {
204 return this.vehicles;
205 }
206
207 /***
208 * Calculate all positions on tracks located 'delta' meters from the start
209 * of the current track. Delta can be positive or negative. When the track
210 * splits, all paths are followed, and points on all the paths are returned.
211 *
212 * @param delta
213 * @return
214 */
215 public List calculateTrackProgressionListAll(final double delta)
216 {
217 List trackProgressionList = new ArrayList();
218 if (delta == 0)
219 {
220 trackProgressionList.add(new TrackProgression(this, 0.0));
221 } else if (delta > 0)
222 calculateTrackProgressionListForward(this, delta,
223 Track.TRACK_ROUTE_ALL, trackProgressionList, null);
224 else
225 {
226 calculateTrackProgressionListBackward(this, delta,
227 Track.TRACK_ROUTE_ALL, trackProgressionList, null);
228 }
229 if (trackProgressionList.size() == 0)
230 System.out.println(this
231 + ", trackProgressionList.size() = 0. Track = " + this
232 + ", delta = " + delta);
233 return trackProgressionList;
234 }
235
236 /***
237 * Calculate a position on the 'active' track located 'delta' meters from
238 * the start of the current track. When the track splits, only the active
239 * path is followed, and a point on that path is returned. The active path
240 * is determined by the current setting of the switches in the links that
241 * connect the tracks.
242 *
243 * @param delta
244 * @return
245 */
246 public TrackProgression calculateTrackProgressionListActive(
247 final double delta)
248 {
249 List trackProgressionList = new ArrayList();
250 if (delta == 0)
251 {
252 trackProgressionList.add(new TrackProgression(this, 0.0));
253 } else if (delta > 0)
254 calculateTrackProgressionListForward(this, delta,
255 Track.TRACK_ROUTE_ACTIVE, trackProgressionList, null);
256 else
257 calculateTrackProgressionListBackward(this, delta,
258 Track.TRACK_ROUTE_ACTIVE, trackProgressionList, null);
259 if (trackProgressionList.size() != 1)
260 {
261 System.out.println("ERROR, calculateTrackProgressionListActive. "
262 + "trackProgressionList.size() != 1 ("
263 + trackProgressionList.size() + "). Track = " + this
264 + ", delta = " + delta);
265 if (trackProgressionList.size() > 1)
266 return (TrackProgression) trackProgressionList.get(0);
267 else
268 return null;
269 } else
270 return (TrackProgression) trackProgressionList.get(0);
271 }
272
273 /***
274 * Calculate a position on a track located 'delta' meters from the start of
275 * the current track. Delta can (for now) only be positive. When the track
276 * splits, the path that is linked to the given line number is followed, and
277 * a point on that path is returned. This path is determined by the way the
278 * switches will be set when a vehicle of the given line number passes.
279 *
280 * @param delta
281 * @param line
282 * @return
283 */
284 public List calculateTrackProgressionListLine(final double delta,
285 final String line)
286 {
287 List trackProgressionList = new ArrayList();
288 if (delta == 0)
289 {
290 trackProgressionList.add(new TrackProgression(this, 0.0));
291 } else if (delta > 0)
292 calculateTrackProgressionListForward(this, delta,
293 Track.TRACK_ROUTE_LINE, trackProgressionList, line);
294 else
295 Logger.warning(this, "calculateTrackProgressionListLine",
296 "Negative delta cannot be calculated for line path");
297 return trackProgressionList;
298 }
299
300 /***
301 * This method gets a track and calculates the point(s) delta meters forward
302 * on the basis of the START of the track.
303 *
304 * @param track
305 * @param delta
306 * @param routeType
307 * @param trackProgressionList
308 * @param line
309 */
310 private void calculateTrackProgressionListForward(
311 final TrackInterface track, final double delta,
312 final int routeType, final List trackProgressionList,
313 final String line)
314 {
315 double length = track.getLength();
316 if (delta < length)
317 {
318 TrackProgression tp = new TrackProgression(track, delta);
319 trackProgressionList.add(tp);
320 return;
321 }
322 TrackLinkInterface link = track.getEndLink();
323 switch (routeType)
324 {
325 case Track.TRACK_ROUTE_ALL:
326 TrackList tl = link.getSuccessors();
327 for (int i = 0; i < tl.size(); i++)
328 {
329 TrackInterface nextTrack = tl.get(i);
330 if (nextTrack == null)
331 {
332 System.err.println("TRACK " + track + ", LINK " + link
333 + " does not have successors");
334 return;
335 }
336 calculateTrackProgressionListForward(nextTrack, delta - length,
337 routeType, trackProgressionList, line);
338 }
339 break;
340 case Track.TRACK_ROUTE_ACTIVE:
341 TrackInterface nextTrack = link.getActiveSuccessor(track);
342 if (nextTrack == null)
343 {
344 System.err.println("TRACK " + track + ", LINK " + link
345 + " does not have successors");
346 return;
347 }
348 calculateTrackProgressionListForward(nextTrack, delta - length,
349 routeType, trackProgressionList, line);
350 break;
351 case Track.TRACK_ROUTE_LINE:
352 Logger.warning(this, "calculateTrackProgressionListForward",
353 "Progression per line cannot be calculated yet");
354 break;
355 default:
356 Logger.warning(this, "calculateTrackProgressionListForward",
357 "parameter 'all' does not have the right value: "
358 + routeType);
359 break;
360 }
361 }
362
363 /***
364 * This method gets a track and has to calculate delta meters BACK on the
365 * basis of the START of the track. When going backward, delta is a POSITIVE
366 * number. When delta is NEGATIVE, the end point is probably ON this track.
367 *
368 * @param track
369 * @param delta
370 * @param routeType
371 * @param trackProgressionList
372 * @param line
373 */
374 private void calculateTrackProgressionListBackward(
375 final TrackInterface track, final double delta,
376 final int routeType, final List trackProgressionList,
377 final String line)
378 {
379 double length = track.getLength();
380 if (delta > length)
381 {
382
383 Logger.warning(this, "calculateTrackProgressionListBackward",
384 "delta larger than track length");
385 System.out.println("calculateTrackProgressionListBackward: "
386 + "delta " + delta + " larger than track " + track
387 + ".length " + length);
388 return;
389 }
390 if (delta >= 0)
391 {
392
393 TrackProgression tp = new TrackProgression(track, delta);
394 trackProgressionList.add(tp);
395 return;
396 }
397
398 TrackLinkInterface link = track.getStartLink();
399 if (routeType == Track.TRACK_ROUTE_ALL)
400 {
401 TrackList tl = link.getPredecessors();
402 for (int i = 0; i < tl.size(); i++)
403 {
404 TrackInterface prevTrack = tl.get(i);
405 calculateTrackProgressionListBackward(prevTrack, delta
406 + prevTrack.getLength(), routeType,
407 trackProgressionList, line);
408 }
409 } else if (routeType == Track.TRACK_ROUTE_ACTIVE)
410 {
411 TrackList tl = link.getPredecessors();
412 if (tl.size() == 1)
413 {
414 TrackInterface prevTrack = tl.get(0);
415 if (prevTrack == null)
416 {
417 Logger.warning(this,
418 "calculateTrackProgressionListBackward",
419 "prevTrack = null");
420 System.out
421 .println("calculateTrackProgressionListBackward: "
422 + "prevTrack = null for Track " + track);
423 } else
424 {
425 calculateTrackProgressionListBackward(prevTrack, delta
426 + prevTrack.getLength(), routeType,
427 trackProgressionList, line);
428 }
429 } else if (tl.size() > 1)
430 {
431 for (int i = 0; i < tl.size(); i++)
432 {
433 TrackInterface prevTrack = tl.get(i);
434 if (track.equals(prevTrack.getEndLink().getActiveSuccessor(
435 prevTrack)))
436 {
437 calculateTrackProgressionListBackward(prevTrack, delta
438 + prevTrack.getLength(), routeType,
439 trackProgressionList, line);
440 }
441 }
442 } else
443 {
444 System.out
445 .println("ERROR calculateTrackProgressionListBackward: "
446 + "No predecessors for link " + link);
447 return;
448 }
449 } else
450 {
451 Logger.warning(this, "calculateTrackProgressionListBackward",
452 "parameter 'all' does not have the right value: "
453 + routeType);
454 return;
455 }
456 }
457
458 /***
459 * @param vehicle0
460 * @param vehicle1
461 * @return
462 */
463 public static double calculateDistanceFrontBack(
464 final VehiclePhysicalInterface vehicle0,
465 final VehiclePhysicalInterface vehicle1)
466 {
467 System.out
468 .println("------------------------------------- calculateDistanceFrontBack "
469 + vehicle0 + "-" + vehicle1);
470
471 double maxDistance = 250.0;
472
473 TrackProgression tp0 = new TrackProgression(vehicle0.getCurrentTrack(),
474 vehicle0.getProgression());
475 System.out.println("tp0 = " + tp0.getTrack() + ":"
476 + tp0.getProgression());
477
478 TrackProgression tp1 = vehicle1.getCurrentTrack()
479 .calculateTrackProgressionListActive(
480 vehicle1.getProgression()
481 - vehicle1.getVehicleType().getLength());
482 System.out.println("tp1 = " + tp1.getTrack() + ":"
483 + tp1.getProgression());
484
485 double distance = calculateDistanceFrontBack(tp0, tp1, maxDistance);
486 System.out.println("Distance between " + vehicle0 + " and " + vehicle1
487 + " = " + distance);
488 return distance;
489 }
490
491 /***
492 * @param tp0
493 * @param tp1
494 * @param maxDistance
495 * @return
496 */
497 public static double calculateDistanceFrontBack(final TrackProgression tp0,
498 final TrackProgression tp1, final double maxDistance)
499 {
500 TrackInterface track = tp0.getTrack();
501 double length = track.getLength() - tp0.getProgression();
502 double distance = 0;
503 while (distance < maxDistance)
504 {
505 if (track.equals(tp1.getTrack()))
506 {
507 return distance + tp1.getProgression();
508 }
509 distance += length;
510 track = track.getEndLink().getActiveSuccessor(track);
511 length = track.getLength();
512 }
513 return -1;
514 }
515 }