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.LaneBasedGTUFollowingDirectedChangeTacticalPlanner;
57 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
58 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
59 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
61 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
62 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
63 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
64 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
65 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
66 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
67 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
68 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
69 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
70 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
71 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
72 import org.opentrafficsim.road.network.factory.LaneFactory;
73 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
74 import org.opentrafficsim.road.network.lane.Lane;
75 import org.opentrafficsim.road.network.lane.LaneType;
76 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
77 import org.opentrafficsim.simulationengine.OTSSimulationException;
78 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
79
80 import nl.tudelft.simulation.dsol.SimRuntimeException;
81 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
82 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
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(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND),
193 propertyList, null, 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(final GTUColorer colorer)
206 {
207 this.model = new RoadSimulationModel(getSavedUserModifiedProperties(), colorer);
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 Rectangle2D.Double makeAnimationRectangle()
222 {
223 return new Rectangle2D.Double(-350, -350, 700, 700);
224 }
225
226
227 @Override
228 protected final JPanel makeCharts(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
315 return charts;
316 }
317
318
319 @Override
320 public final String shortName()
321 {
322 return "Circular Road simulation";
323 }
324
325
326 @Override
327 public final String description()
328 {
329 return "<html><h1>Circular Road simulation</h1>" + "Vehicles are unequally distributed over a two lane ring road.<br>"
330 + "When simulation starts, all vehicles begin driving, some lane changes will occurr and some "
331 + "shockwaves should develop.<br>"
332 + "Trajectories and contourplots are generated during the simulation for both lanes.</html>";
333 }
334
335 }
336
337
338
339
340
341
342
343
344
345
346
347 class RoadSimulationModel implements OTSModelInterface, UNITS
348 {
349
350 private static final long serialVersionUID = 20141121L;
351
352
353 private OTSDEVSSimulatorInterface simulator;
354
355
356 private int carsCreated = 0;
357
358
359 private GTUFollowingModelOld carFollowingModelCars;
360
361
362 private GTUFollowingModelOld carFollowingModelTrucks;
363
364
365 private double carProbability;
366
367
368 private AbstractLaneChangeModel laneChangeModel;
369
370
371 private Length minimumDistance = new Length(0, METER);
372
373
374 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
375
376
377 private List<LaneBasedGTUSampler> plots = new ArrayList<>();
378
379
380 private List<Property<?>> properties = null;
381
382
383 private List<List<Lane>> paths = new ArrayList<>();
384
385
386 private Random randomGenerator = new Random(12345);
387
388
389 private final GTUColorer gtuColorer;
390
391
392 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
393
394
395 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
396
397
398 private final OTSNetwork network = new OTSNetwork("network");
399
400
401
402
403
404 RoadSimulationModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
405 {
406 this.properties = properties;
407 this.gtuColorer = gtuColorer;
408 }
409
410
411
412
413
414 public List<Lane> getPath(final int index)
415 {
416 return this.paths.get(index);
417 }
418
419
420 @Override
421 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
422 throws SimRuntimeException, RemoteException
423 {
424 final int laneCount = 2;
425 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
426 {
427 this.paths.add(new ArrayList<Lane>());
428 }
429 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
430 double radius = 6000 / 2 / Math.PI;
431 double headway = 40;
432 double headwayVariability = 0;
433 try
434 {
435
436
437 String carFollowingModelName = null;
438 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
439 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
440 if (null == cfmp)
441 {
442 throw new Error("Cannot find \"Car following model\" property");
443 }
444 if (cfmp instanceof SelectionProperty)
445 {
446 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
447 }
448 else
449 {
450 throw new Error("\"Car following model\" property has wrong type");
451 }
452
453
454 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
455 {
456 if (ap instanceof CompoundProperty)
457 {
458 CompoundProperty cp = (CompoundProperty) ap;
459 System.out.println("Checking compound property " + cp);
460 if (ap.getKey().contains("IDM"))
461 {
462 System.out.println("Car following model name appears to be " + ap.getKey());
463 Acceleration a = IDMPropertySet.getA(cp);
464 Acceleration b = IDMPropertySet.getB(cp);
465 Length s0 = IDMPropertySet.getS0(cp);
466 Duration tSafe = IDMPropertySet.getTSafe(cp);
467 GTUFollowingModelOld gtuFollowingModel = null;
468 if (carFollowingModelName.equals("IDM"))
469 {
470 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
471 }
472 else if (carFollowingModelName.equals("IDM+"))
473 {
474 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
475 }
476 else
477 {
478 throw new Error("Unknown gtu following model: " + carFollowingModelName);
479 }
480 if (ap.getKey().contains("Car"))
481 {
482 this.carFollowingModelCars = gtuFollowingModel;
483 }
484 else if (ap.getKey().contains("Truck"))
485 {
486 this.carFollowingModelTrucks = gtuFollowingModel;
487 }
488 else
489 {
490 throw new Error("Cannot determine gtu type for " + ap.getKey());
491 }
492 }
493 }
494 }
495
496
497 cfmp = propertyContainer.findByKey("LaneChanging");
498 if (null == cfmp)
499 {
500 throw new Error("Cannot find \"Lane changing\" property");
501 }
502 if (cfmp instanceof SelectionProperty)
503 {
504 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
505 if ("Egoistic".equals(laneChangeModelName))
506 {
507 this.laneChangeModel = new Egoistic();
508 }
509 else if ("Altruistic".equals(laneChangeModelName))
510 {
511 this.laneChangeModel = new Altruistic();
512 }
513 else
514 {
515 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
516 }
517 }
518 else
519 {
520 throw new Error("\"Lane changing\" property has wrong type");
521 }
522
523
524 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
525 {
526 if (ap instanceof SelectionProperty)
527 {
528 SelectionProperty sp = (SelectionProperty) ap;
529 if ("TacticalPlanner".equals(sp.getKey()))
530 {
531 String tacticalPlannerName = sp.getValue();
532 if ("MOBIL/IDM".equals(tacticalPlannerName))
533 {
534 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
535 new LaneBasedCFLCTacticalPlannerFactory(this.carFollowingModelCars, this.laneChangeModel));
536 this.strategicalPlannerGeneratorTrucks =
537 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
538 this.carFollowingModelTrucks, this.laneChangeModel));
539 }
540 else if ("DIRECTED/IDM".equals(tacticalPlannerName))
541 {
542 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
543 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(this.carFollowingModelCars));
544 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
545 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(this.carFollowingModelTrucks));
546 }
547 else if ("LMRS".equals(tacticalPlannerName))
548 {
549
550 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
551 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
552 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
553 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
554 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
555 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
556 }
557 else if ("Toledo".equals(tacticalPlannerName))
558 {
559 this.strategicalPlannerGeneratorCars =
560 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
561 this.strategicalPlannerGeneratorTrucks =
562 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
563 }
564 else
565 {
566 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
567 }
568 }
569 }
570 else if (ap instanceof ProbabilityDistributionProperty)
571 {
572 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
573 if (ap.getKey().equals("TrafficComposition"))
574 {
575 this.carProbability = pdp.getValue()[0];
576 }
577 }
578 else if (ap instanceof IntegerProperty)
579 {
580 IntegerProperty ip = (IntegerProperty) ap;
581 if ("TrackLength".equals(ip.getKey()))
582 {
583 radius = ip.getValue() / 2 / Math.PI;
584 }
585 }
586 else if (ap instanceof ContinuousProperty)
587 {
588 ContinuousProperty cp = (ContinuousProperty) ap;
589 if (cp.getKey().equals("MeanDensity"))
590 {
591 headway = 1000 / cp.getValue();
592 }
593 if (cp.getKey().equals("DensityVariability"))
594 {
595 headwayVariability = cp.getValue();
596 }
597 }
598 else if (ap instanceof CompoundProperty)
599 {
600 if (ap.getKey().equals("OutputGraphs"))
601 {
602 continue;
603 }
604 }
605 }
606 GTUType gtuType = new GTUType("car");
607 Set<GTUType> compatibility = new HashSet<GTUType>();
608 compatibility.add(gtuType);
609 LaneType laneType = new LaneType("CarLane", compatibility);
610 OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
611 OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
612
613 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
614 for (int i = 0; i < coordsHalf1.length; i++)
615 {
616 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
617 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
618 }
619 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
620 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
621 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
622 for (int i = 0; i < coordsHalf2.length; i++)
623 {
624 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
625 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
626 }
627 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
628 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
629 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
630 {
631 this.paths.get(laneIndex).add(lanes1[laneIndex]);
632 this.paths.get(laneIndex).add(lanes2[laneIndex]);
633 }
634
635 double variability = (headway - 20) * headwayVariability;
636 System.out.println("headway is " + headway + " variability limit is " + variability);
637 Random random = new Random(12345);
638 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
639 {
640 double lane1Length = lanes1[laneIndex].getLength().getSI();
641 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
642 for (double pos = 0; pos <= trackLength - headway - variability;)
643 {
644 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
645
646 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
647 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
648
649 generateCar(new Length(laneRelativePos, METER), lane, gtuType);
650 pos += actualHeadway;
651 }
652 }
653
654 this.simulator.scheduleEventAbs(new Time(9.999, SECOND), this, this, "drawGraphs", null);
655 }
656 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException
657 | PropertyException exception)
658 {
659 exception.printStackTrace();
660 }
661 }
662
663
664
665
666 protected final void drawGraphs()
667 {
668 for (LaneBasedGTUSampler plot : this.plots)
669 {
670 plot.reGraph();
671 }
672
673 try
674 {
675 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 10, SECOND), this, this,
676 "drawGraphs", null);
677 }
678 catch (SimRuntimeException exception)
679 {
680 exception.printStackTrace();
681 }
682
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696 protected final void generateCar(final Length initialPosition, final Lane lane, final GTUType gtuType)
697 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
698 {
699
700
701 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
702 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
703 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength,
704 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
705
706
707 LaneBasedStrategicalPlanner strategicalPlanner;
708 if (!generateTruck)
709 {
710 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu);
711 }
712 else
713 {
714 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu);
715 }
716
717
718 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
719 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
720 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
721 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class, this.gtuColorer);
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 }
749
750
751 @Override
752 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
753 {
754 return this.simulator;
755 }
756
757
758
759
760 public final List<LaneBasedGTUSampler> getPlots()
761 {
762 return this.plots;
763 }
764
765
766
767
768 public final Length getMinimumDistance()
769 {
770 return this.minimumDistance;
771 }
772
773
774
775
776
777
778 public void stopSimulator(final OTSDEVSSimulatorInterface theSimulator, final String errorMessage)
779 {
780 System.out.println("Error: " + errorMessage);
781 try
782 {
783 if (theSimulator.isRunning())
784 {
785 theSimulator.stop();
786 }
787 }
788 catch (SimRuntimeException exception)
789 {
790 exception.printStackTrace();
791 }
792 throw new Error(errorMessage);
793 }
794
795 }