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