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