View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.io.Serializable;
4   import java.rmi.RemoteException;
5   import java.util.Arrays;
6   import java.util.LinkedHashMap;
7   import java.util.LinkedHashSet;
8   import java.util.Map;
9   import java.util.Set;
10  
11  import javax.naming.NamingException;
12  
13  import org.djunits.unit.DirectionUnit;
14  import org.djunits.unit.DurationUnit;
15  import org.djunits.unit.LengthUnit;
16  import org.djunits.unit.SpeedUnit;
17  import org.djunits.unit.util.UNITS;
18  import org.djunits.value.vdouble.scalar.Direction;
19  import org.djunits.value.vdouble.scalar.Duration;
20  import org.djunits.value.vdouble.scalar.Length;
21  import org.djunits.value.vdouble.scalar.Speed;
22  import org.djunits.value.vdouble.scalar.base.DoubleScalar;
23  import org.opentrafficsim.base.parameters.ParameterException;
24  import org.opentrafficsim.core.compatibility.Compatible;
25  import org.opentrafficsim.core.distributions.Distribution;
26  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
27  import org.opentrafficsim.core.distributions.Generator;
28  import org.opentrafficsim.core.distributions.ProbabilityException;
29  import org.opentrafficsim.core.dsol.AbstractOTSModel;
30  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
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.idgenerator.IdGenerator;
37  import org.opentrafficsim.core.network.NetworkException;
38  import org.opentrafficsim.core.network.Node;
39  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
40  import org.opentrafficsim.core.network.route.Route;
41  import org.opentrafficsim.core.parameters.ParameterFactory;
42  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
43  import org.opentrafficsim.draw.road.TrafficLightAnimation;
44  import org.opentrafficsim.road.gtu.generator.CFRoomChecker;
45  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
46  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
47  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
48  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
49  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
50  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
51  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
52  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
53  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
54  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
55  import org.opentrafficsim.road.network.OTSRoadNetwork;
56  import org.opentrafficsim.road.network.factory.LaneFactory;
57  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
58  import org.opentrafficsim.road.network.lane.Lane;
59  import org.opentrafficsim.road.network.lane.LaneType;
60  import org.opentrafficsim.road.network.lane.OTSRoadNode;
61  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
62  import org.opentrafficsim.road.network.lane.object.trafficlight.SimpleTrafficLight;
63  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
64  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
65  
66  import nl.tudelft.simulation.dsol.SimRuntimeException;
67  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
68  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
69  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
70  import nl.tudelft.simulation.jstats.distributions.DistContinuous;
71  import nl.tudelft.simulation.jstats.distributions.DistErlang;
72  import nl.tudelft.simulation.jstats.distributions.DistUniform;
73  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
74  import nl.tudelft.simulation.jstats.streams.StreamInterface;
75  
76  /**
77   * Simulate four double lane roads with a crossing in the middle.
78   * <p>
79   * Copyright (c) 2013-2020 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 ug 1, 2014 <br>
84   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
85   */
86  public class CrossingTrafficLightsModel extends AbstractOTSModel implements UNITS
87  {
88      /** */
89      private static final long serialVersionUID = 20140815L;
90  
91      /** The network. */
92      private final OTSRoadNetwork network = new OTSRoadNetwork("network", true);
93  
94      /** the random stream for this demo. */
95      private StreamInterface stream = new MersenneTwister(555);
96  
97      /** Id generator (used by all generators). */
98      private IdGenerator idGenerator = new IdGenerator("");
99  
100     /** The probability distribution for the variable part of the headway. */
101     @SuppressWarnings("checkstyle:visibilitymodifier")
102     protected DistContinuous headwayGenerator;
103 
104     /** The probability that the next generated GTU is a passenger car. */
105     private double carProbability;
106 
107     /** the strategical planner factory for cars. */
108     private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactoryCar;
109 
110     /** the strategical planner factory for trucks. */
111     private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactoryTruck;
112 
113     /** The speed limit on all Lanes. */
114     private Speed speedLimit = new Speed(80, KM_PER_HOUR);
115 
116     /** Fixed green time. */
117     private static final Duration TGREEN = new Duration(39.0, DurationUnit.SI);
118 
119     /** Fixed yellow time. */
120     private static final Duration TYELLOW = new Duration(6.0, DurationUnit.SI);
121 
122     /** Fixed red time. */
123     private static final Duration TRED = new Duration(45.0, DurationUnit.SI);
124 
125     /**
126      * @param simulator OTSSimulatorInterface; the simulator for this model
127      */
128     public CrossingTrafficLightsModel(final OTSSimulatorInterface simulator)
129     {
130         super(simulator);
131         createInputParameters();
132     }
133 
134     /**
135      * Create input parameters for the networks demo.
136      */
137     private void createInputParameters()
138     {
139         try
140         {
141             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
142             InputParameterMap genericMap = (InputParameterMap) this.inputParameterMap.get("generic");
143             genericMap.add(new InputParameterDouble("flow", "Flow per input lane", "Traffic flow per input lane", 250d, 0d,
144                     400d, true, true, "%.0f veh/h", 1.5));
145         }
146         catch (InputParameterException e)
147         {
148             e.printStackTrace();
149         }
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     public final void constructModel() throws SimRuntimeException
155     {
156         try
157         {
158             OTSRoadNode[][] nodes = new OTSRoadNode[4][4];
159             nodes[0][0] = new OTSRoadNode(this.network, "sn1", new OTSPoint3D(10, -500),
160                     new Direction(90, DirectionUnit.EAST_DEGREE));
161             nodes[0][1] =
162                     new OTSRoadNode(this.network, "sn2", new OTSPoint3D(10, -20), new Direction(90, DirectionUnit.EAST_DEGREE));
163             nodes[0][2] =
164                     new OTSRoadNode(this.network, "sn3", new OTSPoint3D(10, +20), new Direction(90, DirectionUnit.EAST_DEGREE));
165             nodes[0][3] = new OTSRoadNode(this.network, "sn4", new OTSPoint3D(10, +600),
166                     new Direction(90, DirectionUnit.EAST_DEGREE));
167 
168             nodes[1][0] = new OTSRoadNode(this.network, "we1", new OTSPoint3D(-500, -10), Direction.ZERO);
169             nodes[1][1] = new OTSRoadNode(this.network, "we2", new OTSPoint3D(-20, -10), Direction.ZERO);
170             nodes[1][2] = new OTSRoadNode(this.network, "we3", new OTSPoint3D(+20, -10), Direction.ZERO);
171             nodes[1][3] = new OTSRoadNode(this.network, "we4", new OTSPoint3D(+600, -10), Direction.ZERO);
172 
173             nodes[2][0] = new OTSRoadNode(this.network, "ns1", new OTSPoint3D(-10, +500),
174                     new Direction(270, DirectionUnit.EAST_DEGREE));
175             nodes[2][1] = new OTSRoadNode(this.network, "ns2", new OTSPoint3D(-10, +20),
176                     new Direction(270, DirectionUnit.EAST_DEGREE));
177             nodes[2][2] = new OTSRoadNode(this.network, "ns3", new OTSPoint3D(-10, -20),
178                     new Direction(270, DirectionUnit.EAST_DEGREE));
179             nodes[2][3] = new OTSRoadNode(this.network, "ns4", new OTSPoint3D(-10, -600),
180                     new Direction(270, DirectionUnit.EAST_DEGREE));
181 
182             nodes[3][0] = new OTSRoadNode(this.network, "ew1", new OTSPoint3D(+500, 10),
183                     new Direction(180, DirectionUnit.EAST_DEGREE));
184             nodes[3][1] = new OTSRoadNode(this.network, "ew2", new OTSPoint3D(+20, 10),
185                     new Direction(180, DirectionUnit.EAST_DEGREE));
186             nodes[3][2] = new OTSRoadNode(this.network, "ew3", new OTSPoint3D(-20, 10),
187                     new Direction(180, DirectionUnit.EAST_DEGREE));
188             nodes[3][3] = new OTSRoadNode(this.network, "ew4", new OTSPoint3D(-600, 10),
189                     new Direction(180, DirectionUnit.EAST_DEGREE));
190 
191             LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
192 
193             Map<Lane, SimpleTrafficLight> trafficLights = new LinkedHashMap<>();
194 
195             this.carProbability = (double) getInputParameter("generic.carProbability");
196             ParameterFactory params = new InputParameterHelper(getInputParameterMap());
197             this.strategicalPlannerFactoryCar = new LaneBasedStrategicalRoutePlannerFactory(
198                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()), params);
199             this.strategicalPlannerFactoryTruck = new LaneBasedStrategicalRoutePlannerFactory(
200                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()), params);
201             this.idGenerator = new IdGenerator("");
202             double contP = (double) getInputParameter("generic.flow");
203             Duration averageHeadway = new Duration(3600.0 / contP, SECOND);
204             Duration minimumHeadway = new Duration(3, SECOND);
205             this.headwayGenerator =
206                     new DistErlang(new MersenneTwister(1234), 4, DoubleScalar.minus(averageHeadway, minimumHeadway).getSI());
207 
208             for (int i = 0; i < 4; i++)
209             {
210                 for (int j = 0; j < 3; j++)
211                 {
212                     Lane[] lanes = LaneFactory.makeMultiLane(this.network,
213                             "Lane_" + nodes[i][j].getId() + "-" + nodes[i][j + 1].getId(), nodes[i][j], nodes[i][j + 1], null,
214                             2, laneType, this.speedLimit, this.simulator);
215                     if (j == 0)
216                     {
217                         for (Lane lane : lanes)
218                         {
219                             // make a generator for the lane
220                             Generator<Route> routeGenerator = new FixedRouteGenerator(new Route("main",
221                                     Arrays.asList(new Node[] {nodes[i][0], nodes[i][1], nodes[i][2], nodes[i][3]})));
222                             makeGenerator(lane, routeGenerator);
223 
224                             // add the traffic light
225                             SimpleTrafficLight tl = new SimpleTrafficLight(lane.getId() + "_TL", lane,
226                                     new Length(lane.getLength().minus(new Length(10.0, LengthUnit.METER))), this.simulator);
227                             trafficLights.put(lane, tl);
228 
229                             try
230                             {
231                                 new TrafficLightAnimation(tl, this.simulator);
232                             }
233                             catch (RemoteException | NamingException exception)
234                             {
235                                 throw new NetworkException(exception);
236                             }
237 
238                             if (i == 0 || i == 2)
239                             {
240                                 this.simulator.scheduleEventRel(Duration.ZERO, this, this, "changeTL", new Object[] {tl});
241                             }
242                             else
243                             {
244                                 this.simulator.scheduleEventRel(TRED, this, this, "changeTL", new Object[] {tl});
245                             }
246                         }
247                     }
248                     if (j == 2)
249                     {
250                         for (Lane lane : lanes)
251                         {
252                             new SinkSensor(lane, new Length(500.0, METER), Compatible.EVERYTHING, this.simulator);
253                         }
254                     }
255                 }
256             }
257         }
258         catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | GTUException
259                 | InputParameterException | ProbabilityException | ParameterException exception)
260         {
261             exception.printStackTrace();
262         }
263     }
264 
265     /**
266      * Build a generator.
267      * @param lane Lane; the lane on which the generated GTUs are placed
268      * @param routeGenerator the fixed route for this lane
269      * @return LaneBasedGTUGenerator
270      * @throws GTUException when lane position out of bounds
271      * @throws SimRuntimeException when generation scheduling fails
272      * @throws ProbabilityException when probability distribution is wrong
273      * @throws ParameterException when a parameter is missing for the perception of the GTU
274      * @throws InputParameterException when a parameter is missing for the perception of the GTU
275      */
276     private LaneBasedGTUGenerator makeGenerator(final Lane lane, final Generator<Route> routeGenerator)
277             throws GTUException, SimRuntimeException, ProbabilityException, ParameterException, InputParameterException
278     {
279         Distribution<LaneBasedTemplateGTUType> distribution = new Distribution<>(this.stream);
280         Length initialPosition = new Length(16, METER);
281         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
282         initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
283 
284         LaneBasedTemplateGTUType template = makeTemplate(this.stream, lane,
285                 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 3, 6), METER),
286                 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 1.6, 2.0), METER),
287                 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(this.stream, 140, 180), KM_PER_HOUR),
288                 initialPositions, this.strategicalPlannerFactoryCar, routeGenerator);
289         // System.out.println("Constructed template " + template);
290         distribution.add(new FrequencyAndObject<>(this.carProbability, template));
291         template = makeTemplate(this.stream, lane,
292                 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 8, 14), METER),
293                 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 2.0, 2.5), METER),
294                 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(this.stream, 100, 140), KM_PER_HOUR),
295                 initialPositions, this.strategicalPlannerFactoryTruck, routeGenerator);
296         // System.out.println("Constructed template " + template);
297         distribution.add(new FrequencyAndObject<>(1.0 - this.carProbability, template));
298         LaneBasedTemplateGTUTypeDistribution templateDistribution = new LaneBasedTemplateGTUTypeDistribution(distribution);
299         LaneBasedGTUGenerator.RoomChecker roomChecker = new CFRoomChecker();
300         return new LaneBasedGTUGenerator(lane.getId(), new Generator<Duration>()
301         {
302             @Override
303             public Duration draw()
304             {
305                 return new Duration(CrossingTrafficLightsModel.this.headwayGenerator.draw(), DurationUnit.SI);
306             }
307         }, templateDistribution, GeneratorPositions.create(initialPositions, this.stream), this.network, this.simulator,
308                 roomChecker, this.idGenerator);
309     }
310 
311     /**
312      * @param randStream StreamInterface; the random stream to use
313      * @param lane Lane; reference lane to generate GTUs on
314      * @param lengthDistribution ContinuousDistDoubleScalar.Rel&lt;Length,LengthUnit&gt;; distribution of the GTU length
315      * @param widthDistribution ContinuousDistDoubleScalar.Rel&lt;Length,LengthUnit&gt;; distribution of the GTU width
316      * @param maximumSpeedDistribution ContinuousDistDoubleScalar.Rel&lt;Speed,SpeedUnit&gt;; distribution of the GTU's maximum
317      *            speed
318      * @param initialPositions Set&lt;DirectedLanePosition&gt;; initial position(s) of the GTU on the Lane(s)
319      * @param strategicalPlannerFactory LaneBasedStrategicalPlannerFactory&lt;LaneBasedStrategicalPlanner&gt;; factory to
320      *            generate the strategical planner for the GTU
321      * @param routeGenerator the route generator
322      * @return template for a GTU
323      * @throws GTUException when characteristics cannot be initialized
324      */
325     @SuppressWarnings("checkstyle:parameternumber")
326     LaneBasedTemplateGTUType makeTemplate(final StreamInterface randStream, final Lane lane,
327             final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> lengthDistribution,
328             final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> widthDistribution,
329             final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> maximumSpeedDistribution,
330             final Set<DirectedLanePosition> initialPositions,
331             final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory,
332             final Generator<Route> routeGenerator) throws GTUException
333     {
334         return new LaneBasedTemplateGTUType(this.network.getGtuType(GTUType.DEFAULTS.CAR), new Generator<Length>()
335         {
336             @Override
337             public Length draw()
338             {
339                 return lengthDistribution.draw();
340             }
341         }, new Generator<Length>()
342         {
343             @Override
344             public Length draw()
345             {
346                 return widthDistribution.draw();
347             }
348         }, new Generator<Speed>()
349         {
350             @Override
351             public Speed draw()
352             {
353                 return maximumSpeedDistribution.draw();
354             }
355         }, strategicalPlannerFactory, routeGenerator);
356 
357     }
358 
359     /**
360      * Change the traffic light to a new color.
361      * @param tl TrafficLight; the traffic light
362      * @throws SimRuntimeException when scheduling fails
363      */
364     protected final void changeTL(final TrafficLight tl) throws SimRuntimeException
365     {
366         if (tl.getTrafficLightColor().isRed())
367         {
368             tl.setTrafficLightColor(TrafficLightColor.GREEN);
369             this.simulator.scheduleEventRel(TGREEN, this, this, "changeTL", new Object[] {tl});
370         }
371         else if (tl.getTrafficLightColor().isGreen())
372         {
373             tl.setTrafficLightColor(TrafficLightColor.YELLOW);
374             this.simulator.scheduleEventRel(TYELLOW, this, this, "changeTL", new Object[] {tl});
375         }
376         else if (tl.getTrafficLightColor().isYellow())
377         {
378             tl.setTrafficLightColor(TrafficLightColor.RED);
379             this.simulator.scheduleEventRel(TRED, this, this, "changeTL", new Object[] {tl});
380         }
381     }
382 
383     /** {@inheritDoc} */
384     @Override
385     public OTSRoadNetwork getNetwork()
386     {
387         return this.network;
388     }
389 
390     /** {@inheritDoc} */
391     @Override
392     public Serializable getSourceId()
393     {
394         return "CrossingTrafficLightsModel";
395     }
396 }