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