View Javadoc
1   package org.opentrafficsim.road.gtu.lane;
2   
3   import java.io.Serializable;
4   import java.lang.reflect.Constructor;
5   import java.lang.reflect.InvocationTargetException;
6   import java.util.HashSet;
7   import java.util.LinkedHashMap;
8   import java.util.Map;
9   import java.util.Set;
10  
11  import javax.naming.NamingException;
12  
13  import org.djunits.unit.AccelerationUnit;
14  import org.djunits.unit.LengthUnit;
15  import org.djunits.value.vdouble.scalar.Acceleration;
16  import org.djunits.value.vdouble.scalar.Length;
17  import org.djunits.value.vdouble.scalar.Speed;
18  import org.opentrafficsim.base.immutablecollections.Immutable;
19  import org.opentrafficsim.base.immutablecollections.ImmutableHashSet;
20  import org.opentrafficsim.base.immutablecollections.ImmutableLinkedHashMap;
21  import org.opentrafficsim.base.immutablecollections.ImmutableMap;
22  import org.opentrafficsim.base.immutablecollections.ImmutableSet;
23  import org.opentrafficsim.core.dsol.OTSAnimatorInterface;
24  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
25  import org.opentrafficsim.core.geometry.OTSGeometryException;
26  import org.opentrafficsim.core.gtu.GTUException;
27  import org.opentrafficsim.core.gtu.GTUType;
28  import org.opentrafficsim.core.gtu.RelativePosition;
29  import org.opentrafficsim.core.gtu.RelativePosition.TYPE;
30  import org.opentrafficsim.core.gtu.animation.GTUColorer;
31  import org.opentrafficsim.core.network.NetworkException;
32  import org.opentrafficsim.core.network.OTSNetwork;
33  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
34  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
35  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
36  
37  import nl.tudelft.simulation.dsol.SimRuntimeException;
38  import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
39  import nl.tudelft.simulation.language.reflection.ClassUtil;
40  
41  /**
42   * Augments the AbstractLaneBasedIndividualGTU with a LaneBasedIndividualCarBuilder and animation support
43   * <p>
44   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
45   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
46   * <p>
47   * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
48   *          initial version Oct 22, 2014 <br>
49   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
50   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
51   */
52  public class LaneBasedIndividualGTU extends AbstractLaneBasedIndividualGTU
53  {
54      /** */
55      private static final long serialVersionUID = 20141025L;
56  
57      /** The animation. */
58      private Renderable2D animation;
59  
60      /** Sensing positions. */
61      private final Map<RelativePosition.TYPE, RelativePosition> relativePositions = new LinkedHashMap<>(4);
62  
63      /** contour points. */
64      private final Set<RelativePosition> contourPoints = new HashSet<>(4);
65  
66      /**
67       * Construct a new LaneBasedIndividualCar.
68       * @param id ID; the id of the GTU
69       * @param gtuType GTUTYpe; the type of GTU, e.g. TruckType, CarType, BusType
70       * @param length Length; the maximum length of the GTU (parallel with driving direction)
71       * @param width Length; the maximum width of the GTU (perpendicular to driving direction)
72       * @param maximumSpeed Speed;the maximum speed of the GTU (in the driving direction)
73       * @param simulator OTSDEVSSimulatorInterface; the simulator
74       * @param network the network that the GTU is initially registered in
75       * @throws NamingException if an error occurs when adding the animation handler
76       * @throws GTUException when a parameter is invalid
77       */
78      @SuppressWarnings("checkstyle:parameternumber")
79      public LaneBasedIndividualGTU(final String id, final GTUType gtuType, final Length length, final Length width,
80              final Speed maximumSpeed, final OTSDEVSSimulatorInterface simulator, final OTSNetwork network)
81              throws NamingException, GTUException
82      {
83          super(id, gtuType, length, width, maximumSpeed, simulator, network);
84  
85          // sensor positions.
86          // We take the rear position of the Car to be the reference point. So the front is the length
87          // of the Car away from the reference point in the positive (driving) X-direction.
88          Length dx2 = new Length(getLength().getSI() / 2.0, LengthUnit.METER);
89          Length dy2 = new Length(getWidth().getSI() / 2.0, LengthUnit.METER);
90          this.relativePositions.put(RelativePosition.FRONT,
91                  new RelativePosition(dx2, Length.ZERO, Length.ZERO, RelativePosition.FRONT));
92          this.relativePositions.put(RelativePosition.REAR,
93                  new RelativePosition(dx2.multiplyBy(-1.0), Length.ZERO, Length.ZERO, RelativePosition.REAR));
94          this.relativePositions.put(RelativePosition.REFERENCE, RelativePosition.REFERENCE_POSITION);
95          this.relativePositions.put(RelativePosition.CENTER,
96                  new RelativePosition(Length.ZERO, Length.ZERO, Length.ZERO, RelativePosition.CENTER));
97  
98          // Contour positions. For now, a rectangle with the four corners.
99          for (int i = -1; i <= 1; i += 2)
100         {
101             for (int j = -1; j <= 1; j += 2)
102             {
103                 this.contourPoints
104                         .add(new RelativePosition(dx2.multiplyBy(i), dy2.multiplyBy(j), Length.ZERO, RelativePosition.CONTOUR));
105             }
106         }
107 
108         setMaximumAcceleration(new Acceleration(1.0, AccelerationUnit.METER_PER_SECOND_2));
109         setMaximumDeceleration(new Acceleration(-1.0, AccelerationUnit.METER_PER_SECOND_2));
110     }
111 
112     /**
113      * @param strategicalPlanner the strategical planner (e.g., route determination) to use
114      * @param initialLongitudinalPositions the initial positions of the car on one or more lanes with their directions
115      * @param initialSpeed the initial speed of the car on the lane
116      * @param animationClass Class&lt;? extends Renderable2D&gt;; the class for animation or null if no animation
117      * @param gtuColorer GTUColorer; the GTUColorer that will be linked from the animation to determine the color (may be null
118      *            in which case a default will be used)
119      * @throws NetworkException when the GTU cannot be placed on the given lane
120      * @throws SimRuntimeException when the move method cannot be scheduled
121      * @throws GTUException when initial values are not correct
122      * @throws OTSGeometryException when the initial path is wrong
123      */
124     public final void initWithAnimation(final LaneBasedStrategicalPlanner strategicalPlanner,
125             final Set<DirectedLanePosition> initialLongitudinalPositions, final Speed initialSpeed,
126             final Class<? extends Renderable2D> animationClass, final GTUColorer gtuColorer)
127             throws NetworkException, SimRuntimeException, GTUException, OTSGeometryException
128     {
129         super.init(strategicalPlanner, initialLongitudinalPositions, initialSpeed);
130 
131         // animation
132         if (getSimulator() instanceof OTSAnimatorInterface && animationClass != null)
133         {
134             try
135             {
136                 Constructor<?> constructor;
137 
138                 if (null == gtuColorer)
139                 {
140                     constructor = ClassUtil.resolveConstructor(animationClass, new Object[] { this, getSimulator() });
141                     this.animation = (Renderable2D) constructor.newInstance(this, getSimulator());
142                 }
143                 else
144                 {
145                     constructor =
146                             ClassUtil.resolveConstructor(animationClass, new Object[] { this, getSimulator(), gtuColorer });
147                     this.animation = (Renderable2D) constructor.newInstance(this, getSimulator(), gtuColorer);
148                 }
149             }
150             catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
151                     | IllegalArgumentException | InvocationTargetException exception)
152             {
153                 throw new GTUException("Could not instantiate car animation of type " + animationClass.getName(), exception);
154             }
155         }
156     }
157 
158     /** {@inheritDoc} */
159     @Override
160     public final RelativePosition getFront()
161     {
162         return this.relativePositions.get(RelativePosition.FRONT);
163     }
164 
165     /** {@inheritDoc} */
166     @Override
167     public final RelativePosition getRear()
168     {
169         return this.relativePositions.get(RelativePosition.REAR);
170     }
171 
172     /** {@inheritDoc} */
173     @Override
174     public final RelativePosition getCenter()
175     {
176         return this.relativePositions.get(RelativePosition.CENTER);
177     }
178 
179     /** {@inheritDoc} */
180     @Override
181     public final ImmutableMap<TYPE, RelativePosition> getRelativePositions()
182     {
183         return new ImmutableLinkedHashMap<>(this.relativePositions, Immutable.WRAP);
184     }
185 
186     /** {@inheritDoc} */
187     @Override
188     public final ImmutableSet<RelativePosition> getContourPoints()
189     {
190         return new ImmutableHashSet<>(this.contourPoints, Immutable.WRAP);
191     }
192 
193     /** {@inheritDoc} */
194     @Override
195     public final void destroy()
196     {
197         if (this.animation != null)
198         {
199             try
200             {
201                 this.animation.destroy();
202                 this.animation = null;
203             }
204             catch (Exception e)
205             {
206                 System.err.println("Car: " + this.getId());
207                 e.printStackTrace();
208             }
209         }
210         super.destroy();
211     }
212 
213     /** {@inheritDoc} */
214     @Override
215     public final String toString()
216     {
217         return "LaneBasedIndividualGTU [id=" + getId() + "]";
218     }
219 
220     /**
221      * Build an individual car and use easy setter methods to instantiate the car. Typical use looks like:
222      * 
223      * <pre>
224      * LaneBasedIndividualCar&lt;String&gt; car = new LaneBasedIndividualCarBuilder&lt;String&gt;().setId("Car:"+nr)
225      *    .setLength(new Length(4.0, METER))....build(); 
226      *    
227      * or
228      * 
229      * LaneBasedIndividualCarBuilder&lt;String&gt; carBuilder = new LaneBasedIndividualCarBuilder&lt;String&gt;();
230      * carBuilder.setId("Car:"+nr);
231      * carBuilder.setLength(new Length(4.0, METER));
232      * carBuilder.setWidth(new Length(1.8, METER));
233      * ...
234      * LaneBasedIndividualCar&lt;String&gt; car = carBuilder.build();
235      * </pre>
236      * <p>
237      * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
238      * All rights reserved. <br>
239      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
240      * <p>
241      * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
242      *          initial Feb 3, 2015 <br>
243      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
244      */
245     @SuppressWarnings("checkstyle:hiddenfield")
246     public static class LaneBasedIndividualCarBuilder implements Serializable
247     {
248         /** */
249         private static final long serialVersionUID = 20160000L;
250 
251         /** The id of the GTU. */
252         private String id = null;
253 
254         /** The type of GTU, e.g. TruckType, CarType, BusType. */
255         private GTUType gtuType = null;
256 
257         /** The initial positions of the car on one or more lanes. */
258         private Set<DirectedLanePosition> initialLongitudinalPositions = null;
259 
260         /** The initial speed of the car on the lane. */
261         private Speed initialSpeed = null;
262 
263         /** The length of the GTU (parallel with driving direction). */
264         private Length length = null;
265 
266         /** The width of the GTU (perpendicular to driving direction). */
267         private Length width = null;
268 
269         /** The maximum speed of the GTU (in the driving direction). */
270         private Speed maximumSpeed = null;
271 
272         /** The simulator. */
273         private OTSDEVSSimulatorInterface simulator = null;
274 
275         /** Animation. */
276         private Class<? extends Renderable2D> animationClass = null;
277 
278         /** GTUColorer. */
279         private GTUColorer gtuColorer = null;
280 
281         /** Network. */
282         private OTSNetwork network = null;
283 
284         /**
285          * @param id set id
286          * @return the class itself for chaining the setters
287          */
288         public final LaneBasedIndividualCarBuilder setId(final String id)
289         {
290             this.id = id;
291             return this;
292         }
293 
294         /**
295          * @param gtuType set gtuType
296          * @return the class itself for chaining the setters
297          */
298         public final LaneBasedIndividualCarBuilder setGtuType(final GTUType gtuType)
299         {
300             this.gtuType = gtuType;
301             return this;
302         }
303 
304         /**
305          * @param initialLongitudinalPositions set initialLongitudinalPositions
306          * @return the class itself for chaining the setters
307          */
308         public final LaneBasedIndividualCarBuilder setInitialLongitudinalPositions(
309                 final Set<DirectedLanePosition> initialLongitudinalPositions)
310         {
311             this.initialLongitudinalPositions = initialLongitudinalPositions;
312             return this;
313         }
314 
315         /**
316          * @param initialSpeed set initialSpeed
317          * @return the class itself for chaining the setters
318          */
319         public final LaneBasedIndividualCarBuilder setInitialSpeed(final Speed initialSpeed)
320         {
321             this.initialSpeed = initialSpeed;
322             return this;
323         }
324 
325         /**
326          * @param length set length
327          * @return the class itself for chaining the setters
328          */
329         public final LaneBasedIndividualCarBuilder setLength(final Length length)
330         {
331             this.length = length;
332             return this;
333         }
334 
335         /**
336          * @param width set width
337          * @return the class itself for chaining the setters
338          */
339         public final LaneBasedIndividualCarBuilder setWidth(final Length width)
340         {
341             this.width = width;
342             return this;
343         }
344 
345         /**
346          * @param maximumSpeed set maximumSpeed
347          * @return the class itself for chaining the setters
348          */
349         public final LaneBasedIndividualCarBuilder setMaximumSpeed(final Speed maximumSpeed)
350         {
351             this.maximumSpeed = maximumSpeed;
352             return this;
353         }
354 
355         /**
356          * @param simulator set simulator
357          * @return the class itself for chaining the setters
358          */
359         public final LaneBasedIndividualCarBuilder setSimulator(final OTSDEVSSimulatorInterface simulator)
360         {
361             this.simulator = simulator;
362             return this;
363         }
364 
365         /**
366          * @param animationClass set animation class
367          * @return the class itself for chaining the setters
368          */
369         public final LaneBasedIndividualCarBuilder setAnimationClass(final Class<? extends Renderable2D> animationClass)
370         {
371             this.animationClass = animationClass;
372             return this;
373         }
374 
375         /**
376          * @param gtuColorer set gtuColorer.
377          * @return the class itself for chaining the setters
378          */
379         public final LaneBasedIndividualCarBuilder setGtuColorer(final GTUColorer gtuColorer)
380         {
381             this.gtuColorer = gtuColorer;
382             return this;
383         }
384 
385         /**
386          * @param network set network
387          * @return the class itself for chaining the setters
388          */
389         public final LaneBasedIndividualCarBuilder setNetwork(final OTSNetwork network)
390         {
391             this.network = network;
392             return this;
393         }
394 
395         /**
396          * @return id.
397          */
398         public final String getId()
399         {
400             return this.id;
401         }
402 
403         /**
404          * @return gtuType.
405          */
406         public final GTUType getGtuType()
407         {
408             return this.gtuType;
409         }
410 
411         /**
412          * @return initialLongitudinalPositions.
413          */
414         public final Set<DirectedLanePosition> getInitialLongitudinalPositions()
415         {
416             return this.initialLongitudinalPositions;
417         }
418 
419         /**
420          * @return initialSpeed.
421          */
422         public final Speed getInitialSpeed()
423         {
424             return this.initialSpeed;
425         }
426 
427         /**
428          * @return length.
429          */
430         public final Length getLength()
431         {
432             return this.length;
433         }
434 
435         /**
436          * @return width.
437          */
438         public final Length getWidth()
439         {
440             return this.width;
441         }
442 
443         /**
444          * @return maximumSpeed.
445          */
446         public final Speed getMaximumSpeed()
447         {
448             return this.maximumSpeed;
449         }
450 
451         /**
452          * @return simulator.
453          */
454         public final OTSDEVSSimulatorInterface getSimulator()
455         {
456             return this.simulator;
457         }
458 
459         /**
460          * @return animationClass.
461          */
462         public final Class<? extends Renderable2D> getAnimationClass()
463         {
464             return this.animationClass;
465         }
466 
467         /**
468          * @return gtuColorer.
469          */
470         public final GTUColorer getGtuColorer()
471         {
472             return this.gtuColorer;
473         }
474 
475         /**
476          * @return network
477          */
478         public final OTSNetwork getNetwork()
479         {
480             return this.network;
481         }
482 
483         /**
484          * Build one LaneBasedIndividualCar.
485          * @param laneBasedStrategicalPlannerFactory factory for the strategical planner
486          * @return the built Car with the set properties
487          * @throws Exception when not all required values have been set
488          */
489         public final LaneBasedIndividualGTU build(
490                 final LaneBasedStrategicalPlannerFactory<? extends LaneBasedStrategicalPlanner> laneBasedStrategicalPlannerFactory)
491                 throws Exception
492         {
493             if (null == this.id || null == this.gtuType || null == this.initialLongitudinalPositions
494                     || null == this.initialSpeed || null == this.length || null == this.width || null == this.maximumSpeed
495                     || null == this.simulator || null == this.network)
496             {
497                 // TODO Should throw a more specific Exception type
498                 throw new GTUException("factory settings incomplete");
499             }
500             LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU(this.id, this.gtuType, this.length, this.width,
501                     this.maximumSpeed, this.simulator, this.network);
502             gtu.initWithAnimation(laneBasedStrategicalPlannerFactory.create(gtu), this.initialLongitudinalPositions,
503                     this.initialSpeed, this.animationClass, this.gtuColorer);
504             return gtu;
505 
506         }
507 
508         /** {@inheritDoc} */
509         @Override
510         public final String toString()
511         {
512             return "LaneBasedIndividualCarBuilder [id=" + this.id + ", gtuType=" + this.gtuType
513                     + ", initialLongitudinalPositions=" + this.initialLongitudinalPositions + ", initialSpeed="
514                     + this.initialSpeed + ", length=" + this.length + ", width=" + this.width + ", maximumSpeed="
515                     + this.maximumSpeed + ", strategicalPlanner=" + "]";
516         }
517 
518     }
519 }