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-09-03 11:54:19 +0200 (Thu, 03 Sep 2020) $, @version $Revision: 6688 $, by $Author: averbraeck $,
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                 animationPanel.enableSimulationControlButtons();
135             }
136             else
137             {
138                 if (exitOnClose)
139                 {
140                     System.exit(0);
141                 }
142             }
143         }
144         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException | OTSSimulationException
145             | DSOLException exception)
146         {
147             exception.printStackTrace();
148         }
149     }
150 
151     /**
152      * Add the statistics tabs.
153      * @param simulator OTSSimulatorInterface; the simulator on which sampling can be scheduled
154      * @throws OTSSimulationException on error
155      */
156     protected final void addStatisticsTabs(final OTSSimulatorInterface simulator) throws OTSSimulationException
157     {
158         final int panelsPerRow = 3;
159         TablePanel charts = new TablePanel(4, panelsPerRow);
160         RoadSampler sampler = new RoadSampler(getModel().getNetwork());
161         for (int plotNumber = 0; plotNumber < 10; plotNumber++)
162         {
163             Length detectorLocation = new Length(400 + 500 * plotNumber, METER);
164             String name = "Fundamental Diagram at " + detectorLocation.getSI() + "m";
165             SwingFundamentalDiagram graph;
166             try
167             {
168                 graph = new SwingFundamentalDiagram(new FundamentalDiagram(name, Quantity.DENSITY, Quantity.FLOW, simulator,
169                     FundamentalDiagram.sourceFromSampler(sampler, GraphLaneUtil.createCrossSection(name,
170                         new DirectedLanePosition(getModel().getLane(), detectorLocation, GTUDirectionality.DIR_PLUS)), false,
171                         Duration.instantiateSI(60.0), false), null));
172             }
173             catch (NetworkException | GTUException exception)
174             {
175                 throw new OTSSimulationException(exception);
176             }
177             charts.setCell(graph.getContentPane(), plotNumber / panelsPerRow, plotNumber % panelsPerRow);
178         }
179         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "statistics ", charts);
180     }
181 
182     /**
183      * Simulate a single lane road of 5 km length. Vehicles are generated at a constant rate of 1500 veh/hour. At time 300s a
184      * blockade is inserted at position 4 km; this blockade is removed at time 500s. The used car following algorithm is IDM+
185      * <a href="http://opentrafficsim.org/downloads/MOTUS%20reference.pdf"><i>Integrated Lane Change Model with Relaxation and
186      * Synchronization</i>, by Wouter J. Schakel, Victor L. Knoop and Bart van Arem, 2012</a>. <br>
187      * Output is a set of FundamentalDiagram plots for various point along the lane.
188      * <p>
189      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
190      * <br>
191      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
192      * <p>
193      * $LastChangedDate: 2020-09-03 11:54:19 +0200 (Thu, 03 Sep 2020) $, @version $Revision: 6688 $, by $Author: averbraeck $,
194      * initial version ug 1, 2014 <br>
195      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
196      */
197     static class FundamentalDiagramPlotsModel extends AbstractOTSModel implements UNITS
198     {
199         /** */
200         private static final long serialVersionUID = 20140820L;
201 
202         /** The network. */
203         private OTSRoadNetwork network = new OTSRoadNetwork("network", true, getSimulator());
204 
205         /** The headway (inter-vehicle time). */
206         private Duration headway;
207 
208         /** Number of cars created. */
209         private int carsCreated = 0;
210 
211         /** Strategical planner generator for cars. */
212         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
213 
214         /** Strategical planner generator for trucks. */
215         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
216 
217         /** Car parameters. */
218         private Parameters parametersCar;
219 
220         /** Truck parameters. */
221         private Parameters parametersTruck;
222 
223         /** The probability that the next generated GTU is a passenger car. */
224         private double carProbability;
225 
226         /** The blocking, implemented as a traffic light. */
227         private SimpleTrafficLight block = null;
228 
229         /** Minimum distance. */
230         private Length minimumDistance = new Length(0, METER);
231 
232         /** Maximum distance. */
233         private Length maximumDistance = new Length(5000, METER);
234 
235         /** The Lane containing the simulated Cars. */
236         private Lane lane;
237 
238         /** The speed limit. */
239         private Speed speedLimit = new Speed(100, KM_PER_HOUR);
240 
241         /** The random number generator used to decide what kind of GTU to generate. */
242         private StreamInterface stream = new MersenneTwister(12345);
243 
244         /**
245          * @param simulator OTSSimulatorInterface; the simulator for this model
246          */
247         FundamentalDiagramPlotsModel(final OTSSimulatorInterface simulator)
248         {
249             super(simulator);
250             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
251         }
252 
253         /** {@inheritDoc} */
254         @Override
255         public final void constructModel() throws SimRuntimeException
256         {
257             try
258             {
259                 OTSRoadNode from = new OTSRoadNode(this.network, "From", new OTSPoint3D(getMinimumDistance().getSI(), 0, 0),
260                     Direction.ZERO);
261                 OTSRoadNode to = new OTSRoadNode(this.network, "To", new OTSPoint3D(getMaximumDistance().getSI(), 0, 0),
262                     Direction.ZERO);
263                 OTSRoadNode end = new OTSRoadNode(this.network, "End", new OTSPoint3D(getMaximumDistance().getSI() + 50.0, 0,
264                     0), Direction.ZERO);
265                 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
266                 this.lane = LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit,
267                     this.simulator);
268                 CrossSectionLink endLink = LaneFactory.makeLink(this.network, "endLink", to, end, null, this.simulator);
269                 // No overtaking, single lane
270                 Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0), this.lane
271                     .getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
272                     this.speedLimit);
273                 new SinkSensor(sinkLane, new Length(10.0, METER), Compatible.EVERYTHING, this.simulator);
274 
275                 this.carProbability = (double) getInputParameter("generic.carProbability");
276                 this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
277                 this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
278 
279                 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(
280                     new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
281                 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(
282                     new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
283 
284                 // 1500 [veh / hour] == 2.4s headway
285                 this.headway = new Duration(3600.0 / 1500.0, SECOND);
286 
287                 // Schedule creation of the first car (this will re-schedule itself one headway later, etc.).
288                 this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null);
289 
290                 this.block = new SimpleTrafficLight(this.lane.getId() + "_TL", this.lane, new Length(new Length(4000.0,
291                     LengthUnit.METER)), this.simulator);
292                 this.block.setTrafficLightColor(TrafficLightColor.GREEN);
293 
294                 // Create a block at t = 5 minutes
295                 this.simulator.scheduleEventAbs(new Time(300, TimeUnit.BASE_SECOND), this, this, "createBlock", null);
296                 // Remove the block at t = 7 minutes
297                 this.simulator.scheduleEventAbs(new Time(420, TimeUnit.BASE_SECOND), this, this, "removeBlock", null);
298             }
299             catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException | ParameterException
300                 | InputParameterException exception)
301             {
302                 exception.printStackTrace();
303             }
304         }
305 
306         /**
307          * Set up the block.
308          */
309         protected final void createBlock()
310         {
311             this.block.setTrafficLightColor(TrafficLightColor.RED);
312         }
313 
314         /**
315          * Remove the block.
316          */
317         protected final void removeBlock()
318         {
319             this.block.setTrafficLightColor(TrafficLightColor.GREEN);
320         }
321 
322         /**
323          * Generate cars at a fixed rate (implemented by re-scheduling this method).
324          */
325         protected final void generateCar()
326         {
327             try
328             {
329                 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
330                 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
331                 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.network.getGtuType(
332                     GTUType.DEFAULTS.CAR), vehicleLength, new Length(1.8, METER), new Speed(200, KM_PER_HOUR), vehicleLength
333                         .times(0.5), this.simulator, this.network);
334                 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
335                 gtu.setNoLaneChangeDistance(Length.ZERO);
336                 gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0));
337                 gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0));
338 
339                 // strategical planner
340                 LaneBasedStrategicalPlanner strategicalPlanner = generateTruck ? this.strategicalPlannerGeneratorTrucks.create(
341                     gtu, null, null, null) : this.strategicalPlannerGeneratorCars.create(gtu, null, null, null);
342 
343                 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
344                 Length initialPosition = new Length(20, METER);
345                 initialPositions.add(new DirectedLanePosition(this.lane, initialPosition, GTUDirectionality.DIR_PLUS));
346                 Speed initialSpeed = new Speed(100.0, KM_PER_HOUR);
347                 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
348                 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
349             }
350             catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException exception)
351             {
352                 exception.printStackTrace();
353             }
354         }
355 
356         /** {@inheritDoc} */
357         @Override
358         public OTSRoadNetwork getNetwork()
359         {
360             return this.network;
361         }
362 
363         /**
364          * @return minimumDistance
365          */
366         public final Length getMinimumDistance()
367         {
368             return this.minimumDistance;
369         }
370 
371         /**
372          * @return maximumDistance
373          */
374         public final Length getMaximumDistance()
375         {
376             return this.maximumDistance;
377         }
378 
379         /**
380          * @return lane.
381          */
382         public Lane getLane()
383         {
384             return this.lane;
385         }
386 
387         /** {@inheritDoc} */
388         @Override
389         public Serializable getSourceId()
390         {
391             return "FundamentalDiagramPlotsModel";
392         }
393     }
394 
395     /** {@inheritDoc} */
396     @Override
397     public final String toString()
398     {
399         return "FundamentalDiagrams [model=" + getModel() + "]";
400     }
401 
402 }