1 package org.opentrafficsim.road.gtu.generator;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.LinkedHashSet;
6 import java.util.List;
7 import java.util.Set;
8
9 import nl.tudelft.simulation.dsol.SimRuntimeException;
10
11 import org.djunits.unit.LengthUnit;
12 import org.djunits.unit.SpeedUnit;
13 import org.djunits.unit.TimeUnit;
14 import org.djunits.value.vdouble.scalar.Duration;
15 import org.djunits.value.vdouble.scalar.Length;
16 import org.djunits.value.vdouble.scalar.Speed;
17 import org.djunits.value.vdouble.scalar.Time;
18 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
19 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
20 import org.opentrafficsim.core.gtu.GTUDirectionality;
21 import org.opentrafficsim.core.gtu.GTUException;
22 import org.opentrafficsim.core.gtu.GTUType;
23 import org.opentrafficsim.core.gtu.RelativePosition;
24 import org.opentrafficsim.core.gtu.animation.GTUColorer;
25 import org.opentrafficsim.core.network.NetworkException;
26 import org.opentrafficsim.core.network.OTSNetwork;
27 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
28 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
29 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
30 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
31 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU.LaneBasedIndividualCarBuilder;
32 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
33 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
34 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayDistance;
35 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTUSimple;
36 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
37 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
38 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
39 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
40 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
41 import org.opentrafficsim.road.network.lane.Lane;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 public abstract class AbstractGTUGenerator implements Serializable
59 {
60
61 private static final long serialVersionUID = 20150202L;
62
63
64 private final String name;
65
66
67 private final GTUType gtuType;
68
69
70 private final Class<?> gtuClass;
71
72
73 private final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist;
74
75
76 private final ContinuousDistDoubleScalar.Rel<Duration, TimeUnit> interarrivelTimeDist;
77
78
79 private long generatedGTUs = 0;
80
81
82 private final long maxGTUs;
83
84
85 private final Time startTime;
86
87
88 private final Time endTime;
89
90
91 private final Lane lane;
92
93
94 private final Length position;
95
96
97 private final GTUDirectionality direction;
98
99
100 private final GTUColorer gtuColorer;
101
102
103 private final LaneBasedStrategicalPlannerFactory<? extends LaneBasedStrategicalPlanner> strategicalPlannerFactory;
104
105
106 private final OTSNetwork network;
107
108
109 private List<LaneBasedIndividualCarBuilder> carBuilderList = new ArrayList<>();
110
111
112 @SuppressWarnings("checkstyle:visibilitymodifier")
113 protected long numberGTUs = 0;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 @SuppressWarnings("checkstyle:parameternumber")
134 public AbstractGTUGenerator(final String name, final OTSDEVSSimulatorInterface simulator, final GTUType gtuType,
135 final Class<?> gtuClass, final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDist,
136 final ContinuousDistDoubleScalar.Rel<Duration, TimeUnit> interarrivelTimeDist, final long maxGTUs,
137 final Time startTime, final Time endTime, final Lane lane, final Length position,
138 final GTUDirectionality direction, final GTUColorer gtuColorer,
139 final LaneBasedStrategicalPlannerFactory<? extends LaneBasedStrategicalPlanner> strategicalPlannerFactory,
140 final OTSNetwork network) throws SimRuntimeException
141 {
142 super();
143 this.name = name;
144 this.gtuType = gtuType;
145 this.gtuClass = gtuClass;
146 this.initialSpeedDist = initialSpeedDist;
147 this.interarrivelTimeDist = interarrivelTimeDist;
148 this.maxGTUs = maxGTUs;
149 this.startTime = startTime;
150 this.endTime = endTime;
151 this.lane = lane;
152 this.position = position;
153 this.direction = direction;
154 this.gtuColorer = gtuColorer;
155 this.strategicalPlannerFactory = strategicalPlannerFactory;
156 this.network = network;
157
158 simulator.scheduleEventAbs(startTime, this, this, "generate", null);
159 }
160
161
162
163
164
165 protected final void generate() throws Exception
166 {
167
168 if (getSimulator().getSimulatorTime().getTime().gt(this.endTime))
169 {
170 return;
171 }
172
173
174 if (this.generatedGTUs >= this.maxGTUs)
175 {
176 return;
177 }
178
179
180 this.numberGTUs++;
181 String id = this.name + ":" + this.numberGTUs;
182
183
184 if (LaneBasedIndividualGTU.class.isAssignableFrom(getGtuClass()))
185 {
186 LaneBasedIndividualCarBuilder carBuilder = new LaneBasedIndividualCarBuilder();
187 carBuilder.setId(id);
188 carBuilder.setGtuType(getGtuType());
189 Length carLength = getLengthDist().draw();
190 carBuilder.setLength(carLength);
191 carBuilder.setWidth(getWidthDist().draw());
192 carBuilder.setMaximumSpeed(getMaximumSpeedDist().draw());
193 carBuilder.setInitialSpeed(getInitialSpeedDist().draw());
194 carBuilder.setSimulator(getSimulator());
195 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>(1);
196 initialLongitudinalPositions.add(new DirectedLanePosition(this.lane, this.position, this.direction));
197 carBuilder.setInitialLongitudinalPositions(initialLongitudinalPositions);
198 carBuilder.setAnimationClass(DefaultCarAnimation.class);
199 carBuilder.setGtuColorer(this.gtuColorer);
200 carBuilder.setNetwork(this.network);
201 this.generatedGTUs++;
202
203 if (enoughSpace(carBuilder))
204 {
205 carBuilder.build(this.strategicalPlannerFactory);
206 }
207 else
208 {
209
210 this.carBuilderList.add(carBuilder);
211
212 if (this.carBuilderList.size() == 1)
213 {
214
215 getSimulator()
216 .scheduleEventRel(new Duration(0.1, TimeUnit.SECOND), this, this, "checkCarBuilderList", null);
217 }
218 }
219 }
220 else
221 {
222 throw new GTUException("GTU class " + getGtuClass().getName() + ": cannot instantiate, no builder.");
223 }
224
225
226 OTSSimTimeDouble nextTime = getSimulator().getSimulatorTime().plus(this.interarrivelTimeDist.draw());
227 if (nextTime.get().le(this.endTime))
228 {
229 getSimulator().scheduleEventAbs(nextTime, this, this, "generate", null);
230 }
231 }
232
233
234
235
236
237
238
239
240
241 protected final boolean enoughSpace(final LaneBasedIndividualCarBuilder carBuilder) throws NetworkException, GTUException
242 {
243 DirectedLanePosition directedLanePosition = carBuilder.getInitialLongitudinalPositions().iterator().next();
244 Lane generatorLane = directedLanePosition.getLane();
245 double genPosSI = directedLanePosition.getPosition().getSI();
246
247
248 double lengthSI = generatorLane.getLength().getSI();
249 double frontNew = (genPosSI + carBuilder.getLength().getSI()) / lengthSI;
250 double rearNew = genPosSI / lengthSI;
251
252
253 for (LaneBasedGTU gtu : generatorLane.getGtuList())
254 {
255 double frontGTU = gtu.fractionalPosition(generatorLane, gtu.getFront());
256 double rearGTU = gtu.fractionalPosition(generatorLane, gtu.getRear());
257 if ((frontNew >= rearGTU && frontNew <= frontGTU) || (rearNew >= rearGTU && rearNew <= frontGTU)
258 || (frontGTU >= rearNew && frontGTU <= frontNew) || (rearGTU >= rearNew && rearGTU <= frontNew))
259 {
260
261 return false;
262 }
263 }
264
265
266 GTUFollowingModelOld followingModel = new IDMPlusOld();
267
268
269 Headway headway = headway(new Length(250.0, LengthUnit.METER), generatorLane);
270 Length minimumHeadway = new Length(0.0, LengthUnit.METER);
271 if (headway.getObjectType().isGtu())
272 {
273 minimumHeadway =
274 followingModel.minimumHeadway(carBuilder.getInitialSpeed(), headway.getSpeed(), new Length(1.0,
275 LengthUnit.CENTIMETER), new Length(250.0, LengthUnit.METER), generatorLane
276 .getSpeedLimit(carBuilder.getGtuType()), carBuilder.getMaximumSpeed());
277 double acc =
278 followingModel.computeAcceleration(carBuilder.getInitialSpeed(), carBuilder.getMaximumSpeed(),
279 headway.getSpeed(), minimumHeadway, carBuilder.getMaximumSpeed()).getSI();
280 if (acc < 0)
281 {
282 System.err.println(getSimulator().getSimulatorTime() + ", generator headway for GTU " + headway.getId()
283 + ", distance " + headway.getDistance().si + " m, max " + minimumHeadway + ", has to brake with a="
284 + acc + " m/s^2");
285 return false;
286 }
287 }
288
289
290
291 return headway.getDistance().ge(minimumHeadway);
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306 private Headway headwayRecursiveForwardSI(final Lane theLane, final double lanePositionSI, final double cumDistanceSI,
307 final double maxDistanceSI, final Time when) throws GTUException
308 {
309
310 LaneBasedGTU otherGTU =
311 theLane.getGtuAhead(new Length(lanePositionSI, LengthUnit.METER), GTUDirectionality.DIR_PLUS,
312 RelativePosition.REAR, when);
313 if (otherGTU != null)
314 {
315 double distanceM = cumDistanceSI + otherGTU.position(theLane, otherGTU.getRear(), when).getSI() - lanePositionSI;
316 if (distanceM > 0 && distanceM <= maxDistanceSI)
317 {
318 return new HeadwayGTUSimple(otherGTU.getId(), otherGTU.getGTUType(), new Length(distanceM, LengthUnit.SI),
319 otherGTU.getLength(), otherGTU.getSpeed(), null);
320 }
321 return new HeadwayDistance(Double.MAX_VALUE);
322 }
323
324
325 if (cumDistanceSI + theLane.getLength().getSI() - lanePositionSI < maxDistanceSI)
326 {
327
328 if (theLane.nextLanes(this.gtuType).size() > 0)
329 {
330 Headway foundMaxGTUDistanceSI = new HeadwayDistance(Double.MAX_VALUE);
331 for (Lane nextLane : theLane.nextLanes(this.gtuType).keySet())
332 {
333
334
335
336
337 {
338 double traveledDistanceSI = cumDistanceSI + theLane.getLength().getSI() - lanePositionSI;
339 Headway closest = headwayRecursiveForwardSI(nextLane, 0.0, traveledDistanceSI, maxDistanceSI, when);
340 if (closest.getDistance().si < maxDistanceSI
341 && closest.getDistance().si < foundMaxGTUDistanceSI.getDistance().si)
342 {
343 foundMaxGTUDistanceSI = closest;
344 }
345 }
346 }
347 return foundMaxGTUDistanceSI;
348 }
349 }
350
351
352 return new HeadwayDistance(Double.MAX_VALUE);
353 }
354
355
356
357
358
359
360
361
362
363
364
365
366
367 private Headway headwayRecursiveBackwardSI(final Lane theLane, final double lanePositionSI, final double cumDistanceSI,
368 final double maxDistanceSI, final Time when) throws GTUException
369 {
370
371 LaneBasedGTU otherGTU =
372 theLane.getGtuBehind(new Length(lanePositionSI, LengthUnit.METER), GTUDirectionality.DIR_PLUS,
373 RelativePosition.FRONT, when);
374 if (otherGTU != null)
375 {
376 double distanceM = cumDistanceSI + otherGTU.position(theLane, otherGTU.getFront(), when).getSI() - lanePositionSI;
377 if (distanceM > 0 && distanceM <= maxDistanceSI)
378 {
379 return new HeadwayGTUSimple(otherGTU.getId(), otherGTU.getGTUType(), new Length(distanceM, LengthUnit.SI),
380 otherGTU.getLength(), otherGTU.getSpeed(), null);
381 }
382 return new HeadwayDistance(Double.MAX_VALUE);
383 }
384
385
386 if (cumDistanceSI + theLane.getLength().getSI() - lanePositionSI < maxDistanceSI)
387 {
388
389 if (theLane.prevLanes(this.gtuType).size() > 0)
390 {
391 Headway foundMaxGTUDistanceSI = new HeadwayDistance(Double.MAX_VALUE);
392 for (Lane prevLane : theLane.prevLanes(this.gtuType).keySet())
393 {
394
395
396
397
398 {
399 double traveledDistanceSI = cumDistanceSI + theLane.getLength().getSI() - lanePositionSI;
400 Headway closest = headwayRecursiveBackwardSI(prevLane, 0.0, traveledDistanceSI, maxDistanceSI, when);
401 if (closest.getDistance().si < maxDistanceSI
402 && closest.getDistance().si < foundMaxGTUDistanceSI.getDistance().si)
403 {
404 foundMaxGTUDistanceSI = closest;
405 }
406 }
407 }
408 return foundMaxGTUDistanceSI;
409 }
410 }
411
412
413 return new HeadwayDistance(Double.MAX_VALUE);
414 }
415
416
417
418
419
420
421
422
423
424 private Headway headwayGTUSIForward(final double maxDistanceSI, final Lane generatorLane) throws GTUException
425 {
426 Time when = getSimulator().getSimulatorTime().getTime();
427 Headway foundMaxGTUDistanceSI = new HeadwayDistance(Double.MAX_VALUE);
428
429 Headway closest;
430 if (this.direction.equals(GTUDirectionality.DIR_PLUS))
431 {
432 closest = headwayRecursiveForwardSI(this.lane, generatorLane.getLength().getSI(), 0.0, maxDistanceSI, when);
433 }
434 else
435 {
436 closest = headwayRecursiveBackwardSI(this.lane, generatorLane.getLength().getSI(), 0.0, maxDistanceSI, when);
437 }
438 if (closest.getDistance().si < maxDistanceSI && closest.getDistance().si < foundMaxGTUDistanceSI.getDistance().si)
439 {
440 foundMaxGTUDistanceSI = closest;
441 }
442 return foundMaxGTUDistanceSI;
443 }
444
445
446
447
448
449
450
451
452 public final Headway headway(final Length maxDistance, final Lane generatorLane) throws GTUException
453 {
454 return headwayGTUSIForward(maxDistance.getSI(), generatorLane);
455 }
456
457
458
459
460
461 protected final void checkCarBuilderList() throws Exception
462 {
463 if (!this.carBuilderList.isEmpty())
464 {
465 LaneBasedIndividualCarBuilder carBuilder = this.carBuilderList.get(0);
466 if (enoughSpace(carBuilder))
467 {
468 this.carBuilderList.remove(0);
469 carBuilder.build(this.strategicalPlannerFactory);
470 }
471 }
472
473
474 if (!this.carBuilderList.isEmpty())
475 {
476 getSimulator().scheduleEventRel(new Duration(0.1, TimeUnit.SECOND), this, this, "checkCarBuilderList", null);
477 }
478 }
479
480
481 public abstract OTSDEVSSimulatorInterface getSimulator();
482
483
484 public abstract ContinuousDistDoubleScalar.Rel<Length, LengthUnit> getLengthDist();
485
486
487 public abstract ContinuousDistDoubleScalar.Rel<Length, LengthUnit> getWidthDist();
488
489
490 public abstract ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> getMaximumSpeedDist();
491
492
493
494
495 public final String getName()
496 {
497 return this.name;
498 }
499
500
501
502
503 public final GTUType getGtuType()
504 {
505 return this.gtuType;
506 }
507
508
509
510
511 public final Class<?> getGtuClass()
512 {
513 return this.gtuClass;
514 }
515
516
517
518
519 public final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> getInitialSpeedDist()
520 {
521 return this.initialSpeedDist;
522 }
523
524
525
526
527 public final ContinuousDistDoubleScalar.Rel<Duration, TimeUnit> getInterarrivelTimeDist()
528 {
529 return this.interarrivelTimeDist;
530 }
531
532
533
534
535 public final long getMaxGTUs()
536 {
537 return this.maxGTUs;
538 }
539
540
541
542
543 public final Time getStartTime()
544 {
545 return this.startTime;
546 }
547
548
549
550
551 public final Time getEndTime()
552 {
553 return this.endTime;
554 }
555
556
557
558
559 public final GTUColorer getGtuColorer()
560 {
561 return this.gtuColorer;
562 }
563
564
565
566
567 public final LaneBasedStrategicalPlannerFactory<? extends LaneBasedStrategicalPlanner> getStrategicalPlannerFactory()
568 {
569 return this.strategicalPlannerFactory;
570 }
571
572 }