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 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("/resources/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 getStreamInformation().addStream("headwayGeneration", stream);
281 getStreamInformation().addStream("gtuClass", streams.get("gtuClass"));
282
283 TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
284 IdGenerator idGenerator = new IdGenerator("");
285
286 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
287 ParameterSet params = new ParameterSet();
288 params.setDefaultParameter(AbstractIDM.DELTA);
289
290 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
291 Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
292 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
293 mandatoryIncentives.add(new IncentiveRoute());
294 if (ADDITIONAL_INCENTIVES)
295 {
296
297 }
298 voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
299 voluntaryIncentives.add(new IncentiveKeep());
300 if (ADDITIONAL_INCENTIVES)
301 {
302 voluntaryIncentives.add(new IncentiveCourtesy());
303 voluntaryIncentives.add(new IncentiveSocioSpeed());
304 }
305 accelerationIncentives.add(new AccelerationSpeedLimitTransition());
306 accelerationIncentives.add(new AccelerationTrafficLights());
307 accelerationIncentives.add(new AccelerationConflicts());
308 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory = new LMRSFactory(idmPlusFactory,
309 new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION, COOPERATION, GapAcceptance.INFORMED, Tailgating.NONE,
310 mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
311
312 GTUType car = new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR));
313 GTUType truck = new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK));
314 Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
315 Route routeAG = !NETWORK.equals("shortWeave") ? null
316 : this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
317 Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
318 Route routeFG = !NETWORK.equals("shortWeave") ? null
319 : this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
320
321 double leftFraction = NETWORK.equals("shortWeave") ? LEFT_FRACTION : 0.0;
322 List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
323 routesA.add(new FrequencyAndObject<>(1.0 - leftFraction, routeAE));
324 routesA.add(new FrequencyAndObject<>(leftFraction, routeAG));
325 List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
326 routesF.add(new FrequencyAndObject<>(1.0 - leftFraction, routeFE));
327 routesF.add(new FrequencyAndObject<>(leftFraction, routeFG));
328 Generator<Route> routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
329 Generator<Route> routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
330
331 Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
332 Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
333
334 CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
335 CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FF2");
336
337 ParameterFactoryByType bcFactory = new ParameterFactoryByType();
338 bcFactory.addParameter(car, ParameterTypes.FSPEED, new DistNormal(stream, 123.7 / 120, 12.0 / 120));
339 bcFactory.addParameter(car, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
340 bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
341 bcFactory.addParameter(truck, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
342 bcFactory.addParameter(Tailgating.RHO, Tailgating.RHO.getDefaultValue());
343
344 Generator<Duration> headwaysA1 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
345 Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
346 Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
347 Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), RAMP_DEMAND);
348
349
350 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
351 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 160, 200), SpeedUnit.KM_PER_HOUR);
352 ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
353 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 80, 95), SpeedUnit.KM_PER_HOUR);
354
355 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
356 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
357
358 LaneBasedTemplateGTUType carA =
359 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
360 new ConstantGenerator<>(Length.instantiateSI(4.0)),
361 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorA);
362 LaneBasedTemplateGTUType carF =
363 new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
364 new ConstantGenerator<>(Length.instantiateSI(4.0)),
365 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorF);
366 LaneBasedTemplateGTUType truckA = new LaneBasedTemplateGTUType(
367 new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
368 new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
369 speedTruck, strategicalFactory, routeGeneratorA);
370 LaneBasedTemplateGTUType truckF = new LaneBasedTemplateGTUType(
371 new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
372 new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
373 speedTruck, strategicalFactory, routeGeneratorF);
374
375 Distribution<LaneBasedTemplateGTUType> gtuTypeAllCarA = new Distribution<>(streams.get("gtuClass"));
376 gtuTypeAllCarA.add(new FrequencyAndObject<>(1.0, carA));
377
378 Distribution<LaneBasedTemplateGTUType> gtuType1LaneF = new Distribution<>(streams.get("gtuClass"));
379 gtuType1LaneF.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carF));
380 gtuType1LaneF.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckF));
381
382 Distribution<LaneBasedTemplateGTUType> gtuType2ndLaneA = new Distribution<>(streams.get("gtuClass"));
383 gtuType2ndLaneA.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carA));
384 gtuType2ndLaneA.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckA));
385
386 Distribution<LaneBasedTemplateGTUType> gtuType3rdLaneA = new Distribution<>(streams.get("gtuClass"));
387 gtuType3rdLaneA.add(new FrequencyAndObject<>(1.0 - 3 * TRUCK_FRACTION, carA));
388 gtuType3rdLaneA.add(new FrequencyAndObject<>(3 * TRUCK_FRACTION, truckA));
389
390 GTUColorer colorer = new LmrsSwitchableColorer();
391 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", idGenerator, gtuTypeAllCarA, headwaysA1, colorer,
392 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
393 if (NETWORK.equals("shortWeave"))
394 {
395 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuTypeAllCarA, headwaysA2, colorer,
396 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
397 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", idGenerator, gtuType3rdLaneA, headwaysA3, colorer,
398 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
399 }
400 else
401 {
402 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuType2ndLaneA, headwaysA2, colorer,
403 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
404 }
405 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", idGenerator, gtuType1LaneF, headwaysF, colorer,
406 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
407
408 new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.instantiateSI(10),
409 this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
410
411 }
412
413
414
415
416
417
418
419 private Lane getLane(final CrossSectionLink link, final String id)
420 {
421 return (Lane) link.getCrossSectionElement(id);
422 }
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id, final IdGenerator idGenerator,
443 final Distribution<LaneBasedTemplateGTUType> distribution, final Generator<Duration> headwayGenerator,
444 final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
445 final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime,
446 final StreamInterface stream) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
447 {
448
449 Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
450
451 initialLongitudinalPositions
452 .add(new DirectedLanePosition(lane, new Length(5.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
453 LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
454 new LaneBasedTemplateGTUTypeDistribution(distribution);
455 new LaneBasedGTUGenerator(id, headwayGenerator, characteristicsGenerator,
456 GeneratorPositions.create(initialLongitudinalPositions, stream), this.network, getSimulator(), roomChecker,
457 idGenerator);
458 }
459
460
461 @Override
462 public Serializable getSourceId()
463 {
464 return "ShortMergeModel";
465 }
466
467 }
468
469
470
471
472
473
474
475
476
477
478
479
480 private static class HeadwayGenerator implements Generator<Duration>
481 {
482
483 private final OTSSimulatorInterface simulator;
484
485
486 private final Frequency demand;
487
488
489
490
491
492 HeadwayGenerator(final OTSSimulatorInterface simulator, final Frequency demand)
493 {
494 this.simulator = simulator;
495 this.demand = demand;
496 }
497
498
499 @Override
500 public Duration draw() throws ProbabilityException, ParameterException
501 {
502 return new Duration(
503 -Math.log(this.simulator.getModel().getStream("headwayGeneration").nextDouble()) / this.demand.si,
504 DurationUnit.SI);
505 }
506
507 }
508
509 }