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