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