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