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 animationPanel.enableSimulationControlButtons();
194 }
195 catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException | IndexOutOfBoundsException
196 | DSOLException exception)
197 {
198 exception.printStackTrace();
199 }
200 }
201
202
203
204
205
206
207
208
209
210
211
212
213 public static class ShortMergeModel extends AbstractOTSModel
214 {
215
216 private static final long serialVersionUID = 20170407L;
217
218
219 private OTSRoadNetwork network;
220
221
222
223
224 public ShortMergeModel(final OTSSimulatorInterface simulator)
225 {
226 super(simulator);
227 }
228
229
230
231
232 public void setNetwork(final OTSRoadNetwork network)
233 {
234 this.network = network;
235 }
236
237
238 @Override
239 public void constructModel() throws SimRuntimeException
240 {
241 try
242 {
243 URL xmlURL = URLResource.getResource("/lmrs/" + NETWORK + ".xml");
244 this.network = new OTSRoadNetwork("ShortMerge", true, getSimulator());
245 XmlNetworkLaneParser.build(xmlURL, this.network, false);
246 addGenerator();
247
248 }
249 catch (Exception exception)
250 {
251 exception.printStackTrace();
252 }
253 }
254
255
256 @Override
257 public OTSRoadNetwork getNetwork()
258 {
259 return this.network;
260 }
261
262
263
264
265
266
267
268
269
270
271 private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
272 SimRuntimeException, RemoteException
273 {
274
275 Random seedGenerator = new Random(1L);
276 Map<String, StreamInterface> streams = new LinkedHashMap<>();
277 StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
278 streams.put("headwayGeneration", stream);
279 streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
280 this.getSimulator().getReplication().setStreams(streams);
281
282 TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
283 IdGenerator idGenerator = new IdGenerator("");
284
285 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
286 ParameterSet params = new ParameterSet();
287 params.setDefaultParameter(AbstractIDM.DELTA);
288
289 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
290 Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
291 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
292 mandatoryIncentives.add(new IncentiveRoute());
293 if (ADDITIONAL_INCENTIVES)
294 {
295
296 }
297 voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
298 voluntaryIncentives.add(new IncentiveKeep());
299 if (ADDITIONAL_INCENTIVES)
300 {
301 voluntaryIncentives.add(new IncentiveCourtesy());
302 voluntaryIncentives.add(new IncentiveSocioSpeed());
303 }
304 accelerationIncentives.add(new AccelerationSpeedLimitTransition());
305 accelerationIncentives.add(new AccelerationTrafficLights());
306 accelerationIncentives.add(new AccelerationConflicts());
307 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory = new LMRSFactory(idmPlusFactory,
308 new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION, COOPERATION, GapAcceptance.INFORMED, Tailgating.NONE,
309 mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
310
311 GTUType car = new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR));
312 GTUType truck = new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK));
313 Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
314 Route routeAG = !NETWORK.equals("shortWeave") ? null
315 : this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
316 Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
317 Route routeFG = !NETWORK.equals("shortWeave") ? null
318 : this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
319
320 double leftFraction = NETWORK.equals("shortWeave") ? LEFT_FRACTION : 0.0;
321 List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
322 routesA.add(new FrequencyAndObject<>(1.0 - leftFraction, routeAE));
323 routesA.add(new FrequencyAndObject<>(leftFraction, routeAG));
324 List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
325 routesF.add(new FrequencyAndObject<>(1.0 - leftFraction, routeFE));
326 routesF.add(new FrequencyAndObject<>(leftFraction, routeFG));
327 Generator<Route> routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
328 Generator<Route> routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
329
330 Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
331 Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
332
333 CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
334 CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FF2");
335
336 ParameterFactoryByType bcFactory = new ParameterFactoryByType();
337 bcFactory.addParameter(car, ParameterTypes.FSPEED, new DistNormal(stream, 123.7 / 120, 12.0 / 120));
338 bcFactory.addParameter(car, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
339 bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
340 bcFactory.addParameter(truck, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
341 bcFactory.addParameter(Tailgating.RHO, Tailgating.RHO.getDefaultValue());
342
343 Generator<Duration> headwaysA1 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
344 Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
345 Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
346 Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), RAMP_DEMAND);
347
348
349 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
350 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 160, 200), SpeedUnit.KM_PER_HOUR);
351 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
352 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 80, 95), SpeedUnit.KM_PER_HOUR);
353
354 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
355 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
356
357 LaneBasedTemplateGTUType carA =
358 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
359 new ConstantGenerator<>(Length.instantiateSI(4.0)),
360 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorA);
361 LaneBasedTemplateGTUType carF =
362 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
363 new ConstantGenerator<>(Length.instantiateSI(4.0)),
364 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorF);
365 LaneBasedTemplateGTUType truckA = new LaneBasedTemplateGTUType(
366 new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
367 new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
368 speedTruck, strategicalFactory, routeGeneratorA);
369 LaneBasedTemplateGTUType truckF = new LaneBasedTemplateGTUType(
370 new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
371 new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
372 speedTruck, strategicalFactory, routeGeneratorF);
373
374 Distribution<LaneBasedTemplateGTUType> gtuTypeAllCarA = new Distribution<>(streams.get("gtuClass"));
375 gtuTypeAllCarA.add(new FrequencyAndObject<>(1.0, carA));
376
377 Distribution<LaneBasedTemplateGTUType> gtuType1LaneF = new Distribution<>(streams.get("gtuClass"));
378 gtuType1LaneF.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carF));
379 gtuType1LaneF.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckF));
380
381 Distribution<LaneBasedTemplateGTUType> gtuType2ndLaneA = new Distribution<>(streams.get("gtuClass"));
382 gtuType2ndLaneA.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carA));
383 gtuType2ndLaneA.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckA));
384
385 Distribution<LaneBasedTemplateGTUType> gtuType3rdLaneA = new Distribution<>(streams.get("gtuClass"));
386 gtuType3rdLaneA.add(new FrequencyAndObject<>(1.0 - 3 * TRUCK_FRACTION, carA));
387 gtuType3rdLaneA.add(new FrequencyAndObject<>(3 * TRUCK_FRACTION, truckA));
388
389 GTUColorer colorer = new LmrsSwitchableColorer();
390 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", idGenerator, gtuTypeAllCarA, headwaysA1, colorer,
391 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
392 if (NETWORK.equals("shortWeave"))
393 {
394 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuTypeAllCarA, headwaysA2, colorer,
395 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
396 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", idGenerator, gtuType3rdLaneA, headwaysA3, colorer,
397 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
398 }
399 else
400 {
401 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuType2ndLaneA, headwaysA2, colorer,
402 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
403 }
404 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", idGenerator, gtuType1LaneF, headwaysF, colorer,
405 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
406
407 new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.instantiateSI(10),
408 this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
409
410 }
411
412
413
414
415
416
417
418 private Lane getLane(final CrossSectionLink link, final String id)
419 {
420 return (Lane) link.getCrossSectionElement(id);
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id, final IdGenerator idGenerator,
442 final Distribution<LaneBasedTemplateGTUType> distribution, final Generator<Duration> headwayGenerator,
443 final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
444 final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime,
445 final StreamInterface stream) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
446 {
447
448 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
449
450 initialLongitudinalPositions
451 .add(new DirectedLanePosition(lane, new Length(5.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
452 LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
453 new LaneBasedTemplateGTUTypeDistribution(distribution);
454 new LaneBasedGTUGenerator(id, headwayGenerator, characteristicsGenerator,
455 GeneratorPositions.create(initialLongitudinalPositions, stream), this.network, getSimulator(), roomChecker,
456 idGenerator);
457 }
458
459
460 @Override
461 public Serializable getSourceId()
462 {
463 return "ShortMergeModel";
464 }
465
466 }
467
468
469
470
471
472
473
474
475
476
477
478
479 private static class HeadwayGenerator implements Generator<Duration>
480 {
481
482 private final OTSSimulatorInterface simulator;
483
484
485 private final Frequency demand;
486
487
488
489
490
491 HeadwayGenerator(final OTSSimulatorInterface simulator, final Frequency demand)
492 {
493 this.simulator = simulator;
494 this.demand = demand;
495 }
496
497
498 @Override
499 public Duration draw() throws ProbabilityException, ParameterException
500 {
501 return new Duration(
502 -Math.log(this.simulator.getReplication().getStream("headwayGeneration").nextDouble()) / this.demand.si,
503 DurationUnit.SI);
504 }
505
506 }
507
508 }