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
77
78
79
80
81
82
83
84
85 public class CrossingTrafficLightsModel extends AbstractOTSModel implements UNITS
86 {
87
88 private static final long serialVersionUID = 20140815L;
89
90
91 private final OTSRoadNetwork network = new OTSRoadNetwork("network", true);
92
93
94 private StreamInterface stream = new MersenneTwister(555);
95
96
97 private IdGenerator idGenerator = new IdGenerator("");
98
99
100 @SuppressWarnings("checkstyle:visibilitymodifier")
101 protected DistContinuous headwayGenerator;
102
103
104 private double carProbability;
105
106
107 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactoryCar;
108
109
110 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactoryTruck;
111
112
113 private Speed speedLimit = new Speed(80, KM_PER_HOUR);
114
115
116 private static final Duration TGREEN = new Duration(39.0, DurationUnit.SI);
117
118
119 private static final Duration TYELLOW = new Duration(6.0, DurationUnit.SI);
120
121
122 private static final Duration TRED = new Duration(45.0, DurationUnit.SI);
123
124
125
126
127 public CrossingTrafficLightsModel(final OTSSimulatorInterface simulator)
128 {
129 super(simulator);
130 createInputParameters();
131 }
132
133
134
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
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
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
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
266
267
268
269
270
271
272
273
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
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
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
312
313
314
315
316
317
318
319
320
321
322
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
360
361
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
383 @Override
384 public OTSRoadNetwork getNetwork()
385 {
386 return this.network;
387 }
388 }