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