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