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