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;
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 this.network = new OTSRoadNetwork("network", true, simulator);
132 createInputParameters();
133 }
134
135
136
137
138 private void createInputParameters()
139 {
140 try
141 {
142 InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
143 InputParameterMap genericMap = (InputParameterMap) this.inputParameterMap.get("generic");
144 genericMap.add(new InputParameterDouble("flow", "Flow per input lane", "Traffic flow per input lane", 250d, 0d,
145 400d, true, true, "%.0f veh/h", 1.5));
146 }
147 catch (InputParameterException e)
148 {
149 e.printStackTrace();
150 }
151 }
152
153
154 @Override
155 public final void constructModel() throws SimRuntimeException
156 {
157 try
158 {
159 OTSRoadNode[][] nodes = new OTSRoadNode[4][4];
160 nodes[0][0] = new OTSRoadNode(this.network, "sn1", new OTSPoint3D(10, -500),
161 new Direction(90, DirectionUnit.EAST_DEGREE));
162 nodes[0][1] =
163 new OTSRoadNode(this.network, "sn2", new OTSPoint3D(10, -20), new Direction(90, DirectionUnit.EAST_DEGREE));
164 nodes[0][2] =
165 new OTSRoadNode(this.network, "sn3", new OTSPoint3D(10, +20), new Direction(90, DirectionUnit.EAST_DEGREE));
166 nodes[0][3] = new OTSRoadNode(this.network, "sn4", new OTSPoint3D(10, +600),
167 new Direction(90, DirectionUnit.EAST_DEGREE));
168
169 nodes[1][0] = new OTSRoadNode(this.network, "we1", new OTSPoint3D(-500, -10), Direction.ZERO);
170 nodes[1][1] = new OTSRoadNode(this.network, "we2", new OTSPoint3D(-20, -10), Direction.ZERO);
171 nodes[1][2] = new OTSRoadNode(this.network, "we3", new OTSPoint3D(+20, -10), Direction.ZERO);
172 nodes[1][3] = new OTSRoadNode(this.network, "we4", new OTSPoint3D(+600, -10), Direction.ZERO);
173
174 nodes[2][0] = new OTSRoadNode(this.network, "ns1", new OTSPoint3D(-10, +500),
175 new Direction(270, DirectionUnit.EAST_DEGREE));
176 nodes[2][1] = new OTSRoadNode(this.network, "ns2", new OTSPoint3D(-10, +20),
177 new Direction(270, DirectionUnit.EAST_DEGREE));
178 nodes[2][2] = new OTSRoadNode(this.network, "ns3", new OTSPoint3D(-10, -20),
179 new Direction(270, DirectionUnit.EAST_DEGREE));
180 nodes[2][3] = new OTSRoadNode(this.network, "ns4", new OTSPoint3D(-10, -600),
181 new Direction(270, DirectionUnit.EAST_DEGREE));
182
183 nodes[3][0] = new OTSRoadNode(this.network, "ew1", new OTSPoint3D(+500, 10),
184 new Direction(180, DirectionUnit.EAST_DEGREE));
185 nodes[3][1] = new OTSRoadNode(this.network, "ew2", new OTSPoint3D(+20, 10),
186 new Direction(180, DirectionUnit.EAST_DEGREE));
187 nodes[3][2] = new OTSRoadNode(this.network, "ew3", new OTSPoint3D(-20, 10),
188 new Direction(180, DirectionUnit.EAST_DEGREE));
189 nodes[3][3] = new OTSRoadNode(this.network, "ew4", new OTSPoint3D(-600, 10),
190 new Direction(180, DirectionUnit.EAST_DEGREE));
191
192 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
193
194 Map<Lane, SimpleTrafficLight> trafficLights = new LinkedHashMap<>();
195
196 this.carProbability = (double) getInputParameter("generic.carProbability");
197 ParameterFactory params = new InputParameterHelper(getInputParameterMap());
198 this.strategicalPlannerFactoryCar = new LaneBasedStrategicalRoutePlannerFactory(
199 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()), params);
200 this.strategicalPlannerFactoryTruck = new LaneBasedStrategicalRoutePlannerFactory(
201 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()), params);
202 this.idGenerator = new IdGenerator("");
203 double contP = (double) getInputParameter("generic.flow");
204 Duration averageHeadway = new Duration(3600.0 / contP, SECOND);
205 Duration minimumHeadway = new Duration(3, SECOND);
206 this.headwayGenerator =
207 new DistErlang(new MersenneTwister(1234), DoubleScalar.minus(averageHeadway, minimumHeadway).getSI(), 4);
208
209 for (int i = 0; i < 4; i++)
210 {
211 for (int j = 0; j < 3; j++)
212 {
213 Lane[] lanes = LaneFactory.makeMultiLane(this.network,
214 "Lane_" + nodes[i][j].getId() + "-" + nodes[i][j + 1].getId(), nodes[i][j], nodes[i][j + 1], null,
215 2, laneType, this.speedLimit, this.simulator);
216 if (j == 0)
217 {
218 for (Lane lane : lanes)
219 {
220
221 Generator<Route> routeGenerator = new FixedRouteGenerator(new Route("main",
222 Arrays.asList(new Node[] {nodes[i][0], nodes[i][1], nodes[i][2], nodes[i][3]})));
223 makeGenerator(lane, routeGenerator);
224
225
226 SimpleTrafficLight tl = new SimpleTrafficLight(lane.getId() + "_TL", lane,
227 new Length(lane.getLength().minus(new Length(10.0, LengthUnit.METER))), this.simulator);
228 trafficLights.put(lane, tl);
229
230 try
231 {
232 new TrafficLightAnimation(tl, this.simulator);
233 }
234 catch (RemoteException | NamingException exception)
235 {
236 throw new NetworkException(exception);
237 }
238
239 if (i == 0 || i == 2)
240 {
241 this.simulator.scheduleEventRel(Duration.ZERO, this, this, "changeTL", new Object[] {tl});
242 }
243 else
244 {
245 this.simulator.scheduleEventRel(TRED, this, this, "changeTL", new Object[] {tl});
246 }
247 }
248 }
249 if (j == 2)
250 {
251 for (Lane lane : lanes)
252 {
253 new SinkSensor(lane, new Length(500.0, METER), Compatible.EVERYTHING, this.simulator);
254 }
255 }
256 }
257 }
258 }
259 catch (SimRuntimeException | NamingException | NetworkException | OTSGeometryException | GTUException
260 | InputParameterException | ProbabilityException | ParameterException exception)
261 {
262 exception.printStackTrace();
263 }
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277 private LaneBasedGTUGenerator makeGenerator(final Lane lane, final Generator<Route> routeGenerator)
278 throws GTUException, SimRuntimeException, ProbabilityException, ParameterException, InputParameterException
279 {
280 Distribution<LaneBasedTemplateGTUType> distribution = new Distribution<>(this.stream);
281 Length initialPosition = new Length(16, METER);
282 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
283 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
284
285 LaneBasedTemplateGTUType template = makeTemplate(this.stream, lane,
286 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 3, 6), METER),
287 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 1.6, 2.0), METER),
288 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(this.stream, 140, 180), KM_PER_HOUR),
289 initialPositions, this.strategicalPlannerFactoryCar, routeGenerator);
290
291 distribution.add(new FrequencyAndObject<>(this.carProbability, template));
292 template = makeTemplate(this.stream, lane,
293 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 8, 14), METER),
294 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(this.stream, 2.0, 2.5), METER),
295 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(this.stream, 100, 140), KM_PER_HOUR),
296 initialPositions, this.strategicalPlannerFactoryTruck, routeGenerator);
297
298 distribution.add(new FrequencyAndObject<>(1.0 - this.carProbability, template));
299 LaneBasedTemplateGTUTypeDistribution templateDistribution = new LaneBasedTemplateGTUTypeDistribution(distribution);
300 LaneBasedGTUGenerator.RoomChecker roomChecker = new CFRoomChecker();
301 return new LaneBasedGTUGenerator(lane.getId(), new Generator<Duration>()
302 {
303 @Override
304 public Duration draw()
305 {
306 return new Duration(CrossingTrafficLightsModel.this.headwayGenerator.draw(), DurationUnit.SI);
307 }
308 }, templateDistribution, GeneratorPositions.create(initialPositions, this.stream), this.network, this.simulator,
309 roomChecker, this.idGenerator);
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326 @SuppressWarnings("checkstyle:parameternumber")
327 LaneBasedTemplateGTUType makeTemplate(final StreamInterface randStream, final Lane lane,
328 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> lengthDistribution,
329 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> widthDistribution,
330 final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> maximumSpeedDistribution,
331 final Set<DirectedLanePosition> initialPositions,
332 final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory,
333 final Generator<Route> routeGenerator) throws GTUException
334 {
335 return new LaneBasedTemplateGTUType(this.network.getGtuType(GTUType.DEFAULTS.CAR), new Generator<Length>()
336 {
337 @Override
338 public Length draw()
339 {
340 return lengthDistribution.draw();
341 }
342 }, new Generator<Length>()
343 {
344 @Override
345 public Length draw()
346 {
347 return widthDistribution.draw();
348 }
349 }, new Generator<Speed>()
350 {
351 @Override
352 public Speed draw()
353 {
354 return maximumSpeedDistribution.draw();
355 }
356 }, strategicalPlannerFactory, routeGenerator);
357
358 }
359
360
361
362
363
364
365 protected final void changeTL(final TrafficLight tl) throws SimRuntimeException
366 {
367 if (tl.getTrafficLightColor().isRed())
368 {
369 tl.setTrafficLightColor(TrafficLightColor.GREEN);
370 this.simulator.scheduleEventRel(TGREEN, this, this, "changeTL", new Object[] {tl});
371 }
372 else if (tl.getTrafficLightColor().isGreen())
373 {
374 tl.setTrafficLightColor(TrafficLightColor.YELLOW);
375 this.simulator.scheduleEventRel(TYELLOW, this, this, "changeTL", new Object[] {tl});
376 }
377 else if (tl.getTrafficLightColor().isYellow())
378 {
379 tl.setTrafficLightColor(TrafficLightColor.RED);
380 this.simulator.scheduleEventRel(TRED, this, this, "changeTL", new Object[] {tl});
381 }
382 }
383
384
385 @Override
386 public OTSRoadNetwork getNetwork()
387 {
388 return this.network;
389 }
390
391
392 @Override
393 public Serializable getSourceId()
394 {
395 return "CrossingTrafficLightsModel";
396 }
397 }