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