View Javadoc
1   package org.opentrafficsim.demo.conflictAndControl;
2   
3   import java.awt.BorderLayout;
4   import java.awt.Dimension;
5   import java.net.URL;
6   import java.rmi.RemoteException;
7   import java.util.HashSet;
8   import java.util.Set;
9   
10  import javax.naming.NamingException;
11  import javax.swing.JPanel;
12  import javax.swing.JScrollPane;
13  
14  import org.djunits.unit.LengthUnit;
15  import org.djunits.value.vdouble.scalar.Duration;
16  import org.djunits.value.vdouble.scalar.Length;
17  import org.djunits.value.vdouble.scalar.Time;
18  import org.djutils.io.URLResource;
19  import org.opentrafficsim.core.animation.gtu.colorer.DefaultSwitchableGTUColorer;
20  import org.opentrafficsim.core.compatibility.Compatible;
21  import org.opentrafficsim.core.dsol.AbstractOTSModel;
22  import org.opentrafficsim.core.dsol.OTSAnimator;
23  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
24  import org.opentrafficsim.core.gtu.GTUType;
25  import org.opentrafficsim.core.gtu.RelativePosition;
26  import org.opentrafficsim.core.network.NetworkException;
27  import org.opentrafficsim.demo.conflictAndControl.DemoTrafcodAndTurbo.TrafCODModel;
28  import org.opentrafficsim.draw.core.OTSDrawingException;
29  import org.opentrafficsim.draw.road.TrafficLightAnimation;
30  import org.opentrafficsim.road.network.OTSRoadNetwork;
31  import org.opentrafficsim.road.network.factory.xml.old.XmlNetworkLaneParserOld;
32  import org.opentrafficsim.road.network.lane.CrossSectionLink;
33  import org.opentrafficsim.road.network.lane.CrossSectionLink.Priority;
34  import org.opentrafficsim.road.network.lane.Lane;
35  import org.opentrafficsim.road.network.lane.conflict.ConflictBuilder;
36  import org.opentrafficsim.road.network.lane.object.sensor.TrafficLightSensor;
37  import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
38  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
39  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
40  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
41  import org.opentrafficsim.trafficcontrol.TrafficController;
42  import org.opentrafficsim.trafficcontrol.trafcod.TrafCOD;
43  
44  import nl.tudelft.simulation.dsol.SimRuntimeException;
45  import nl.tudelft.simulation.event.EventInterface;
46  import nl.tudelft.simulation.event.EventListenerInterface;
47  import nl.tudelft.simulation.event.EventType;
48  
49  /**
50   * <p>
51   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
52   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
53   * <p>
54   * @version $Revision: 5158 $, $LastChangedDate: 2019-03-17 22:16:44 +0100 (Sun, 17 Mar 2019) $, by $Author: averbraeck $,
55   *          initial version Dec 06, 2016 <br>
56   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
57   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
58   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
59   */
60  public class DemoTrafcodAndTurbo extends OTSSimulationApplication<TrafCODModel>
61  {
62      /** */
63      private static final long serialVersionUID = 20161118L;
64  
65      /**
66       * Create a TrafcodAndTurbo demo.
67       * @param title String; the title of the Frame
68       * @param panel OTSAnimationPanel; the tabbed panel to display
69       * @param model TrafCODModel; the model
70       * @throws OTSDrawingException on animation error
71       */
72      public DemoTrafcodAndTurbo(final String title, final OTSAnimationPanel panel, final TrafCODModel model)
73              throws OTSDrawingException
74      {
75          super(model, panel);
76      }
77  
78      /**
79       * Main program.
80       * @param args String[]; the command line arguments (not used)
81       */
82      public static void main(final String[] args)
83      {
84          demo(true);
85      }
86  
87      /**
88       * Start the demo.
89       * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false
90       */
91      public static void demo(final boolean exitOnClose)
92      {
93          try
94          {
95              OTSAnimator simulator = new OTSAnimator();
96              final TrafCODModel junctionModel = new TrafCODModel(simulator);
97              simulator.initialize(Time.ZERO, Duration.ZERO, Duration.createSI(3600.0), junctionModel);
98              OTSAnimationPanel animationPanel =
99                      new OTSAnimationPanel(junctionModel.getNetwork().getExtent(), new Dimension(800, 600), simulator,
100                             junctionModel, new DefaultSwitchableGTUColorer(), junctionModel.getNetwork());
101             DemoTrafcodAndTurbo app = new DemoTrafcodAndTurbo("TrafCOD Turbo demo", animationPanel, junctionModel);
102             app.setExitOnClose(exitOnClose);
103         }
104         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
105         {
106             exception.printStackTrace();
107         }
108     }
109 
110     /**
111      * Add tab with trafCOD status.
112      */
113     protected void addTabs()
114     {
115         JScrollPane scrollPane = new JScrollPane(getModel().getControllerDisplayPanel());
116         JPanel wrapper = new JPanel(new BorderLayout());
117         wrapper.add(scrollPane);
118         getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount() - 1,
119                 getModel().getTrafCOD().getId(), wrapper);
120     }
121 
122     /**
123      * The simulation model.
124      */
125     static class TrafCODModel extends AbstractOTSModel implements EventListenerInterface
126     {
127         /** */
128         private static final long serialVersionUID = 20161020L;
129 
130         /** The network. */
131         private OTSRoadNetwork network;
132 
133         /** The TrafCOD controller. */
134         private TrafCOD trafCOD;
135 
136         /** TrafCOD controller display. */
137         private JPanel controllerDisplayPanel = new JPanel(new BorderLayout());
138 
139         /**
140          * @param simulator OTSSimulatorInterface; the simulator for this model
141          */
142         TrafCODModel(final OTSSimulatorInterface simulator)
143         {
144             super(simulator);
145         }
146 
147         /** {@inheritDoc} */
148         @Override
149         public void constructModel() throws SimRuntimeException
150         {
151             try
152             {
153                 URL url = URLResource.getResource("/conflictAndControl/TurboRoundaboutAndSignal.xml");
154                 XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(this.simulator);
155                 this.network = nlp.build(url, true);
156                 // add conflicts
157                 ((CrossSectionLink) this.network.getLink("EBNA")).setPriority(Priority.PRIORITY);
158                 ((CrossSectionLink) this.network.getLink("NBWA")).setPriority(Priority.PRIORITY);
159                 ((CrossSectionLink) this.network.getLink("WBSA")).setPriority(Priority.PRIORITY);
160                 ((CrossSectionLink) this.network.getLink("SBEA")).setPriority(Priority.PRIORITY);
161                 ConflictBuilder.buildConflicts(this.network, this.network.getGtuType(GTUType.DEFAULTS.VEHICLE), this.simulator,
162                         new ConflictBuilder.FixedWidthGenerator(new Length(2.0, LengthUnit.SI)));
163 
164                 // CrossSectionLink csLink = ((CrossSectionLink)
165                 // this.network.getLink("WWW"));
166                 // Lane lane = (Lane) csLink.getCrossSectionElement("RIGHT");
167                 // GTUColorer gtuColorer = null;
168                 // setupBlock(lane, (DEVSSimulatorInterface.TimeDoubleUnit) this.simulator,
169                 // gtuColorer );
170 
171                 String[] directions = {"E", "S", "W", "N"};
172                 // Add the traffic lights and the detectors
173                 Set<TrafficLight> trafficLights = new HashSet<>();
174                 Set<TrafficLightSensor> sensors = new HashSet<>();
175                 Length stopLineMargin = new Length(0.1, LengthUnit.METER);
176                 Length headDetectorLength = new Length(1, LengthUnit.METER);
177                 Length headDetectorMargin = stopLineMargin.plus(headDetectorLength).plus(new Length(3, LengthUnit.METER));
178                 Length longDetectorLength = new Length(30, LengthUnit.METER);
179                 Length longDetectorMargin = stopLineMargin.plus(longDetectorLength).plus(new Length(10, LengthUnit.METER));
180                 int stream = 1;
181                 for (String direction : directions)
182                 {
183                     for (int laneNumber = 3; laneNumber >= 1; laneNumber--)
184                     {
185                         Lane lane = (Lane) ((CrossSectionLink) this.network.getLink(direction + "S", direction + "C"))
186                                 .getCrossSectionElement("FORWARD" + laneNumber);
187                         if (lane != null)
188                         {
189                             if (stream != 7)
190                             {
191                                 TrafficLight tl = new SimpleTrafficLight(String.format("TL%02d", stream), lane,
192                                         lane.getLength().minus(stopLineMargin), this.simulator);
193                                 trafficLights.add(tl);
194 
195                                 try
196                                 {
197                                     new TrafficLightAnimation(tl, this.simulator);
198                                 }
199                                 catch (RemoteException | NamingException exception)
200                                 {
201                                     throw new NetworkException(exception);
202                                 }
203 
204                                 sensors.add(new TrafficLightSensor(String.format("D%02d1", stream), lane,
205                                         lane.getLength().minus(headDetectorMargin), lane,
206                                         lane.getLength().minus(headDetectorMargin).plus(headDetectorLength), null,
207                                         RelativePosition.FRONT, RelativePosition.REAR, this.simulator, Compatible.EVERYTHING));
208                                 sensors.add(new TrafficLightSensor(String.format("D%02d2", stream), lane,
209                                         lane.getLength().minus(longDetectorMargin), lane,
210                                         lane.getLength().minus(longDetectorMargin).plus(longDetectorLength), null,
211                                         RelativePosition.FRONT, RelativePosition.REAR, this.simulator, Compatible.EVERYTHING));
212                             }
213                             else
214                             {
215                                 lane = (Lane) ((CrossSectionLink) this.network.getLink("ESS1", "ESS"))
216                                         .getCrossSectionElement("FORWARD");
217                                 TrafficLight tl = new SimpleTrafficLight(String.format("TL%02d", stream), lane,
218                                         lane.getLength().minus(stopLineMargin), this.simulator);
219                                 trafficLights.add(tl);
220 
221                                 try
222                                 {
223                                     new TrafficLightAnimation(tl, this.simulator);
224                                 }
225                                 catch (RemoteException | NamingException exception)
226                                 {
227                                     throw new NetworkException(exception);
228                                 }
229 
230                                 sensors.add(new TrafficLightSensor(String.format("D%02d1", stream), lane,
231                                         lane.getLength().minus(headDetectorMargin), lane,
232                                         lane.getLength().minus(headDetectorMargin).plus(headDetectorLength), null,
233                                         RelativePosition.FRONT, RelativePosition.REAR, this.simulator, Compatible.EVERYTHING));
234                                 sensors.add(new TrafficLightSensor(String.format("D%02d2", stream), lane,
235                                         lane.getLength().minus(longDetectorMargin), lane,
236                                         lane.getLength().minus(longDetectorMargin).plus(longDetectorLength), null,
237                                         RelativePosition.FRONT, RelativePosition.REAR, this.simulator, Compatible.EVERYTHING));
238 
239                             }
240 
241                         }
242                         stream++;
243                     }
244                 }
245                 String controllerName = "Not so simple TrafCOD controller";
246                 this.trafCOD = new TrafCOD(controllerName, URLResource.getResource("/conflictAndControl/Intersection12Dir.tfc"),
247                         this.simulator, this.controllerDisplayPanel);
248                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONTROLLER_EVALUATING);
249                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONTROLLER_WARNING);
250                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_CONFLICT_GROUP_CHANGED);
251                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_STATE_CHANGED);
252                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_VARIABLE_CREATED);
253                 this.trafCOD.addListener(this, TrafficController.TRAFFICCONTROL_TRACED_VARIABLE_UPDATED);
254                 // Subscribe the TrafCOD machine to trace command events that we
255                 // emit
256                 addListener(this.trafCOD, TrafficController.TRAFFICCONTROL_SET_TRACING);
257                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
258                 // Object[] {controllerName, "TGX", 8, true});
259                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
260                 // Object[] {controllerName, "XR1", 11, true});
261                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
262                 // Object[] {controllerName, "TD1", 11, true});
263                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
264                 // Object[] {controllerName, "TGX", 11, true});
265                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
266                 // Object[] {controllerName, "TL", 11, true});
267                 // System.out.println("demo: emitting a SET TRACING event for
268                 // all variables related to stream 11");
269                 // fireEvent(TrafficController.TRAFFICCONTROL_SET_TRACING, new
270                 // Object[] { controllerName, "", 11, true });
271 
272                 // TrafCODDemo2.this.trafCOD.traceVariablesOfStream(TrafficController.NO_STREAM,
273                 // true);
274                 // TrafCODDemo2.this.trafCOD.traceVariablesOfStream(11, true);
275                 // TrafCODDemo2.this.trafCOD.traceVariable("MRV", 11, true);
276             }
277             catch (Exception exception)
278             {
279                 exception.printStackTrace();
280             }
281         }
282 
283         /** {@inheritDoc} */
284         @Override
285         public final OTSRoadNetwork getNetwork()
286         {
287             return this.network;
288         }
289 
290         /**
291          * @return trafCOD
292          */
293         public final TrafCOD getTrafCOD()
294         {
295             return this.trafCOD;
296         }
297 
298         /**
299          * @return controllerDisplayPanel
300          */
301         public final JPanel getControllerDisplayPanel()
302         {
303             return this.controllerDisplayPanel;
304         }
305 
306         /** {@inheritDoc} */
307         @Override
308         public void notify(final EventInterface event) throws RemoteException
309         {
310             EventType type = event.getType();
311             Object[] payload = (Object[]) event.getContent();
312             if (TrafficController.TRAFFICCONTROL_CONTROLLER_EVALUATING.equals(type))
313             {
314                 // System.out.println("Evaluation starts at " +
315                 // getSimulator().getSimulatorTime());
316                 return;
317             }
318             else if (TrafficController.TRAFFICCONTROL_CONFLICT_GROUP_CHANGED.equals(type))
319             {
320                 System.out.println("Conflict group changed from " + ((String) payload[1]) + " to " + ((String) payload[2]));
321             }
322             else if (TrafficController.TRAFFICCONTROL_TRACED_VARIABLE_UPDATED.equals(type))
323             {
324                 System.out.println(String.format("Variable changed %s <- %d   %s", payload[1], payload[4], payload[5]));
325             }
326             else if (TrafficController.TRAFFICCONTROL_CONTROLLER_WARNING.equals(type))
327             {
328                 System.out.println("Warning " + payload[1]);
329             }
330             else
331             {
332                 System.out.print("TrafCODDemo received event of type " + event.getType() + ", payload [");
333                 String separator = "";
334                 for (Object o : payload)
335                 {
336                     System.out.print(separator + o);
337                     separator = ",";
338                 }
339                 System.out.println("]");
340             }
341         }
342     }
343 }