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