1 package org.opentrafficsim.demo.carFollowing;
2
3 import java.awt.Container;
4 import java.awt.Frame;
5 import java.awt.geom.Rectangle2D;
6 import java.rmi.RemoteException;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.LinkedHashSet;
10 import java.util.List;
11 import java.util.Random;
12 import java.util.Set;
13
14 import javax.naming.NamingException;
15 import javax.swing.JPanel;
16 import javax.swing.SwingUtilities;
17
18 import org.djunits.unit.UNITS;
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.base.modelproperties.BooleanProperty;
25 import org.opentrafficsim.base.modelproperties.CompoundProperty;
26 import org.opentrafficsim.base.modelproperties.ContinuousProperty;
27 import org.opentrafficsim.base.modelproperties.IntegerProperty;
28 import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty;
29 import org.opentrafficsim.base.modelproperties.Property;
30 import org.opentrafficsim.base.modelproperties.PropertyException;
31 import org.opentrafficsim.base.modelproperties.SelectionProperty;
32 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
33 import org.opentrafficsim.core.dsol.OTSModelInterface;
34 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
35 import org.opentrafficsim.core.geometry.OTSGeometryException;
36 import org.opentrafficsim.core.geometry.OTSPoint3D;
37 import org.opentrafficsim.core.gtu.GTUDirectionality;
38 import org.opentrafficsim.core.gtu.GTUException;
39 import org.opentrafficsim.core.gtu.GTUType;
40 import org.opentrafficsim.core.gtu.animation.GTUColorer;
41 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
42 import org.opentrafficsim.core.network.LongitudinalDirectionality;
43 import org.opentrafficsim.core.network.NetworkException;
44 import org.opentrafficsim.core.network.OTSNetwork;
45 import org.opentrafficsim.core.network.OTSNode;
46 import org.opentrafficsim.graphs.AccelerationContourPlot;
47 import org.opentrafficsim.graphs.ContourPlot;
48 import org.opentrafficsim.graphs.DensityContourPlot;
49 import org.opentrafficsim.graphs.FlowContourPlot;
50 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
51 import org.opentrafficsim.graphs.SpeedContourPlot;
52 import org.opentrafficsim.graphs.TrajectoryPlot;
53 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
54 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
55 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
56 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
57 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
58 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
59 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
61 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
62 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
63 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
64 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
65 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
66 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
67 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
68 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
69 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
70 import org.opentrafficsim.road.network.factory.LaneFactory;
71 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
72 import org.opentrafficsim.road.network.lane.Lane;
73 import org.opentrafficsim.road.network.lane.LaneType;
74 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
75 import org.opentrafficsim.simulationengine.OTSSimulationException;
76 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
77
78 import nl.tudelft.simulation.dsol.SimRuntimeException;
79 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
80 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
81
82
83
84
85
86
87
88
89
90
91
92 public class CircularRoad extends AbstractWrappableAnimation implements UNITS
93 {
94
95 private static final long serialVersionUID = 1L;
96
97
98 private RoadSimulationModel model;
99
100
101
102
103
104 public CircularRoad() throws PropertyException
105 {
106 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
107 "<html>The lane change strategies vary in politeness.<br>"
108 + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
109 + "<li>Altruistic (assigns effect on new and current follower the same weight as "
110 + "the personal gain).</html>",
111 new String[] { "Egoistic", "Altruistic" }, 0, false, 500));
112 this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
113 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
114 new String[] { "MOBIL", "LMRS", "Toledo" }, 0, false, 600));
115 this.properties.add(new IntegerProperty("TrackLength", "Track length", "Circumference of the track", 2000, 500, 6000,
116 "Track length %dm", false, 10));
117 this.properties.add(new ContinuousProperty("MeanDensity", "Mean density", "Number of vehicles per km", 40.0, 5.0, 45.0,
118 "Density %.1f veh/km", false, 11));
119 this.properties.add(new ContinuousProperty("DensityVariability", "Density variability",
120 "Variability of the number of vehicles per km", 0.0, 0.0, 1.0, "%.1f", false, 12));
121 List<Property<?>> outputProperties = new ArrayList<Property<?>>();
122 for (int lane = 1; lane <= 2; lane++)
123 {
124 String laneId = String.format("Lane %d ", lane);
125 outputProperties.add(new BooleanProperty(laneId + "Density", laneId + " Density", laneId + "Density contour plot",
126 true, false, 0));
127 outputProperties
128 .add(new BooleanProperty(laneId + "Flow", laneId + " Flow", laneId + "Flow contour plot", true, false, 1));
129 outputProperties.add(
130 new BooleanProperty(laneId + "Speed", laneId + " Speed", laneId + "Speed contour plot", true, false, 2));
131 outputProperties.add(new BooleanProperty(laneId + "Acceleration", laneId + " Acceleration",
132 laneId + "Acceleration contour plot", true, false, 3));
133 outputProperties.add(new BooleanProperty(laneId + "Fixed Sample Rate Trajectories", laneId + " FSR Trajectories",
134 laneId + "Trajectory (time/distance) diagram", true, false, 4));
135 outputProperties.add(new BooleanProperty(laneId + "Variable Sample Rate Trajectories", laneId + " VSR Trajectories",
136 laneId + "Trajectory (time/distance) diagram", true, false, 5));
137 }
138 this.properties.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
139 outputProperties, true, 1000));
140 }
141
142
143 @Override
144 public final void stopTimersThreads()
145 {
146 super.stopTimersThreads();
147 this.model = null;
148 }
149
150
151
152
153
154
155 public static void main(final String[] args) throws SimRuntimeException
156 {
157 SwingUtilities.invokeLater(new Runnable()
158 {
159 @Override
160 public void run()
161 {
162 try
163 {
164 CircularRoad circularRoad = new CircularRoad();
165 List<Property<?>> propertyList = circularRoad.getProperties();
166 try
167 {
168 propertyList.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
169 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
170 new Double[] { 0.8, 0.2 }, false, 10));
171 }
172 catch (PropertyException exception)
173 {
174 exception.printStackTrace();
175 }
176 propertyList.add(new SelectionProperty("CarFollowingModel", "Car following model",
177 "<html>The car following model determines "
178 + "the acceleration that a vehicle will make taking into account "
179 + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
180 + "curvature of the road) capabilities of the vehicle and personality "
181 + "of the driver.</html>",
182 new String[] { "IDM", "IDM+" }, 1, false, 1));
183 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car",
184 new Acceleration(1.0, METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2),
185 new Length(2.0, METER), new Duration(1.0, SECOND), 2));
186 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck",
187 new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2),
188 new Length(2.0, METER), new Duration(1.0, SECOND), 3));
189
190 circularRoad.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND),
191 propertyList, null, true);
192 }
193 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
194 {
195 exception.printStackTrace();
196 }
197 }
198 });
199 }
200
201
202 @Override
203 protected final OTSModelInterface makeModel(final GTUColorer colorer)
204 {
205 this.model = new RoadSimulationModel(getSavedUserModifiedProperties(), colorer);
206 return this.model;
207 }
208
209
210
211
212 private List<Property<?>> getSavedUserModifiedProperties()
213 {
214 return this.savedUserModifiedProperties;
215 }
216
217
218 @Override
219 protected final Rectangle2D.Double makeAnimationRectangle()
220 {
221 return new Rectangle2D.Double(-350, -350, 700, 700);
222 }
223
224
225 @Override
226 protected final JPanel makeCharts(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
227 {
228
229 Property<?> output = new CompoundProperty("", "", "", this.properties, false, 0).findByKey("OutputGraphs");
230 if (null == output)
231 {
232 throw new Error("Cannot find output properties");
233 }
234 ArrayList<BooleanProperty> graphs = new ArrayList<BooleanProperty>();
235 if (output instanceof CompoundProperty)
236 {
237 CompoundProperty outputProperties = (CompoundProperty) output;
238 for (Property<?> ap : outputProperties.getValue())
239 {
240 if (ap instanceof BooleanProperty)
241 {
242 BooleanProperty bp = (BooleanProperty) ap;
243 if (bp.getValue())
244 {
245 graphs.add(bp);
246 }
247 }
248 }
249 }
250 else
251 {
252 throw new Error("output properties should be compound");
253 }
254
255 int graphCount = graphs.size();
256 int columns = (int) Math.ceil(Math.sqrt(graphCount));
257 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
258 TablePanel charts = new TablePanel(columns, rows);
259
260 for (int i = 0; i < graphCount; i++)
261 {
262 String graphName = graphs.get(i).getKey();
263 Container container = null;
264 LaneBasedGTUSampler graph;
265 int pos = graphName.indexOf(' ') + 1;
266 String laneNumberText = graphName.substring(pos, pos + 1);
267 int lane = Integer.parseInt(laneNumberText) - 1;
268
269 if (graphName.contains("Trajectories"))
270 {
271 Duration sampleInterval = graphName.contains("Variable Sample Rate") ? null : new Duration(0.2, SECOND);
272 TrajectoryPlot tp = new TrajectoryPlot(graphName, sampleInterval, this.model.getPath(lane), simulator);
273 tp.setTitle("Trajectory Graph");
274 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
275 graph = tp;
276 container = tp.getContentPane();
277 }
278 else
279 {
280 ContourPlot cp;
281 if (graphName.contains("Density"))
282 {
283 cp = new DensityContourPlot(graphName, this.model.getPath(lane));
284 cp.setTitle("Density Contour Graph");
285 }
286 else if (graphName.contains("Speed"))
287 {
288 cp = new SpeedContourPlot(graphName, this.model.getPath(lane));
289 cp.setTitle("Speed Contour Graph");
290 }
291 else if (graphName.contains("Flow"))
292 {
293 cp = new FlowContourPlot(graphName, this.model.getPath(lane));
294 cp.setTitle("Flow Contour Graph");
295 }
296 else if (graphName.contains("Acceleration"))
297 {
298 cp = new AccelerationContourPlot(graphName, this.model.getPath(lane));
299 cp.setTitle("Acceleration Contour Graph");
300 }
301 else
302 {
303 throw new Error("Unhandled type of contourplot: " + graphName);
304 }
305 graph = cp;
306 container = cp.getContentPane();
307 }
308
309 charts.setCell(container, i % columns, i / columns);
310 this.model.getPlots().add(graph);
311 }
312
313 return charts;
314 }
315
316
317 @Override
318 public final String shortName()
319 {
320 return "Circular Road simulation";
321 }
322
323
324 @Override
325 public final String description()
326 {
327 return "<html><h1>Circular Road simulation</h1>" + "Vehicles are unequally distributed over a two lane ring road.<br>"
328 + "When simulation starts, all vehicles begin driving, some lane changes will occurr and some "
329 + "shockwaves should develop.<br>"
330 + "Trajectories and contourplots are generated during the simulation for both lanes.</html>";
331 }
332
333 }
334
335
336
337
338
339
340
341
342
343
344
345 class RoadSimulationModel implements OTSModelInterface, UNITS
346 {
347
348 private static final long serialVersionUID = 20141121L;
349
350
351 private OTSDEVSSimulatorInterface simulator;
352
353
354 private int carsCreated = 0;
355
356
357 private GTUFollowingModelOld carFollowingModelCars;
358
359
360 private GTUFollowingModelOld carFollowingModelTrucks;
361
362
363 private double carProbability;
364
365
366 private AbstractLaneChangeModel laneChangeModel;
367
368
369 private Length minimumDistance = new Length(0, METER);
370
371
372 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
373
374
375 private List<LaneBasedGTUSampler> plots = new ArrayList<>();
376
377
378 private List<Property<?>> properties = null;
379
380
381 private List<List<Lane>> paths = new ArrayList<>();
382
383
384 private Random randomGenerator = new Random(12345);
385
386
387 private final GTUColorer gtuColorer;
388
389
390 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
391
392
393 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
394
395
396 private final OTSNetwork network = new OTSNetwork("network");
397
398
399
400
401
402 RoadSimulationModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
403 {
404 this.properties = properties;
405 this.gtuColorer = gtuColorer;
406 }
407
408
409
410
411
412 public List<Lane> getPath(final int index)
413 {
414 return this.paths.get(index);
415 }
416
417
418 @Override
419 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
420 throws SimRuntimeException, RemoteException
421 {
422 final int laneCount = 2;
423 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
424 {
425 this.paths.add(new ArrayList<Lane>());
426 }
427 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
428 double radius = 6000 / 2 / Math.PI;
429 double headway = 40;
430 double headwayVariability = 0;
431 try
432 {
433
434
435 String carFollowingModelName = null;
436 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
437 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
438 if (null == cfmp)
439 {
440 throw new Error("Cannot find \"Car following model\" property");
441 }
442 if (cfmp instanceof SelectionProperty)
443 {
444 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
445 }
446 else
447 {
448 throw new Error("\"Car following model\" property has wrong type");
449 }
450
451
452 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
453 {
454 if (ap instanceof CompoundProperty)
455 {
456 CompoundProperty cp = (CompoundProperty) ap;
457 System.out.println("Checking compound property " + cp);
458 if (ap.getKey().contains("IDM"))
459 {
460 System.out.println("Car following model name appears to be " + ap.getKey());
461 Acceleration a = IDMPropertySet.getA(cp);
462 Acceleration b = IDMPropertySet.getB(cp);
463 Length s0 = IDMPropertySet.getS0(cp);
464 Duration tSafe = IDMPropertySet.getTSafe(cp);
465 GTUFollowingModelOld gtuFollowingModel = null;
466 if (carFollowingModelName.equals("IDM"))
467 {
468 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
469 }
470 else if (carFollowingModelName.equals("IDM+"))
471 {
472 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
473 }
474 else
475 {
476 throw new Error("Unknown gtu following model: " + carFollowingModelName);
477 }
478 if (ap.getKey().contains("Car"))
479 {
480 this.carFollowingModelCars = gtuFollowingModel;
481 }
482 else if (ap.getKey().contains("Truck"))
483 {
484 this.carFollowingModelTrucks = gtuFollowingModel;
485 }
486 else
487 {
488 throw new Error("Cannot determine gtu type for " + ap.getKey());
489 }
490 }
491 }
492 }
493
494
495 cfmp = propertyContainer.findByKey("LaneChanging");
496 if (null == cfmp)
497 {
498 throw new Error("Cannot find \"Lane changing\" property");
499 }
500 if (cfmp instanceof SelectionProperty)
501 {
502 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
503 if ("Egoistic".equals(laneChangeModelName))
504 {
505 this.laneChangeModel = new Egoistic();
506 }
507 else if ("Altruistic".equals(laneChangeModelName))
508 {
509 this.laneChangeModel = new Altruistic();
510 }
511 else
512 {
513 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
514 }
515 }
516 else
517 {
518 throw new Error("\"Lane changing\" property has wrong type");
519 }
520
521
522 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
523 {
524 if (ap instanceof SelectionProperty)
525 {
526 SelectionProperty sp = (SelectionProperty) ap;
527 if ("TacticalPlanner".equals(sp.getKey()))
528 {
529 String tacticalPlannerName = sp.getValue();
530 if ("MOBIL".equals(tacticalPlannerName))
531 {
532 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
533 new LaneBasedCFLCTacticalPlannerFactory(this.carFollowingModelCars, this.laneChangeModel));
534 this.strategicalPlannerGeneratorTrucks =
535 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
536 this.carFollowingModelTrucks, this.laneChangeModel));
537 }
538 else if ("LMRS".equals(tacticalPlannerName))
539 {
540
541 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
542 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
543 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
544 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
545 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
546 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
547 }
548 else if ("Toledo".equals(tacticalPlannerName))
549 {
550 this.strategicalPlannerGeneratorCars =
551 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
552 this.strategicalPlannerGeneratorTrucks =
553 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
554 }
555 else
556 {
557 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
558 }
559 }
560 }
561 else if (ap instanceof ProbabilityDistributionProperty)
562 {
563 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
564 if (ap.getKey().equals("TrafficComposition"))
565 {
566 this.carProbability = pdp.getValue()[0];
567 }
568 }
569 else if (ap instanceof IntegerProperty)
570 {
571 IntegerProperty ip = (IntegerProperty) ap;
572 if ("TrackLength".equals(ip.getKey()))
573 {
574 radius = ip.getValue() / 2 / Math.PI;
575 }
576 }
577 else if (ap instanceof ContinuousProperty)
578 {
579 ContinuousProperty cp = (ContinuousProperty) ap;
580 if (cp.getKey().equals("MeanDensity"))
581 {
582 headway = 1000 / cp.getValue();
583 }
584 if (cp.getKey().equals("DensityVariability"))
585 {
586 headwayVariability = cp.getValue();
587 }
588 }
589 else if (ap instanceof CompoundProperty)
590 {
591 if (ap.getKey().equals("OutputGraphs"))
592 {
593 continue;
594 }
595 }
596 }
597 GTUType gtuType = new GTUType("car");
598 Set<GTUType> compatibility = new HashSet<GTUType>();
599 compatibility.add(gtuType);
600 LaneType laneType = new LaneType("CarLane", compatibility);
601 OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
602 OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
603
604 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
605 for (int i = 0; i < coordsHalf1.length; i++)
606 {
607 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
608 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
609 }
610 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
611 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
612 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
613 for (int i = 0; i < coordsHalf2.length; i++)
614 {
615 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
616 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
617 }
618 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
619 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
620 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
621 {
622 this.paths.get(laneIndex).add(lanes1[laneIndex]);
623 this.paths.get(laneIndex).add(lanes2[laneIndex]);
624 }
625
626 double variability = (headway - 20) * headwayVariability;
627 System.out.println("headway is " + headway + " variability limit is " + variability);
628 Random random = new Random(12345);
629 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
630 {
631 double lane1Length = lanes1[laneIndex].getLength().getSI();
632 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
633 for (double pos = 0; pos <= trackLength - headway - variability;)
634 {
635 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
636
637 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
638 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
639
640 generateCar(new Length(laneRelativePos, METER), lane, gtuType);
641 pos += actualHeadway;
642 }
643 }
644
645 this.simulator.scheduleEventAbs(new Time(9.999, SECOND), this, this, "drawGraphs", null);
646 }
647 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException
648 | PropertyException exception)
649 {
650 exception.printStackTrace();
651 }
652 }
653
654
655
656
657 protected final void drawGraphs()
658 {
659 for (LaneBasedGTUSampler plot : this.plots)
660 {
661 plot.reGraph();
662 }
663
664 try
665 {
666 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 10, SECOND), this, this,
667 "drawGraphs", null);
668 }
669 catch (SimRuntimeException exception)
670 {
671 exception.printStackTrace();
672 }
673
674 }
675
676
677
678
679
680
681
682
683
684
685
686
687 protected final void generateCar(final Length initialPosition, final Lane lane, final GTUType gtuType)
688 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
689 {
690
691
692 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
693 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
694 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength,
695 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
696
697
698 LaneBasedStrategicalPlanner strategicalPlanner;
699 if (!generateTruck)
700 {
701 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu);
702 }
703 else
704 {
705 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu);
706 }
707
708
709 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
710 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
711 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
712 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class, this.gtuColorer);
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739 }
740
741
742 @Override
743 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
744 {
745 return this.simulator;
746 }
747
748
749
750
751 public final List<LaneBasedGTUSampler> getPlots()
752 {
753 return this.plots;
754 }
755
756
757
758
759 public final Length getMinimumDistance()
760 {
761 return this.minimumDistance;
762 }
763
764
765
766
767
768
769 public void stopSimulator(final OTSDEVSSimulatorInterface theSimulator, final String errorMessage)
770 {
771 System.out.println("Error: " + errorMessage);
772 try
773 {
774 if (theSimulator.isRunning())
775 {
776 theSimulator.stop();
777 }
778 }
779 catch (SimRuntimeException exception)
780 {
781 exception.printStackTrace();
782 }
783 throw new Error(errorMessage);
784 }
785
786 }