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