View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.awt.Dimension;
4   import java.rmi.RemoteException;
5   import java.util.LinkedHashSet;
6   import java.util.Set;
7   
8   import javax.naming.NamingException;
9   
10  import org.djunits.unit.LengthUnit;
11  import org.djunits.unit.TimeUnit;
12  import org.djunits.unit.UNITS;
13  import org.djunits.value.vdouble.scalar.Acceleration;
14  import org.djunits.value.vdouble.scalar.Duration;
15  import org.djunits.value.vdouble.scalar.Length;
16  import org.djunits.value.vdouble.scalar.Speed;
17  import org.djunits.value.vdouble.scalar.Time;
18  import org.djutils.exceptions.Try;
19  import org.opentrafficsim.base.parameters.ParameterException;
20  import org.opentrafficsim.base.parameters.Parameters;
21  import org.opentrafficsim.core.dsol.AbstractOTSModel;
22  import org.opentrafficsim.core.dsol.OTSAnimator;
23  import org.opentrafficsim.core.dsol.OTSSimulationException;
24  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
25  import org.opentrafficsim.core.geometry.OTSGeometryException;
26  import org.opentrafficsim.core.geometry.OTSPoint3D;
27  import org.opentrafficsim.core.gtu.GTUDirectionality;
28  import org.opentrafficsim.core.gtu.GTUException;
29  import org.opentrafficsim.core.gtu.GTUType;
30  import org.opentrafficsim.core.network.NetworkException;
31  import org.opentrafficsim.core.network.OTSNode;
32  import org.opentrafficsim.demo.FundamentalDiagrams.FundamentalDiagramPlotsModel;
33  import org.opentrafficsim.draw.core.OTSDrawingException;
34  import org.opentrafficsim.draw.graphs.FundamentalDiagram;
35  import org.opentrafficsim.draw.graphs.FundamentalDiagram.Quantity;
36  import org.opentrafficsim.draw.graphs.road.GraphLaneUtil;
37  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
38  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
39  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
40  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
41  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
42  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
43  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
44  import org.opentrafficsim.road.network.OTSRoadNetwork;
45  import org.opentrafficsim.road.network.factory.LaneFactory;
46  import org.opentrafficsim.road.network.lane.CrossSectionLink;
47  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
48  import org.opentrafficsim.road.network.lane.Lane;
49  import org.opentrafficsim.road.network.lane.LaneType;
50  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
51  import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
52  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
53  import org.opentrafficsim.road.network.sampling.RoadSampler;
54  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
55  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
56  
57  import nl.tudelft.simulation.dsol.SimRuntimeException;
58  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
59  import nl.tudelft.simulation.dsol.swing.gui.TablePanel;
60  import nl.tudelft.simulation.dsol.swing.gui.inputparameters.TabbedParameterDialog;
61  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
62  import nl.tudelft.simulation.jstats.streams.StreamInterface;
63  
64  /**
65   * Demonstrate the FundamentalDiagram plot.
66   * <p>
67   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
68   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
69   * <p>
70   * $LastChangedDate: 2019-03-27 07:42:05 +0100 (Wed, 27 Mar 2019) $, @version $Revision: 5192 $, by $Author: averbraeck $,
71   * initial version 17 dec. 2014 <br>
72   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
73   */
74  public class FundamentalDiagrams extends OTSSimulationApplication<FundamentalDiagramPlotsModel> implements UNITS
75  {
76      /** */
77      private static final long serialVersionUID = 1L;
78  
79      /**
80       * Create a Straight Swing application.
81       * @param title String; the title of the Frame
82       * @param panel OTSAnimationPanel; the tabbed panel to display
83       * @param model FundamentalDiagramPlotsModel; the model
84       * @throws OTSDrawingException on animation error
85       * @throws OTSSimulationException on graph error
86       */
87      public FundamentalDiagrams(final String title, final OTSAnimationPanel panel, final FundamentalDiagramPlotsModel model)
88              throws OTSDrawingException, OTSSimulationException
89      {
90          super(model, panel);
91          OTSRoadNetwork network = model.getNetwork();
92          System.out.println(network.getLinkMap());
93      }
94  
95      /** {@inheritDoc} */
96      @Override
97      protected void addTabs()
98      {
99          Try.execute(() -> addStatisticsTabs(getModel().getSimulator()), RuntimeException.class,
100                 "Exception while setting up the statistics tabs.");
101     }
102 
103     /**
104      * Main program.
105      * @param args String[]; the command line arguments (not used)
106      */
107     public static void main(final String[] args)
108     {
109         demo(true);
110     }
111 
112     /**
113      * Start the demo.
114      * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false
115      */
116     public static void demo(final boolean exitOnClose)
117     {
118         try
119         {
120             OTSAnimator simulator = new OTSAnimator();
121             final FundamentalDiagramPlotsModel otsModel = new FundamentalDiagramPlotsModel(simulator);
122             if (TabbedParameterDialog.process(otsModel.getInputParameterMap()))
123             {
124                 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.createSI(3600.0), otsModel);
125                 OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(),
126                         new Dimension(800, 600), simulator, otsModel, DEFAULT_COLORER, otsModel.getNetwork());
127                 FundamentalDiagrams app = new FundamentalDiagrams("FundamentalDiagrams", animationPanel, otsModel);
128                 app.setExitOnClose(exitOnClose);
129             }
130             else
131             {
132                 if (exitOnClose)
133                 {
134                     System.exit(0);
135                 }
136             }
137         }
138         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException | OTSSimulationException exception)
139         {
140             exception.printStackTrace();
141         }
142     }
143 
144     /**
145      * Add the statistics tabs.
146      * @param simulator OTSSimulatorInterface; the simulator on which sampling can be scheduled
147      * @throws OTSSimulationException on error
148      */
149     protected final void addStatisticsTabs(final OTSSimulatorInterface simulator) throws OTSSimulationException
150     {
151         final int panelsPerRow = 3;
152         TablePanel charts = new TablePanel(4, panelsPerRow);
153         RoadSampler sampler = new RoadSampler(simulator);
154         for (int plotNumber = 0; plotNumber < 10; plotNumber++)
155         {
156             Length detectorLocation = new Length(400 + 500 * plotNumber, METER);
157             String name = "Fundamental Diagram at " + detectorLocation.getSI() + "m";
158             FundamentalDiagram graph;
159             try
160             {
161                 graph = new FundamentalDiagram(name, Quantity.DENSITY, Quantity.FLOW, simulator, sampler,
162                         GraphLaneUtil.createCrossSection(name,
163                                 new DirectedLanePosition(getModel().getLane(), detectorLocation, GTUDirectionality.DIR_PLUS)),
164                         false, Duration.createSI(60.0), false);
165             }
166             catch (NetworkException | GTUException exception)
167             {
168                 throw new OTSSimulationException(exception);
169             }
170             charts.setCell(graph.getContentPane(), plotNumber / panelsPerRow, plotNumber % panelsPerRow);
171         }
172         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "statistics ", charts);
173     }
174 
175     /**
176      * Simulate a single lane road of 5 km length. Vehicles are generated at a constant rate of 1500 veh/hour. At time 300s a
177      * blockade is inserted at position 4 km; this blockade is removed at time 500s. The used car following algorithm is IDM+
178      * <a href="http://opentrafficsim.org/downloads/MOTUS%20reference.pdf"><i>Integrated Lane Change Model with Relaxation and
179      * Synchronization</i>, by Wouter J. Schakel, Victor L. Knoop and Bart van Arem, 2012</a>. <br>
180      * Output is a set of FundamentalDiagram plots for various point along the lane.
181      * <p>
182      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
183      * <br>
184      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
185      * <p>
186      * $LastChangedDate: 2019-03-27 07:42:05 +0100 (Wed, 27 Mar 2019) $, @version $Revision: 5192 $, by $Author: averbraeck $,
187      * initial version ug 1, 2014 <br>
188      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
189      */
190     static class FundamentalDiagramPlotsModel extends AbstractOTSModel implements UNITS
191     {
192         /** */
193         private static final long serialVersionUID = 20140820L;
194 
195         /** The network. */
196         private OTSRoadNetwork network = new OTSRoadNetwork("network", true);
197 
198         /** The headway (inter-vehicle time). */
199         private Duration headway;
200 
201         /** Number of cars created. */
202         private int carsCreated = 0;
203 
204         /** Strategical planner generator for cars. */
205         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
206 
207         /** Strategical planner generator for trucks. */
208         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
209 
210         /** Car parameters. */
211         private Parameters parametersCar;
212 
213         /** Truck parameters. */
214         private Parameters parametersTruck;
215 
216         /** The probability that the next generated GTU is a passenger car. */
217         private double carProbability;
218 
219         /** The blocking, implemented as a traffic light. */
220         private SimpleTrafficLight block = null;
221 
222         /** Minimum distance. */
223         private Length minimumDistance = new Length(0, METER);
224 
225         /** Maximum distance. */
226         private Length maximumDistance = new Length(5000, METER);
227 
228         /** The Lane containing the simulated Cars. */
229         private Lane lane;
230 
231         /** The speed limit. */
232         private Speed speedLimit = new Speed(100, KM_PER_HOUR);
233 
234         /** The random number generator used to decide what kind of GTU to generate. */
235         private StreamInterface stream = new MersenneTwister(12345);
236 
237         /**
238          * @param simulator OTSSimulatorInterface; the simulator for this model
239          */
240         FundamentalDiagramPlotsModel(final OTSSimulatorInterface simulator)
241         {
242             super(simulator);
243             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
244         }
245 
246         /** {@inheritDoc} */
247         @Override
248         public final void constructModel() throws SimRuntimeException
249         {
250             try
251             {
252                 OTSNode from = new OTSNode(this.network, "From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0));
253                 OTSNode to = new OTSNode(this.network, "To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0));
254                 OTSNode end = new OTSNode(this.network, "End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0, 0));
255                 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
256                 this.lane =
257                         LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit, this.simulator);
258                 CrossSectionLink endLink = LaneFactory.makeLink(this.network, "endLink", to, end, null, this.simulator);
259                 // No overtaking, single lane
260                 Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
261                         this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
262                         this.speedLimit);
263                 new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
264 
265                 this.carProbability = (double) getInputParameter("generic.carProbability");
266                 this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
267                 this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
268 
269                 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
270                         new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
271                 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
272                         new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
273 
274                 // 1500 [veh / hour] == 2.4s headway
275                 this.headway = new Duration(3600.0 / 1500.0, SECOND);
276 
277                 // Schedule creation of the first car (this will re-schedule itself one headway later, etc.).
278                 this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null);
279 
280                 this.block = new SimpleTrafficLight(this.lane.getId() + "_TL", this.lane,
281                         new Length(new Length(4000.0, LengthUnit.METER)), this.simulator);
282                 this.block.setTrafficLightColor(TrafficLightColor.GREEN);
283 
284                 // Create a block at t = 5 minutes
285                 this.simulator.scheduleEventAbs(new Time(300, TimeUnit.BASE_SECOND), this, this, "createBlock", null);
286                 // Remove the block at t = 7 minutes
287                 this.simulator.scheduleEventAbs(new Time(420, TimeUnit.BASE_SECOND), this, this, "removeBlock", null);
288             }
289             catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException | ParameterException
290                     | InputParameterException exception)
291             {
292                 exception.printStackTrace();
293             }
294         }
295 
296         /**
297          * Set up the block.
298          */
299         protected final void createBlock()
300         {
301             this.block.setTrafficLightColor(TrafficLightColor.RED);
302         }
303 
304         /**
305          * Remove the block.
306          */
307         protected final void removeBlock()
308         {
309             this.block.setTrafficLightColor(TrafficLightColor.GREEN);
310         }
311 
312         /**
313          * Generate cars at a fixed rate (implemented by re-scheduling this method).
314          */
315         protected final void generateCar()
316         {
317             try
318             {
319                 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
320                 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
321                 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated),
322                         this.network.getGtuType(GTUType.DEFAULTS.CAR), vehicleLength, new Length(1.8, METER),
323                         new Speed(200, KM_PER_HOUR), vehicleLength.multiplyBy(0.5), this.simulator, this.network);
324                 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
325                 gtu.setNoLaneChangeDistance(Length.ZERO);
326                 gtu.setMaximumAcceleration(Acceleration.createSI(3.0));
327                 gtu.setMaximumDeceleration(Acceleration.createSI(-8.0));
328 
329                 // strategical planner
330                 LaneBasedStrategicalPlanner strategicalPlanner =
331                         generateTruck ? this.strategicalPlannerGeneratorTrucks.create(gtu, null, null, null)
332                                 : this.strategicalPlannerGeneratorCars.create(gtu, null, null, null);
333 
334                 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
335                 Length initialPosition = new Length(20, METER);
336                 initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
337                 Speed initialSpeed = new Speed(100.0, KM_PER_HOUR);
338                 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
339                 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
340             }
341             catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException exception)
342             {
343                 exception.printStackTrace();
344             }
345         }
346 
347         /** {@inheritDoc} */
348         @Override
349         public OTSRoadNetwork getNetwork()
350         {
351             return this.network;
352         }
353 
354         /**
355          * @return minimumDistance
356          */
357         public final Length getMinimumDistance()
358         {
359             return this.minimumDistance;
360         }
361 
362         /**
363          * @return maximumDistance
364          */
365         public final Length getMaximumDistance()
366         {
367             return this.maximumDistance;
368         }
369 
370         /**
371          * @return lane.
372          */
373         public Lane getLane()
374         {
375             return this.lane;
376         }
377     }
378 
379     /** {@inheritDoc} */
380     @Override
381     public final String toString()
382     {
383         return "FundamentalDiagrams [model=" + getModel() + "]";
384     }
385 
386 }