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