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.rmi.RemoteException;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Random;
13 import java.util.Set;
14
15 import javax.naming.NamingException;
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.core.network.route.Route;
47 import org.opentrafficsim.graphs.AccelerationContourPlot;
48 import org.opentrafficsim.graphs.ContourPlot;
49 import org.opentrafficsim.graphs.DensityContourPlot;
50 import org.opentrafficsim.graphs.FlowContourPlot;
51 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
52 import org.opentrafficsim.graphs.SpeedContourPlot;
53 import org.opentrafficsim.graphs.TrajectoryPlot;
54 import org.opentrafficsim.road.animation.AnimationToggles;
55 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
56 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
57 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
58 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
59 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
61 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
62 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
64 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
65 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
66 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
67 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
68 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
69 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
70 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
71 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
72 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
73 import org.opentrafficsim.road.network.factory.LaneFactory;
74 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
75 import org.opentrafficsim.road.network.lane.Lane;
76 import org.opentrafficsim.road.network.lane.LaneType;
77 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
78 import org.opentrafficsim.simulationengine.OTSSimulationException;
79 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
80
81 import nl.tudelft.simulation.dsol.SimRuntimeException;
82 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
83 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
84
85
86
87
88
89
90
91
92
93
94
95 public class CircularRoad extends AbstractWrappableAnimation implements UNITS
96 {
97
98 private static final long serialVersionUID = 1L;
99
100
101 private RoadSimulationModel model;
102
103
104
105
106
107 public CircularRoad() throws PropertyException
108 {
109 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
110 "<html>The lane change strategies vary in politeness.<br>"
111 + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
112 + "<li>Altruistic (assigns effect on new and current follower the same weight as "
113 + "the personal gain).</html>",
114 new String[] { "Egoistic", "Altruistic" }, 0, false, 500));
115 this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
116 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
117 new String[] { "IDM", "MOBIL/IDM", "DIRECTED/IDM", "LMRS", "Toledo" }, 1, false, 600));
118 this.properties.add(new IntegerProperty("TrackLength", "Track length", "Circumference of the track", 2000, 500, 6000,
119 "Track length %dm", false, 10));
120 this.properties.add(new ContinuousProperty("MeanDensity", "Mean density", "Number of vehicles per km", 40.0, 5.0, 45.0,
121 "Density %.1f veh/km", false, 11));
122 this.properties.add(new ContinuousProperty("DensityVariability", "Density variability",
123 "Variability of the number of vehicles per km", 0.0, 0.0, 1.0, "%.1f", false, 12));
124 List<Property<?>> outputProperties = new ArrayList<Property<?>>();
125 for (int lane = 1; lane <= 2; lane++)
126 {
127 String laneId = String.format("Lane %d ", lane);
128 outputProperties.add(new BooleanProperty(laneId + "Density", laneId + " Density", laneId + "Density contour plot",
129 true, false, 0));
130 outputProperties
131 .add(new BooleanProperty(laneId + "Flow", laneId + " Flow", laneId + "Flow contour plot", true, false, 1));
132 outputProperties.add(
133 new BooleanProperty(laneId + "Speed", laneId + " Speed", laneId + "Speed contour plot", true, false, 2));
134 outputProperties.add(new BooleanProperty(laneId + "Acceleration", laneId + " Acceleration",
135 laneId + "Acceleration contour plot", true, false, 3));
136 outputProperties.add(new BooleanProperty(laneId + "Fixed Sample Rate Trajectories", laneId + " FSR Trajectories",
137 laneId + "Trajectory (time/distance) diagram", true, false, 4));
138 outputProperties.add(new BooleanProperty(laneId + "Variable Sample Rate Trajectories", laneId + " VSR Trajectories",
139 laneId + "Trajectory (time/distance) diagram", true, false, 5));
140 }
141 this.properties.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
142 outputProperties, true, 1000));
143 }
144
145
146 @Override
147 public final void stopTimersThreads()
148 {
149 super.stopTimersThreads();
150 this.model = null;
151 }
152
153
154
155
156
157
158 public static void main(final String[] args) throws SimRuntimeException
159 {
160 SwingUtilities.invokeLater(new Runnable()
161 {
162 @Override
163 public void run()
164 {
165 try
166 {
167 CircularRoad circularRoad = new CircularRoad();
168 List<Property<?>> propertyList = circularRoad.getProperties();
169 try
170 {
171 propertyList.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
172 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
173 new Double[] { 0.8, 0.2 }, false, 10));
174 }
175 catch (PropertyException exception)
176 {
177 exception.printStackTrace();
178 }
179 propertyList.add(new SelectionProperty("CarFollowingModel", "Car following model",
180 "<html>The car following model determines "
181 + "the acceleration that a vehicle will make taking into account "
182 + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
183 + "curvature of the road) capabilities of the vehicle and personality "
184 + "of the driver.</html>",
185 new String[] { "IDM", "IDM+" }, 1, false, 1));
186 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car",
187 new Acceleration(1.0, METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2),
188 new Length(2.0, METER), new Duration(1.0, SECOND), 2));
189 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck",
190 new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2),
191 new Length(2.0, METER), new Duration(1.0, SECOND), 3));
192
193 circularRoad.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND),
194 propertyList, null, true);
195 }
196 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
197 {
198 exception.printStackTrace();
199 }
200 }
201 });
202 }
203
204
205 @Override
206 protected final OTSModelInterface makeModel(final GTUColorer colorer)
207 {
208 this.model = new RoadSimulationModel(getSavedUserModifiedProperties(), colorer);
209 return this.model;
210 }
211
212
213
214
215 private List<Property<?>> getSavedUserModifiedProperties()
216 {
217 return this.savedUserModifiedProperties;
218 }
219
220
221 @Override
222 protected final void addAnimationToggles()
223 {
224 AnimationToggles.setTextAnimationTogglesStandard(this);
225 }
226
227
228 @Override
229 protected final void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
230 {
231
232 Property<?> output = new CompoundProperty("", "", "", this.properties, false, 0).findByKey("OutputGraphs");
233 if (null == output)
234 {
235 throw new Error("Cannot find output properties");
236 }
237 ArrayList<BooleanProperty> graphs = new ArrayList<BooleanProperty>();
238 if (output instanceof CompoundProperty)
239 {
240 CompoundProperty outputProperties = (CompoundProperty) output;
241 for (Property<?> ap : outputProperties.getValue())
242 {
243 if (ap instanceof BooleanProperty)
244 {
245 BooleanProperty bp = (BooleanProperty) ap;
246 if (bp.getValue())
247 {
248 graphs.add(bp);
249 }
250 }
251 }
252 }
253 else
254 {
255 throw new Error("output properties should be compound");
256 }
257
258 int graphCount = graphs.size();
259 int columns = (int) Math.ceil(Math.sqrt(graphCount));
260 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
261 TablePanel charts = new TablePanel(columns, rows);
262
263 for (int i = 0; i < graphCount; i++)
264 {
265 String graphName = graphs.get(i).getKey();
266 Container container = null;
267 LaneBasedGTUSampler graph;
268 int pos = graphName.indexOf(' ') + 1;
269 String laneNumberText = graphName.substring(pos, pos + 1);
270 int lane = Integer.parseInt(laneNumberText) - 1;
271
272 if (graphName.contains("Trajectories"))
273 {
274 Duration sampleInterval = graphName.contains("Variable Sample Rate") ? null : new Duration(0.2, SECOND);
275 TrajectoryPlot tp = new TrajectoryPlot(graphName, sampleInterval, this.model.getPath(lane), simulator);
276 tp.setTitle("Trajectory Graph");
277 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
278 graph = tp;
279 container = tp.getContentPane();
280 }
281 else
282 {
283 ContourPlot cp;
284 if (graphName.contains("Density"))
285 {
286 cp = new DensityContourPlot(graphName, this.model.getPath(lane));
287 cp.setTitle("Density Contour Graph");
288 }
289 else if (graphName.contains("Speed"))
290 {
291 cp = new SpeedContourPlot(graphName, this.model.getPath(lane));
292 cp.setTitle("Speed Contour Graph");
293 }
294 else if (graphName.contains("Flow"))
295 {
296 cp = new FlowContourPlot(graphName, this.model.getPath(lane));
297 cp.setTitle("Flow Contour Graph");
298 }
299 else if (graphName.contains("Acceleration"))
300 {
301 cp = new AccelerationContourPlot(graphName, this.model.getPath(lane));
302 cp.setTitle("Acceleration Contour Graph");
303 }
304 else
305 {
306 throw new Error("Unhandled type of contourplot: " + graphName);
307 }
308 graph = cp;
309 container = cp.getContentPane();
310 }
311
312 charts.setCell(container, i % columns, i / columns);
313 this.model.getPlots().add(graph);
314 }
315 addTab(getTabCount(), "statistics", 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(
546 this.carFollowingModelTrucks));
547 }
548 else if ("LMRS".equals(tacticalPlannerName))
549 {
550
551 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
552 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
553 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
554 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
555 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
556 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
557 }
558 else if ("Toledo".equals(tacticalPlannerName))
559 {
560 this.strategicalPlannerGeneratorCars =
561 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
562 this.strategicalPlannerGeneratorTrucks =
563 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
564 }
565 else
566 {
567 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
568 }
569 }
570 }
571 else if (ap instanceof ProbabilityDistributionProperty)
572 {
573 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
574 if (ap.getKey().equals("TrafficComposition"))
575 {
576 this.carProbability = pdp.getValue()[0];
577 }
578 }
579 else if (ap instanceof IntegerProperty)
580 {
581 IntegerProperty ip = (IntegerProperty) ap;
582 if ("TrackLength".equals(ip.getKey()))
583 {
584 radius = ip.getValue() / 2 / Math.PI;
585 }
586 }
587 else if (ap instanceof ContinuousProperty)
588 {
589 ContinuousProperty cp = (ContinuousProperty) ap;
590 if (cp.getKey().equals("MeanDensity"))
591 {
592 headway = 1000 / cp.getValue();
593 }
594 if (cp.getKey().equals("DensityVariability"))
595 {
596 headwayVariability = cp.getValue();
597 }
598 }
599 else if (ap instanceof CompoundProperty)
600 {
601 if (ap.getKey().equals("OutputGraphs"))
602 {
603 continue;
604 }
605 }
606 }
607 GTUType gtuType = CAR;
608 Set<GTUType> compatibility = new HashSet<GTUType>();
609 compatibility.add(gtuType);
610 LaneType laneType = new LaneType("CarLane", compatibility);
611 OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
612 OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
613
614 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
615 for (int i = 0; i < coordsHalf1.length; i++)
616 {
617 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
618 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
619 }
620 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
621 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
622 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
623 for (int i = 0; i < coordsHalf2.length; i++)
624 {
625 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
626 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
627 }
628 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
629 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
630 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
631 {
632 this.paths.get(laneIndex).add(lanes1[laneIndex]);
633 this.paths.get(laneIndex).add(lanes2[laneIndex]);
634 }
635
636 double variability = (headway - 20) * headwayVariability;
637 System.out.println("headway is " + headway + " variability limit is " + variability);
638 Random random = new Random(12345);
639 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
640 {
641 double lane1Length = lanes1[laneIndex].getLength().getSI();
642 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
643 for (double pos = 0; pos <= trackLength - headway - variability;)
644 {
645 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
646
647 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
648 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
649
650 generateCar(new Length(laneRelativePos, METER), lane, gtuType);
651 pos += actualHeadway;
652 }
653 }
654
655 this.simulator.scheduleEventAbs(new Time(9.999, SECOND), this, this, "drawGraphs", null);
656 }
657 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException
658 | PropertyException exception)
659 {
660 exception.printStackTrace();
661 }
662 }
663
664
665
666
667 protected final void drawGraphs()
668 {
669 for (LaneBasedGTUSampler plot : this.plots)
670 {
671 plot.reGraph();
672 }
673
674 try
675 {
676 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 10, SECOND), this, this,
677 "drawGraphs", null);
678 }
679 catch (SimRuntimeException exception)
680 {
681 exception.printStackTrace();
682 }
683
684 }
685
686
687
688
689
690
691
692
693
694
695
696
697 protected final void generateCar(final Length initialPosition, final Lane lane, final GTUType gtuType)
698 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
699 {
700
701
702 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
703 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
704 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength,
705 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
706
707
708 LaneBasedStrategicalPlanner strategicalPlanner;
709 Route route = null;
710 if (!generateTruck)
711 {
712 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route);
713 }
714 else
715 {
716 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route);
717 }
718
719
720 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
721 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
722 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
723 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class, this.gtuColorer);
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
752
753 @Override
754 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
755 {
756 return this.simulator;
757 }
758
759
760 @Override
761 public OTSNetwork getNetwork()
762 {
763 return this.network;
764 }
765
766
767
768
769 public final List<LaneBasedGTUSampler> getPlots()
770 {
771 return this.plots;
772 }
773
774
775
776
777 public final Length getMinimumDistance()
778 {
779 return this.minimumDistance;
780 }
781
782
783
784
785
786
787 public void stopSimulator(final OTSDEVSSimulatorInterface theSimulator, final String errorMessage)
788 {
789 System.out.println("Error: " + errorMessage);
790 try
791 {
792 if (theSimulator.isRunning())
793 {
794 theSimulator.stop();
795 }
796 }
797 catch (SimRuntimeException exception)
798 {
799 exception.printStackTrace();
800 }
801 throw new Error(errorMessage);
802 }
803
804 }