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.core.dsol.OTSAnimatorInterface;
19  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
20  import org.opentrafficsim.core.geometry.OTSGeometryException;
21  import org.opentrafficsim.core.gtu.GTUException;
22  import org.opentrafficsim.core.gtu.GTUType;
23  import org.opentrafficsim.core.gtu.RelativePosition;
24  import org.opentrafficsim.core.gtu.RelativePosition.TYPE;
25  import org.opentrafficsim.core.gtu.animation.GTUColorer;
26  import org.opentrafficsim.core.network.NetworkException;
27  import org.opentrafficsim.core.network.OTSNetwork;
28  import org.opentrafficsim.core.network.route.Route;
29  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
30  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
31  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
32  
33  import nl.tudelft.simulation.dsol.SimRuntimeException;
34  import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
35  import nl.tudelft.simulation.immutablecollections.Immutable;
36  import nl.tudelft.simulation.immutablecollections.ImmutableHashSet;
37  import nl.tudelft.simulation.immutablecollections.ImmutableLinkedHashMap;
38  import nl.tudelft.simulation.immutablecollections.ImmutableMap;
39  import nl.tudelft.simulation.immutablecollections.ImmutableSet;
40  import nl.tudelft.simulation.language.reflection.ClassUtil;
41  
42  /**
43   * Augments the AbstractLaneBasedIndividualGTU with a LaneBasedIndividualCarBuilder and animation support
44   * <p>
45   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
46   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
47   * <p>
48   * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
49   *          initial version Oct 22, 2014 <br>
50   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
51   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
52   */
53  public class LaneBasedIndividualGTU extends AbstractLaneBasedIndividualGTU
54  {
55      /** */
56      private static final long serialVersionUID = 20141025L;
57  
58      /** The animation. */
59      private Renderable2D animation;
60  
61      /** Sensing positions. */
62      private final Map<RelativePosition.TYPE, RelativePosition> relativePositions = new LinkedHashMap<>(4);
63  
64      /** contour points. */
65      private final Set<RelativePosition> contourPoints = new HashSet<>(4);
66  
67      /**
68       * Construct a new LaneBasedIndividualCar.
69       * @param id ID; the id of the GTU
70       * @param gtuType GTUTYpe; the type of GTU, e.g. TruckType, CarType, BusType
71       * @param length Length; the maximum length of the GTU (parallel with driving direction)
72       * @param width Length; the maximum width of the GTU (perpendicular to driving direction)
73       * @param maximumSpeed Speed;the maximum speed of the GTU (in the driving direction)
74       * @param simulator OTSDEVSSimulatorInterface; the simulator
75       * @param network the network that the GTU is initially registered in
76       * @throws NamingException if an error occurs when adding the animation handler
77       * @throws GTUException when a parameter is invalid
78       */
79      @SuppressWarnings("checkstyle:parameternumber")
80      public LaneBasedIndividualGTU(final String id, final GTUType gtuType, final Length length, final Length width,
81              final Speed maximumSpeed, final OTSDEVSSimulatorInterface simulator, final OTSNetwork network)
82              throws NamingException, GTUException
83      {
84          super(id, gtuType, length, width, maximumSpeed, simulator, network);
85  
86          // sensor positions.
87          // We take the rear position of the Car to be the reference point. So the front is the length
88          // of the Car away from the reference point in the positive (driving) X-direction.
89          Length dx2 = new Length(getLength().getSI() / 2.0, LengthUnit.METER);
90          Length dy2 = new Length(getWidth().getSI() / 2.0, LengthUnit.METER);
91          this.relativePositions.put(RelativePosition.FRONT,
92                  new RelativePosition(dx2, Length.ZERO, Length.ZERO, RelativePosition.FRONT));
93          this.relativePositions.put(RelativePosition.REAR,
94                  new RelativePosition(dx2.neg(), Length.ZERO, Length.ZERO, RelativePosition.REAR));
95          this.relativePositions.put(RelativePosition.REFERENCE, RelativePosition.REFERENCE_POSITION);
96          this.relativePositions.put(RelativePosition.CENTER,
97                  new RelativePosition(Length.ZERO, Length.ZERO, Length.ZERO, RelativePosition.CENTER));
98  
99          // Contour positions. For now, a rectangle with the four corners.
100         for (int i = -1; i <= 1; i += 2)
101         {
102             for (int j = -1; j <= 1; j += 2)
103             {
104                 this.contourPoints
105                         .add(new RelativePosition(dx2.multiplyBy(i), dy2.multiplyBy(j), Length.ZERO, RelativePosition.CONTOUR));
106             }
107         }
108 
109         setMaximumAcceleration(new Acceleration(1.8, AccelerationUnit.METER_PER_SECOND_2));
110         setMaximumDeceleration(new Acceleration(-3.5, AccelerationUnit.METER_PER_SECOND_2));
111     }
112 
113     /**
114      * @param strategicalPlanner the strategical planner (e.g., route determination) to use
115      * @param initialLongitudinalPositions the initial positions of the car on one or more lanes with their directions
116      * @param initialSpeed the initial speed of the car on the lane
117      * @param animationClass Class&lt;? extends Renderable2D&gt;; the class for animation or null if no animation
118      * @param gtuColorer GTUColorer; the GTUColorer that will be linked from the animation to determine the color (may be null
119      *            in which case a default will be used)
120      * @throws NetworkException when the GTU cannot be placed on the given lane
121      * @throws SimRuntimeException when the move method cannot be scheduled
122      * @throws GTUException when initial values are not correct
123      * @throws OTSGeometryException when the initial path is wrong
124      */
125     public final void initWithAnimation(final LaneBasedStrategicalPlanner strategicalPlanner,
126             final Set<DirectedLanePosition> initialLongitudinalPositions, final Speed initialSpeed,
127             final Class<? extends Renderable2D> animationClass, final GTUColorer gtuColorer)
128             throws NetworkException, SimRuntimeException, GTUException, OTSGeometryException
129     {
130         super.init(strategicalPlanner, initialLongitudinalPositions, initialSpeed);
131 
132         // animation
133         if (getSimulator() instanceof OTSAnimatorInterface && animationClass != null)
134         {
135             try
136             {
137                 Constructor<?> constructor;
138 
139                 if (null == gtuColorer)
140                 {
141                     constructor = ClassUtil.resolveConstructor(animationClass, new Object[] { this, getSimulator() });
142                     this.animation = (Renderable2D) constructor.newInstance(this, getSimulator());
143                 }
144                 else
145                 {
146                     constructor =
147                             ClassUtil.resolveConstructor(animationClass, new Object[] { this, getSimulator(), gtuColorer });
148                     this.animation = (Renderable2D) constructor.newInstance(this, getSimulator(), gtuColorer);
149                 }
150             }
151             catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
152                     | IllegalArgumentException | InvocationTargetException exception)
153             {
154                 throw new GTUException("Could not instantiate car animation of type " + animationClass.getName(), exception);
155             }
156         }
157     }
158 
159     /** {@inheritDoc} */
160     @Override
161     public final RelativePosition getFront()
162     {
163         return this.relativePositions.get(RelativePosition.FRONT);
164     }
165 
166     /** {@inheritDoc} */
167     @Override
168     public final RelativePosition getRear()
169     {
170         return this.relativePositions.get(RelativePosition.REAR);
171     }
172 
173     /** {@inheritDoc} */
174     @Override
175     public final RelativePosition getCenter()
176     {
177         return this.relativePositions.get(RelativePosition.CENTER);
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public final ImmutableMap<TYPE, RelativePosition> getRelativePositions()
183     {
184         return new ImmutableLinkedHashMap<>(this.relativePositions, Immutable.WRAP);
185     }
186 
187     /** {@inheritDoc} */
188     @Override
189     public final ImmutableSet<RelativePosition> getContourPoints()
190     {
191         return new ImmutableHashSet<>(this.contourPoints, Immutable.WRAP);
192     }
193 
194     /** {@inheritDoc} */
195     @Override
196     public final void destroy()
197     {
198         if (this.animation != null)
199         {
200             try
201             {
202                 this.animation.destroy();
203                 this.animation = null;
204             }
205             catch (Exception e)
206             {
207                 System.err.println("Error when destroying the animation of car: " + this.getId());
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          * @param route route
487          * @return the built Car with the set properties
488          * @throws Exception when not all required values have been set
489          */
490         public final LaneBasedIndividualGTU build(
491                 final LaneBasedStrategicalPlannerFactory<? extends LaneBasedStrategicalPlanner> laneBasedStrategicalPlannerFactory,
492                 final Route route) throws Exception
493         {
494             if (null == this.id || null == this.gtuType || null == this.initialLongitudinalPositions
495                     || null == this.initialSpeed || null == this.length || null == this.width || null == this.maximumSpeed
496                     || null == this.simulator || null == this.network)
497             {
498                 // TODO Should throw a more specific Exception type
499                 throw new GTUException("factory settings incomplete");
500             }
501             LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU(this.id, this.gtuType, this.length, this.width,
502                     this.maximumSpeed, this.simulator, this.network);
503             gtu.initWithAnimation(laneBasedStrategicalPlannerFactory.create(gtu, route), this.initialLongitudinalPositions,
504                     this.initialSpeed, this.animationClass, this.gtuColorer);
505             return gtu;
506 
507         }
508 
509         /** {@inheritDoc} */
510         @Override
511         public final String toString()
512         {
513             return "LaneBasedIndividualCarBuilder [id=" + this.id + ", gtuType=" + this.gtuType
514                     + ", initialLongitudinalPositions=" + this.initialLongitudinalPositions + ", initialSpeed="
515                     + this.initialSpeed + ", length=" + this.length + ", width=" + this.width + ", maximumSpeed="
516                     + this.maximumSpeed + ", strategicalPlanner=" + "]";
517         }
518 
519     }
520 }