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