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