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
33
34
35
36
37
38
39
40
41
42 public class LaneBasedIndividualCar<ID> extends AbstractLaneBasedIndividualGTU<ID>
43 {
44
45 private static final long serialVersionUID = 20141025L;
46
47
48 private Renderable2D animation;
49
50
51 private final Map<RelativePosition.TYPE, RelativePosition> relativePositions = new HashMap<>();
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
119
120
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
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
148 @Override
149 @SuppressWarnings("checkstyle:designforextension")
150 public RelativePosition getFront()
151 {
152 return this.relativePositions.get(RelativePosition.FRONT);
153 }
154
155
156 @Override
157 @SuppressWarnings("checkstyle:designforextension")
158 public RelativePosition getRear()
159 {
160 return this.relativePositions.get(RelativePosition.REAR);
161 }
162
163
164 @Override
165 public final Map<TYPE, RelativePosition> getRelativePositions()
166 {
167 return this.relativePositions;
168 }
169
170
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
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
201 return String.format("Car %s [NO POS]", getId());
202 }
203 }
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 @SuppressWarnings("checkstyle:hiddenfield")
231 public static class LaneBasedIndividualCarBuilder<ID>
232 {
233
234 private ID id = null;
235
236
237 private GTUType<ID> gtuType = null;;
238
239
240 private Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions = null;;
241
242
243 private DoubleScalar.Abs<SpeedUnit> initialSpeed = null;
244
245
246 private GTUFollowingModel gtuFollowingModel = null;
247
248
249 private AbstractLaneChangeModel laneChangeModel = null;
250
251
252 private DoubleScalar.Rel<LengthUnit> length = null;
253
254
255 private DoubleScalar.Rel<LengthUnit> width = null;
256
257
258 private DoubleScalar.Abs<SpeedUnit> maximumVelocity = null;
259
260
261 private OTSDEVSSimulatorInterface simulator = null;
262
263
264 private Class<? extends Renderable2D> animationClass = null;
265
266
267
268
269
270 public final LaneBasedIndividualCarBuilder<ID> setId(final ID id)
271 {
272 this.id = id;
273 return this;
274 }
275
276
277
278
279
280 public final LaneBasedIndividualCarBuilder<ID> setGtuType(final GTUType<ID> gtuType)
281 {
282 this.gtuType = gtuType;
283 return this;
284 }
285
286
287
288
289
290 public final LaneBasedIndividualCarBuilder<ID> setGTUFollowingModel(final GTUFollowingModel gtuFollowingModel)
291 {
292 this.gtuFollowingModel = gtuFollowingModel;
293 return this;
294 }
295
296
297
298
299
300 public final LaneBasedIndividualCarBuilder<ID> setLaneChangeModel(final AbstractLaneChangeModel laneChangeModel)
301 {
302 this.laneChangeModel = laneChangeModel;
303 return this;
304 }
305
306
307
308
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
319
320
321 public final LaneBasedIndividualCarBuilder<ID> setInitialSpeed(final DoubleScalar.Abs<SpeedUnit> initialSpeed)
322 {
323 this.initialSpeed = initialSpeed;
324 return this;
325 }
326
327
328
329
330
331 public final LaneBasedIndividualCarBuilder<ID> setLength(final DoubleScalar.Rel<LengthUnit> length)
332 {
333 this.length = length;
334 return this;
335 }
336
337
338
339
340
341 public final LaneBasedIndividualCarBuilder<ID> setWidth(final DoubleScalar.Rel<LengthUnit> width)
342 {
343 this.width = width;
344 return this;
345 }
346
347
348
349
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
360
361
362 public final LaneBasedIndividualCarBuilder<ID> setSimulator(final OTSDEVSSimulatorInterface simulator)
363 {
364 this.simulator = simulator;
365 return this;
366 }
367
368
369
370
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
381
382
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
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 }