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