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