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