View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.awt.Dimension;
4   import java.rmi.RemoteException;
5   import java.util.ArrayList;
6   import java.util.Arrays;
7   import java.util.LinkedHashSet;
8   import java.util.List;
9   import java.util.Set;
10  
11  import javax.naming.NamingException;
12  
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.opentrafficsim.base.parameters.ParameterException;
21  import org.opentrafficsim.base.parameters.Parameters;
22  import org.opentrafficsim.core.compatibility.Compatible;
23  import org.opentrafficsim.core.dsol.AbstractOTSModel;
24  import org.opentrafficsim.core.dsol.OTSAnimator;
25  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
26  import org.opentrafficsim.core.geometry.OTSGeometryException;
27  import org.opentrafficsim.core.geometry.OTSLine3D;
28  import org.opentrafficsim.core.geometry.OTSPoint3D;
29  import org.opentrafficsim.core.gtu.GTUDirectionality;
30  import org.opentrafficsim.core.gtu.GTUException;
31  import org.opentrafficsim.core.gtu.GTUType;
32  import org.opentrafficsim.core.network.NetworkException;
33  import org.opentrafficsim.demo.SequentialLanes.SequentialModel;
34  import org.opentrafficsim.draw.core.OTSDrawingException;
35  import org.opentrafficsim.draw.graphs.ContourDataSource;
36  import org.opentrafficsim.draw.graphs.ContourPlotAcceleration;
37  import org.opentrafficsim.draw.graphs.ContourPlotDensity;
38  import org.opentrafficsim.draw.graphs.ContourPlotFlow;
39  import org.opentrafficsim.draw.graphs.ContourPlotSpeed;
40  import org.opentrafficsim.draw.graphs.GraphPath;
41  import org.opentrafficsim.draw.graphs.TrajectoryPlot;
42  import org.opentrafficsim.draw.graphs.road.GraphLaneUtil;
43  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
44  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
45  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
46  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
47  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
48  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
49  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
50  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
51  import org.opentrafficsim.road.network.OTSRoadNetwork;
52  import org.opentrafficsim.road.network.factory.LaneFactory;
53  import org.opentrafficsim.road.network.lane.CrossSectionLink;
54  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
55  import org.opentrafficsim.road.network.lane.Lane;
56  import org.opentrafficsim.road.network.lane.LaneDirection;
57  import org.opentrafficsim.road.network.lane.LaneType;
58  import org.opentrafficsim.road.network.lane.OTSRoadNode;
59  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
60  import org.opentrafficsim.road.network.sampling.RoadSampler;
61  import org.opentrafficsim.swing.graphs.SwingContourPlot;
62  import org.opentrafficsim.swing.graphs.SwingPlot;
63  import org.opentrafficsim.swing.graphs.SwingTrajectoryPlot;
64  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
65  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
66  
67  import nl.tudelft.simulation.dsol.SimRuntimeException;
68  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
69  import nl.tudelft.simulation.dsol.swing.gui.TablePanel;
70  import nl.tudelft.simulation.dsol.swing.gui.inputparameters.TabbedParameterDialog;
71  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
72  import nl.tudelft.simulation.jstats.streams.StreamInterface;
73  
74  /**
75   * Single lane road consisting of three consecutive links.<br>
76   * Tests that GTUs correctly transfer themselves onto the next lane and that the graph samplers handle this situation.
77   * <p>
78   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
79   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
80   * <p>
81   * $LastChangedDate: 2020-01-23 11:14:19 +0100 (Thu, 23 Jan 2020) $, @version $Revision: 6010 $, by $Author: averbraeck $,
82   * initial version 30 jan. 2015 <br>
83   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
84   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
85   */
86  public class SequentialLanes extends OTSSimulationApplication<SequentialModel> implements UNITS
87  {
88      /** */
89      private static final long serialVersionUID = 1L;
90  
91      /**
92       * Create a Straight Swing application.
93       * @param title String; the title of the Frame
94       * @param panel OTSAnimationPanel; the tabbed panel to display
95       * @param model SequentialModel; the model
96       * @throws OTSDrawingException on animation error
97       */
98      public SequentialLanes(final String title, final OTSAnimationPanel panel, final SequentialModel model)
99              throws OTSDrawingException
100     {
101         super(model, panel);
102         OTSRoadNetwork network = model.getNetwork();
103         System.out.println(network.getLinkMap());
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     protected void addTabs()
109     {
110         addStatisticsTabs(getModel().getSimulator());
111     }
112 
113     /**
114      * Main program.
115      * @param args String[]; the command line arguments (not used)
116      */
117     public static void main(final String[] args)
118     {
119         demo(true);
120     }
121 
122     /**
123      * Start the demo.
124      * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false
125      */
126     public static void demo(final boolean exitOnClose)
127     {
128         try
129         {
130             OTSAnimator simulator = new OTSAnimator();
131             final SequentialModel otsModel = new SequentialModel(simulator);
132             if (TabbedParameterDialog.process(otsModel.getInputParameterMap()))
133             {
134                 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel);
135                 OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(),
136                         new Dimension(800, 600), simulator, otsModel, DEFAULT_COLORER, otsModel.getNetwork());
137                 SequentialLaneses.html#SequentialLanes">SequentialLanes app = new SequentialLanes("SequentialLanes", animationPanel, otsModel);
138                 app.setExitOnClose(exitOnClose);
139             }
140             else
141             {
142                 if (exitOnClose)
143                 {
144                     System.exit(0);
145                 }
146             }
147         }
148         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
149         {
150             exception.printStackTrace();
151         }
152     }
153 
154     /**
155      * Add the statistics tabs.
156      * @param simulator OTSSimulatorInterface; the simulator on which sampling can be scheduled
157      */
158     protected final void addStatisticsTabs(final OTSSimulatorInterface simulator)
159     {
160         GraphPath<KpiLaneDirection> path;
161         try
162         {
163             path = GraphLaneUtil.createPath("Lane", new LaneDirection(getModel().getPath().get(0), GTUDirectionality.DIR_PLUS));
164         }
165         catch (NetworkException exception)
166         {
167             throw new RuntimeException("Could not create a path as a lane has no set speed limit.", exception);
168         }
169 
170         RoadSampler sampler = new RoadSampler(simulator);
171         ContourDataSource<?> dataPool = new ContourDataSource<>(sampler, path);
172         TablePanel charts = new TablePanel(3, 2);
173         SwingPlot plot = null;
174 
175         plot = new SwingTrajectoryPlot(new TrajectoryPlot("TrajectoryPlot", Duration.instantiateSI(10.0), simulator, sampler, path));
176         charts.setCell(plot.getContentPane(), 0, 0);
177 
178         plot = new SwingContourPlot(new ContourPlotDensity("DensityPlot", simulator, dataPool));
179         charts.setCell(plot.getContentPane(), 1, 0);
180 
181         plot = new SwingContourPlot(new ContourPlotSpeed("SpeedPlot", simulator, dataPool));
182         charts.setCell(plot.getContentPane(), 2, 0);
183 
184         plot = new SwingContourPlot(new ContourPlotFlow("FlowPlot", simulator, dataPool));
185         charts.setCell(plot.getContentPane(), 1, 1);
186 
187         plot = new SwingContourPlot(new ContourPlotAcceleration("AccelerationPlot", simulator, dataPool));
188         charts.setCell(plot.getContentPane(), 2, 1);
189 
190         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "statistics ", charts);
191     }
192 
193     /**
194      * Build the sequential model.
195      * <p>
196      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
197      * <br>
198      * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
199      * <p>
200      * $LastChangedDate: 2020-01-23 11:14:19 +0100 (Thu, 23 Jan 2020) $, @version $Revision: 6010 $, by $Author: averbraeck $,
201      * initial version 0 jan. 2015 <br>
202      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
203      */
204     static class SequentialModel extends AbstractOTSModel implements UNITS
205     {
206         /** */
207         private static final long serialVersionUID = 20150130L;
208 
209         /** The network. */
210         private final OTSRoadNetwork network = new OTSRoadNetwork("network", true);
211 
212         /** The nodes of our network in the order that all GTUs will visit them. */
213         private List<OTSRoadNode> nodes = new ArrayList<>();
214 
215         /** Strategical planner generator for cars. */
216         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
217 
218         /** Strategical planner generator for trucks. */
219         private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
220 
221         /** Car parameters. */
222         private Parameters parametersCar;
223 
224         /** Truck parameters. */
225         private Parameters parametersTruck;
226 
227         /** The probability that the next generated GTU is a passenger car. */
228         private double carProbability;
229 
230         /** The headway (inter-vehicle time). */
231         private Duration headway;
232 
233         /** Number of cars created. */
234         private int carsCreated = 0;
235 
236         /** Minimum distance. */
237         private Length minimumDistance = new Length(0, METER);
238 
239         /** The Lane where newly created Cars initially placed on. */
240         private Lane initialLane;
241 
242         /** Maximum distance. */
243         private Length maximumDistance = new Length(2001, METER);
244 
245         /** The random number generator used to decide what kind of GTU to generate. */
246         private StreamInterface stream = new MersenneTwister(12345);
247 
248         /** The sequence of Lanes that all vehicles will follow. */
249         private List<Lane> path = new ArrayList<>();
250 
251         /** The speedLimit on all Lanes. */
252         private Speed speedLimit;
253 
254         /**
255          * @param simulator OTSSimulatorInterface; the simulator for this model
256          */
257         SequentialModel(final OTSSimulatorInterface simulator)
258         {
259             super(simulator);
260             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
261         }
262 
263         /**
264          * @return a newly created path (which all GTUs in this simulation will follow).
265          */
266         public List<Lane> getPath()
267         {
268             return new ArrayList<>(this.path);
269         }
270 
271         /** {@inheritDoc} */
272         @Override
273         public final void constructModel() throws SimRuntimeException
274         {
275             this.speedLimit = new Speed(100, KM_PER_HOUR);
276 
277             // TODO Bezier curves make 180 degree mistake when minus is true
278             boolean minus = false;
279 
280             this.nodes = new ArrayList<>();
281             try
282             {
283                 OTSPoint3D p2 = new OTSPoint3D(1020, 3);
284                 OTSPoint3D p3 = new OTSPoint3D(2000, 197);
285                 Direction dir23 = p2.horizontalDirection(p3);
286                 OTSRoadNode n0 = new OTSRoadNode(this.network, "Node-0-(0,0)", new OTSPoint3D(0, 0), Direction.ZERO);
287                 OTSRoadNode n1 = new OTSRoadNode(this.network, "Node-1-(1000,0)", new OTSPoint3D(1000, 0), Direction.ZERO);
288                 OTSRoadNode n2 = new OTSRoadNode(this.network, "Node-2-(1020,3)", p2, dir23);
289                 OTSRoadNode n3 = new OTSRoadNode(this.network, "Node-3-(2000,197)", p3, dir23);
290                 OTSRoadNode n4 = new OTSRoadNode(this.network, "Node-4-(2020,200)", new OTSPoint3D(2020, 200), Direction.ZERO);
291                 OTSRoadNode n5 = new OTSRoadNode(this.network, "Node-5-(2200,200)", new OTSPoint3D(2200, 200), Direction.ZERO);
292                 this.nodes.addAll(Arrays.asList(new OTSRoadNode[] {n0, n1, n2, n3, n4, n5}));
293 
294                 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
295 
296                 // Now we can build a series of Links with one Lane on them
297                 ArrayList<CrossSectionLink> links = new ArrayList<>();
298                 OTSLine3D l01 = new OTSLine3D(n0.getPoint(), n1.getPoint());
299                 OTSLine3D l12 = LaneFactory.makeBezier(n0, n1, n2, n3);
300                 OTSLine3D l23 =
301                         minus ? new OTSLine3D(n3.getPoint(), n2.getPoint()) : new OTSLine3D(n2.getPoint(), n3.getPoint());
302                 OTSLine3D l34 = LaneFactory.makeBezier(n2, n3, n4, n5);
303                 OTSLine3D l45 = new OTSLine3D(n4.getPoint(), n5.getPoint());
304                 OTSLine3D[] lines = new OTSLine3D[] {l01, l12, l23, l34, l45};
305 
306                 for (int i = 1; i < this.nodes.size(); i++)
307                 {
308                     OTSRoadNode fromNode = this.nodes.get(i - 1);
309                     OTSRoadNode toNode = this.nodes.get(i);
310                     OTSLine3D line = lines[i - 1];
311                     String linkName = fromNode.getId() + "-" + toNode.getId();
312                     // LongitudinalDirectionality direction = line.equals(l23) && minus ? LongitudinalDirectionality.DIR_MINUS
313                     // : LongitudinalDirectionality.DIR_PLUS;
314                     Lane[] lanes = LaneFactory.makeMultiLane(this.network, linkName, fromNode, toNode, line.getPoints(), 1,
315                             laneType, this.speedLimit, this.simulator);
316                     if (i == this.nodes.size() - 1)
317                     {
318                         new SinkSensor(lanes[0], new Length(100.0, METER), Compatible.EVERYTHING, this.simulator);
319                     }
320                     this.path.add(lanes[0]);
321                     links.add(lanes[0].getParentLink());
322                     if (1 == i)
323                     {
324                         this.initialLane = lanes[0];
325                     }
326                 }
327 
328                 this.carProbability = (double) getInputParameter("generic.carProbability");
329                 this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
330                 this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
331 
332                 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
333                         new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
334                 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
335                         new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
336 
337                 // 1500 [veh / hour] == 2.4s headway
338                 this.headway = new Duration(3600.0 / 1500.0, SECOND);
339 
340                 // Schedule creation of the first car (it will re-schedule itself one headway later, etc.).
341                 this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null);
342             }
343             catch (NamingException | NetworkException | OTSGeometryException | ParameterException | InputParameterException
344                     | GTUException exception)
345             {
346                 exception.printStackTrace();
347             }
348         }
349 
350         /** {@inheritDoc} */
351         @Override
352         public OTSRoadNetwork getNetwork()
353         {
354             return this.network;
355         }
356 
357         /**
358          * @return minimumDistance
359          */
360         public final Length getMinimumDistance()
361         {
362             return this.minimumDistance;
363         }
364 
365         /**
366          * @return maximumDistance
367          */
368         public final Length getMaximumDistance()
369         {
370             return this.maximumDistance;
371         }
372 
373         /**
374          * Generate cars at a fixed rate (implemented by re-scheduling this method).
375          */
376         protected final void generateCar()
377         {
378             try
379             {
380                 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
381                 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
382                 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated),
383                         this.network.getGtuType(GTUType.DEFAULTS.CAR), vehicleLength, new Length(1.8, METER),
384                         new Speed(200, KM_PER_HOUR), vehicleLength.times(0.5), this.simulator, this.network);
385                 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
386                 gtu.setNoLaneChangeDistance(Length.ZERO);
387                 gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0));
388                 gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0));
389 
390                 // strategical planner
391                 LaneBasedStrategicalPlanner strategicalPlanner =
392                         generateTruck ? this.strategicalPlannerGeneratorTrucks.create(gtu, null, null, null)
393                                 : this.strategicalPlannerGeneratorCars.create(gtu, null, null, null);
394 
395                 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
396                 Length initialPosition = new Length(20, METER);
397                 initialPositions.add(new DirectedLanePosition(this.initialLane, initialPosition, GTUDirectionality.DIR_PLUS));
398                 Speed initialSpeed = new Speed(100.0, KM_PER_HOUR);
399                 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
400                 this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null);
401             }
402             catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException exception)
403             {
404                 exception.printStackTrace();
405             }
406         }
407 
408     }
409 }