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.dsol.OTSDEVSSimulatorInterface;
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.following.GTUFollowingModel;
22  import org.opentrafficsim.core.gtu.lane.AbstractLaneBasedIndividualGTU;
23  import org.opentrafficsim.core.gtu.lane.changing.AbstractLaneChangeModel;
24  import org.opentrafficsim.core.gtu.lane.changing.LaneChangeModel;
25  import org.opentrafficsim.core.network.NetworkException;
26  import org.opentrafficsim.core.network.lane.Lane;
27  import org.opentrafficsim.core.unit.LengthUnit;
28  import org.opentrafficsim.core.unit.SpeedUnit;
29  import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
30  
31  /**
32   * <p>
33   * Copyright (c) 2013-2014 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights
34   * reserved. <br>
35   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
36   * <p>
37   * @version Oct 22, 2014 <br>
38   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
39   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
40   * @param <ID> The type of ID, e.g., String or Integer
41   */
42  public class LaneBasedIndividualCar<ID> extends AbstractLaneBasedIndividualGTU<ID>
43  {
44      /** */
45      private static final long serialVersionUID = 20141025L;
46  
47      /** animation. */
48      private Renderable2D animation;
49  
50      /** Sensing positions. */
51      private final Map<RelativePosition.TYPE, RelativePosition> relativePositions = new HashMap<>();
52  
53      /**
54       * @param id ID; the id of the GTU, could be String or Integer
55       * @param gtuType GTUTYpe&lt;?&gt;; the type of GTU, e.g. TruckType, CarType, BusType
56       * @param gtuFollowingModel GTUFollowingModel; the following model, including a reference to the simulator
57       * @param laneChangeModel LaneChangeModel; the lane change model
58       * @param initialLongitudinalPositions Map&lt;Lane, DoubleScalar.Rel&lt;LengthUnit&gt;&gt;; the initial positions of
59       *            the car on one or more lanes
60       * @param initialSpeed DoubleScalar.Abs&lt;SpeedUnit&gt;; the initial speed of the car on the lane
61       * @param length DoubleScalar.Rel&lt;LengthUnit&gt;; the maximum length of the GTU (parallel with driving direction)
62       * @param width DoubleScalar.Rel&lt;LengthUnit&gt;; the maximum width of the GTU (perpendicular to driving
63       *            direction)
64       * @param maximumVelocity DoubleScalar.Abs&lt;SpeedUnit&gt;;the maximum speed of the GTU (in the driving direction)
65       * @param simulator OTSDEVSSimulatorInterface; the simulator
66       * @throws NamingException if an error occurs when adding the animation handler
67       * @throws RemoteException when the simulator cannot be reached
68       * @throws NetworkException when the GTU cannot be placed on the given lane
69       * @throws SimRuntimeException when the move method cannot be scheduled
70       * @throws GTUException when a parameter is invalid
71       */
72      @SuppressWarnings("checkstyle:parameternumber")
73      public LaneBasedIndividualCar(final ID id, final GTUType<?> gtuType, final GTUFollowingModel gtuFollowingModel,
74              final LaneChangeModel laneChangeModel,
75              final Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions,
76              final DoubleScalar.Abs<SpeedUnit> initialSpeed, final DoubleScalar.Rel<LengthUnit> length,
77              final DoubleScalar.Rel<LengthUnit> width, final DoubleScalar.Abs<SpeedUnit> maximumVelocity,
78              final OTSDEVSSimulatorInterface simulator) throws NamingException, RemoteException, NetworkException,
79              SimRuntimeException, GTUException
80      {
81          this(id, gtuType, gtuFollowingModel, laneChangeModel, initialLongitudinalPositions, initialSpeed, length,
82                  width, maximumVelocity, simulator, DefaultCarAnimation.class);
83      }
84  
85      /**
86       * Construct a new LaneBasedIndividualCar.
87       * @param id ID; the id of the GTU, could be String or Integer
88       * @param gtuType GTUTYpe&lt;?&gt;; the type of GTU, e.g. TruckType, CarType, BusType
89       * @param gtuFollowingModel GTUFollowingModel; the following model, including a reference to the simulator
90       * @param laneChangeModel LaneChangeModel; the lane change model
91       * @param initialLongitudinalPositions Map&lt;Lane, DoubleScalar.Rel&lt;LengthUnit&gt;&gt;; the initial positions of
92       *            the car on one or more lanes
93       * @param initialSpeed DoubleScalar.Abs&lt;SpeedUnit&gt;; the initial speed of the car on the lane
94       * @param length DoubleScalar.Rel&lt;LengthUnit&gt;; the maximum length of the GTU (parallel with driving direction)
95       * @param width DoubleScalar.Rel&lt;LengthUnit&gt;; the maximum width of the GTU (perpendicular to driving
96       *            direction)
97       * @param maximumVelocity DoubleScalar.Abs&lt;SpeedUnit&gt;;the maximum speed of the GTU (in the driving direction)
98       * @param simulator OTSDEVSSimulatorInterface; the simulator
99       * @param animationClass Class&lt;? extends Renderable2D&gt;; the class for animation or null if no animation
100      * @throws NamingException if an error occurs when adding the animation handler
101      * @throws RemoteException when the simulator cannot be reached
102      * @throws NetworkException when the GTU cannot be placed on the given lane
103      * @throws SimRuntimeException when the move method cannot be scheduled
104      * @throws GTUException when a parameter is invalid
105      */
106     @SuppressWarnings("checkstyle:parameternumber")
107     public LaneBasedIndividualCar(final ID id, final GTUType<?> gtuType, final GTUFollowingModel gtuFollowingModel,
108             final LaneChangeModel laneChangeModel,
109             final Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions,
110             final DoubleScalar.Abs<SpeedUnit> initialSpeed, final DoubleScalar.Rel<LengthUnit> length,
111             final DoubleScalar.Rel<LengthUnit> width, final DoubleScalar.Abs<SpeedUnit> maximumVelocity,
112             final OTSDEVSSimulatorInterface simulator, final Class<? extends Renderable2D> animationClass)
113             throws NamingException, RemoteException, NetworkException, SimRuntimeException, GTUException
114     {
115         super(id, gtuType, gtuFollowingModel, laneChangeModel, initialLongitudinalPositions, initialSpeed, length,
116                 width, maximumVelocity, simulator);
117 
118         // sensor positions.
119         // We take the rear position of the Car to be the reference point. So the front is the length
120         // of the Car away from the reference point in the positive (driving) X-direction.
121         DoubleScalar.Rel<LengthUnit> zero = new DoubleScalar.Rel<LengthUnit>(0.0d, LengthUnit.METER);
122         DoubleScalar.Rel<LengthUnit> dx = new DoubleScalar.Rel<LengthUnit>(getLength().getSI(), LengthUnit.METER);
123         this.relativePositions
124                 .put(RelativePosition.FRONT, new RelativePosition(dx, zero, zero, RelativePosition.FRONT));
125         this.relativePositions
126                 .put(RelativePosition.REAR, new RelativePosition(zero, zero, zero, RelativePosition.REAR));
127         this.relativePositions.put(RelativePosition.REFERENCE, RelativePosition.REFERENCE_POSITION);
128 
129         // animation
130         if (simulator instanceof OTSAnimatorInterface && animationClass != null)
131         {
132             try
133             {
134                 Constructor<?> constructor =
135                         ClassUtil.resolveConstructor(animationClass, new Object[]{this, simulator});
136                 this.animation = (Renderable2D) constructor.newInstance(this, simulator);
137             }
138             catch (InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException
139                     | IllegalArgumentException | InvocationTargetException exception)
140             {
141                 throw new NetworkException("Could not instantiate car animation of type " + animationClass.getName(),
142                         exception);
143             }
144         }
145     }
146 
147     /** {@inheritDoc} */
148     @Override
149     @SuppressWarnings("checkstyle:designforextension")
150     public RelativePosition getFront()
151     {
152         return this.relativePositions.get(RelativePosition.FRONT);
153     }
154 
155     /** {@inheritDoc} */
156     @Override
157     @SuppressWarnings("checkstyle:designforextension")
158     public RelativePosition getRear()
159     {
160         return this.relativePositions.get(RelativePosition.REAR);
161     }
162 
163     /** {@inheritDoc} */
164     @Override
165     public final Map<TYPE, RelativePosition> getRelativePositions()
166     {
167         return this.relativePositions;
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public final void destroy()
173     {
174         if (this.animation != null)
175         {
176             try
177             {
178                 this.animation.destroy();
179             }
180             catch (Exception e)
181             {
182                 System.err.println("Car: " + this.getId());
183                 e.printStackTrace();
184             }
185         }
186         super.destroy();
187     }
188 
189     /** {@inheritDoc} */
190     public final String toString()
191     {
192         try
193         {
194             Map<Lane, DoubleScalar.Rel<LengthUnit>> frontPositions = positions(getFront());
195             Lane frontLane = frontPositions.keySet().iterator().next();
196             return String.format("Car %s front: %s[%s]", getId(), frontLane, frontPositions.get(frontLane));
197         }
198         catch (RuntimeException | RemoteException | NetworkException exception)
199         {
200             // exception.printStackTrace();
201             return String.format("Car %s [NO POS]", getId());
202         }
203     }
204 
205     /**
206      * Build an individual car and use easy setter methods to instantiate the car. Typical use looks like:
207      * 
208      * <pre>
209      * LaneBasedIndividualCar<String> car = new LaneBasedIndividualCarBuilder<String>().setId("Car:"+nr)
210      *    .setLength(new DoubleScalar.Rel<LengthUnit>(4.0, LengthUnit.METER))....build(); 
211      *    
212      * or
213      * 
214      * LaneBasedIndividualCarBuilder<String> carBuilder = new LaneBasedIndividualCarBuilder<String>();
215      * carBuilder.setId("Car:"+nr);
216      * carBuilder.setLength(new DoubleScalar.Rel<LengthUnit>(4.0, LengthUnit.METER));
217      * carBuilder.setWidth(new DoubleScalar.Rel<LengthUnit>(1.8, LengthUnit.METER));
218      * ...
219      * LaneBasedIndividualCar<String> car = carBuilder.build();
220      * </pre>
221      * <p>
222      * Copyright (c) 2013-2014 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
223      * All rights reserved. <br>
224      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
225      * <p>
226      * @version Feb 3, 2015 <br>
227      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
228      * @param <ID> the ID type of the Car, e.g. String or Integer or Long.
229      */
230     @SuppressWarnings("checkstyle:hiddenfield")
231     public static class LaneBasedIndividualCarBuilder<ID>
232     {
233         /** The id of the GTU, could be String or Integer. */
234         private ID id = null;
235 
236         /** The type of GTU, e.g. TruckType, CarType, BusType. */
237         private GTUType<ID> gtuType = null;;
238 
239         /** The initial positions of the car on one or more lanes. */
240         private Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions = null;;
241 
242         /** The initial speed of the car on the lane. */
243         private DoubleScalar.Abs<SpeedUnit> initialSpeed = null;
244 
245         /** CarFollowingModel used by this Car. */
246         private GTUFollowingModel gtuFollowingModel = null;
247 
248         /** The lane change model. */
249         private AbstractLaneChangeModel laneChangeModel = null;
250 
251         /** The maximum length of the GTU (parallel with driving direction). */
252         private DoubleScalar.Rel<LengthUnit> length = null;
253 
254         /** The maximum width of the GTU (perpendicular to driving direction). */
255         private DoubleScalar.Rel<LengthUnit> width = null;
256 
257         /** The maximum speed of the GTU (in the driving direction). */
258         private DoubleScalar.Abs<SpeedUnit> maximumVelocity = null;
259 
260         /** The simulator. */
261         private OTSDEVSSimulatorInterface simulator = null;
262 
263         /** Animation. */
264         private Class<? extends Renderable2D> animationClass = null;
265 
266         /**
267          * @param id set id.
268          * @return the class itself for chaining the setters.
269          */
270         public final LaneBasedIndividualCarBuilder<ID> setId(final ID id)
271         {
272             this.id = id;
273             return this;
274         }
275 
276         /**
277          * @param gtuType set gtuType.
278          * @return the class itself for chaining the setters.
279          */
280         public final LaneBasedIndividualCarBuilder<ID> setGtuType(final GTUType<ID> gtuType)
281         {
282             this.gtuType = gtuType;
283             return this;
284         }
285 
286         /**
287          * @param gtuFollowingModel GTUFollowingModel; the GTU following model used by the built cars
288          * @return the class itself for chaining the setters.
289          */
290         public final LaneBasedIndividualCarBuilder<ID> setGTUFollowingModel(final GTUFollowingModel gtuFollowingModel)
291         {
292             this.gtuFollowingModel = gtuFollowingModel;
293             return this;
294         }
295 
296         /**
297          * @param laneChangeModel AbstractLaneChangeModel; the lane change model
298          * @return the class itself for chaining the setters.
299          */
300         public final LaneBasedIndividualCarBuilder<ID> setLaneChangeModel(final AbstractLaneChangeModel laneChangeModel)
301         {
302             this.laneChangeModel = laneChangeModel;
303             return this;
304         }
305 
306         /**
307          * @param initialLongitudinalPositions set initialLongitudinalPositions.
308          * @return the class itself for chaining the setters.
309          */
310         public final LaneBasedIndividualCarBuilder<ID> setInitialLongitudinalPositions(
311                 final Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions)
312         {
313             this.initialLongitudinalPositions = initialLongitudinalPositions;
314             return this;
315         }
316 
317         /**
318          * @param initialSpeed set initialSpeed.
319          * @return the class itself for chaining the setters.
320          */
321         public final LaneBasedIndividualCarBuilder<ID> setInitialSpeed(final DoubleScalar.Abs<SpeedUnit> initialSpeed)
322         {
323             this.initialSpeed = initialSpeed;
324             return this;
325         }
326 
327         /**
328          * @param length set length.
329          * @return the class itself for chaining the setters.
330          */
331         public final LaneBasedIndividualCarBuilder<ID> setLength(final DoubleScalar.Rel<LengthUnit> length)
332         {
333             this.length = length;
334             return this;
335         }
336 
337         /**
338          * @param width set width.
339          * @return the class itself for chaining the setters.
340          */
341         public final LaneBasedIndividualCarBuilder<ID> setWidth(final DoubleScalar.Rel<LengthUnit> width)
342         {
343             this.width = width;
344             return this;
345         }
346 
347         /**
348          * @param maximumVelocity set maximumVelocity.
349          * @return the class itself for chaining the setters.
350          */
351         public final LaneBasedIndividualCarBuilder<ID> setMaximumVelocity(
352                 final DoubleScalar.Abs<SpeedUnit> maximumVelocity)
353         {
354             this.maximumVelocity = maximumVelocity;
355             return this;
356         }
357 
358         /**
359          * @param simulator set simulator.
360          * @return the class itself for chaining the setters.
361          */
362         public final LaneBasedIndividualCarBuilder<ID> setSimulator(final OTSDEVSSimulatorInterface simulator)
363         {
364             this.simulator = simulator;
365             return this;
366         }
367 
368         /**
369          * @param animationClass set animation class.
370          * @return the class itself for chaining the setters.
371          */
372         public final LaneBasedIndividualCarBuilder<ID> setAnimationClass(
373                 final Class<? extends Renderable2D> animationClass)
374         {
375             this.animationClass = animationClass;
376             return this;
377         }
378 
379         /**
380          * Build one LaneBasedIndividualCar.
381          * @return the built Car with the set properties
382          * @throws Exception when not all required values have been set
383          */
384         public final LaneBasedIndividualCar<ID> build() throws Exception
385         {
386             if (null == this.id || null == this.gtuType || null == this.gtuFollowingModel
387                     || null == this.laneChangeModel || null == this.initialLongitudinalPositions
388                     || null == this.initialSpeed || null == this.length || null == this.width
389                     || null == this.maximumVelocity || null == this.simulator)
390             {
391                 // TODO Should throw a more specific Exception type
392                 throw new Exception("factory settings incomplete");
393             }
394             return new LaneBasedIndividualCar<ID>(this.id, this.gtuType, this.gtuFollowingModel, this.laneChangeModel,
395                     this.initialLongitudinalPositions, this.initialSpeed, this.length, this.width,
396                     this.maximumVelocity, this.simulator, this.animationClass);
397         }
398     }
399 }