View Javadoc
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.io.IOException;
8   import java.net.URL;
9   import java.rmi.RemoteException;
10  import java.util.ArrayList;
11  import java.util.HashSet;
12  import java.util.LinkedHashSet;
13  import java.util.List;
14  import java.util.Random;
15  import java.util.Set;
16  
17  import javax.naming.NamingException;
18  import javax.swing.JComponent;
19  import javax.swing.JPanel;
20  import javax.swing.JScrollPane;
21  import javax.swing.SwingUtilities;
22  
23  import org.djunits.unit.AccelerationUnit;
24  import org.djunits.unit.DurationUnit;
25  import org.djunits.unit.LengthUnit;
26  import org.djunits.unit.TimeUnit;
27  import org.djunits.unit.UNITS;
28  import org.djunits.value.vdouble.scalar.Acceleration;
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.base.modelproperties.BooleanProperty;
34  import org.opentrafficsim.base.modelproperties.CompoundProperty;
35  import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty;
36  import org.opentrafficsim.base.modelproperties.Property;
37  import org.opentrafficsim.base.modelproperties.PropertyException;
38  import org.opentrafficsim.base.modelproperties.SelectionProperty;
39  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
40  import org.opentrafficsim.core.dsol.OTSModelInterface;
41  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
42  import org.opentrafficsim.core.geometry.OTSGeometryException;
43  import org.opentrafficsim.core.geometry.OTSPoint3D;
44  import org.opentrafficsim.core.gtu.GTUDirectionality;
45  import org.opentrafficsim.core.gtu.GTUException;
46  import org.opentrafficsim.core.gtu.GTUType;
47  import org.opentrafficsim.core.gtu.animation.GTUColorer;
48  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
49  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
50  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
51  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
52  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan.Segment;
53  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
54  import org.opentrafficsim.core.network.LongitudinalDirectionality;
55  import org.opentrafficsim.core.network.NetworkException;
56  import org.opentrafficsim.core.network.OTSNetwork;
57  import org.opentrafficsim.core.network.OTSNode;
58  import org.opentrafficsim.graphs.AccelerationContourPlot;
59  import org.opentrafficsim.graphs.ContourPlot;
60  import org.opentrafficsim.graphs.DensityContourPlot;
61  import org.opentrafficsim.graphs.FlowContourPlot;
62  import org.opentrafficsim.graphs.LaneBasedGTUSampler;
63  import org.opentrafficsim.graphs.SpeedContourPlot;
64  import org.opentrafficsim.graphs.TrajectoryPlot;
65  import org.opentrafficsim.road.animation.AnimationToggles;
66  import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
67  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
68  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
69  import org.opentrafficsim.road.gtu.lane.perception.CategorialLanePerception;
70  import org.opentrafficsim.road.gtu.lane.perception.categories.DefaultSimplePerception;
71  import org.opentrafficsim.road.gtu.lane.perception.headway.Headway;
72  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
73  import org.opentrafficsim.road.gtu.lane.tactical.LanePathInfo;
74  import org.opentrafficsim.road.gtu.lane.tactical.following.AccelerationStep;
75  import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
76  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
77  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
78  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
79  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
80  import org.opentrafficsim.road.modelproperties.IDMPropertySet;
81  import org.opentrafficsim.road.network.factory.LaneFactory;
82  import org.opentrafficsim.road.network.lane.CrossSectionLink;
83  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
84  import org.opentrafficsim.road.network.lane.Lane;
85  import org.opentrafficsim.road.network.lane.LaneType;
86  import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
87  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
88  import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
89  import org.opentrafficsim.simulationengine.OTSSimulationException;
90  import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
91  
92  import nl.tudelft.simulation.dsol.SimRuntimeException;
93  import nl.tudelft.simulation.dsol.gui.swing.HTMLPanel;
94  import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
95  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
96  import nl.tudelft.simulation.jstats.distributions.DistContinuous;
97  import nl.tudelft.simulation.jstats.distributions.DistTriangular;
98  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
99  import nl.tudelft.simulation.language.d3.DirectedPoint;
100 
101 /**
102  * Simplest contour plots demonstration.
103  * <p>
104  * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
105  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
106  * <p>
107  * $LastChangedDate: 2016-01-05 06:14:49 +0100 (Tue, 05 Jan 2016) $, @version $Revision: 1685 $, by $Author: averbraeck $,
108  * initial version 12 nov. 2014 <br>
109  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
110  */
111 public class StraightPerception extends AbstractWrappableAnimation implements UNITS
112 {
113     /** */
114     private static final long serialVersionUID = 1L;
115 
116     /** The model. */
117     private StraightPerceptionModel model;
118 
119     /**
120      * Create a ContourPlots simulation.
121      * @throws PropertyException when the provided properties could not be handled
122      */
123     public StraightPerception() throws PropertyException
124     {
125         List<Property<?>> outputProperties = new ArrayList<>();
126         outputProperties.add(new BooleanProperty("DensityPlot", "Density", "Density contour plot", true, false, 0));
127         outputProperties.add(new BooleanProperty("FlowPlot", "Flow", "Flow contour plot", true, false, 1));
128         outputProperties.add(new BooleanProperty("SpeedPlot", "Speed", "Speed contour plot", true, false, 2));
129         outputProperties
130                 .add(new BooleanProperty("AccelerationPlot", "Acceleration", "Acceleration contour plot", true, false, 3));
131         outputProperties.add(
132                 new BooleanProperty("TrajectoryPlot", "Trajectories", "Trajectory (time/distance) diagram", true, false, 4));
133         this.properties.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
134                 outputProperties, true, 1000));
135     }
136 
137     /** {@inheritDoc} */
138     @Override
139     public final void stopTimersThreads()
140     {
141         super.stopTimersThreads();
142         this.model = null;
143     }
144 
145     /**
146      * Main program.
147      * @param args String[]; the command line arguments (not used)
148      * @throws SimRuntimeException when simulation cannot be created with given parameters
149      */
150     public static void main(final String[] args) throws SimRuntimeException
151     {
152         SwingUtilities.invokeLater(new Runnable()
153         {
154             @SuppressWarnings("synthetic-access")
155             @Override
156             public void run()
157             {
158                 try
159                 {
160                     StraightPerception straight = new StraightPerception();
161                     List<Property<?>> localProperties = straight.getProperties();
162                     try
163                     {
164                         localProperties.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
165                                 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
166                                 new Double[] { 0.8, 0.2 }, false, 10));
167                     }
168                     catch (PropertyException exception)
169                     {
170                         exception.printStackTrace();
171                     }
172                     localProperties.add(new SelectionProperty("CarFollowingModel", "Car following model",
173                             "<html>The car following model determines "
174                                     + "the acceleration that a vehicle will make taking into account "
175                                     + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
176                                     + "curvature of the road) capabilities of the vehicle and personality "
177                                     + "of the driver.</html>",
178                             new String[] { "IDM", "IDM+" }, 1, false, 1));
179                     localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car",
180                             new Acceleration(1.0, METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2),
181                             new Length(2.0, METER), new Duration(1.0, SECOND), 2));
182                     localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck",
183                             new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2),
184                             new Length(2.0, METER), new Duration(1.0, SECOND), 3));
185                     straight.buildAnimator(Time.ZERO, Duration.ZERO, new Duration(3600.0, SECOND), localProperties, null, true);
186                     straight.panel.getTabbedPane().addTab("info", straight.makeInfoPane());
187                 }
188                 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
189                 {
190                     exception.printStackTrace();
191                 }
192             }
193         });
194     }
195 
196     /** {@inheritDoc} */
197     @Override
198     protected final void addAnimationToggles()
199     {
200         AnimationToggles.setTextAnimationTogglesStandard(this);
201     }
202 
203     /** {@inheritDoc} */
204     @Override
205     protected final OTSModelInterface makeModel(final GTUColorer colorer)
206     {
207         this.model = new StraightPerceptionModel(this.savedUserModifiedProperties, colorer);
208         return this.model;
209     }
210 
211     /**
212      * @return an info pane to be added to the tabbed pane.
213      */
214     protected final JComponent makeInfoPane()
215     {
216         // Make the info tab
217         String helpSource = "/" + StraightPerceptionModel.class.getPackage().getName().replace('.', '/') + "/IDMPlus.html";
218         URL page = StraightPerceptionModel.class.getResource(helpSource);
219         if (page != null)
220         {
221             try
222             {
223                 HTMLPanel htmlPanel = new HTMLPanel(page);
224                 return new JScrollPane(htmlPanel);
225             }
226             catch (IOException exception)
227             {
228                 exception.printStackTrace();
229             }
230         }
231         return new JPanel();
232     }
233 
234     /** {@inheritDoc} */
235     @Override
236     protected final void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
237     {
238 
239         // Make the tab with the plots
240         Property<?> output = new CompoundProperty("", "", "", this.properties, false, 0).findByKey("OutputGraphs");
241         if (null == output)
242         {
243             throw new Error("Cannot find output properties");
244         }
245         ArrayList<BooleanProperty> graphs = new ArrayList<>();
246         if (output instanceof CompoundProperty)
247         {
248             CompoundProperty outputProperties = (CompoundProperty) output;
249             for (Property<?> ap : outputProperties.getValue())
250             {
251                 if (ap instanceof BooleanProperty)
252                 {
253                     BooleanProperty bp = (BooleanProperty) ap;
254                     if (bp.getValue())
255                     {
256                         graphs.add(bp);
257                     }
258                 }
259             }
260         }
261         else
262         {
263             throw new Error("output properties should be compound");
264         }
265         int graphCount = graphs.size();
266         int columns = (int) Math.ceil(Math.sqrt(graphCount));
267         int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
268         TablePanel charts = new TablePanel(columns, rows);
269 
270         for (int i = 0; i < graphCount; i++)
271         {
272             String graphName = graphs.get(i).getKey();
273             Container container = null;
274             LaneBasedGTUSampler graph;
275             if (graphName.contains("Trajectories"))
276             {
277                 List<Lane> path = new ArrayList<>();
278                 path.add(this.model.getLane());
279                 TrajectoryPlot tp = new TrajectoryPlot("TrajectoryPlot", new Duration(0.5, SECOND), path, simulator);
280                 tp.setTitle("Trajectory Graph");
281                 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
282                 graph = tp;
283                 container = tp.getContentPane();
284             }
285             else
286             {
287                 ContourPlot cp;
288                 if (graphName.contains("DensityPlot"))
289                 {
290                     cp = new DensityContourPlot("DensityPlot", this.model.getPath());
291                     cp.setTitle("Density Contour Graph");
292                 }
293                 else if (graphName.contains("SpeedPlot"))
294                 {
295                     cp = new SpeedContourPlot("SpeedPlot", this.model.getPath());
296                     cp.setTitle("Speed Contour Graph");
297                 }
298                 else if (graphName.contains("FlowPlot"))
299                 {
300                     cp = new FlowContourPlot("FlowPlot", this.model.getPath());
301                     cp.setTitle("Flow Contour Graph");
302                 }
303                 else if (graphName.contains("AccelerationPlot"))
304                 {
305                     cp = new AccelerationContourPlot("AccelerationPlot", this.model.getPath());
306                     cp.setTitle("Acceleration Contour Graph");
307                 }
308                 else
309                 {
310                     throw new Error("Unhandled type of contourplot: " + graphName);
311                 }
312                 graph = cp;
313                 container = cp.getContentPane();
314             }
315             // Add the container to the matrix
316             charts.setCell(container, i % columns, i / columns);
317             this.model.getPlots().add(graph);
318         }
319         addTab(getTabCount(), "statistics", charts);
320     }
321 
322     /** {@inheritDoc} */
323     @Override
324     public final String shortName()
325     {
326         return "Straight lane";
327     }
328 
329     /** {@inheritDoc} */
330     @Override
331     public final String description()
332     {
333         return "<html><h1>Simulation of a straight one-lane road with opening bridge</H1>"
334                 + "Simulation of a single lane road of 5 km length. Vehicles are generated at a constant rate of "
335                 + "1500 veh/hour. At time 300s a blockade is inserted at position 4km; this blockade is removed at "
336                 + "time 420s. This blockade simulates a bridge opening.<br>"
337                 + "The blockade causes a traffic jam that slowly dissolves after the blockade is removed.<br>"
338                 + "Selected trajectory and contour plots are generated during the simulation.</html>";
339     }
340 
341 }
342 
343 /**
344  * Simulate a single lane road of 5 km length. Vehicles are generated at a constant rate of 1500 veh/hour. At time 300s a
345  * blockade is inserted at position 4 km; this blockade is removed at time 500s. The used car following algorithm is IDM+
346  * <a href="http://opentrafficsim.org/downloads/MOTUS%20reference.pdf"><i>Integrated Lane Change Model with Relaxation and
347  * Synchronization</i>, by Wouter J. Schakel, Victor L. Knoop and Bart van Arem, 2012</a>. <br>
348  * Output is a set of block charts:
349  * <ul>
350  * <li>Traffic density</li>
351  * <li>Speed</li>
352  * <li>Flow</li>
353  * <li>Acceleration</li>
354  * </ul>
355  * All these graphs display simulation time along the horizontal axis and distance along the road along the vertical axis.
356  * <p>
357  * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
358  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
359  * <p>
360  * $LastChangedDate: 2016-01-05 06:14:49 +0100 (Tue, 05 Jan 2016) $, @version $Revision: 1685 $, by $Author: averbraeck $,
361  * initial version ug 1, 2014 <br>
362  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
363  */
364 class StraightPerceptionModel implements OTSModelInterface, UNITS
365 {
366     /** */
367     private static final long serialVersionUID = 20140815L;
368 
369     /** The simulator. */
370     private OTSDEVSSimulatorInterface simulator;
371 
372     /** The network. */
373     private OTSNetwork network = new OTSNetwork("network");
374 
375     /** The headway (inter-vehicle time). */
376     private Duration headway;
377 
378     /** Number of cars created. */
379     private int carsCreated = 0;
380 
381     /** Type of all GTUs. */
382     private GTUType gtuType = CAR;
383 
384     /** The car following model, e.g. IDM Plus for cars. */
385     private GTUFollowingModelOld carFollowingModelCars;
386 
387     /** The probability that the next generated GTU is a passenger car. */
388     private double carProbability;
389 
390     /** The blocking car. */
391     private LaneBasedIndividualGTU block = null;
392 
393     /** Minimum distance. */
394     private Length minimumDistance = new Length(0, METER);
395 
396     /** Maximum distance. */
397     private Length maximumDistance = new Length(5000, METER);
398 
399     /** The Lane that contains the simulated Cars. */
400     private Lane lane;
401 
402     /** The contour plots. */
403     private List<LaneBasedGTUSampler> plots = new ArrayList<>();
404 
405     /** User settable properties. */
406     private List<Property<?>> properties = null;
407 
408     /** The random number generator used to decide what kind of GTU to generate. */
409     private Random randomGenerator = new Random(12345);
410 
411     /** The GTUColorer for the generated vehicles. */
412     private final GTUColorer gtuColorer;
413 
414     /**
415      * @param properties the user settable properties
416      * @param gtuColorer the default and initial GTUColorer, e.g. a DefaultSwitchableTUColorer.
417      */
418     StraightPerceptionModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
419     {
420         this.properties = properties;
421         this.gtuColorer = gtuColorer;
422     }
423 
424     /** The sequence of Lanes that all vehicles will follow. */
425     private List<Lane> path = new ArrayList<>();
426 
427     /** The speed limit on all Lanes. */
428     private Speed speedLimit = new Speed(100, KM_PER_HOUR);
429 
430     /** The perception interval distribution. */
431     @SuppressWarnings("visibilitymodifier")
432     DistContinuous perceptionIntervalDist = new DistTriangular(new MersenneTwister(2), 0.25, 1, 2);
433 
434     /** The forward headway distribution. */
435     @SuppressWarnings("visibilitymodifier")
436     DistContinuous forwardHeadwayDist = new DistTriangular(new MersenneTwister(20), 20, 50, 100);
437 
438     /**
439      * @return List&lt;Lane&gt;; the set of lanes for the specified index
440      */
441     public List<Lane> getPath()
442     {
443         return new ArrayList<>(this.path);
444     }
445 
446     /** {@inheritDoc} */
447     @Override
448     public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
449             throws SimRuntimeException, RemoteException
450     {
451         this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
452         try
453         {
454             OTSNode from = new OTSNode(this.network, "From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
455             OTSNode to = new OTSNode(this.network, "To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
456             OTSNode end = new OTSNode(this.network, "End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
457             Set<GTUType> compatibility = new HashSet<>();
458             compatibility.add(this.gtuType);
459             LaneType laneType = new LaneType("CarLane", compatibility);
460             this.lane = LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit, this.simulator,
461                     LongitudinalDirectionality.DIR_PLUS);
462             this.path.add(this.lane);
463             CrossSectionLink endLink = LaneFactory.makeLink(this.network, "endLink", to, end, null,
464                     LongitudinalDirectionality.DIR_PLUS, this.simulator);
465             // No overtaking, single lane
466             Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
467                     this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
468                     LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.None());
469             new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
470             String carFollowingModelName = null;
471             CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
472             Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
473             if (null == cfmp)
474             {
475                 throw new Error("Cannot find \"Car following model\" property");
476             }
477             if (cfmp instanceof SelectionProperty)
478             {
479                 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
480             }
481             else
482             {
483                 throw new Error("\"Car following model\" property has wrong type");
484             }
485             for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
486             {
487                 if (ap instanceof SelectionProperty)
488                 {
489                     SelectionProperty sp = (SelectionProperty) ap;
490                     if ("CarFollowingModel".equals(sp.getKey()))
491                     {
492                         carFollowingModelName = sp.getValue();
493                     }
494                 }
495                 else if (ap instanceof ProbabilityDistributionProperty)
496                 {
497                     ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
498                     String modelName = ap.getKey();
499                     if (modelName.equals("TrafficComposition"))
500                     {
501                         this.carProbability = pdp.getValue()[0];
502                     }
503                 }
504                 else if (ap instanceof CompoundProperty)
505                 {
506                     CompoundProperty cp = (CompoundProperty) ap;
507                     if (ap.getKey().equals("OutputGraphs"))
508                     {
509                         continue; // Output settings are handled elsewhere
510                     }
511                     if (ap.getKey().contains("IDM"))
512                     {
513                         Acceleration a = IDMPropertySet.getA(cp);
514                         Acceleration b = IDMPropertySet.getB(cp);
515                         Length s0 = IDMPropertySet.getS0(cp);
516                         Duration tSafe = IDMPropertySet.getTSafe(cp);
517                         GTUFollowingModelOld gtuFollowingModel = null;
518                         if (carFollowingModelName.equals("IDM"))
519                         {
520                             gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
521                         }
522                         else if (carFollowingModelName.equals("IDM+"))
523                         {
524                             gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
525                         }
526                         else
527                         {
528                             throw new Error("Unknown gtu following model: " + carFollowingModelName);
529                         }
530                         if (ap.getKey().contains("Car"))
531                         {
532                             this.carFollowingModelCars = gtuFollowingModel;
533                         }
534                         else if (ap.getKey().contains("Truck"))
535                         {
536                         }
537                         else
538                         {
539                             throw new Error("Cannot determine gtu type for " + ap.getKey());
540                         }
541                         /*
542                          * System.out.println("Created " + carFollowingModelName + " for " + p.getKey());
543                          * System.out.println("a: " + a); System.out.println("b: " + b); System.out.println("s0: " + s0);
544                          * System.out.println("tSafe: " + tSafe);
545                          */
546                     }
547                 }
548             }
549 
550             // 1500 [veh / hour] == 2.4s headway
551             this.headway = new Duration(3600.0 / 1500.0, SECOND);
552             // Schedule creation of the first car (it will re-schedule itself one headway later, etc.).
553             this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null);
554             // Create a block at t = 5 minutes
555             this.simulator.scheduleEventAbs(new Time(300, TimeUnit.BASE_SECOND), this, this, "createBlock", null);
556             // Remove the block at t = 7 minutes
557             this.simulator.scheduleEventAbs(new Time(420, TimeUnit.BASE_SECOND), this, this, "removeBlock", null);
558             // Schedule regular updates of the graphs
559             for (int t = 1; t <= 1800; t++)
560             {
561                 this.simulator.scheduleEventAbs(new Time(t - 0.001, TimeUnit.BASE_SECOND), this, this, "drawGraphs", null);
562             }
563         }
564         catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | PropertyException exception)
565         {
566             exception.printStackTrace();
567         }
568     }
569 
570     /**
571      * Notify the contour plots that the underlying data has changed.
572      */
573     protected final void drawGraphs()
574     {
575         for (LaneBasedGTUSampler plot : this.plots)
576         {
577             plot.reGraph();
578         }
579     }
580 
581     /**
582      * Set up the block.
583      */
584     protected final void createBlock()
585     {
586         Length initialPosition = new Length(4000, METER);
587         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
588         try
589         {
590             initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
591             BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
592 
593             this.block = new LaneBasedIndividualGTU("999999", this.gtuType, new Length(4, METER), new Length(1.8, METER),
594                     new Speed(0.0, KM_PER_HOUR), this.simulator, this.network);
595             LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
596                     new GTUFollowingTacticalPlannerNoPerceive(this.carFollowingModelCars, this.block), this.block);
597             this.block.initWithAnimation(strategicalPlanner, initialPositions, Speed.ZERO, DefaultCarAnimation.class,
598                     this.gtuColorer);
599         }
600         catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
601         {
602             exception.printStackTrace();
603         }
604     }
605 
606     /**
607      * Remove the block.
608      */
609     protected final void removeBlock()
610     {
611         this.block.destroy();
612         this.block = null;
613     }
614 
615     /**
616      * Generate cars at a fixed rate (implemented by re-scheduling this method).
617      * @throws ParameterException in case of a parameter problem.
618      */
619     protected final void generateCar() throws ParameterException
620     {
621         boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
622         Length initialPosition = new Length(0, METER);
623         Speed initialSpeed = new Speed(100, KM_PER_HOUR);
624         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
625         try
626         {
627             initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
628             Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
629             GTUFollowingModelOld gtuFollowingModel;
630             if (generateTruck)
631             {
632                 Acceleration a = new Acceleration(0.5, AccelerationUnit.METER_PER_SECOND_2); // max acceleration
633                 Acceleration b = new Acceleration(1.25, AccelerationUnit.METER_PER_SECOND_2); // max xomfortable deceleration
634                 Length s0 = new Length(4, LengthUnit.METER); // headway distance
635                 Duration tSafe = new Duration(2.0, DurationUnit.SECOND); // time headway
636                 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
637             }
638             else
639             {
640                 Acceleration a = new Acceleration(2.0, AccelerationUnit.METER_PER_SECOND_2); // max acceleration
641                 Acceleration b = new Acceleration(3, AccelerationUnit.METER_PER_SECOND_2); // max xomfortable deceleration
642                 Length s0 = new Length(2.0, LengthUnit.METER); // headway distance
643                 Duration tSafe = new Duration(1.0, DurationUnit.SECOND); // time headway
644                 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
645             }
646             BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
647             LaneBasedPerceivingCar car = new LaneBasedPerceivingCar("" + (++this.carsCreated), this.gtuType, vehicleLength,
648                     new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
649             LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
650                     new GTUFollowingTacticalPlannerNoPerceive(gtuFollowingModel, car), car);
651             car.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
652                     this.gtuColorer);
653             this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
654             car.setPerceptionInterval(new Duration(this.perceptionIntervalDist.draw(), DurationUnit.SECOND));
655             car.getStrategicalPlanner().getBehavioralCharacteristics().setParameter(ParameterTypes.LOOKAHEAD,
656                     new Length(this.forwardHeadwayDist.draw(), LengthUnit.METER));
657             // .setForwardHeadwayDistance(new Length(this.forwardHeadwayDist.draw(), LengthUnit.METER));
658         }
659         catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
660         {
661             exception.printStackTrace();
662         }
663     }
664 
665     /** {@inheritDoc} */
666     @Override
667     public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
668     {
669         return this.simulator;
670     }
671 
672     /** {@inheritDoc} */
673     @Override
674     public OTSNetwork getNetwork()
675     {
676         return this.network;
677     }
678 
679     /**
680      * @return contourPlots
681      */
682     public final List<LaneBasedGTUSampler> getPlots()
683     {
684         return this.plots;
685     }
686 
687     /**
688      * @return minimumDistance
689      */
690     public final Length getMinimumDistance()
691     {
692         return this.minimumDistance;
693     }
694 
695     /**
696      * @return maximumDistance
697      */
698     public final Length getMaximumDistance()
699     {
700         return this.maximumDistance;
701     }
702 
703     /**
704      * @return lane.
705      */
706     public Lane getLane()
707     {
708         return this.lane;
709     }
710 
711     /**
712      * Perceiving car.
713      */
714     class LaneBasedPerceivingCar extends LaneBasedIndividualGTU
715     {
716         /** */
717         private static final long serialVersionUID = 1L;
718 
719         /** */
720         private Duration perceptionInterval = new Duration(0.5, DurationUnit.SECOND);
721 
722         /**
723          * @param id ID; the id of the GTU
724          * @param gtuType GTUType; the type of GTU, e.g. TruckType, CarType, BusType
725          * @param length Length; the maximum length of the GTU (parallel with driving direction)
726          * @param width Length; the maximum width of the GTU (perpendicular to driving direction)
727          * @param maximumSpeed Speed;the maximum speed of the GTU (in the driving direction)
728          * @param simulator OTSDEVSSimulatorInterface; the simulator
729          * @param network the network that the GTU is initially registered in
730          * @throws NamingException if an error occurs when adding the animation handler
731          * @throws NetworkException when the GTU cannot be placed on the given lane
732          * @throws SimRuntimeException when the move method cannot be scheduled
733          * @throws GTUException when a parameter is invalid
734          * @throws OTSGeometryException when the initial path is wrong
735          * @throws ParameterException in case of a parameter problem.
736          */
737         LaneBasedPerceivingCar(final String id, final GTUType gtuType, final Length length, final Length width,
738                 final Speed maximumSpeed, final OTSDEVSSimulatorInterface simulator, final OTSNetwork network)
739                 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException,
740                 ParameterException
741         {
742             super(id, gtuType, length, width, maximumSpeed, simulator, network);
743             perceive();
744         }
745 
746         /**
747          * @param perceptionInterval the interval for perceiving.
748          */
749         public void setPerceptionInterval(final Duration perceptionInterval)
750         {
751             this.perceptionInterval = perceptionInterval;
752         }
753 
754         /**
755          * Perceive and reschedule.
756          * @throws SimRuntimeException RTE
757          * @throws GTUException GTUE
758          * @throws NetworkException NE
759          * @throws ParameterException in case of a parameter problem.
760          */
761         public void perceive() throws SimRuntimeException, GTUException, NetworkException, ParameterException
762         {
763             getTacticalPlanner().getPerception().perceive();
764             getSimulator().scheduleEventRel(this.perceptionInterval, this, this, "perceive", null);
765         }
766     }
767 
768     /**
769      * Tactical planner without perception update.
770      */
771     class GTUFollowingTacticalPlannerNoPerceive extends AbstractLaneBasedTacticalPlanner
772     {
773         /** */
774         private static final long serialVersionUID = 20151125L;
775 
776         /**
777          * Instantiated a tactical planner with just GTU following behavior and no lane changes.
778          * @param carFollowingModel Car-following model.
779          * @param gtu GTU
780          */
781         GTUFollowingTacticalPlannerNoPerceive(final GTUFollowingModelOld carFollowingModel, final LaneBasedGTU gtu)
782         {
783             super(carFollowingModel, gtu, new CategorialLanePerception(gtu));
784         }
785 
786         /** {@inheritDoc} */
787         @Override
788         public OperationalPlan generateOperationalPlan(final Time startTime, final DirectedPoint locationAtStartTime)
789                 throws OperationalPlanException, NetworkException, GTUException, ParameterException
790         {
791             // ask Perception for the local situation
792 
793             // if the GTU's maximum speed is zero (block), generate a stand still plan
794             if (getGtu().getMaximumSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
795             {
796                 // time equal to fastest reaction time of GTU
797                 return new OperationalPlan(getGtu(), locationAtStartTime, startTime,
798                         new Duration(StraightPerceptionModel.this.perceptionIntervalDist.draw(), DurationUnit.SECOND));
799             }
800 
801             // get some models to help us make a plan
802             // GTUFollowingModelOld gtuFollowingModel =
803             // laneBasedGTU.getStrategicalPlanner().getBehavioralCharacteristics().getGTUFollowingModel();
804 
805             // get the lane plan
806             LanePathInfo lanePathInfo =
807                     buildLanePathInfo(getGtu(), getGtu().getBehavioralCharacteristics().getParameter(ParameterTypes.LOOKAHEAD));
808             Length maxDistance = lanePathInfo.getPath().getLength();
809 
810             // look at the conditions for headway
811             Headway headway = getPerception().getPerceptionCategory(DefaultSimplePerception.class).getForwardHeadwayGTU();
812             AccelerationStep accelerationStep = null;
813             if (headway.getDistance().le(maxDistance))
814             {
815                 accelerationStep = ((GTUFollowingModelOld) this.getCarFollowingModel()).computeAccelerationStepWithNoLeader(
816                         getGtu(), maxDistance,
817                         getPerception().getPerceptionCategory(DefaultSimplePerception.class).getSpeedLimit());
818             }
819             else
820             {
821                 // TODO do not use the speed of the other GTU, but the PERCEIVED speed
822                 accelerationStep = ((GTUFollowingModelOld) this.getCarFollowingModel()).computeAccelerationStep(getGtu(),
823                         headway.getSpeed(), headway.getDistance(), maxDistance,
824                         getPerception().getPerceptionCategory(DefaultSimplePerception.class).getSpeedLimit());
825             }
826 
827             // see if we have to continue standing still. In that case, generate a stand still plan
828             if (accelerationStep.getAcceleration().si < 1E-6 && getGtu().getSpeed().si < OperationalPlan.DRIFTING_SPEED_SI)
829             {
830                 return new OperationalPlan(getGtu(), locationAtStartTime, startTime, accelerationStep.getDuration());
831             }
832 
833             List<Segment> operationalPlanSegmentList = new ArrayList<>();
834             if (accelerationStep.getAcceleration().si == 0.0)
835             {
836                 Segment segment = new OperationalPlan.SpeedSegment(accelerationStep.getDuration());
837                 operationalPlanSegmentList.add(segment);
838             }
839             else
840             {
841                 Segment segment = new OperationalPlan.AccelerationSegment(accelerationStep.getDuration(),
842                         accelerationStep.getAcceleration());
843                 operationalPlanSegmentList.add(segment);
844             }
845             OperationalPlan op = new OperationalPlan(getGtu(), lanePathInfo.getPath(), startTime, getGtu().getSpeed(),
846                     operationalPlanSegmentList);
847             return op;
848         }
849     }
850 }