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