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