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