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