View Javadoc
1   package org.opentrafficsim.road.car;
2   
3   import java.lang.reflect.Constructor;
4   import java.lang.reflect.InvocationTargetException;
5   import java.util.LinkedHashMap;
6   import java.util.Map;
7   
8   import javax.naming.NamingException;
9   
10  import nl.tudelft.simulation.dsol.SimRuntimeException;
11  import nl.tudelft.simulation.dsol.animation.D2.Renderable2D;
12  import nl.tudelft.simulation.language.reflection.ClassUtil;
13  
14  import org.opentrafficsim.core.dsol.OTSAnimatorInterface;
15  import org.opentrafficsim.core.gtu.GTUException;
16  import org.opentrafficsim.core.gtu.RelativePosition;
17  import org.opentrafficsim.core.gtu.RelativePosition.TYPE;
18  import org.opentrafficsim.core.gtu.TemplateGTUType;
19  import org.opentrafficsim.core.network.NetworkException;
20  import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
21  import org.opentrafficsim.road.gtu.following.GTUFollowingModel;
22  import org.opentrafficsim.road.gtu.lane.AbstractLaneBasedTemplateGTU;
23  import org.opentrafficsim.road.network.lane.Lane;
24  import org.opentrafficsim.road.network.route.CompleteLaneBasedRouteNavigator;
25  
26  /**
27   * <p>
28   * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
29   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
30   * <p>
31   * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
32   *          initial version Oct 22, 2014 <br>
33   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
34   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
35   */
36  public class LaneBasedTemplateCar extends AbstractLaneBasedTemplateGTU
37  {
38      /** */
39      private static final long serialVersionUID = 20141025L;
40  
41      /** animation. */
42      private Renderable2D animation;
43  
44      /** Sensing positions. */
45      private final Map<RelativePosition.TYPE, RelativePosition> relativePositions = new LinkedHashMap<>();
46  
47      /**
48       * @param id ID; the id of the GTU
49       * @param templateGtuType the template of the GTU
50       * @param gtuFollowingModel GTUFollowingModel; the following model, including a reference to the simulator
51       * @param initialLongitudinalPositions Map&lt;Lane, DoubleScalar.Rel&lt;LengthUnit&gt;&gt;; the initial positions of the car
52       *            on one or more lanes
53       * @param initialSpeed DoubleScalar.Abs&lt;SpeedUnit&gt;; the initial speed of the car on the lane
54       * @param routeNavigator Route of the GTU
55       * @throws NamingException if an error occurs when adding the animation handler.
56       * @throws NetworkException when the GTU cannot be placed on the given lane.
57       * @throws SimRuntimeException when the move method cannot be scheduled.
58       * @throws GTUException when gtuFollowingModel is null
59       */
60      public LaneBasedTemplateCar(final String id, final TemplateGTUType templateGtuType,
61          final GTUFollowingModel gtuFollowingModel, final Map<Lane, Length.Rel> initialLongitudinalPositions,
62          final Speed.Abs initialSpeed, final CompleteLaneBasedRouteNavigator routeNavigator) throws NamingException,
63          NetworkException, SimRuntimeException, GTUException
64      {
65          this(id, templateGtuType, gtuFollowingModel, initialLongitudinalPositions, initialSpeed, routeNavigator,
66              DefaultCarAnimation.class);
67      }
68  
69      /**
70       * @param id ID; the id of the GTU
71       * @param templateGtuType the template of the GTU
72       * @param gtuFollowingModel GTUFollowingModel; the following model, including a reference to the simulator
73       * @param initialLongitudinalPositions Map&lt;Lane, DoubleScalar.Rel&lt;LengthUnit&gt;&gt;; the initial positions of the car
74       *            on one or more lanes
75       * @param initialSpeed DoubleScalar.Abs&lt;SpeedUnit&gt;; the initial speed of the car on the lane
76       * @param routeNavigator Route; the route of the new car
77       * @param animationClass Class&lt;? extends Renderable2D&gt;; the class for animation or null if no animation.
78       * @throws NamingException if an error occurs when adding the animation handler.
79       * @throws NetworkException when the GTU cannot be placed on the given lane.
80       * @throws SimRuntimeException when the move method cannot be scheduled.
81       * @throws GTUException when gtuFollowingModel is null
82       */
83      public LaneBasedTemplateCar(final String id, final TemplateGTUType templateGtuType,
84          final GTUFollowingModel gtuFollowingModel, final Map<Lane, Length.Rel> initialLongitudinalPositions,
85          final Speed.Abs initialSpeed, final CompleteLaneBasedRouteNavigator routeNavigator,
86          final Class<? extends Renderable2D> animationClass) throws NamingException, NetworkException,
87          SimRuntimeException, GTUException
88      {
89          super(id, templateGtuType, gtuFollowingModel, initialLongitudinalPositions, initialSpeed, routeNavigator);
90  
91          // sensor positions.
92          // We take the rear position of the Car to be the reference point. So the front is the length
93          // of the Car away from the reference point in the positive (driving) X-direction.
94          Length.Rel zero = new Length.Rel(0.0d, METER);
95          Length.Rel dx = new Length.Rel(getLength().getSI(), METER);
96          this.relativePositions
97              .put(RelativePosition.FRONT, new RelativePosition(dx, zero, zero, RelativePosition.FRONT));
98          this.relativePositions
99              .put(RelativePosition.REAR, new RelativePosition(zero, zero, zero, RelativePosition.REAR));
100         this.relativePositions.put(RelativePosition.REFERENCE, RelativePosition.REFERENCE_POSITION);
101 
102         // animation
103         if (getSimulator() instanceof OTSAnimatorInterface && animationClass != null)
104         {
105             try
106             {
107                 Constructor<?> constructor =
108                     ClassUtil.resolveConstructor(animationClass, new Object[]{this, getSimulator()});
109                 this.animation = (Renderable2D) constructor.newInstance(this, getSimulator());
110             }
111             catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
112                 | IllegalArgumentException | InvocationTargetException exception)
113             {
114                 throw new NetworkException("Could not instantiate car animation of type " + animationClass.getName(),
115                     exception);
116             }
117         }
118     }
119 
120     /** {@inheritDoc} */
121     @Override
122     @SuppressWarnings("checkstyle:designforextension")
123     public RelativePosition getFront()
124     {
125         return this.relativePositions.get(RelativePosition.FRONT);
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     @SuppressWarnings("checkstyle:designforextension")
131     public RelativePosition getRear()
132     {
133         return this.relativePositions.get(RelativePosition.REAR);
134     }
135 
136     /** {@inheritDoc} */
137     @Override
138     public final Map<TYPE, RelativePosition> getRelativePositions()
139     {
140         return this.relativePositions;
141     }
142 
143     /** {@inheritDoc} */
144     @Override
145     public final void destroy()
146     {
147         if (this.animation != null)
148         {
149             try
150             {
151                 this.animation.destroy();
152             }
153             catch (Exception e)
154             {
155                 System.err.println("Car: " + this.getId());
156                 e.printStackTrace();
157             }
158         }
159         super.destroy();
160     }
161 
162     /** {@inheritDoc} */
163     public final String toString()
164     {
165         try
166         {
167             Map<Lane, Length.Rel> frontPositions = positions(getFront());
168             Lane frontLane = frontPositions.keySet().iterator().next();
169             return String.format("Car %s front:%s[%s]", getId(), frontLane, frontPositions.get(frontLane));
170         }
171         catch (NetworkException exception)
172         {
173             exception.printStackTrace();
174         }
175         return "Caught exception in toString";
176     }
177 
178     /**
179      * Build a template car and use easy setter methods to instantiate the car. Typical use looks like:
180      * 
181      * <pre>
182      * LaneBasedTemplateCar&lt;String&gt; car = new LaneBasedTemplateCarBuilder&lt;String&gt;().setId("Car:"+nr)
183      *    .setInitialSpeed(new DoubleScalar.Rel&lt;SpeedUnit&gt;(80.0, KM_PER_HOUR))....build(); 
184      *    
185      * or
186      * 
187      * LaneBasedTemplateCarBuilder&lt;String&gt; carBuilder = new LaneBasedTemplateCarBuilder&lt;String&gt;();
188      * carBuilder.setId("Car:"+nr);
189      * carBuilder.setTemplateGtuType(TruckTemplate);
190      * carBuilder.setInitialSpeed(new DoubleScalar.Rel&lt;SpeedUnit&gt;(80.0, KM_PER_HOUR));
191      * ...
192      * LaneBasedTemplateCar&lt;String&gt; car = carBuilder.build();
193      * </pre>
194      * <p>
195      * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
196      * All rights reserved. <br>
197      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
198      * <p>
199      * @version $Revision: 1401 $, $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, by $Author: averbraeck $,
200      *          initial Feb 3, 2015 <br>
201      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
202      */
203     @SuppressWarnings("checkstyle:hiddenfield")
204     public static class LaneBasedTemplateCarBuilder
205     {
206         /** the id of the GTU. */
207         private String id = null;
208 
209         /** the type of GTU, e.g. TruckType, CarType, BusType. */
210         private TemplateGTUType templateGtuType = null;
211 
212         /** the initial positions of the car on one or more lanes. */
213         private Map<Lane, Length.Rel> initialLongitudinalPositions = null;;
214 
215         /** the initial speed of the car on the lane. */
216         private Speed.Abs initialSpeed = null;
217 
218         /** CarFollowingModel used by this Car. */
219         private GTUFollowingModel gtuFollowingModel = null;
220 
221         /** Route followed by this Car. */
222         private CompleteLaneBasedRouteNavigator routeNavigator = null;
223 
224         /** animation. */
225         private Class<? extends Renderable2D> animationClass = null;
226 
227         /**
228          * @param id set id
229          * @return the class itself for chaining the setters
230          */
231         public final LaneBasedTemplateCarBuilder setId(final String id)
232         {
233             this.id = id;
234             return this;
235         }
236 
237         /**
238          * @param templateGtuType set the template for the gtuType
239          * @return the class itself for chaining the setters
240          */
241         public final LaneBasedTemplateCarBuilder setTemplateGtuType(final TemplateGTUType templateGtuType)
242         {
243             this.templateGtuType = templateGtuType;
244             return this;
245         }
246 
247         /**
248          * @param initialLongitudinalPositions set initialLongitudinalPositions
249          * @return the class itself for chaining the setters
250          */
251         public final LaneBasedTemplateCarBuilder setInitialLongitudinalPositions(
252             final Map<Lane, Length.Rel> initialLongitudinalPositions)
253         {
254             this.initialLongitudinalPositions = initialLongitudinalPositions;
255             return this;
256         }
257 
258         /**
259          * @param initialSpeed set initialSpeed
260          * @return the class itself for chaining the setters
261          */
262         public final LaneBasedTemplateCarBuilder setInitialSpeed(final Speed.Abs initialSpeed)
263         {
264             this.initialSpeed = initialSpeed;
265             return this;
266         }
267 
268         /**
269          * @param routeNavigator RouteNavigator; the route
270          * @return the class itself for chaining the setters
271          */
272         public final LaneBasedTemplateCarBuilder
273             setRouteNavigator(final CompleteLaneBasedRouteNavigator routeNavigator)
274         {
275             this.routeNavigator = routeNavigator;
276             return this;
277         }
278 
279         /**
280          * @param animationClass set animation class
281          * @return the class itself for chaining the setters
282          */
283         public final LaneBasedTemplateCarBuilder setAnimationClass(final Class<? extends Renderable2D> animationClass)
284         {
285             this.animationClass = animationClass;
286             return this;
287         }
288 
289         /**
290          * @return the built Car with the set properties
291          * @throws NamingException if an error occurs when adding the animation handler
292          * @throws NetworkException when the GTU cannot be placed on the given lane
293          * @throws SimRuntimeException when the move method cannot be scheduled
294          * @throws GTUException when gtuFollowingModel is null
295          */
296         public final LaneBasedTemplateCar build() throws NamingException, NetworkException, SimRuntimeException,
297             GTUException
298         {
299             // TODO check that none of the variables (except animationClass) is null, and throw an exception if it is.
300 
301             return new LaneBasedTemplateCar(this.id, this.templateGtuType, this.gtuFollowingModel,
302                 this.initialLongitudinalPositions, this.initialSpeed, this.routeNavigator, this.animationClass);
303         }
304     }
305 
306 }