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.Collection;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.Map;
12 import java.util.Random;
13
14 import javax.naming.NamingException;
15 import javax.swing.SwingUtilities;
16
17 import nl.tudelft.simulation.dsol.SimRuntimeException;
18 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
19 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
20
21 import org.opentrafficsim.car.Car;
22 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
23 import org.opentrafficsim.core.dsol.OTSModelInterface;
24 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
25 import org.opentrafficsim.core.gtu.GTUType;
26 import org.opentrafficsim.core.gtu.following.GTUFollowingModel;
27 import org.opentrafficsim.core.gtu.following.GTUFollowingModel.GTUFollowingModelResult;
28 import org.opentrafficsim.core.gtu.following.IDM;
29 import org.opentrafficsim.core.gtu.following.IDMPlus;
30 import org.opentrafficsim.core.network.NetworkException;
31 import org.opentrafficsim.core.network.factory.LaneFactory;
32 import org.opentrafficsim.core.network.factory.Node;
33 import org.opentrafficsim.core.network.lane.CrossSectionLink;
34 import org.opentrafficsim.core.network.lane.Lane;
35 import org.opentrafficsim.core.network.lane.LaneType;
36 import org.opentrafficsim.core.unit.AccelerationUnit;
37 import org.opentrafficsim.core.unit.LengthUnit;
38 import org.opentrafficsim.core.unit.SpeedUnit;
39 import org.opentrafficsim.core.unit.TimeUnit;
40 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar;
41 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar.Abs;
42 import org.opentrafficsim.core.value.vdouble.scalar.DoubleScalar.Rel;
43 import org.opentrafficsim.graphs.AccelerationContourPlot;
44 import org.opentrafficsim.graphs.ContourPlot;
45 import org.opentrafficsim.graphs.DensityContourPlot;
46 import org.opentrafficsim.graphs.FlowContourPlot;
47 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
48 import org.opentrafficsim.graphs.SpeedContourPlot;
49 import org.opentrafficsim.graphs.TrajectoryPlot;
50 import org.opentrafficsim.simulationengine.AbstractProperty;
51 import org.opentrafficsim.simulationengine.BooleanProperty;
52 import org.opentrafficsim.simulationengine.CompoundProperty;
53 import org.opentrafficsim.simulationengine.ContinuousProperty;
54 import org.opentrafficsim.simulationengine.ControlPanel;
55 import org.opentrafficsim.simulationengine.IDMPropertySet;
56 import org.opentrafficsim.simulationengine.IntegerProperty;
57 import org.opentrafficsim.simulationengine.ProbabilityDistributionProperty;
58 import org.opentrafficsim.simulationengine.PropertyException;
59 import org.opentrafficsim.simulationengine.SelectionProperty;
60 import org.opentrafficsim.simulationengine.SimpleSimulator;
61 import org.opentrafficsim.simulationengine.SimulatorFrame;
62 import org.opentrafficsim.simulationengine.WrappableSimulation;
63
64 import com.vividsolutions.jts.geom.Coordinate;
65
66
67
68
69
70
71
72
73
74
75 public class CircularLane implements WrappableSimulation
76 {
77
78 private ArrayList<AbstractProperty<?>> properties = new ArrayList<AbstractProperty<?>>();
79
80
81 public CircularLane()
82 {
83 this.properties.add(new IntegerProperty("Track length", "Circumference of the track", 2000, 500, 6000,
84 "Track length %dm", false, 10));
85 this.properties.add(new ContinuousProperty("Mean density", "Number of vehicles per km", 40.0, 5.0, 45.0,
86 "Density %.1f veh/km", false, 11));
87 this.properties.add(new ContinuousProperty("Density variability", "Variability of the number of vehicles per km",
88 0.0, 0.0, 1.0, "%.1f", false, 12));
89 ArrayList<AbstractProperty<?>> outputProperties = new ArrayList<AbstractProperty<?>>();
90 outputProperties.add(new BooleanProperty("Density", "Density contour plot", true, false, 0));
91 outputProperties.add(new BooleanProperty("Flow", "Flow contour plot", true, false, 1));
92 outputProperties.add(new BooleanProperty("Speed", "Speed contour plot", true, false, 2));
93 outputProperties.add(new BooleanProperty("Acceleration", "Acceleration contour plot", true, false, 3));
94 outputProperties.add(new BooleanProperty("Trajectories", "Trajectory (time/distance) diagram", true, false, 4));
95 this.properties.add(new CompoundProperty("Output", "Select the graphical output", outputProperties, true, 1000));
96 }
97
98
99
100
101
102
103
104 public static void main(final String[] args) throws RemoteException, SimRuntimeException
105 {
106 SwingUtilities.invokeLater(new Runnable()
107 {
108 @Override
109 public void run()
110 {
111 try
112 {
113 CircularLane circularLane = new CircularLane();
114 ArrayList<AbstractProperty<?>> properties = circularLane.getProperties();
115 try
116 {
117 properties.add(new ProbabilityDistributionProperty("Traffic composition",
118 "<html>Mix of passenger cars and trucks</html>", new String[] {"passenger car", "truck"},
119 new Double[] {0.8, 0.2}, false, 10));
120 }
121 catch (PropertyException exception)
122 {
123 exception.printStackTrace();
124 }
125 properties.add(new SelectionProperty("Car following model", "<html>The car following model determines "
126 + "the acceleration that a vehicle will make taking into account "
127 + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
128 + "curvature of the road) capabilities of the vehicle and personality " + "of the driver.</html>",
129 new String[] {"IDM", "IDM+"}, 1, false, 1));
130 properties.add(IDMPropertySet.makeIDMPropertySet("Car", new DoubleScalar.Abs<AccelerationUnit>(1.0,
131 AccelerationUnit.METER_PER_SECOND_2), new DoubleScalar.Abs<AccelerationUnit>(1.5,
132 AccelerationUnit.METER_PER_SECOND_2), new DoubleScalar.Rel<LengthUnit>(2.0, LengthUnit.METER),
133 new DoubleScalar.Rel<TimeUnit>(1.0, TimeUnit.SECOND), 2));
134 properties.add(IDMPropertySet.makeIDMPropertySet("Truck", new DoubleScalar.Abs<AccelerationUnit>(0.5,
135 AccelerationUnit.METER_PER_SECOND_2), new DoubleScalar.Abs<AccelerationUnit>(1.25,
136 AccelerationUnit.METER_PER_SECOND_2), new DoubleScalar.Rel<LengthUnit>(2.0, LengthUnit.METER),
137 new DoubleScalar.Rel<TimeUnit>(1.0, TimeUnit.SECOND), 3));
138 new SimulatorFrame("Circular Lane animation", circularLane.buildSimulator(properties).getPanel());
139 }
140 catch (RemoteException | SimRuntimeException exception)
141 {
142 exception.printStackTrace();
143 }
144 }
145 });
146 }
147
148
149
150
151
152
153
154 public SimpleSimulator buildSimulator(ArrayList<AbstractProperty<?>> userModifiedProperties) throws RemoteException,
155 SimRuntimeException
156 {
157 LaneSimulationModel model = new LaneSimulationModel(userModifiedProperties);
158 SimpleSimulator result =
159 new SimpleSimulator(new OTSSimTimeDouble(new DoubleScalar.Abs<TimeUnit>(0.0, TimeUnit.SECOND)),
160 new DoubleScalar.Rel<TimeUnit>(0.0, TimeUnit.SECOND),
161 new DoubleScalar.Rel<TimeUnit>(3600.0, TimeUnit.SECOND), model, new Rectangle2D.Double(-1000, -1000, 2000,
162 2000));
163 new ControlPanel(result);
164
165
166 AbstractProperty<?> output =
167 new CompoundProperty("", "", userModifiedProperties, false, 0).findByShortName("Output");
168 if (null == output)
169 {
170 throw new Error("Cannot find output properties");
171 }
172 ArrayList<BooleanProperty> graphs = new ArrayList<BooleanProperty>();
173 if (output instanceof CompoundProperty)
174 {
175 CompoundProperty outputProperties = (CompoundProperty) output;
176 for (AbstractProperty<?> ap : outputProperties.getValue())
177 {
178 if (ap instanceof BooleanProperty)
179 {
180 BooleanProperty bp = (BooleanProperty) ap;
181 if (bp.getValue())
182 {
183 graphs.add(bp);
184 }
185 }
186 }
187 }
188 else
189 {
190 throw new Error("output properties should be compound");
191 }
192 int graphCount = graphs.size();
193 int columns = (int) Math.ceil(Math.sqrt(graphCount));
194 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
195 TablePanel charts = new TablePanel(columns, rows);
196 result.getPanel().getTabbedPane().addTab("statistics", charts);
197
198 for (int i = 0; i < graphCount; i++)
199 {
200 String graphName = graphs.get(i).getShortName();
201 Container container = null;
202 LaneBasedGTUSampler graph;
203 if (graphName.contains("Trajectories"))
204 {
205 TrajectoryPlot tp =
206 new TrajectoryPlot("TrajectoryPlot", new DoubleScalar.Rel<TimeUnit>(0.5, TimeUnit.SECOND), model
207 .getMinimumDistance(), model.lane1.getLength());
208 tp.setTitle("Trajectory Graph");
209 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
210 graph = tp;
211 container = tp.getContentPane();
212 }
213 else
214 {
215 ContourPlot cp;
216 if (graphName.contains("Density"))
217 {
218 cp = new DensityContourPlot("DensityPlot", model.getMinimumDistance(), model.lane1.getLength());
219 cp.setTitle("Density Contour Graph");
220 }
221 else if (graphName.contains("Speed"))
222 {
223 cp = new SpeedContourPlot("SpeedPlot", model.getMinimumDistance(), model.lane1.getLength());
224 cp.setTitle("Speed Contour Graph");
225 }
226 else if (graphName.contains("Flow"))
227 {
228 cp = new FlowContourPlot("FlowPlot", model.getMinimumDistance(), model.lane1.getLength());
229 cp.setTitle("Flow Contour Graph");
230 }
231 else if (graphName.contains("Acceleration"))
232 {
233 cp =
234 new AccelerationContourPlot("AccelerationPlot", model.getMinimumDistance(), model.lane1.getLength());
235 cp.setTitle("Acceleration Contour Graph");
236 }
237 else
238 {
239 throw new Error("Unhandled type of contourplot: " + graphName);
240 }
241 graph = cp;
242 container = cp.getContentPane();
243 }
244
245 charts.setCell(container, i % columns, i / columns);
246 model.getPlots().add(graph);
247 }
248 return result;
249 }
250
251
252 @Override
253 public String shortName()
254 {
255 return "Circular Lane simulation";
256 }
257
258
259 @Override
260 public String description()
261 {
262 return "<html><h1>Circular Lane simulation</h1>"
263 + "Vehicles are unequally distributed over a one lane ring road.<br />"
264 + "When simulation starts, all vehicles begin driving and some shockwaves may develop (depending on "
265 + "the selected track length and car following parameters).<br />"
266 + "Selected trajectory and contour plots are generated during the simulation.</html>";
267 }
268
269
270 @Override
271 public ArrayList<AbstractProperty<?>> getProperties()
272 {
273 return new ArrayList<AbstractProperty<?>>(this.properties);
274 }
275
276 }
277
278
279
280
281
282
283
284
285
286
287 class LaneSimulationModel implements OTSModelInterface
288 {
289
290 private static final long serialVersionUID = 20141121L;
291
292
293 private OTSDEVSSimulatorInterface simulator;
294
295
296 private int carsCreated = 0;
297
298
299 protected GTUFollowingModel carFollowingModelCars;
300
301
302 protected GTUFollowingModel carFollowingModelTrucks;
303
304
305 double carProbability;
306
307
308 ArrayList<Car<Integer>> cars = new ArrayList<Car<Integer>>();
309
310
311 private DoubleScalar.Rel<LengthUnit> minimumDistance = new DoubleScalar.Rel<LengthUnit>(0, LengthUnit.METER);
312
313
314 Lane lane1, lane2;
315
316
317 DoubleScalar.Abs<SpeedUnit> speedLimit = new DoubleScalar.Abs<SpeedUnit>(100, SpeedUnit.KM_PER_HOUR);
318
319
320 private ArrayList<LaneBasedGTUSampler> contourPlots = new ArrayList<LaneBasedGTUSampler>();
321
322
323 private ArrayList<TrajectoryPlot> trajectoryPlots = new ArrayList<TrajectoryPlot>();
324
325
326 ArrayList<AbstractProperty<?>> properties = null;
327
328
329 Random randomGenerator = new Random(12345);
330
331
332
333
334 public LaneSimulationModel(ArrayList<AbstractProperty<?>> properties)
335 {
336 this.properties = properties;
337 }
338
339
340 @Override
341 public void constructModel(SimulatorInterface<Abs<TimeUnit>, Rel<TimeUnit>, OTSSimTimeDouble> theSimulator)
342 throws SimRuntimeException, RemoteException
343 {
344 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
345 double radius = 2000 / 2 / Math.PI;
346 double headway = 40;
347 double headwayVariability = 0;
348 try
349 {
350 String carFollowingModelName = null;
351 CompoundProperty propertyContainer = new CompoundProperty("", "", this.properties, false, 0);
352 AbstractProperty<?> cfmp = propertyContainer.findByShortName("Car following model");
353 if (null == cfmp)
354 {
355 throw new Error("Cannot find \"Car following model\" property");
356 }
357 if (cfmp instanceof SelectionProperty)
358 {
359 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
360 }
361 else
362 {
363 throw new Error("\"Car following model\" property has wrong type");
364 }
365 Iterator<AbstractProperty<ArrayList<AbstractProperty<?>>>> iterator =
366 new CompoundProperty("", "", this.properties, false, 0).iterator();
367 while (iterator.hasNext())
368 {
369 AbstractProperty<?> ap = iterator.next();
370
371 if (ap instanceof SelectionProperty)
372 {
373 SelectionProperty sp = (SelectionProperty) ap;
374 if ("Car following model".equals(sp.getShortName()))
375 {
376 carFollowingModelName = sp.getValue();
377 }
378 }
379 else if (ap instanceof ProbabilityDistributionProperty)
380 {
381 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
382 String modelName = ap.getShortName();
383 if (modelName.equals("Traffic composition"))
384 {
385 this.carProbability = pdp.getValue()[0];
386 }
387 }
388 else if (ap instanceof IntegerProperty)
389 {
390 IntegerProperty ip = (IntegerProperty) ap;
391 if ("Track length".equals(ip.getShortName()))
392 {
393 radius = ip.getValue() / 2 / Math.PI;
394 }
395 }
396 else if (ap instanceof ContinuousProperty)
397 {
398 ContinuousProperty cp = (ContinuousProperty) ap;
399 if (cp.getShortName().equals("Mean density"))
400 {
401 headway = 1000 / cp.getValue();
402 }
403 if (cp.getShortName().equals("Density variability"))
404 {
405 headwayVariability = cp.getValue();
406 }
407 }
408 else if (ap instanceof CompoundProperty)
409 {
410 CompoundProperty cp = (CompoundProperty) ap;
411 if (ap.getShortName().equals("Output"))
412 {
413 continue;
414 }
415 if (ap.getShortName().contains("IDM"))
416 {
417
418 DoubleScalar.Abs<AccelerationUnit> a = IDMPropertySet.getA(cp);
419 DoubleScalar.Abs<AccelerationUnit> b = IDMPropertySet.getB(cp);
420 DoubleScalar.Rel<LengthUnit> s0 = IDMPropertySet.getS0(cp);
421 DoubleScalar.Rel<TimeUnit> tSafe = IDMPropertySet.getTSafe(cp);
422 GTUFollowingModel gtuFollowingModel = null;
423 if (carFollowingModelName.equals("IDM"))
424 {
425 gtuFollowingModel = new IDM(a, b, s0, tSafe, 1.0);
426 }
427 else if (carFollowingModelName.equals("IDM+"))
428 {
429 gtuFollowingModel = new IDMPlus(a, b, s0, tSafe, 1.0);
430 }
431 else
432 {
433 throw new Error("Unknown gtu following model: " + carFollowingModelName);
434 }
435 if (ap.getShortName().contains(" Car "))
436 {
437 this.carFollowingModelCars = gtuFollowingModel;
438 }
439 else if (ap.getShortName().contains(" Truck "))
440 {
441 this.carFollowingModelTrucks = gtuFollowingModel;
442 }
443 else
444 {
445 throw new Error("Cannot determine gtu type for " + ap.getShortName());
446 }
447 }
448
449
450
451
452
453 }
454 }
455
456 Node start = new Node("Start", new Coordinate(radius, 0, 0));
457 Node halfway = new Node("Halfway", new Coordinate(-radius, 0, 0));
458 LaneType<String> laneType = new LaneType<String>("CarLane");
459
460 Coordinate[] coordsHalf1 = new Coordinate[127];
461 for (int i = 0; i < coordsHalf1.length; i++)
462 {
463 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
464 coordsHalf1[i] = new Coordinate(radius * Math.cos(angle), radius * Math.sin(angle), 0);
465 }
466 this.lane1 = LaneFactory.makeMultiLane("Lane1", start, halfway, coordsHalf1, 1, laneType, this.simulator)[0];
467
468 Coordinate[] coordsHalf2 = new Coordinate[127];
469 for (int i = 0; i < coordsHalf2.length; i++)
470 {
471 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
472 coordsHalf2[i] = new Coordinate(radius * Math.cos(angle), radius * Math.sin(angle), 0);
473 }
474 this.lane2 = LaneFactory.makeMultiLane("Lane2", halfway, start, coordsHalf2, 1, laneType, this.simulator)[0];
475
476 CrossSectionLink link1 = this.lane1.getParentLink();
477 CrossSectionLink link2 = this.lane2.getParentLink();
478 this.lane1.getParentLink().getStartNode().addLinkIn(link2);
479 this.lane1.getParentLink().getEndNode().addLinkOut(link2);
480 this.lane2.getParentLink().getStartNode().addLinkIn(link1);
481 this.lane2.getParentLink().getEndNode().addLinkOut(link1);
482
483
484 double trackLength = this.lane1.getLength().getSI();
485 double variability = (headway - 20) * headwayVariability;
486 System.out.println("headway is " + headway + " variability limit is " + variability);
487 Random random = new Random(12345);
488 for (double pos = 0; pos <= trackLength - headway - variability;)
489 {
490
491 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
492 generateCar(lane1, new DoubleScalar.Rel<LengthUnit>(pos, LengthUnit.METER));
493 pos += actualHeadway;
494 }
495
496
497 trackLength = this.lane2.getLength().getSI();
498 variability = (headway - 20) * headwayVariability;
499 System.out.println("headway is " + headway + " variability limit is " + variability);
500 random = new Random(54321);
501 for (double pos = 0; pos <= trackLength - headway - variability;)
502 {
503
504 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
505 generateCar(lane2, new DoubleScalar.Rel<LengthUnit>(pos, LengthUnit.METER));
506 pos += actualHeadway;
507 }
508
509
510 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(0.999, TimeUnit.SECOND), this, this,
511 "drawGraphs", null);
512 }
513 catch (RemoteException | SimRuntimeException | NamingException | NetworkException exception)
514 {
515 exception.printStackTrace();
516 }
517 }
518
519
520
521
522
523
524
525 protected final void addToPlots(final Car<?> car) throws NetworkException, RemoteException
526 {
527 for (LaneBasedGTUSampler contourPlot : this.contourPlots)
528 {
529 contourPlot.addData(car);
530 }
531 for (TrajectoryPlot trajectoryPlot : this.trajectoryPlots)
532 {
533 trajectoryPlot.addData(car);
534 }
535 }
536
537
538
539
540 protected final void drawGraphs()
541 {
542 for (LaneBasedGTUSampler contourPlot : this.contourPlots)
543 {
544 contourPlot.reGraph();
545 }
546 for (TrajectoryPlot trajectoryPlot : this.trajectoryPlots)
547 {
548 trajectoryPlot.reGraph();
549 }
550
551 try
552 {
553 this.simulator.scheduleEventAbs(new DoubleScalar.Abs<TimeUnit>(
554 this.simulator.getSimulatorTime().get().getSI() + 1, TimeUnit.SECOND), this, this, "drawGraphs", null);
555 }
556 catch (RemoteException | SimRuntimeException exception)
557 {
558 exception.printStackTrace();
559 }
560
561 }
562
563
564
565
566 protected final void generateCar(Lane lane, DoubleScalar.Rel<LengthUnit> initialPosition)
567 {
568 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
569 DoubleScalar.Abs<SpeedUnit> initialSpeed = new DoubleScalar.Abs<SpeedUnit>(0, SpeedUnit.KM_PER_HOUR);
570 Map<Lane, DoubleScalar.Rel<LengthUnit>> initialPositions = new HashMap<Lane, DoubleScalar.Rel<LengthUnit>>();
571 initialPositions.put(lane, initialPosition);
572 try
573 {
574 DoubleScalar.Rel<LengthUnit> vehicleLength =
575 new DoubleScalar.Rel<LengthUnit>(generateTruck ? 15 : 4, LengthUnit.METER);
576 GTUFollowingModel gtuFollowingModel = generateTruck ? this.carFollowingModelTrucks : this.carFollowingModelCars;
577 if (null == gtuFollowingModel)
578 {
579 throw new Error("gtuFollowingModel is null");
580 }
581 IDMCar car =
582 new IDMCar(++this.carsCreated, null, this.simulator, gtuFollowingModel, vehicleLength, this.simulator
583 .getSimulatorTime().get(), initialPositions, initialSpeed);
584 this.cars.add(car);
585 }
586 catch (RemoteException | NamingException | SimRuntimeException | NetworkException exception)
587 {
588 exception.printStackTrace();
589 }
590 }
591
592
593 @Override
594 public SimulatorInterface<Abs<TimeUnit>, Rel<TimeUnit>, OTSSimTimeDouble> getSimulator() throws RemoteException
595 {
596 return null;
597 }
598
599
600
601
602 public final ArrayList<LaneBasedGTUSampler> getPlots()
603 {
604 return this.contourPlots;
605 }
606
607
608
609
610 public final ArrayList<TrajectoryPlot> getTrajectoryPlots()
611 {
612 return this.trajectoryPlots;
613 }
614
615
616
617
618 public final DoubleScalar.Rel<LengthUnit> getMinimumDistance()
619 {
620 return this.minimumDistance;
621 }
622
623
624 protected class IDMCar extends Car<Integer>
625 {
626
627 private static final long serialVersionUID = 20141030L;
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643 public IDMCar(final int id, GTUType<String> gtuType, final OTSDEVSSimulatorInterface simulator,
644 final GTUFollowingModel carFollowingModel, DoubleScalar.Rel<LengthUnit> vehicleLength,
645 final DoubleScalar.Abs<TimeUnit> initialTime,
646 final Map<Lane, DoubleScalar.Rel<LengthUnit>> initialLongitudinalPositions,
647 final DoubleScalar.Abs<SpeedUnit> initialSpeed) throws RemoteException, NamingException, SimRuntimeException,
648 NetworkException
649 {
650 super(id, gtuType, carFollowingModel, initialLongitudinalPositions, initialSpeed, vehicleLength,
651 new DoubleScalar.Rel<LengthUnit>(1.8, LengthUnit.METER), new DoubleScalar.Abs<SpeedUnit>(200,
652 SpeedUnit.KM_PER_HOUR), simulator);
653 try
654 {
655 if (id >= 0)
656 {
657 simulator.scheduleEventAbs(simulator.getSimulatorTime(), this, this, "move", null);
658 }
659 }
660 catch (SimRuntimeException exception)
661 {
662 exception.printStackTrace();
663 }
664 }
665
666
667
668
669
670
671
672
673 protected final void move() throws RemoteException, NamingException, NetworkException, SimRuntimeException
674 {
675
676 if (this.getId() < 0)
677 {
678 return;
679 }
680 Collection<Car<Integer>> leaders = new ArrayList<Car<Integer>>();
681
682
683 int carIndex = LaneSimulationModel.this.cars.indexOf(this);
684 if (carIndex < LaneSimulationModel.this.cars.size() - 1)
685 {
686 leaders.add(LaneSimulationModel.this.cars.get(carIndex + 1));
687 }
688 else
689 {
690 leaders.add(LaneSimulationModel.this.cars.get(0));
691 }
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 GTUFollowingModelResult cfmr =
714 this.getGTUFollowingModel().computeAcceleration(this, leaders, LaneSimulationModel.this.speedLimit);
715 setState(cfmr);
716
717
718
719
720
721 getSimulator().scheduleEventRel(new DoubleScalar.Rel<TimeUnit>(0.5, TimeUnit.SECOND), this, this, "move", null);
722 }
723 }
724
725 }