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.core.perception.HistoryManagerDevs;
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://github.com/peter-knoppers">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 the title of the Frame
69       * @param panel the tabbed panel to display
70       * @param model the model
71       */
72      public CircularRoadSwing(final String title, final OtsAnimationPanel panel, final CircularRoadModel model)
73      {
74          super(model, panel, DefaultsFactory.GTU_TYPE_MARKERS.toMap());
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      @Override
83      protected void addTabs()
84      {
85          addStatisticsTabs(getModel().getSimulator());
86      }
87  
88      /**
89       * Main program.
90       * @param args the command line arguments (not used)
91       */
92      public static void main(final String[] args)
93      {
94          // simulatorDemo();
95          demo(true);
96      }
97  
98      /**
99       * Run the simulation without animation.
100      */
101     public static void simulatorDemo()
102     {
103         try
104         {
105             OtsSimulator simulator = new OtsSimulator("CircularRoadSwing");
106             final CircularRoadModel otsModel = new CircularRoadModel(simulator);
107             System.out.println(otsModel.getInputParameterMap());
108             TabbedParameterDialog.process(otsModel.getInputParameterMap());
109             simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel,
110                     HistoryManagerDevs.noHistory(simulator));
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 some component that could be the start button, or a container that contains the start button
159      * @return 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 some component that (hopefully) is, or contains the start button
189      * @return 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 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                         HistoryManagerDevs.noHistory(simulator));
263                 OtsAnimationPanel animationPanel = new OtsAnimationPanel(otsModel.getNetwork().getExtent(),
264                         new Dimension(800, 600), simulator, otsModel, DEFAULT_GTU_COLORERS, otsModel.getNetwork());
265                 CircularRoadSwing app = new CircularRoadSwing("Circular Road", animationPanel, otsModel);
266                 app.setExitOnClose(exitOnClose);
267                 animationPanel.enableSimulationControlButtons();
268                 // simulator.setSpeedFactor(Double.MAX_VALUE, true);
269                 // simulator.setSpeedFactor(1000.0, true);
270                 // for (Component component : app.getComponents())
271                 // {
272                 // if (clickRunPause(component))
273                 // {
274                 // break;
275                 // }
276                 // }
277             }
278             else
279             {
280                 if (exitOnClose)
281                 {
282                     System.exit(0);
283                 }
284             }
285         }
286         catch (SimRuntimeException | NamingException | RemoteException | DsolException exception)
287         {
288             exception.printStackTrace();
289         }
290     }
291 
292     /**
293      * Add the statistics tabs.
294      * @param simulator the simulator on which sampling can be scheduled
295      */
296     protected final void addStatisticsTabs(final OtsSimulatorInterface simulator)
297     {
298         GraphPath<LaneDataRoad> path01;
299         GraphPath<LaneDataRoad> path0;
300         GraphPath<LaneDataRoad> path1;
301         try
302         {
303             List<String> names = new ArrayList<>();
304             names.add("Left lane");
305             names.add("Right lane");
306             List<Lane> start = new ArrayList<>();
307             start.add(getModel().getPath(0).get(0));
308             start.add(getModel().getPath(1).get(0));
309             path01 = GraphLaneUtil.createPath(names, start);
310             path0 = GraphLaneUtil.createPath(names.get(0), start.get(0));
311             path1 = GraphLaneUtil.createPath(names.get(1), start.get(1));
312         }
313         catch (NetworkException exception)
314         {
315             throw new RuntimeException("Could not create a path as a lane has no set speed limit.", exception);
316         }
317         RoadSampler sampler = new RoadSampler(getModel().getNetwork());
318         GraphPath.initRecording(sampler, path01);
319         GraphPath.initRecording(sampler, path0);
320         GraphPath.initRecording(sampler, path1);
321         ContourDataSource dataPool0 = new ContourDataSource(sampler.getSamplerData(), path0);
322         ContourDataSource dataPool1 = new ContourDataSource(sampler.getSamplerData(), path1);
323         Duration updateInterval = Duration.instantiateSI(10.0);
324 
325         SwingPlot plot = null;
326         GraphPath<LaneDataRoad> path = null;
327         ContourDataSource dataPool = null;
328 
329         TablePanel trajectoryChart = new TablePanel(2, 2);
330         PlotScheduler scheduler = new OtsPlotScheduler(simulator);
331         plot = new SwingTrajectoryPlot(
332                 new TrajectoryPlot("Trajectory all lanes", updateInterval, scheduler, sampler.getSamplerData(), path01));
333         trajectoryChart.setCell(plot.getContentPane(), 0, 0);
334 
335         List<LaneData> lanes = new ArrayList<>();
336         List<Length> positions = new ArrayList<>();
337         lanes.add(path01.get(0).getSource(0));
338         lanes.add(path1.get(0).getSource(0));
339         positions.add(Length.ZERO);
340         positions.add(Length.ZERO);
341         List<String> names = new ArrayList<>();
342         names.add("Left lane");
343         names.add("Right lane");
344         LinkPosition linkPosition = new LinkPosition(getModel().getPath(0).get(0).getLink(), 0.0);
345         GraphCrossSection<LaneDataRoad> crossSection;
346         try
347         {
348             crossSection = GraphLaneUtil.createCrossSection(names, linkPosition);
349         }
350         catch (NetworkException exception)
351         {
352             throw new RuntimeException(exception);
353         }
354 
355         plot = new SwingFundamentalDiagram(new FundamentalDiagram("Fundamental diagram Density-Flow", Quantity.DENSITY,
356                 Quantity.FLOW, scheduler,
357                 FundamentalDiagram.sourceFromSampler(sampler, crossSection, true, Duration.instantiateSI(60.0), false), null));
358         trajectoryChart.setCell(plot.getContentPane(), 1, 0);
359 
360         plot = new SwingFundamentalDiagram(new FundamentalDiagram("Fundamental diagram Flow-Speed", Quantity.FLOW,
361                 Quantity.SPEED, scheduler,
362                 FundamentalDiagram.sourceFromSampler(sampler, crossSection, false, Duration.instantiateSI(60.0), false), null));
363         trajectoryChart.setCell(plot.getContentPane(), 1, 1);
364 
365         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "Trajectories",
366                 trajectoryChart);
367 
368         for (int lane : new int[] {0, 1})
369         {
370             TablePanel charts = new TablePanel(3, 2);
371             path = lane == 0 ? path0 : path1;
372             dataPool = lane == 0 ? dataPool0 : dataPool1;
373 
374             plot = new SwingTrajectoryPlot(
375                     new TrajectoryPlot("Trajectory lane " + lane, updateInterval, scheduler, sampler.getSamplerData(), path));
376             charts.setCell(plot.getContentPane(), 0, 0);
377 
378             plot = new SwingContourPlot(new ContourPlotDensity("Density lane " + lane, scheduler, dataPool));
379             charts.setCell(plot.getContentPane(), 1, 0);
380 
381             plot = new SwingContourPlot(new ContourPlotSpeed("Speed lane " + lane, scheduler, dataPool));
382             charts.setCell(plot.getContentPane(), 1, 1);
383 
384             plot = new SwingContourPlot(new ContourPlotFlow("Flow lane " + lane, scheduler, dataPool));
385             charts.setCell(plot.getContentPane(), 2, 0);
386 
387             plot = new SwingContourPlot(new ContourPlotAcceleration("Accceleration lane " + lane, scheduler, dataPool));
388             charts.setCell(plot.getContentPane(), 2, 1);
389 
390             getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "stats lane " + lane,
391                     charts);
392         }
393     }
394 
395 }