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<?>; 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<Lane, DoubleScalar.Rel<LengthUnit>>; the initial positions of
59 * the car on one or more lanes
60 * @param initialSpeed DoubleScalar.Abs<SpeedUnit>; the initial speed of the car on the lane
61 * @param length DoubleScalar.Rel<LengthUnit>; the maximum length of the GTU (parallel with driving direction)
62 * @param width DoubleScalar.Rel<LengthUnit>; the maximum width of the GTU (perpendicular to driving
63 * direction)
64 * @param maximumVelocity DoubleScalar.Abs<SpeedUnit>;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<?>; 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<Lane, DoubleScalar.Rel<LengthUnit>>; the initial positions of
92 * the car on one or more lanes
93 * @param initialSpeed DoubleScalar.Abs<SpeedUnit>; the initial speed of the car on the lane
94 * @param length DoubleScalar.Rel<LengthUnit>; the maximum length of the GTU (parallel with driving direction)
95 * @param width DoubleScalar.Rel<LengthUnit>; the maximum width of the GTU (perpendicular to driving
96 * direction)
97 * @param maximumVelocity DoubleScalar.Abs<SpeedUnit>;the maximum speed of the GTU (in the driving direction)
98 * @param simulator OTSDEVSSimulatorInterface; the simulator
99 * @param animationClass Class<? extends Renderable2D>; 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 }