View Javadoc
1   package org.opentrafficsim.demo.carFollowing;
2   
3   import java.awt.geom.Rectangle2D;
4   import java.io.IOException;
5   import java.net.URL;
6   import java.rmi.RemoteException;
7   import java.util.HashMap;
8   import java.util.HashSet;
9   import java.util.LinkedHashSet;
10  import java.util.List;
11  import java.util.Map;
12  import java.util.Set;
13  
14  import javax.naming.NamingException;
15  import javax.swing.JComponent;
16  import javax.swing.JPanel;
17  import javax.swing.JScrollPane;
18  import javax.swing.SwingUtilities;
19  
20  import org.djunits.unit.LengthUnit;
21  import org.djunits.unit.SpeedUnit;
22  import org.djunits.unit.TimeUnit;
23  import org.djunits.unit.UNITS;
24  import org.djunits.value.vdouble.scalar.Duration;
25  import org.djunits.value.vdouble.scalar.Length;
26  import org.djunits.value.vdouble.scalar.Speed;
27  import org.djunits.value.vdouble.scalar.Time;
28  import org.opentrafficsim.base.modelproperties.Property;
29  import org.opentrafficsim.base.modelproperties.PropertyException;
30  import org.opentrafficsim.base.modelproperties.SelectionProperty;
31  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
32  import org.opentrafficsim.core.dsol.OTSModelInterface;
33  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
34  import org.opentrafficsim.core.geometry.OTSGeometryException;
35  import org.opentrafficsim.core.geometry.OTSPoint3D;
36  import org.opentrafficsim.core.gtu.GTUDirectionality;
37  import org.opentrafficsim.core.gtu.GTUException;
38  import org.opentrafficsim.core.gtu.GTUType;
39  import org.opentrafficsim.core.gtu.animation.GTUColorer;
40  import org.opentrafficsim.core.network.LongitudinalDirectionality;
41  import org.opentrafficsim.core.network.NetworkException;
42  import org.opentrafficsim.core.network.OTSNetwork;
43  import org.opentrafficsim.core.network.OTSNode;
44  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
45  import org.opentrafficsim.demo.PropertiesParser;
46  import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
47  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
48  import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
49  import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel;
50  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
51  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
52  import org.opentrafficsim.road.network.factory.LaneFactory;
53  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
54  import org.opentrafficsim.road.network.lane.Lane;
55  import org.opentrafficsim.road.network.lane.LaneType;
56  import org.opentrafficsim.road.network.lane.object.sensor.Sensor;
57  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
58  import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
59  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
60  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
61  import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
62  import org.opentrafficsim.simulationengine.OTSSimulationException;
63  import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
64  
65  import nl.tudelft.simulation.dsol.SimRuntimeException;
66  import nl.tudelft.simulation.dsol.gui.swing.HTMLPanel;
67  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
68  import nl.tudelft.simulation.jstats.distributions.DistTriangular;
69  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
70  import nl.tudelft.simulation.jstats.streams.StreamInterface;
71  
72  /**
73   * Demonstration of a crossing with traffic lights.
74   * <p>
75   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
76   * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
77   * <p>
78   * $LastChangedDate: 2016-10-28 16:34:11 +0200 (Fri, 28 Oct 2016) $, @version $Revision: 2429 $, by $Author: pknoppers $,
79   * initial version 12 nov. 2014 <br>
80   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
81   */
82  public class CrossingTrafficLights extends AbstractWrappableAnimation implements UNITS
83  {
84      /** */
85      private static final long serialVersionUID = 1L;
86  
87      /** The model. */
88      private CrossingTrafficLightstModel model;
89      
90      /** Fixed green time. */
91      protected static final Duration TGREEN = new Duration(39.0, TimeUnit.SI); 
92      
93      /** Fixed yellow time. */
94      protected static final Duration TYELLOW = new Duration(6.0, TimeUnit.SI); 
95      
96      /** Fixed red time. */
97      protected static final Duration TRED = new Duration(45.0, TimeUnit.SI); 
98  
99      /**
100      * Create a CrossingTrafficLights simulation.
101      * @throws PropertyException when a property is not handled
102      */
103     public CrossingTrafficLights() throws PropertyException
104     {
105         this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
106                 "<html>The lane change strategies vary in politeness.<br>"
107                         + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
108                         + "<li>Altruistic (assigns effect on new and current follower the same weight as "
109                         + "the personal gain).</html>",
110                 new String[] { "Egoistic", "Altruistic" }, 0, false, 500));
111         this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
112                 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
113                 new String[] { "IDM", "MOBIL/IDM", "DIRECTED/IDM", "LMRS", "Toledo" }, 0, false, 600));
114     }
115 
116     /** {@inheritDoc} */
117     @Override
118     public final void stopTimersThreads()
119     {
120         super.stopTimersThreads();
121         this.model = null;
122     }
123 
124     /**
125      * Main program.
126      * @param args String[]; the command line arguments (not used)
127      * @throws SimRuntimeException when simulation cannot be created with given parameters
128      */
129     public static void main(final String[] args) throws SimRuntimeException
130     {
131         SwingUtilities.invokeLater(new Runnable()
132         {
133             @SuppressWarnings("synthetic-access")
134             @Override
135             public void run()
136             {
137                 try
138                 {
139                     CrossingTrafficLights crossingTrafficLights = new CrossingTrafficLights();
140                     List<Property<?>> localProperties = crossingTrafficLights.getProperties();
141                     crossingTrafficLights.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND),
142                             new Duration(3600.0, SECOND), localProperties, null, true);
143 
144                     crossingTrafficLights.panel.getTabbedPane().addTab("info", crossingTrafficLights.makeInfoPane());
145                 }
146                 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
147                 {
148                     exception.printStackTrace();
149                 }
150             }
151         });
152     }
153 
154     /** {@inheritDoc} */
155     @Override
156     protected final Rectangle2D.Double makeAnimationRectangle()
157     {
158         return new Rectangle2D.Double(-600, -600, 1200, 1200);
159     }
160 
161     /** {@inheritDoc} */
162     @Override
163     protected final OTSModelInterface makeModel(final GTUColorer colorer)
164     {
165         this.model = new CrossingTrafficLightstModel(this.savedUserModifiedProperties, colorer);
166         return this.model;
167     }
168 
169     /**
170      * @return an info pane to be added to the tabbed pane.
171      */
172     protected final JComponent makeInfoPane()
173     {
174         // Make the info tab
175         String helpSource = "/" + CrossingTrafficLightstModel.class.getPackage().getName().replace('.', '/') + "/IDMPlus.html";
176         URL page = CrossingTrafficLightstModel.class.getResource(helpSource);
177         if (page != null)
178         {
179             try
180             {
181                 HTMLPanel htmlPanel = new HTMLPanel(page);
182                 return new JScrollPane(htmlPanel);
183             }
184             catch (IOException exception)
185             {
186                 exception.printStackTrace();
187             }
188         }
189         return new JPanel();
190     }
191 
192     /** {@inheritDoc} */
193     @Override
194     protected final JPanel makeCharts(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
195     {
196         return null;
197     }
198 
199     /** {@inheritDoc} */
200     @Override
201     public final String shortName()
202     {
203         return "Crossing with Traffic Lights";
204     }
205 
206     /** {@inheritDoc} */
207     @Override
208     public final String description()
209     {
210         return "<html><h1>Simulation of a crossing with traffic lights</h1>"
211                 + "Simulation of four double lane roads with a crossing in the middle.</html>";
212     }
213 
214 }
215 
216 /**
217  * Simulate four double lane roads with a crossing in the middle.
218  * <p>
219  * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
220  * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
221  * </p>
222  * $LastChangedDate: 2016-10-28 16:34:11 +0200 (Fri, 28 Oct 2016) $, @version $Revision: 2429 $, by $Author: pknoppers $,
223  * initial version ug 1, 2014 <br>
224  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
225  */
226 class CrossingTrafficLightstModel implements OTSModelInterface, UNITS
227 {
228     /** */
229     private static final long serialVersionUID = 20140815L;
230 
231     /** The simulator. */
232     private OTSDEVSSimulatorInterface simulator;
233 
234     /** The network. */
235     private final OTSNetwork network = new OTSNetwork("network");
236 
237     /** the random stream for this demo. */
238     private StreamInterface stream = new MersenneTwister(555);
239 
240     /** The headway (inter-vehicle time) distribution. */
241     private ContinuousDistDoubleScalar.Rel<Duration, TimeUnit> headwayDistribution =
242             new ContinuousDistDoubleScalar.Rel<>(new DistTriangular(this.stream, 7, 9, 15), TimeUnit.SECOND);
243 
244     /** The speed distribution. */
245     private ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedDistribution =
246             new ContinuousDistDoubleScalar.Rel<>(new DistTriangular(this.stream, 50, 60, 70), SpeedUnit.KM_PER_HOUR);
247 
248     /** Number of cars created. */
249     private int carsCreated = 0;
250 
251     /** Type of all GTUs. */
252     private GTUType gtuType = new GTUType("Car");
253 
254     /** The car following model, e.g. IDM Plus for cars. */
255     private GTUFollowingModelOld carFollowingModel;
256 
257     /** The lane change model, e.g. Egoistic for cars. */
258     private LaneChangeModel laneChangeModel;
259 
260     /** User settable properties. */
261     private List<Property<?>> properties = null;
262 
263     /** The GTUColorer for the generated vehicles. */
264     private final GTUColorer gtuColorer;
265 
266     /** the tactical planner factory for this model. */
267     private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory;
268 
269     /** The speed limit on all Lanes. */
270     private Speed speedLimit = new Speed(80, KM_PER_HOUR);
271 
272     /**
273      * @param properties the user settable properties
274      * @param gtuColorer the default and initial GTUColorer, e.g. a DefaultSwitchableTUColorer.
275      */
276     CrossingTrafficLightstModel(final List<Property<?>> properties, final GTUColorer gtuColorer)
277     {
278         this.properties = properties;
279         this.gtuColorer = gtuColorer;
280     }
281 
282     /** {@inheritDoc} */
283     @Override
284     public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
285             throws SimRuntimeException, RemoteException
286     {
287         this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
288         try
289         {
290             OTSNode[][] nodes = new OTSNode[4][4];
291             nodes[0][0] = new OTSNode(this.network, "sn1", new OTSPoint3D(10, -500));
292             nodes[0][1] = new OTSNode(this.network, "sn2", new OTSPoint3D(10, -20));
293             nodes[0][2] = new OTSNode(this.network, "sn3", new OTSPoint3D(10, +20));
294             nodes[0][3] = new OTSNode(this.network, "sn4", new OTSPoint3D(10, +5000));
295 
296             nodes[1][0] = new OTSNode(this.network, "we1", new OTSPoint3D(-500, -10));
297             nodes[1][1] = new OTSNode(this.network, "we2", new OTSPoint3D(-20, -10));
298             nodes[1][2] = new OTSNode(this.network, "we3", new OTSPoint3D(+20, -10));
299             nodes[1][3] = new OTSNode(this.network, "we4", new OTSPoint3D(+5000, -10));
300 
301             nodes[2][0] = new OTSNode(this.network, "ns1", new OTSPoint3D(-10, +500));
302             nodes[2][1] = new OTSNode(this.network, "ns2", new OTSPoint3D(-10, +20));
303             nodes[2][2] = new OTSNode(this.network, "ns3", new OTSPoint3D(-10, -20));
304             nodes[2][3] = new OTSNode(this.network, "ns4", new OTSPoint3D(-10, -5000));
305 
306             nodes[3][0] = new OTSNode(this.network, "ew1", new OTSPoint3D(+500, 10));
307             nodes[3][1] = new OTSNode(this.network, "ew2", new OTSPoint3D(+20, 10));
308             nodes[3][2] = new OTSNode(this.network, "ew3", new OTSPoint3D(-20, 10));
309             nodes[3][3] = new OTSNode(this.network, "ew4", new OTSPoint3D(-5000, 10));
310 
311             Set<GTUType> compatibility = new HashSet<>();
312             compatibility.add(this.gtuType);
313             LaneType laneType = new LaneType("CarLane", compatibility);
314 
315             Map<Lane, SimpleTrafficLight> trafficLights = new HashMap<>();
316 
317             for (int i = 0; i < 4; i++)
318             {
319                 for (int j = 0; j < 3; j++)
320                 {
321                     Lane[] lanes = LaneFactory.makeMultiLane(this.network,
322                             "Lane_" + nodes[i][j].getId() + "-" + nodes[i][j + 1].getId(), nodes[i][j], nodes[i][j + 1], null,
323                             2, laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
324                     if (j == 0)
325                     {
326                         for (Lane lane : lanes)
327                         {
328                             this.simulator.scheduleEventRel(this.headwayDistribution.draw(), this, this, "generateCar",
329                                     new Object[] { lane });
330                             SimpleTrafficLight tl = new SimpleTrafficLight(lane.getId() + "_TL", lane,
331                                     new Length(lane.getLength().minus(new Length(10.0, LengthUnit.METER))), this.simulator);
332                             lane.addLaneBasedObject(tl);
333                             trafficLights.put(lane, tl);
334                             if (i == 0 || i == 2)
335                             {
336                                 this.simulator.scheduleEventRel(Duration.ZERO, this, this, "changeTL",
337                                         new Object[] { tl });
338                             }
339                             else
340                             {
341                                 this.simulator.scheduleEventRel(CrossingTrafficLights.TRED, this, this, "changeTL",
342                                         new Object[] { tl });
343                             }
344                         }
345                     }
346                     if (j == 2)
347                     {
348                         for (Lane lane : lanes)
349                         {
350                             Sensor sensor = new SinkSensor(lane, new Length(500.0, METER), this.simulator);
351                         }
352                     }
353                 }
354             }
355 
356             this.carFollowingModel = PropertiesParser.parseGTUFollowingModelOld(this.properties, "Car");
357             this.laneChangeModel = PropertiesParser.parseLaneChangeModel(this.properties);
358             this.strategicalPlannerFactory =
359                     PropertiesParser.parseStrategicalPlannerFactory(this.properties, this.carFollowingModel, this.laneChangeModel);
360         }
361         catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | PropertyException
362                 | GTUException exception)
363         {
364             exception.printStackTrace();
365         }
366     }
367 
368     /**
369      * Change the traffic light to a new color.
370      * @param tl the traffic light
371      * @throws SimRuntimeException when scheduling fails
372      */
373     protected final void changeTL(final TrafficLight tl) throws SimRuntimeException
374     {
375         if (tl.getTrafficLightColor().isRed())
376         {
377             tl.setTrafficLightColor(TrafficLightColor.GREEN);
378             this.simulator.scheduleEventRel(CrossingTrafficLights.TGREEN, this, this, "changeTL", new Object[] { tl });
379         }
380         else if (tl.getTrafficLightColor().isGreen())
381         {
382             tl.setTrafficLightColor(TrafficLightColor.YELLOW);
383             this.simulator.scheduleEventRel(CrossingTrafficLights.TYELLOW, this, this, "changeTL", new Object[] { tl });
384         }
385         else if (tl.getTrafficLightColor().isYellow())
386         {
387             tl.setTrafficLightColor(TrafficLightColor.RED);
388             this.simulator.scheduleEventRel(CrossingTrafficLights.TRED, this, this, "changeTL", new Object[] { tl });
389         }
390     }
391 
392     /**
393      * Generate cars at a fixed rate (implemented by re-scheduling this method).
394      * @param lane the lane to generate the car on
395      */
396     protected final void generateCar(final Lane lane)
397     {
398         Length initialPosition = new Length(10, METER);
399         Speed initialSpeed = new Speed(0, KM_PER_HOUR);
400         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
401         try
402         {
403             initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
404             Length vehicleLength = new Length(4, METER);
405             LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength,
406                     new Length(1.8, METER), this.speedDistribution.draw(), this.simulator, this.network);
407             LaneBasedStrategicalPlanner strategicalPlanner = this.strategicalPlannerFactory.create(gtu);
408             gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
409                     this.gtuColorer);
410             this.simulator.scheduleEventRel(this.headwayDistribution.draw(), this, this, "generateCar", new Object[] { lane });
411         }
412         catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException exception)
413         {
414             exception.printStackTrace();
415         }
416     }
417 
418     /** {@inheritDoc} */
419     @Override
420     public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
421     {
422         return this.simulator;
423     }
424 }