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