View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.awt.Component;
4   import java.awt.Container;
5   import java.awt.Dimension;
6   import java.awt.Window;
7   import java.rmi.RemoteException;
8   import java.util.ArrayList;
9   import java.util.List;
10  
11  import javax.naming.NamingException;
12  import javax.swing.JButton;
13  
14  import org.djunits.value.vdouble.scalar.Duration;
15  import org.djunits.value.vdouble.scalar.Length;
16  import org.djunits.value.vdouble.scalar.Time;
17  import org.opentrafficsim.core.dsol.OTSAnimator;
18  import org.opentrafficsim.core.dsol.OTSSimulator;
19  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
20  import org.opentrafficsim.core.gtu.GTU;
21  import org.opentrafficsim.core.gtu.GTUDirectionality;
22  import org.opentrafficsim.core.network.DirectedLinkPosition;
23  import org.opentrafficsim.core.network.NetworkException;
24  import org.opentrafficsim.draw.core.OTSDrawingException;
25  import org.opentrafficsim.draw.graphs.ContourDataSource;
26  import org.opentrafficsim.draw.graphs.ContourPlotAcceleration;
27  import org.opentrafficsim.draw.graphs.ContourPlotDensity;
28  import org.opentrafficsim.draw.graphs.ContourPlotFlow;
29  import org.opentrafficsim.draw.graphs.ContourPlotSpeed;
30  import org.opentrafficsim.draw.graphs.FundamentalDiagram;
31  import org.opentrafficsim.draw.graphs.FundamentalDiagram.Quantity;
32  import org.opentrafficsim.draw.graphs.GraphCrossSection;
33  import org.opentrafficsim.draw.graphs.GraphPath;
34  import org.opentrafficsim.draw.graphs.TrajectoryPlot;
35  import org.opentrafficsim.draw.graphs.road.GraphLaneUtil;
36  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
37  import org.opentrafficsim.road.network.OTSRoadNetwork;
38  import org.opentrafficsim.road.network.lane.LaneDirection;
39  import org.opentrafficsim.road.network.sampling.RoadSampler;
40  import org.opentrafficsim.swing.graphs.SwingContourPlot;
41  import org.opentrafficsim.swing.graphs.SwingFundamentalDiagram;
42  import org.opentrafficsim.swing.graphs.SwingPlot;
43  import org.opentrafficsim.swing.graphs.SwingTrajectoryPlot;
44  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
45  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
46  
47  import nl.tudelft.simulation.dsol.SimRuntimeException;
48  import nl.tudelft.simulation.dsol.swing.gui.TablePanel;
49  import nl.tudelft.simulation.dsol.swing.gui.inputparameters.TabbedParameterDialog;
50  import nl.tudelft.simulation.language.DSOLException;
51  
52  /**
53   * Circular road simulation demo.
54   * <p>
55   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
56   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
57   * <p>
58   * $LastChangedDate: 2018-11-18 20:49:04 +0100 (Sun, 18 Nov 2018) $, @version $Revision: 4743 $, by $Author: averbraeck $,
59   * initial version 21 nov. 2014 <br>
60   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
61   */
62  public class CircularRoadSwing extends OTSSimulationApplication<CircularRoadModel>
63  {
64      /** */
65      private static final long serialVersionUID = 1L;
66  
67      /**
68       * Create a CircularRoad Swing application.
69       * @param title String; the title of the Frame
70       * @param panel OTSAnimationPanel; the tabbed panel to display
71       * @param model CircularRoadModel; the model
72       * @throws OTSDrawingException on animation error
73       */
74      public CircularRoadSwing(final String title, final OTSAnimationPanel panel, final CircularRoadModel model)
75              throws OTSDrawingException
76      {
77          super(model, panel);
78  
79          // NetworkAnimation networkAnimation = new NetworkAnimation(model.getNetwork());
80          // networkAnimation.addDrawingInfoClass(Lane.class, new DrawingInfoShape<>(Color.GRAY));
81          OTSRoadNetwork network = model.getNetwork();
82          System.out.println(network.getLinkMap());
83      }
84  
85      /** {@inheritDoc} */
86      @Override
87      protected void addTabs()
88      {
89          addStatisticsTabs(getModel().getSimulator());
90      }
91  
92      /**
93       * Main program.
94       * @param args String[]; the command line arguments (not used)
95       */
96      public static void main(final String[] args)
97      {
98          // simulatorDemo();
99          demo(true);
100     }
101 
102     /**
103      * Run the simulation without animation.
104      */
105     public static void simulatorDemo()
106     {
107         try
108         {
109             OTSSimulator simulator = new OTSSimulator("CircularRoadSwing");
110             final CircularRoadModelml#CircularRoadModel">CircularRoadModel otsModel = new CircularRoadModel(simulator);
111             System.out.println(otsModel.getInputParameterMap());
112             TabbedParameterDialog.process(otsModel.getInputParameterMap());
113             simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel);
114             Thread getLocationThread = new Thread()
115             {
116                 @Override
117                 public void run()
118                 {
119                     System.out.println("getLocationThread starts up");
120                     int iteration = 0;
121                     int getLocationCalls = 0;
122                     while (simulator.isStartingOrRunning())
123                     {
124                         iteration++;
125                         for (GTU gtu : otsModel.getNetwork().getGTUs())
126                         {
127                             try
128                             {
129                                 gtu.getLocation();
130                                 getLocationCalls++;
131                             }
132                             catch (RemoteException e)
133                             {
134                                 e.printStackTrace();
135                             }
136                         }
137                         try
138                         {
139                             Thread.sleep(1);
140                         }
141                         catch (InterruptedException e)
142                         {
143                             e.printStackTrace();
144                         }
145                     }
146                     System.out.println("getLocationThread exits after " + iteration + " iterations and " + getLocationCalls
147                             + " getLocation calls");
148                 }
149 
150             };
151             simulator.start();
152             getLocationThread.start();
153             while (simulator.isStartingOrRunning())
154             {
155                 Thread.sleep(1000);
156                 // System.out.println("Simulator time is " + simulator.getSimulatorTime());
157             }
158         }
159         catch (Exception e)
160         {
161             e.printStackTrace();
162         }
163         System.exit(0);
164     }
165 
166     /**
167      * Find the start simulation button and click it.
168      * @param component Component; some component that could be the start button, or a container that contains the start button
169      * @return boolean; true if the start button was found (and clicked); false otherwise
170      */
171     public static boolean clickStart(final Component component)
172     {
173         if (component instanceof JButton)
174         {
175             JButton button = (JButton) component;
176             if (button.getText().contains("Start simulation model"))
177             {
178                 button.doClick();
179                 System.out.println("Auto clicked the start button");
180                 return true;
181             }
182         }
183         else if (component instanceof Container)
184         {
185             for (Component comp : ((Container) component).getComponents())
186             {
187                 if (clickStart(comp))
188                 {
189                     return true;
190                 }
191             }
192         }
193         return false;
194     }
195     
196     /**
197      * Click the button that starts the animated simulation.
198      * @param component Component; some component that (hopefully) is, or contains the start button
199      * @return boolean; true if the button was found (and clicked); false if the start button was not found
200      */
201     public static boolean clickRunPause(final Component component)
202     {
203         if (component instanceof JButton)
204         {
205             JButton button = (JButton) component;
206             // System.out.println("Found button with name " + button.getName());
207             if (button.getName().equals("runPauseButton"))
208             {
209                 button.doClick();
210                 System.out.println("Auto clicked the run button");
211                 return true;
212             }
213         }
214         else if (component instanceof Container)
215         {
216             for (Component comp : ((Container) component).getComponents())
217             {
218                 if (clickRunPause(comp))
219                 {
220                     return true;
221                 }
222             }
223         }
224         return false;
225     }
226     
227     /**
228      * Start the demo.
229      * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false
230      */
231     public static void demo(final boolean exitOnClose)
232     {
233         try
234         {
235             OTSAnimator simulator = new OTSAnimator("CircularRoadSwing");
236             final CircularRoadModelml#CircularRoadModel">CircularRoadModel otsModel = new CircularRoadModel(simulator);
237             // Thread buttonClick = new Thread()
238             // {
239             // @Override
240             // public void run()
241             // {
242             // try
243             // {
244             // Thread.sleep(1000);
245             // }
246             // catch (InterruptedException e)
247             // {
248             // e.printStackTrace();
249             // } // wait for the TabbedParameterDialog to start up
250             // // Find the window
251             // for (Window window : Window.getWindows())
252             // {
253             // // System.out.println("Name of window is " + window.getName());
254             // if (window.getName().startsWith("dialog"))
255             // {
256             // for (Component comp : window.getComponents())
257             // {
258             // if (clickStart(comp))
259             // {
260             // return;
261             // }
262             // }
263             // }
264             // }
265             //
266             // }
267             // };
268             // buttonClick.start(); // start the thread that will try to click on the start button
269             if (TabbedParameterDialog.process(otsModel.getInputParameterMap()))
270             {
271                 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel);
272                 OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(),
273                         new Dimension(800, 600), simulator, otsModel, DEFAULT_COLORER, otsModel.getNetwork());
274                 CircularRoadSwingng.html#CircularRoadSwing">CircularRoadSwing app = new CircularRoadSwing("Circular Road", animationPanel, otsModel);
275                 app.setExitOnClose(exitOnClose);
276                 animationPanel.enableSimulationControlButtons();
277                 // simulator.setSpeedFactor(Double.MAX_VALUE, true);
278                 // simulator.setSpeedFactor(1000.0, true);
279                 // for (Component component : app.getComponents())
280                 // {
281                 // if (clickRunPause(component))
282                 // {
283                 // break;
284                 // }
285                 // }
286             }
287             else
288             {
289                 if (exitOnClose)
290                 {
291                     System.exit(0);
292                 }
293             }
294         }
295         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException | DSOLException exception)
296         {
297             exception.printStackTrace();
298         }
299     }
300 
301     /**
302      * Add the statistics tabs.
303      * @param simulator OTSSimulatorInterface; the simulator on which sampling can be scheduled
304      */
305     protected final void addStatisticsTabs(final OTSSimulatorInterface simulator)
306     {
307         GraphPath<KpiLaneDirection> path01;
308         GraphPath<KpiLaneDirection> path0;
309         GraphPath<KpiLaneDirection> path1;
310         try
311         {
312             List<String> names = new ArrayList<>();
313             names.add("Left lane");
314             names.add("Right lane");
315             List<LaneDirection> start = new ArrayList<>();
316             start.add(new LaneDirection(getModel().getPath(0).get(0), GTUDirectionality.DIR_PLUS));
317             start.add(new LaneDirection(getModel().getPath(1).get(0), GTUDirectionality.DIR_PLUS));
318             path01 = GraphLaneUtil.createPath(names, start);
319             path0 = GraphLaneUtil.createPath(names.get(0), start.get(0));
320             path1 = GraphLaneUtil.createPath(names.get(1), start.get(1));
321         }
322         catch (NetworkException exception)
323         {
324             throw new RuntimeException("Could not create a path as a lane has no set speed limit.", exception);
325         }
326         RoadSampler sampler = new RoadSampler(getModel().getNetwork());
327         GraphPath.initRecording(sampler, path01);
328         GraphPath.initRecording(sampler, path0);
329         GraphPath.initRecording(sampler, path1);
330         ContourDataSource<?> dataPool0 = new ContourDataSource<>(sampler.getSamplerData(), path0);
331         ContourDataSource<?> dataPool1 = new ContourDataSource<>(sampler.getSamplerData(), path1);
332         Duration updateInterval = Duration.instantiateSI(10.0);
333 
334         SwingPlot plot = null;
335         GraphPath<KpiLaneDirection> path = null;
336         ContourDataSource<?> dataPool = null;
337 
338         TablePanel trajectoryChart = new TablePanel(2, 2);
339         plot = new SwingTrajectoryPlot(
340                 new TrajectoryPlot("Trajectory all lanes", updateInterval, simulator, sampler.getSamplerData(), path01));
341         trajectoryChart.setCell(plot.getContentPane(), 0, 0);
342 
343         List<KpiLaneDirection> lanes = new ArrayList<>();
344         List<Length> positions = new ArrayList<>();
345         lanes.add(path01.get(0).getSource(0));
346         lanes.add(path1.get(0).getSource(0));
347         positions.add(Length.ZERO);
348         positions.add(Length.ZERO);
349         List<String> names = new ArrayList<>();
350         names.add("Left lane");
351         names.add("Right lane");
352         DirectedLinkPosition linkPosition =
353                 new DirectedLinkPosition(getModel().getPath(0).get(0).getParentLink(), 0.0, GTUDirectionality.DIR_PLUS);
354         GraphCrossSection<KpiLaneDirection> crossSection;
355         try
356         {
357             crossSection = GraphLaneUtil.createCrossSection(names, linkPosition);
358         }
359         catch (NetworkException exception)
360         {
361             throw new RuntimeException(exception);
362         }
363 
364         plot = new SwingFundamentalDiagram(new FundamentalDiagram("Fundamental diagram Density-Flow", Quantity.DENSITY,
365                 Quantity.FLOW, simulator,
366                 FundamentalDiagram.sourceFromSampler(sampler, crossSection, true, Duration.instantiateSI(60.0), false), null));
367         trajectoryChart.setCell(plot.getContentPane(), 1, 0);
368 
369         plot = new SwingFundamentalDiagram(new FundamentalDiagram("Fundamental diagram Flow-Speed", Quantity.FLOW,
370                 Quantity.SPEED, simulator,
371                 FundamentalDiagram.sourceFromSampler(sampler, crossSection, false, Duration.instantiateSI(60.0), false), null));
372         trajectoryChart.setCell(plot.getContentPane(), 1, 1);
373 
374         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "Trajectories",
375                 trajectoryChart);
376 
377         for (int lane : new int[] { 0, 1 })
378         {
379             TablePanel charts = new TablePanel(3, 2);
380             path = lane == 0 ? path0 : path1;
381             dataPool = lane == 0 ? dataPool0 : dataPool1;
382 
383             plot = new SwingTrajectoryPlot(
384                     new TrajectoryPlot("Trajectory lane " + lane, updateInterval, simulator, sampler.getSamplerData(), path));
385             charts.setCell(plot.getContentPane(), 0, 0);
386 
387             plot = new SwingContourPlot(new ContourPlotDensity("Density lane " + lane, simulator, dataPool));
388             charts.setCell(plot.getContentPane(), 1, 0);
389 
390             plot = new SwingContourPlot(new ContourPlotSpeed("Speed lane " + lane, simulator, dataPool));
391             charts.setCell(plot.getContentPane(), 1, 1);
392 
393             plot = new SwingContourPlot(new ContourPlotFlow("Flow lane " + lane, simulator, dataPool));
394             charts.setCell(plot.getContentPane(), 2, 0);
395 
396             plot = new SwingContourPlot(new ContourPlotAcceleration("Accceleration lane " + lane, simulator, dataPool));
397             charts.setCell(plot.getContentPane(), 2, 1);
398 
399             getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "stats lane " + lane,
400                     charts);
401         }
402     }
403 
404 }