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