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