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