View Javadoc

1   /*
2    * Created on Dec 4, 2003
3    * 
4    * Copyright (c) 2003, 2004 Delft University of Technology Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the General Public License
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             // error, should be on this track
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             // on this track
393             TrackProgression tp = new TrackProgression(track, delta);
394             trackProgressionList.add(tp);
395             return;
396         }
397         // on the previous track
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         // the maximum distance to check is 250 m
471         double maxDistance = 250.0;
472         // calculate the front location of vehicle0
473         TrackProgression tp0 = new TrackProgression(vehicle0.getCurrentTrack(),
474                 vehicle0.getProgression());
475         System.out.println("tp0 = " + tp0.getTrack() + ":"
476                 + tp0.getProgression());
477         // calculate the back location of vehicle1
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         // find tp1 forward from tp0. If it is not found, -1 will be returned
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 }