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