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.Iterator;
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.JPanel;
17 import javax.swing.SwingUtilities;
18
19 import nl.tudelft.simulation.dsol.SimRuntimeException;
20 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
21 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
22
23 import org.djunits.unit.TimeUnit;
24 import org.djunits.unit.UNITS;
25 import org.djunits.value.vdouble.scalar.Acceleration;
26 import org.djunits.value.vdouble.scalar.DoubleScalar;
27 import org.djunits.value.vdouble.scalar.DoubleScalar.Abs;
28 import org.djunits.value.vdouble.scalar.DoubleScalar.Rel;
29 import org.djunits.value.vdouble.scalar.Duration;
30 import org.djunits.value.vdouble.scalar.Length;
31 import org.djunits.value.vdouble.scalar.Speed;
32 import org.djunits.value.vdouble.scalar.Time;
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.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.gtu.animation.DefaultCarAnimation;
55 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
56 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
57 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingChange0TacticalPlannerFactory;
58 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingLaneChangeTacticalPlannerFactory;
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.IDMPlus;
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.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.properties.AbstractProperty;
79 import org.opentrafficsim.simulationengine.properties.BooleanProperty;
80 import org.opentrafficsim.simulationengine.properties.CompoundProperty;
81 import org.opentrafficsim.simulationengine.properties.ContinuousProperty;
82 import org.opentrafficsim.simulationengine.properties.IDMPropertySet;
83 import org.opentrafficsim.simulationengine.properties.IntegerProperty;
84 import org.opentrafficsim.simulationengine.properties.ProbabilityDistributionProperty;
85 import org.opentrafficsim.simulationengine.properties.PropertyException;
86 import org.opentrafficsim.simulationengine.properties.SelectionProperty;
87
88
89
90
91
92
93
94
95
96
97
98 public class CircularRoad extends AbstractWrappableAnimation implements UNITS
99 {
100
101 private static final long serialVersionUID = 1L;
102
103
104 private RoadSimulationModel model;
105
106
107
108
109
110 public CircularRoad() throws PropertyException
111 {
112 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
113 "<html>The lane change strategies vary in politeness.<br>"
114 + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
115 + "<li>Altruistic (assigns effect on new and current follower the same weight as "
116 + "the personal gain).</html>", 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>", new String[] {"MOBIL",
119 "Verbraeck", "Verbraeck0", "LMRS", "Toledo"}, 0, false, 600));
120 this.properties.add(new IntegerProperty("TrackLength", "Track length", "Circumference of the track", 2000, 500,
121 6000, "Track length %dm", false, 10));
122 this.properties.add(new ContinuousProperty("MeanDensity", "Mean density", "Number of vehicles per km", 40.0, 5.0,
123 45.0, "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 ArrayList<AbstractProperty<?>> outputProperties = new ArrayList<AbstractProperty<?>>();
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
131 + "Density contour plot", true, false, 0));
132 outputProperties.add(new BooleanProperty(laneId + "Flow", laneId + " Flow", laneId + "Flow contour plot", true,
133 false, 1));
134 outputProperties.add(new BooleanProperty(laneId + "Speed", laneId + " Speed", laneId + "Speed contour plot",
135 true, false, 2));
136 outputProperties.add(new BooleanProperty(laneId + "Acceleration", laneId + " Acceleration", laneId
137 + "Acceleration contour plot", true, false, 3));
138 outputProperties.add(new BooleanProperty(laneId + "Trajectories", laneId + " Trajectories", laneId
139 + "Trajectory (time/distance) diagram", true, false, 4));
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 ArrayList<AbstractProperty<?>> 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>", new String[] {"IDM", "IDM+"}, 1, false, 1));
185 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car", new Acceleration(1.0,
186 METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2), new Length(2.0, METER),
187 new Duration(1.0, SECOND), 2));
188 propertyList.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck", new Acceleration(0.5,
189 METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2), new Length(2.0, METER),
190 new Duration(1.0, SECOND), 3));
191
192 circularRoad.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND),
193 new Duration(3600.0, SECOND), 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 ArrayList<AbstractProperty<?>> 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() throws OTSSimulationException, PropertyException
229 {
230
231 AbstractProperty<?> 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 (AbstractProperty<?> 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 TrajectoryPlot tp = new TrajectoryPlot(graphName, new Duration(0.5, SECOND), this.model.getPath(lane));
274 tp.setTitle("Trajectory Graph");
275 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
276 graph = tp;
277 container = tp.getContentPane();
278 }
279 else
280 {
281 ContourPlot cp;
282 if (graphName.contains("Density"))
283 {
284 cp = new DensityContourPlot(graphName, this.model.getPath(lane));
285 cp.setTitle("Density Contour Graph");
286 }
287 else if (graphName.contains("Speed"))
288 {
289 cp = new SpeedContourPlot(graphName, this.model.getPath(lane));
290 cp.setTitle("Speed Contour Graph");
291 }
292 else if (graphName.contains("Flow"))
293 {
294 cp = new FlowContourPlot(graphName, this.model.getPath(lane));
295 cp.setTitle("Flow Contour Graph");
296 }
297 else if (graphName.contains("Acceleration"))
298 {
299 cp = new AccelerationContourPlot(graphName, this.model.getPath(lane));
300 cp.setTitle("Acceleration Contour Graph");
301 }
302 else
303 {
304 throw new Error("Unhandled type of contourplot: " + graphName);
305 }
306 graph = cp;
307 container = cp.getContentPane();
308 }
309
310 charts.setCell(container, i % columns, i / columns);
311 this.model.getPlots().add(graph);
312 }
313
314 return charts;
315 }
316
317
318 @Override
319 public final String shortName()
320 {
321 return "Circular Road simulation";
322 }
323
324
325 @Override
326 public final String description()
327 {
328 return "<html><h1>Circular Road simulation</h1>"
329 + "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 OTSNetwork network = new OTSNetwork("network");
357
358
359 private int carsCreated = 0;
360
361
362 private GTUFollowingModelOld carFollowingModelCars;
363
364
365 private GTUFollowingModelOld carFollowingModelTrucks;
366
367
368 private double carProbability;
369
370
371 private AbstractLaneChangeModel laneChangeModel;
372
373
374 private Length minimumDistance = new Length(0, METER);
375
376
377 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
378
379
380 private ArrayList<LaneBasedGTUSampler> plots = new ArrayList<LaneBasedGTUSampler>();
381
382
383 private ArrayList<AbstractProperty<?>> properties = null;
384
385
386 private ArrayList<List<Lane>> paths = new ArrayList<List<Lane>>();
387
388
389 private Random randomGenerator = new Random(12345);
390
391
392 private final GTUColorer gtuColorer;
393
394
395 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
396
397
398 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
399
400
401
402
403
404 public RoadSimulationModel(final ArrayList<AbstractProperty<?>> 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<Abs<TimeUnit>, Rel<TimeUnit>, 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 AbstractProperty<?> 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 Iterator<AbstractProperty<List<AbstractProperty<?>>>> iterator =
455 new CompoundProperty("", "", "", this.properties, false, 0).iterator();
456 while (iterator.hasNext())
457 {
458 AbstractProperty<?> ap = iterator.next();
459 if (ap instanceof CompoundProperty)
460 {
461 CompoundProperty cp = (CompoundProperty) ap;
462 System.out.println("Checking compound property " + cp);
463 if (ap.getKey().contains("IDM"))
464 {
465 System.out.println("Car following model name appears to be " + ap.getKey());
466 Acceleration a = IDMPropertySet.getA(cp);
467 Acceleration b = IDMPropertySet.getB(cp);
468 Length s0 = IDMPropertySet.getS0(cp);
469 Duration tSafe = IDMPropertySet.getTSafe(cp);
470 GTUFollowingModelOld gtuFollowingModel = null;
471 if (carFollowingModelName.equals("IDM"))
472 {
473 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
474 }
475 else if (carFollowingModelName.equals("IDM+"))
476 {
477 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
478 }
479 else
480 {
481 throw new Error("Unknown gtu following model: " + carFollowingModelName);
482 }
483 if (ap.getKey().contains("Car"))
484 {
485 this.carFollowingModelCars = gtuFollowingModel;
486 }
487 else if (ap.getKey().contains("Truck"))
488 {
489 this.carFollowingModelTrucks = gtuFollowingModel;
490 }
491 else
492 {
493 throw new Error("Cannot determine gtu type for " + ap.getKey());
494 }
495 }
496 }
497 }
498
499
500 cfmp = propertyContainer.findByKey("LaneChanging");
501 if (null == cfmp)
502 {
503 throw new Error("Cannot find \"Lane changing\" property");
504 }
505 if (cfmp instanceof SelectionProperty)
506 {
507 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
508 if ("Egoistic".equals(laneChangeModelName))
509 {
510 this.laneChangeModel = new Egoistic();
511 }
512 else if ("Altruistic".equals(laneChangeModelName))
513 {
514 this.laneChangeModel = new Altruistic();
515 }
516 else
517 {
518 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
519 }
520 }
521 else
522 {
523 throw new Error("\"Lane changing\" property has wrong type");
524 }
525
526
527 iterator = new CompoundProperty("", "", "", this.properties, false, 0).iterator();
528 while (iterator.hasNext())
529 {
530 AbstractProperty<?> ap = iterator.next();
531 if (ap instanceof SelectionProperty)
532 {
533 SelectionProperty sp = (SelectionProperty) ap;
534 if ("TacticalPlanner".equals(sp.getKey()))
535 {
536 String tacticalPlannerName = sp.getValue();
537 if ("MOBIL".equals(tacticalPlannerName))
538 {
539 this.strategicalPlannerGeneratorCars =
540 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
541 this.carFollowingModelCars, this.laneChangeModel));
542 this.strategicalPlannerGeneratorTrucks =
543 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
544 this.carFollowingModelTrucks, this.laneChangeModel));
545 }
546 else if ("Verbraeck".equals(tacticalPlannerName))
547 {
548 this.strategicalPlannerGeneratorCars =
549 new LaneBasedStrategicalRoutePlannerFactory(
550 new LaneBasedGTUFollowingLaneChangeTacticalPlannerFactory(this.carFollowingModelCars));
551 this.strategicalPlannerGeneratorTrucks =
552 new LaneBasedStrategicalRoutePlannerFactory(
553 new LaneBasedGTUFollowingLaneChangeTacticalPlannerFactory(this.carFollowingModelTrucks));
554 }
555 else if ("Verbraeck0".equals(tacticalPlannerName))
556 {
557 this.strategicalPlannerGeneratorCars =
558 new LaneBasedStrategicalRoutePlannerFactory(
559 new LaneBasedGTUFollowingChange0TacticalPlannerFactory(this.carFollowingModelCars));
560 this.strategicalPlannerGeneratorTrucks =
561 new LaneBasedStrategicalRoutePlannerFactory(
562 new LaneBasedGTUFollowingChange0TacticalPlannerFactory(this.carFollowingModelTrucks));
563 }
564 else if ("LMRS".equals(tacticalPlannerName))
565 {
566
567 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
568 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
569 this.strategicalPlannerGeneratorCars =
570 new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(IDMPlus.class,
571 defaultBehavioralCFCharacteristics));
572 this.strategicalPlannerGeneratorTrucks =
573 new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(IDMPlus.class,
574 defaultBehavioralCFCharacteristics));
575 }
576 else if ("Toledo".equals(tacticalPlannerName))
577 {
578 this.strategicalPlannerGeneratorCars =
579 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
580 this.strategicalPlannerGeneratorTrucks =
581 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
582 }
583 else
584 {
585 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
586 }
587 }
588 }
589 else if (ap instanceof ProbabilityDistributionProperty)
590 {
591 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
592 if (ap.getKey().equals("TrafficComposition"))
593 {
594 this.carProbability = pdp.getValue()[0];
595 }
596 }
597 else if (ap instanceof IntegerProperty)
598 {
599 IntegerProperty ip = (IntegerProperty) ap;
600 if ("TrackLength".equals(ip.getKey()))
601 {
602 radius = ip.getValue() / 2 / Math.PI;
603 }
604 }
605 else if (ap instanceof ContinuousProperty)
606 {
607 ContinuousProperty cp = (ContinuousProperty) ap;
608 if (cp.getKey().equals("MeanDensity"))
609 {
610 headway = 1000 / cp.getValue();
611 }
612 if (cp.getKey().equals("DensityVariability"))
613 {
614 headwayVariability = cp.getValue();
615 }
616 }
617 else if (ap instanceof CompoundProperty)
618 {
619 if (ap.getKey().equals("OutputGraphs"))
620 {
621 continue;
622 }
623 }
624 }
625 GTUType gtuType = new GTUType("car");
626 Set<GTUType> compatibility = new HashSet<GTUType>();
627 compatibility.add(gtuType);
628 LaneType laneType = new LaneType("CarLane", compatibility);
629 OTSNode start = new OTSNode("Start", new OTSPoint3D(radius, 0, 0));
630 OTSNode halfway = new OTSNode("Halfway", new OTSPoint3D(-radius, 0, 0));
631
632 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
633 for (int i = 0; i < coordsHalf1.length; i++)
634 {
635 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
636 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
637 }
638 Lane[] lanes1 =
639 LaneFactory.makeMultiLane("FirstHalf", start, halfway, coordsHalf1, laneCount, laneType, this.speedLimit,
640 this.simulator, LongitudinalDirectionality.DIR_PLUS);
641 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
642 for (int i = 0; i < coordsHalf2.length; i++)
643 {
644 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
645 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
646 }
647 Lane[] lanes2 =
648 LaneFactory.makeMultiLane("SecondHalf", halfway, start, coordsHalf2, laneCount, laneType, this.speedLimit,
649 this.simulator, LongitudinalDirectionality.DIR_PLUS);
650 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
651 {
652 this.paths.get(laneIndex).add(lanes1[laneIndex]);
653 this.paths.get(laneIndex).add(lanes2[laneIndex]);
654 }
655
656 double variability = (headway - 20) * headwayVariability;
657 System.out.println("headway is " + headway + " variability limit is " + variability);
658 Random random = new Random(12345);
659 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
660 {
661 double lane1Length = lanes1[laneIndex].getLength().getSI();
662 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
663 for (double pos = 0; pos <= trackLength - headway - variability;)
664 {
665 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
666
667 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
668 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
669
670 generateCar(new Length(laneRelativePos, METER), lane, gtuType);
671 pos += actualHeadway;
672 }
673 }
674
675 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(9.999, SECOND), this, this, "drawGraphs", null);
676 }
677 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException
678 | PropertyException exception)
679 {
680 exception.printStackTrace();
681 }
682 }
683
684
685
686
687 protected final void drawGraphs()
688 {
689 for (LaneBasedGTUSampler plot : this.plots)
690 {
691 plot.reGraph();
692 }
693
694 try
695 {
696 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 10, SECOND), this,
697 this, "drawGraphs", null);
698 }
699 catch (SimRuntimeException exception)
700 {
701 exception.printStackTrace();
702 }
703
704 }
705
706
707
708
709
710
711
712
713
714
715
716
717 protected final void generateCar(final Length initialPosition, final Lane lane, final GTUType gtuType)
718 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
719 {
720
721
722 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
723 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
724 LaneBasedIndividualGTU gtu =
725 new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength, new Length(1.8, METER), new Speed(
726 200, KM_PER_HOUR), this.simulator, DefaultCarAnimation.class, this.gtuColorer, this.network);
727
728
729 LaneBasedStrategicalPlanner strategicalPlanner;
730 if (!generateTruck)
731 {
732 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu);
733 }
734 else
735 {
736 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu);
737 }
738
739
740 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
741 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
742 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
743 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
744
745 }
746
747
748 @Override
749 public SimulatorInterface<Abs<TimeUnit>, Rel<TimeUnit>, OTSSimTimeDouble> getSimulator() throws RemoteException
750 {
751 return this.simulator;
752 }
753
754
755
756
757 public final ArrayList<LaneBasedGTUSampler> getPlots()
758 {
759 return this.plots;
760 }
761
762
763
764
765 public final Length getMinimumDistance()
766 {
767 return this.minimumDistance;
768 }
769
770
771
772
773
774
775 public void stopSimulator(final OTSDEVSSimulatorInterface theSimulator, final String errorMessage)
776 {
777 System.out.println("Error: " + errorMessage);
778 try
779 {
780 if (theSimulator.isRunning())
781 {
782 theSimulator.stop();
783 }
784 }
785 catch (SimRuntimeException exception)
786 {
787 exception.printStackTrace();
788 }
789 throw new Error(errorMessage);
790 }
791
792 }