1 package org.opentrafficsim.demo.carFollowing;
2
3 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4
5 import java.awt.Container;
6 import java.awt.Frame;
7 import java.io.IOException;
8 import java.net.URL;
9 import java.rmi.RemoteException;
10 import java.util.ArrayList;
11 import java.util.HashSet;
12 import java.util.LinkedHashSet;
13 import java.util.List;
14 import java.util.Random;
15 import java.util.Set;
16
17 import javax.naming.NamingException;
18 import javax.swing.JComponent;
19 import javax.swing.JPanel;
20 import javax.swing.JScrollPane;
21 import javax.swing.SwingUtilities;
22
23 import org.djunits.unit.AccelerationUnit;
24 import org.djunits.unit.LengthUnit;
25 import org.djunits.unit.TimeUnit;
26 import org.djunits.unit.UNITS;
27 import org.djunits.value.vdouble.scalar.Acceleration;
28 import org.djunits.value.vdouble.scalar.Duration;
29 import org.djunits.value.vdouble.scalar.Length;
30 import org.djunits.value.vdouble.scalar.Speed;
31 import org.djunits.value.vdouble.scalar.Time;
32 import org.opentrafficsim.base.modelproperties.BooleanProperty;
33 import org.opentrafficsim.base.modelproperties.CompoundProperty;
34 import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty;
35 import org.opentrafficsim.base.modelproperties.Property;
36 import org.opentrafficsim.base.modelproperties.PropertyException;
37 import org.opentrafficsim.base.modelproperties.SelectionProperty;
38 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
39 import org.opentrafficsim.core.dsol.OTSModelInterface;
40 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
41 import org.opentrafficsim.core.geometry.OTSGeometryException;
42 import org.opentrafficsim.core.geometry.OTSPoint3D;
43 import org.opentrafficsim.core.gtu.GTUDirectionality;
44 import org.opentrafficsim.core.gtu.GTUException;
45 import org.opentrafficsim.core.gtu.GTUType;
46 import org.opentrafficsim.core.gtu.animation.GTUColorer;
47 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
48 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
49 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
50 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
51 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan.Segment;
52 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
53 import org.opentrafficsim.core.network.LongitudinalDirectionality;
54 import org.opentrafficsim.core.network.NetworkException;
55 import org.opentrafficsim.core.network.OTSNetwork;
56 import org.opentrafficsim.core.network.OTSNode;
57 import org.opentrafficsim.graphs.AccelerationContourPlot;
58 import org.opentrafficsim.graphs.ContourPlot;
59 import org.opentrafficsim.graphs.DensityContourPlot;
60 import org.opentrafficsim.graphs.FlowContourPlot;
61 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
62 import org.opentrafficsim.graphs.SpeedContourPlot;
63 import org.opentrafficsim.graphs.TrajectoryPlot;
64 import org.opentrafficsim.road.animation.AnimationToggles;
65 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
66 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
67 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
68 import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
69 import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
70 import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
71 import org.opentrafficsim.road.gtu.lane.tactical.LanePathInfo;
72 import org.opentrafficsim.road.gtu.lane.tactical.following.AccelerationStep;
73 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
74 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
75 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
76 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
77 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
78 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
79 import org.opentrafficsim.road.network.factory.LaneFactory;
80 import org.opentrafficsim.road.network.lane.CrossSectionLink;
81 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
82 import org.opentrafficsim.road.network.lane.Lane;
83 import org.opentrafficsim.road.network.lane.LaneType;
84 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
85 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
86 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
87 import org.opentrafficsim.simulationengine.OTSSimulationException;
88 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
89
90 import nl.tudelft.simulation.dsol.SimRuntimeException;
91 import nl.tudelft.simulation.dsol.gui.swing.HTMLPanel;
92 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
93 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
94 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
95 import nl.tudelft.simulation.jstats.distributions.DistTriangular;
96 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
97 import nl.tudelft.simulation.language.d3.DirectedPoint;
98
99
100
101
102
103
104
105
106
107
108
109 public class StraightPerception extends AbstractWrappableAnimation implements UNITS
110 {
111
112 private static final long serialVersionUID = 1L;
113
114
115 private StraightPerceptionModel model;
116
117
118
119
120
121 public StraightPerception() throws PropertyException
122 {
123 List<Property<?>> outputProperties = new ArrayList<>();
124 outputProperties.add(new BooleanProperty("DensityPlot", "Density", "Density contour plot", true, false, 0));
125 outputProperties.add(new BooleanProperty("FlowPlot", "Flow", "Flow contour plot", true, false, 1));
126 outputProperties.add(new BooleanProperty("SpeedPlot", "Speed", "Speed contour plot", true, false, 2));
127 outputProperties.add(new BooleanProperty("AccelerationPlot", "Acceleration", "Acceleration contour plot", true, false,
128 3));
129 outputProperties.add(new BooleanProperty("TrajectoryPlot", "Trajectories", "Trajectory (time/distance) diagram", true,
130 false, 4));
131 this.properties.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
132 outputProperties, true, 1000));
133 }
134
135
136 @Override
137 public final void stopTimersThreads()
138 {
139 super.stopTimersThreads();
140 this.model = null;
141 }
142
143
144
145
146
147
148 public static void main(final String[] args) throws SimRuntimeException
149 {
150 SwingUtilities.invokeLater(new Runnable()
151 {
152 @SuppressWarnings("synthetic-access")
153 @Override
154 public void run()
155 {
156 try
157 {
158 StraightPerception straight = new StraightPerception();
159 List<Property<?>> localProperties = straight.getProperties();
160 try
161 {
162 localProperties.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
163 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
164 new Double[] { 0.8, 0.2 }, false, 10));
165 }
166 catch (PropertyException exception)
167 {
168 exception.printStackTrace();
169 }
170 localProperties.add(new SelectionProperty("CarFollowingModel", "Car following model",
171 "<html>The car following model determines "
172 + "the acceleration that a vehicle will make taking into account "
173 + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
174 + "curvature of the road) capabilities of the vehicle and personality "
175 + "of the driver.</html>", new String[] { "IDM", "IDM+" }, 1, false, 1));
176 localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car", new Acceleration(1.0,
177 METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2), new Length(2.0, METER),
178 new Duration(1.0, SECOND), 2));
179 localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck", new Acceleration(0.5,
180 METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2), new Length(2.0, METER),
181 new Duration(1.0, SECOND), 3));
182 straight.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND),
183 localProperties, null, true);
184 straight.panel.getTabbedPane().addTab("info", straight.makeInfoPane());
185 }
186 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
187 {
188 exception.printStackTrace();
189 }
190 }
191 });
192 }
193
194
195 @Override
196 protected final void addAnimationToggles()
197 {
198 AnimationToggles.setTextAnimationTogglesStandard(this);
199 }
200
201
202 @Override
203 protected final OTSModelInterface makeModel(final GTUColorer colorer)
204 {
205 this.model = new StraightPerceptionModel(this.savedUserModifiedProperties, colorer);
206 return this.model;
207 }
208
209
210
211
212 protected final JComponent makeInfoPane()
213 {
214
215 String helpSource = "/" + StraightPerceptionModel.class.getPackage().getName().replace('.', '/') + "/IDMPlus.html";
216 URL page = StraightPerceptionModel.class.getResource(helpSource);
217 if (page != null)
218 {
219 try
220 {
221 HTMLPanel htmlPanel = new HTMLPanel(page);
222 return new JScrollPane(htmlPanel);
223 }
224 catch (IOException exception)
225 {
226 exception.printStackTrace();
227 }
228 }
229 return new JPanel();
230 }
231
232
233 @Override
234 protected final void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
235 {
236
237
238 Property<?> output = new CompoundProperty("", "", "", this.properties, false, 0).findByKey("OutputGraphs");
239 if (null == output)
240 {
241 throw new Error("Cannot find output properties");
242 }
243 ArrayList<BooleanProperty> graphs = new ArrayList<>();
244 if (output instanceof CompoundProperty)
245 {
246 CompoundProperty outputProperties = (CompoundProperty) output;
247 for (Property<?> ap : outputProperties.getValue())
248 {
249 if (ap instanceof BooleanProperty)
250 {
251 BooleanProperty bp = (BooleanProperty) ap;
252 if (bp.getValue())
253 {
254 graphs.add(bp);
255 }
256 }
257 }
258 }
259 else
260 {
261 throw new Error("output properties should be compound");
262 }
263 int graphCount = graphs.size();
264 int columns = (int) Math.ceil(Math.sqrt(graphCount));
265 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
266 TablePanel charts = new TablePanel(columns, rows);
267
268 for (int i = 0; i < graphCount; i++)
269 {
270 String graphName = graphs.get(i).getKey();
271 Container container = null;
272 LaneBasedGTUSampler graph;
273 if (graphName.contains("Trajectories"))
274 {
275 List<Lane> path = new ArrayList<>();
276 path.add(this.model.getLane());
277 TrajectoryPlot tp = new TrajectoryPlot("TrajectoryPlot", new Duration(0.5, SECOND), path, simulator);
278 tp.setTitle("Trajectory Graph");
279 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
280 graph = tp;
281 container = tp.getContentPane();
282 }
283 else
284 {
285 ContourPlot cp;
286 if (graphName.contains("DensityPlot"))
287 {
288 cp = new DensityContourPlot("DensityPlot", this.model.getPath());
289 cp.setTitle("Density Contour Graph");
290 }
291 else if (graphName.contains("SpeedPlot"))
292 {
293 cp = new SpeedContourPlot("SpeedPlot", this.model.getPath());
294 cp.setTitle("Speed Contour Graph");
295 }
296 else if (graphName.contains("FlowPlot"))
297 {
298 cp = new FlowContourPlot("FlowPlot", this.model.getPath());
299 cp.setTitle("Flow Contour Graph");
300 }
301 else if (graphName.contains("AccelerationPlot"))
302 {
303 cp = new AccelerationContourPlot("AccelerationPlot", this.model.getPath());
304 cp.setTitle("Acceleration Contour Graph");
305 }
306 else
307 {
308 throw new Error("Unhandled type of contourplot: " + graphName);
309 }
310 graph = cp;
311 container = cp.getContentPane();
312 }
313
314 charts.setCell(container, i % columns, i / columns);
315 this.model.getPlots().add(graph);
316 }
317 addTab(getTabCount(), "statistics", charts);
318 }
319
320
321 @Override
322 public final String shortName()
323 {
324 return "Straight lane";
325 }
326
327
328 @Override
329 public final String description()
330 {
331 return "<html><h1>Simulation of a straight one-lane road with opening bridge</H1>"
332 + "Simulation of a single lane road of 5 km length. Vehicles are generated at a constant rate of "
333 + "1500 veh/hour. At time 300s a blockade is inserted at position 4km; this blockade is removed at "
334 + "time 420s. This blockade simulates a bridge opening.<br>"
335 + "The blockade causes a traffic jam that slowly dissolves after the blockade is removed.<br>"
336 + "Selected trajectory and contour plots are generated during the simulation.</html>";
337 }
338
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362 class StraightPerceptionModel implements OTSModelInterface, UNITS
363 {
364
365 private static final long serialVersionUID = 20140815L;
366
367
368 private OTSDEVSSimulatorInterface simulator;
369
370
371 private OTSNetwork network = new OTSNetwork("network");
372
373
374 private Duration headway;
375
376
377 private int carsCreated = 0;
378
379
380 private GTUType gtuType = CAR;
381
382
383 private GTUFollowingModelOld carFollowingModelCars;
384
385
386 private double carProbability;
387
388
389 private LaneBasedIndividualGTU block = null;
390
391
392 private Length minimumDistance = new Length(0, METER);
393
394
395 private Length maximumDistance = new Length(5000, METER);
396
397
398 private Lane lane;
399
400
401 private List<LaneBasedGTUSampler> plots = new ArrayList<>();
402
403
404 private List<Property<?>> properties = null;
405
406
407 private Random randomGenerator = new Random(12345);
408
409
410 private final GTUColorer gtuColorer;
411
412
413
414
415
416 StraightPerceptionModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
417 {
418 this.properties = properties;
419 this.gtuColorer = gtuColorer;
420 }
421
422
423 private List<Lane> path = new ArrayList<>();
424
425
426 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
427
428
429 @SuppressWarnings("visibilitymodifier")
430 DistContinuous perceptionIntervalDist = new DistTriangular(new MersenneTwister(2), 0.25, 1, 2);
431
432
433 @SuppressWarnings("visibilitymodifier")
434 DistContinuous forwardHeadwayDist = new DistTriangular(new MersenneTwister(20), 20, 50, 100);
435
436
437
438
439 public List<Lane> getPath()
440 {
441 return new ArrayList<>(this.path);
442 }
443
444
445 @Override
446 public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
447 throws SimRuntimeException, RemoteException
448 {
449 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
450 try
451 {
452 OTSNode from = new OTSNode(this.network, "From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
453 OTSNode to = new OTSNode(this.network, "To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
454 OTSNode end = new OTSNode(this.network, "End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
455 Set<GTUType> compatibility = new HashSet<>();
456 compatibility.add(this.gtuType);
457 LaneType laneType = new LaneType("CarLane", compatibility);
458 this.lane =
459 LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit, this.simulator,
460 LongitudinalDirectionality.DIR_PLUS);
461 this.path.add(this.lane);
462 CrossSectionLink endLink =
463 LaneFactory.makeLink(this.network, "endLink", to, end, null, LongitudinalDirectionality.DIR_PLUS, simulator);
464
465 Lane sinkLane =
466 new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
467 this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0),
468 laneType, LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
469 new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
470 String carFollowingModelName = null;
471 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
472 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
473 if (null == cfmp)
474 {
475 throw new Error("Cannot find \"Car following model\" property");
476 }
477 if (cfmp instanceof SelectionProperty)
478 {
479 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
480 }
481 else
482 {
483 throw new Error("\"Car following model\" property has wrong type");
484 }
485 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
486 {
487 if (ap instanceof SelectionProperty)
488 {
489 SelectionProperty sp = (SelectionProperty) ap;
490 if ("CarFollowingModel".equals(sp.getKey()))
491 {
492 carFollowingModelName = sp.getValue();
493 }
494 }
495 else if (ap instanceof ProbabilityDistributionProperty)
496 {
497 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
498 String modelName = ap.getKey();
499 if (modelName.equals("TrafficComposition"))
500 {
501 this.carProbability = pdp.getValue()[0];
502 }
503 }
504 else if (ap instanceof CompoundProperty)
505 {
506 CompoundProperty cp = (CompoundProperty) ap;
507 if (ap.getKey().equals("OutputGraphs"))
508 {
509 continue;
510 }
511 if (ap.getKey().contains("IDM"))
512 {
513 Acceleration a = IDMPropertySet.getA(cp);
514 Acceleration b = IDMPropertySet.getB(cp);
515 Length s0 = IDMPropertySet.getS0(cp);
516 Duration tSafe = IDMPropertySet.getTSafe(cp);
517 GTUFollowingModelOld gtuFollowingModel = null;
518 if (carFollowingModelName.equals("IDM"))
519 {
520 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
521 }
522 else if (carFollowingModelName.equals("IDM+"))
523 {
524 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
525 }
526 else
527 {
528 throw new Error("Unknown gtu following model: " + carFollowingModelName);
529 }
530 if (ap.getKey().contains("Car"))
531 {
532 this.carFollowingModelCars = gtuFollowingModel;
533 }
534 else if (ap.getKey().contains("Truck"))
535 {
536 }
537 else
538 {
539 throw new Error("Cannot determine gtu type for " + ap.getKey());
540 }
541
542
543
544
545
546 }
547 }
548 }
549
550
551 this.headway = new Duration(3600.0 / 1500.0, SECOND);
552
553 this.simulator.scheduleEventAbs(new Time(0.0, SECOND), this, this, "generateCar", null);
554
555 this.simulator.scheduleEventAbs(new Time(300, SECOND), this, this, "createBlock", null);
556
557 this.simulator.scheduleEventAbs(new Time(420, SECOND), this, this, "removeBlock", null);
558
559 for (int t = 1; t <= 1800; t++)
560 {
561 this.simulator.scheduleEventAbs(new Time(t - 0.001, SECOND), this, this, "drawGraphs", null);
562 }
563 }
564 catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | PropertyException exception)
565 {
566 exception.printStackTrace();
567 }
568 }
569
570
571
572
573 protected final void drawGraphs()
574 {
575 for (LaneBasedGTUSampler plot : this.plots)
576 {
577 plot.reGraph();
578 }
579 }
580
581
582
583
584 protected final void createBlock()
585 {
586 Length initialPosition = new Length(4000, METER);
587 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
588 try
589 {
590 initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
591 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
592
593 this.block =
594 new LaneBasedIndividualGTU("999999", this.gtuType, new Length(4, METER), new Length(1.8, METER), new Speed(
595 0.0, KM_PER_HOUR), this.simulator, this.network);
596 LaneBasedStrategicalPlanner strategicalPlanner =
597 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new GTUFollowingTacticalPlannerNoPerceive(
598 this.carFollowingModelCars, this.block), this.block);
599 this.block.initWithAnimation(strategicalPlanner, initialPositions, new Speed(0.0, KM_PER_HOUR),
600 DefaultCarAnimation.class, this.gtuColorer);
601 }
602 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
603 {
604 exception.printStackTrace();
605 }
606 }
607
608
609
610
611 protected final void removeBlock()
612 {
613 this.block.destroy();
614 this.block = null;
615 }
616
617
618
619
620
621 protected final void generateCar() throws ParameterException
622 {
623 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
624 Length initialPosition = new Length(0, METER);
625 Speed initialSpeed = new Speed(100, KM_PER_HOUR);
626 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
627 try
628 {
629 initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
630 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
631 GTUFollowingModelOld gtuFollowingModel;
632 if (generateTruck)
633 {
634 Acceleration a = new Acceleration(0.5, AccelerationUnit.METER_PER_SECOND_2);
635 Acceleration b = new Acceleration(1.25, AccelerationUnit.METER_PER_SECOND_2);
636 Length s0 = new Length(4, LengthUnit.METER);
637 Duration tSafe = new Duration(2.0, TimeUnit.SECOND);
638 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
639 }
640 else
641 {
642 Acceleration a = new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2);
643 Acceleration b = new Acceleration(3, AccelerationUnit.METER_PER_SECOND_2);
644 Length s0 = new Length(2.0, LengthUnit.METER);
645 Duration tSafe = new Duration(1.0, TimeUnit.SECOND);
646 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
647 }
648 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
649 LaneBasedPerceivingCar car =
650 new LaneBasedPerceivingCar("" + (++this.carsCreated), this.gtuType, vehicleLength, new Length(1.8, METER),
651 new Speed(200, KM_PER_HOUR), this.simulator, this.network);
652 LaneBasedStrategicalPlanner strategicalPlanner =
653 new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics, new GTUFollowingTacticalPlannerNoPerceive(
654 gtuFollowingModel, car), car);
655 car.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
656 this.gtuColorer);
657 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
658 car.setPerceptionInterval(new Duration(this.perceptionIntervalDist.draw(), TimeUnit.SECOND));
659 car.getStrategicalPlanner().getBehavioralCharacteristics()
660 .setParameter(ParameterTypes.LOOKAHEAD, new Length(this.forwardHeadwayDist.draw(), LengthUnit.METER));
661
662 }
663 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
664 {
665 exception.printStackTrace();
666 }
667 }
668
669
670 @Override
671 public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
672 {
673 return this.simulator;
674 }
675
676
677 @Override
678 public OTSNetwork getNetwork()
679 {
680 return this.network;
681 }
682
683
684
685
686 public final List<LaneBasedGTUSampler> getPlots()
687 {
688 return this.plots;
689 }
690
691
692
693
694 public final Length getMinimumDistance()
695 {
696 return this.minimumDistance;
697 }
698
699
700
701
702 public final Length getMaximumDistance()
703 {
704 return this.maximumDistance;
705 }
706
707
708
709
710 public Lane getLane()
711 {
712 return this.lane;
713 }
714
715
716
717
718 class LaneBasedPerceivingCar extends LaneBasedIndividualGTU
719 {
720
721 private static final long serialVersionUID = 1L;
722
723
724 private Duration perceptionInterval = new Duration(0.5, TimeUnit.SECOND);
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741 LaneBasedPerceivingCar(final String id, final GTUType gtuType, final Length length, final Length width,
742 final Speed maximumSpeed, final OTSDEVSSimulatorInterface simulator, final OTSNetwork network)
743 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException,
744 ParameterException
745 {
746 super(id, gtuType, length, width, maximumSpeed, simulator, network);
747 perceive();
748 }
749
750
751
752
753 public void setPerceptionInterval(final Duration perceptionInterval)
754 {
755 this.perceptionInterval = perceptionInterval;
756 }
757
758
759
760
761
762
763
764
765 public void perceive() throws SimRuntimeException, GTUException, NetworkException, ParameterException
766 {
767 getTacticalPlanner().getPerception().perceive();
768 getSimulator().scheduleEventRel(this.perceptionInterval, this, this, "perceive", null);
769 }
770 }
771
772
773
774
775 class GTUFollowingTacticalPlannerNoPerceive extends AbstractLaneBasedTacticalPlanner
776 {
777
778 private static final long serialVersionUID = 20151125L;
779
780
781
782
783
784
785 GTUFollowingTacticalPlannerNoPerceive(final GTUFollowingModelOld carFollowingModel, final LaneBasedGTU gtu)
786 {
787 super(carFollowingModel, gtu);
788 }
789
790
791 @Override
792 public OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
793 throws OperationalPlanException, NetworkException, GTUException, ParameterException
794 {
795
796
797
798 if (getGtu().getMaximumSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
799 {
800
801 return new OperationalPlan(getGtu(), locationAtStartTime, startTime, new Duration(
802 perceptionIntervalDist.draw(), TimeUnit.SECOND));
803 }
804
805
806
807
808
809
810 LanePathInfo lanePathInfo =
811 buildLanePathInfo(getGtu(), getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD));
812 Length maxDistance = lanePathInfo.getPath().getLength();
813
814
815 Headway headway = getPerception().getPerceptionCategory(DefaultSimplePerception.class).getForwardHeadwayGTU();
816 AccelerationStep accelerationStep = null;
817 if (headway.getDistance().le(maxDistance))
818 {
819 accelerationStep =
820 ((GTUFollowingModelOld) this.getCarFollowingModel()).computeAccelerationStepWithNoLeader(getGtu(),
821 maxDistance, getPerception().getPerceptionCategory(DefaultSimplePerception.class).getSpeedLimit());
822 }
823 else
824 {
825
826 accelerationStep =
827 ((GTUFollowingModelOld) this.getCarFollowingModel()).computeAccelerationStep(getGtu(),
828 headway.getSpeed(), headway.getDistance(), maxDistance,
829 getPerception().getPerceptionCategory(DefaultSimplePerception.class).getSpeedLimit());
830 }
831
832
833 if (accelerationStep.getAcceleration().si < 1E-6 && getGtu().getSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
834 {
835 return new OperationalPlan(getGtu(), locationAtStartTime, startTime, accelerationStep.getDuration());
836 }
837
838 List<Segment> operationalPlanSegmentList = new ArrayList<>();
839 if (accelerationStep.getAcceleration().si == 0.0)
840 {
841 Segment segment = new OperationalPlan.SpeedSegment(accelerationStep.getDuration());
842 operationalPlanSegmentList.add(segment);
843 }
844 else
845 {
846 Segment segment =
847 new OperationalPlan.AccelerationSegment(accelerationStep.getDuration(),
848 accelerationStep.getAcceleration());
849 operationalPlanSegmentList.add(segment);
850 }
851 OperationalPlan op =
852 new OperationalPlan(getGtu(), lanePathInfo.getPath(), startTime, getGtu().getSpeed(),
853 operationalPlanSegmentList);
854 return op;
855 }
856 }
857 }