1 package org.opentrafficsim.demo;
2
3 import java.awt.Dimension;
4 import java.io.InputStream;
5 import java.rmi.RemoteException;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.LinkedHashSet;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Random;
12 import java.util.Set;
13
14 import javax.naming.NamingException;
15
16 import org.djunits.unit.AccelerationUnit;
17 import org.djunits.unit.DurationUnit;
18 import org.djunits.unit.FrequencyUnit;
19 import org.djunits.unit.LengthUnit;
20 import org.djunits.unit.SpeedUnit;
21 import org.djunits.value.vdouble.scalar.Acceleration;
22 import org.djunits.value.vdouble.scalar.Duration;
23 import org.djunits.value.vdouble.scalar.Frequency;
24 import org.djunits.value.vdouble.scalar.Length;
25 import org.djunits.value.vdouble.scalar.Speed;
26 import org.djunits.value.vdouble.scalar.Time;
27 import org.djutils.io.URLResource;
28 import org.opentrafficsim.base.parameters.ParameterException;
29 import org.opentrafficsim.base.parameters.ParameterSet;
30 import org.opentrafficsim.base.parameters.ParameterTypes;
31 import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
32 import org.opentrafficsim.core.distributions.ConstantGenerator;
33 import org.opentrafficsim.core.distributions.Distribution;
34 import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
35 import org.opentrafficsim.core.distributions.Generator;
36 import org.opentrafficsim.core.distributions.ProbabilityException;
37 import org.opentrafficsim.core.dsol.AbstractOTSModel;
38 import org.opentrafficsim.core.dsol.OTSAnimator;
39 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
40 import org.opentrafficsim.core.gtu.GTUDirectionality;
41 import org.opentrafficsim.core.gtu.GTUException;
42 import org.opentrafficsim.core.gtu.GTUType;
43 import org.opentrafficsim.core.idgenerator.IdGenerator;
44 import org.opentrafficsim.core.network.LongitudinalDirectionality;
45 import org.opentrafficsim.core.network.NetworkException;
46 import org.opentrafficsim.core.network.OTSLink;
47 import org.opentrafficsim.core.network.OTSNode;
48 import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
49 import org.opentrafficsim.core.network.route.Route;
50 import org.opentrafficsim.core.parameters.ParameterFactory;
51 import org.opentrafficsim.core.parameters.ParameterFactoryByType;
52 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
53 import org.opentrafficsim.demo.ShortMerge.ShortMergeModel;
54 import org.opentrafficsim.draw.core.OTSDrawingException;
55 import org.opentrafficsim.road.gtu.colorer.LmrsSwitchableColorer;
56 import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
57 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
58 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
59 import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
60 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
61 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
62 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
64 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
65 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
66 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
67 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationConflicts;
68 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
69 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationSpeedLimitTransition;
70 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationTrafficLights;
71 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
72 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveCourtesy;
73 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
74 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
75 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
76 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
77 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
78 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
79 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
80 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
81 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
82 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
83 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
84 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
85 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
86 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
87 import org.opentrafficsim.road.network.OTSRoadNetwork;
88 import org.opentrafficsim.road.network.factory.xml.old.XmlNetworkLaneParserOld;
89 import org.opentrafficsim.road.network.lane.CrossSectionLink;
90 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
91 import org.opentrafficsim.road.network.lane.Lane;
92 import org.opentrafficsim.road.network.lane.object.SpeedSign;
93 import org.opentrafficsim.swing.gui.AnimationToggles;
94 import org.opentrafficsim.swing.gui.OTSAnimationPanel;
95 import org.opentrafficsim.swing.gui.OTSSimulationApplication;
96
97 import nl.tudelft.simulation.dsol.SimRuntimeException;
98 import nl.tudelft.simulation.jstats.distributions.DistNormal;
99 import nl.tudelft.simulation.jstats.distributions.DistUniform;
100 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
101 import nl.tudelft.simulation.jstats.streams.StreamInterface;
102
103
104
105
106
107
108
109
110
111
112
113 public class ShortMerge extends OTSSimulationApplication<ShortMergeModel>
114 {
115
116 private static final long serialVersionUID = 20170407L;
117
118
119 static final String NETWORK = "shortMerge";
120
121
122 static final double TRUCK_FRACTION = 0.15;
123
124
125 static final double LEFT_FRACTION = 0.3;
126
127
128 static final Frequency MAIN_DEMAND = new Frequency(1000, FrequencyUnit.PER_HOUR);
129
130
131 static final Frequency RAMP_DEMAND = new Frequency(500, FrequencyUnit.PER_HOUR);
132
133
134 static final Synchronization SYNCHRONIZATION = Synchronization.ALIGN_GAP;
135
136
137 static final Cooperation COOPERATION = Cooperation.PASSIVE_MOVING;
138
139
140 static final boolean ADDITIONAL_INCENTIVES = true;
141
142
143 public static final Time SIMTIME = Time.createSI(3600);
144
145
146
147
148
149
150
151
152 public ShortMerge(final String title, final OTSAnimationPanel panel, final ShortMergeModel model) throws OTSDrawingException
153 {
154 super(model, panel);
155 }
156
157
158 @Override
159 protected void setAnimationToggles()
160 {
161 AnimationToggles.setTextAnimationTogglesFull(getAnimationPanel());
162 getAnimationPanel().getAnimationPanel().toggleClass(OTSLink.class);
163 getAnimationPanel().getAnimationPanel().toggleClass(OTSNode.class);
164 getAnimationPanel().getAnimationPanel().showClass(SpeedSign.class);
165 }
166
167
168
169
170
171 public static void main(final String[] args)
172 {
173 demo(true);
174 }
175
176
177
178
179
180 public static void demo(final boolean exitOnClose)
181 {
182 try
183 {
184 OTSAnimator simulator = new OTSAnimator();
185 final ShortMergeModel otsModel = new ShortMergeModel(simulator);
186 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.createSI(3600.0), otsModel);
187 OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(), new Dimension(800, 600),
188 simulator, otsModel, new LmrsSwitchableColorer(), otsModel.getNetwork());
189 ShortMerge app = new ShortMerge("ShortMerge", animationPanel, otsModel);
190 app.setExitOnClose(exitOnClose);
191 }
192 catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
193 {
194 exception.printStackTrace();
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209 static class ShortMergeModel extends AbstractOTSModel
210 {
211
212 private static final long serialVersionUID = 20170407L;
213
214
215 private OTSRoadNetwork network;
216
217
218
219
220 ShortMergeModel(final OTSSimulatorInterface simulator)
221 {
222 super(simulator);
223 }
224
225
226
227
228 public void setNetwork(final OTSRoadNetwork network)
229 {
230 this.network = network;
231 }
232
233
234 @Override
235 public void constructModel() throws SimRuntimeException
236 {
237 try
238 {
239 InputStream stream = URLResource.getResourceAsStream("/lmrs/" + NETWORK + ".xml");
240 XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(this.simulator);
241 this.network = new OTSRoadNetwork("ShortMerge", true);
242 nlp.build(stream, this.network, false);
243
244 addGenerator();
245
246 }
247 catch (Exception exception)
248 {
249 exception.printStackTrace();
250 }
251 }
252
253
254 @Override
255 public OTSRoadNetwork getNetwork()
256 {
257 return this.network;
258 }
259
260
261
262
263
264
265
266
267
268
269 private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
270 SimRuntimeException, RemoteException
271 {
272
273 Random seedGenerator = new Random(1L);
274 Map<String, StreamInterface> streams = new HashMap<>();
275 StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
276 streams.put("headwayGeneration", stream);
277 streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
278 this.getSimulator().getReplication().setStreams(streams);
279
280 TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
281 IdGenerator idGenerator = new IdGenerator("");
282
283 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
284 ParameterSet params = new ParameterSet();
285 params.setDefaultParameter(AbstractIDM.DELTA);
286
287 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
288 Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
289 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
290 mandatoryIncentives.add(new IncentiveRoute());
291 if (ADDITIONAL_INCENTIVES)
292 {
293
294 }
295 voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
296 voluntaryIncentives.add(new IncentiveKeep());
297 if (ADDITIONAL_INCENTIVES)
298 {
299 voluntaryIncentives.add(new IncentiveCourtesy());
300 voluntaryIncentives.add(new IncentiveSocioSpeed());
301 }
302 accelerationIncentives.add(new AccelerationSpeedLimitTransition());
303 accelerationIncentives.add(new AccelerationTrafficLights());
304 accelerationIncentives.add(new AccelerationConflicts());
305 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory = new LMRSFactory(idmPlusFactory,
306 new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION, COOPERATION, GapAcceptance.INFORMED, Tailgating.NONE,
307 mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
308
309 GTUType car = new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR));
310 GTUType truck = new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK));
311 Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
312 Route routeAG = !NETWORK.equals("shortWeave") ? null
313 : this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
314 Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
315 Route routeFG = !NETWORK.equals("shortWeave") ? null
316 : this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
317
318 double leftFraction = NETWORK.equals("shortWeave") ? LEFT_FRACTION : 0.0;
319 List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
320 routesA.add(new FrequencyAndObject<>(1.0 - leftFraction, routeAE));
321 routesA.add(new FrequencyAndObject<>(leftFraction, routeAG));
322 List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
323 routesF.add(new FrequencyAndObject<>(1.0 - leftFraction, routeFE));
324 routesF.add(new FrequencyAndObject<>(leftFraction, routeFG));
325 Generator<Route> routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
326 Generator<Route> routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
327
328 Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
329 Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
330
331 CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
332 CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FF2");
333
334 ParameterFactoryByType bcFactory = new ParameterFactoryByType();
335 bcFactory.addParameter(car, ParameterTypes.FSPEED, new DistNormal(stream, 123.7 / 120, 12.0 / 120));
336 bcFactory.addParameter(car, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
337 bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
338 bcFactory.addParameter(truck, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
339 bcFactory.addParameter(Tailgating.RHO, Tailgating.RHO.getDefaultValue());
340
341 Generator<Duration> headwaysA1 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
342 Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
343 Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
344 Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), RAMP_DEMAND);
345
346
347 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
348 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 160, 200), SpeedUnit.KM_PER_HOUR);
349 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
350 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 80, 95), SpeedUnit.KM_PER_HOUR);
351
352 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
353 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
354
355 LaneBasedTemplateGTUType carA =
356 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
357 new ConstantGenerator<>(Length.createSI(4.0)), new ConstantGenerator<>(Length.createSI(2.0)),
358 speedCar, strategicalFactory, routeGeneratorA);
359 LaneBasedTemplateGTUType carF =
360 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
361 new ConstantGenerator<>(Length.createSI(4.0)), new ConstantGenerator<>(Length.createSI(2.0)),
362 speedCar, strategicalFactory, routeGeneratorF);
363 LaneBasedTemplateGTUType truckA =
364 new LaneBasedTemplateGTUType(new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
365 new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
366 speedTruck, strategicalFactory, routeGeneratorA);
367 LaneBasedTemplateGTUType truckF =
368 new LaneBasedTemplateGTUType(new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
369 new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
370 speedTruck, strategicalFactory, routeGeneratorF);
371
372 Distribution<LaneBasedTemplateGTUType> gtuTypeAllCarA = new Distribution<>(streams.get("gtuClass"));
373 gtuTypeAllCarA.add(new FrequencyAndObject<>(1.0, carA));
374
375 Distribution<LaneBasedTemplateGTUType> gtuType1LaneF = new Distribution<>(streams.get("gtuClass"));
376 gtuType1LaneF.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carF));
377 gtuType1LaneF.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckF));
378
379 Distribution<LaneBasedTemplateGTUType> gtuType2ndLaneA = new Distribution<>(streams.get("gtuClass"));
380 gtuType2ndLaneA.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carA));
381 gtuType2ndLaneA.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckA));
382
383 Distribution<LaneBasedTemplateGTUType> gtuType3rdLaneA = new Distribution<>(streams.get("gtuClass"));
384 gtuType3rdLaneA.add(new FrequencyAndObject<>(1.0 - 3 * TRUCK_FRACTION, carA));
385 gtuType3rdLaneA.add(new FrequencyAndObject<>(3 * TRUCK_FRACTION, truckA));
386
387 GTUColorer colorer = new LmrsSwitchableColorer();
388 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", idGenerator, gtuTypeAllCarA, headwaysA1, colorer,
389 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
390 if (NETWORK.equals("shortWeave"))
391 {
392 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuTypeAllCarA, headwaysA2, colorer,
393 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
394 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", idGenerator, gtuType3rdLaneA, headwaysA3, colorer,
395 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
396 }
397 else
398 {
399 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuType2ndLaneA, headwaysA2, colorer,
400 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
401 }
402 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", idGenerator, gtuType1LaneF, headwaysF, colorer,
403 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
404
405 new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.createSI(10),
406 this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
407
408 }
409
410
411
412
413
414
415
416 private Lane getLane(final CrossSectionLink link, final String id)
417 {
418 return (Lane) link.getCrossSectionElement(id);
419 }
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id, final IdGenerator idGenerator,
440 final Distribution<LaneBasedTemplateGTUType> distribution, final Generator<Duration> headwayGenerator,
441 final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
442 final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime,
443 final StreamInterface stream) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
444 {
445
446 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
447
448 initialLongitudinalPositions
449 .add(new DirectedLanePosition(lane, new Length(5.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
450 LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
451 new LaneBasedTemplateGTUTypeDistribution(distribution);
452 new LaneBasedGTUGenerator(id, headwayGenerator, characteristicsGenerator,
453 GeneratorPositions.create(initialLongitudinalPositions, stream), this.network, getSimulator(), roomChecker,
454 idGenerator);
455 }
456
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470 private static class HeadwayGenerator implements Generator<Duration>
471 {
472
473 private final OTSSimulatorInterface simulator;
474
475
476 private final Frequency demand;
477
478
479
480
481
482 HeadwayGenerator(final OTSSimulatorInterface simulator, final Frequency demand)
483 {
484 this.simulator = simulator;
485 this.demand = demand;
486 }
487
488
489 @Override
490 public Duration draw() throws ProbabilityException, ParameterException
491 {
492 return new Duration(
493 -Math.log(this.simulator.getReplication().getStream("headwayGeneration").nextDouble()) / this.demand.si,
494 DurationUnit.SI);
495 }
496
497 }
498
499 }