1 package org.opentrafficsim.demo.carFollowing;
2
3 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4 import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.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.HashSet;
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 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.opentrafficsim.base.modelproperties.Property;
29 import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
30 import org.opentrafficsim.core.distributions.Generator;
31 import org.opentrafficsim.core.distributions.ProbabilityException;
32 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
33 import org.opentrafficsim.core.dsol.OTSModelInterface;
34 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
35 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
36 import org.opentrafficsim.core.gtu.GTUDirectionality;
37 import org.opentrafficsim.core.gtu.GTUException;
38 import org.opentrafficsim.core.gtu.GTUType;
39 import org.opentrafficsim.core.gtu.animation.GTUColorer;
40 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
41 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
42 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactoryByType;
43 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
44 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
45 import org.opentrafficsim.core.idgenerator.IdGenerator;
46 import org.opentrafficsim.core.network.LongitudinalDirectionality;
47 import org.opentrafficsim.core.network.NetworkException;
48 import org.opentrafficsim.core.network.OTSLink;
49 import org.opentrafficsim.core.network.OTSNetwork;
50 import org.opentrafficsim.core.network.OTSNode;
51 import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
52 import org.opentrafficsim.core.network.route.Route;
53 import org.opentrafficsim.core.network.route.RouteGenerator;
54 import org.opentrafficsim.road.animation.AnimationToggles;
55 import org.opentrafficsim.road.gtu.animation.LmrsSwitchableColorer;
56 import org.opentrafficsim.road.gtu.generator.CharacteristicsGenerator;
57 import org.opentrafficsim.road.gtu.generator.GTUTypeGenerator;
58 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
59 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
60 import org.opentrafficsim.road.gtu.generator.SpeedGenerator;
61 import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
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.IncentiveGetInLane;
74 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveHierarchal;
75 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
76 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
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.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.VoluntaryIncentive;
84 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
85 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
86 import org.opentrafficsim.road.network.lane.CrossSectionLink;
87 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
88 import org.opentrafficsim.road.network.lane.Lane;
89 import org.opentrafficsim.road.network.lane.object.SpeedSign;
90 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
91 import org.opentrafficsim.simulationengine.OTSSimulationException;
92
93 import nl.tudelft.simulation.dsol.SimRuntimeException;
94 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
95 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
96 import nl.tudelft.simulation.jstats.streams.StreamInterface;
97 import nl.tudelft.simulation.language.io.URLResource;
98
99
100
101
102
103
104
105
106
107
108
109 public class ShortMerge extends AbstractWrappableAnimation
110 {
111
112
113 static final String NETWORK = "shortMerge";
114
115
116 static final double TRUCK_FRACTION = 0.15;
117
118
119 static final double LEFT_FRACTION = 0.6;
120
121
122 static final Frequency MAIN_DEMAND = new Frequency(1200, FrequencyUnit.PER_HOUR);
123
124
125 static final Frequency RAMP_DEMAND = new Frequency(0, FrequencyUnit.PER_HOUR);
126
127
128 static final Synchronization SYNCHRONIZATION = Synchronization.ACTIVE;
129
130
131 static final boolean ADDITIONAL_INCENTIVES = true;
132
133
134 public static final Time SIMTIME = Time.createSI(3600);
135
136
137 private static final long serialVersionUID = 20170407L;
138
139
140 private OTSDEVSSimulatorInterface sim;
141
142
143 @Override
144 public String shortName()
145 {
146 return "ShortMerge";
147 }
148
149
150 @Override
151 public String description()
152 {
153 return "Short merge to test lane change models.";
154 }
155
156
157 @Override
158 protected final void addAnimationToggles()
159 {
160 AnimationToggles.setTextAnimationTogglesFull(this);
161 this.toggleAnimationClass(OTSLink.class);
162 this.toggleAnimationClass(OTSNode.class);
163 showAnimationClass(SpeedSign.class);
164 }
165
166
167 @Override
168 protected GTUColorer getColorer()
169 {
170 return new LmrsSwitchableColorer();
171 }
172
173
174 @Override
175 protected OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
176 {
177 return new ShortMergeModel(colorer);
178 }
179
180
181
182
183 public OTSDEVSSimulatorInterface getSimulator()
184 {
185 return this.sim;
186 }
187
188
189
190
191 public void setSimulator(final OTSDEVSSimulatorInterface simulator)
192 {
193 this.sim = simulator;
194 }
195
196
197
198
199
200 public static void main(final String[] args)
201 {
202
203 ShortMerge shortMerge = new ShortMerge();
204 try
205 {
206 shortMerge.buildAnimator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMTIME.si), new ArrayList<Property<?>>(),
207 null, true);
208 }
209 catch (Exception exception)
210 {
211 exception.printStackTrace();
212 }
213
214 }
215
216
217
218
219
220
221
222
223
224
225
226
227 class ShortMergeModel implements OTSModelInterface
228 {
229
230
231
232
233 public void setNetwork(final OTSNetwork network)
234 {
235 this.network = network;
236 }
237
238
239 private static final long serialVersionUID = 20170407L;
240
241
242 private OTSNetwork network;
243
244
245 private final GTUColorer colorer;
246
247
248
249
250 ShortMergeModel(final GTUColorer colorer)
251 {
252 this.colorer = colorer;
253 }
254
255
256 @Override
257 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
258 throws SimRuntimeException, RemoteException
259 {
260 ShortMerge.this.setSimulator((OTSDEVSSimulatorInterface) simulator);
261
262 try
263 {
264 InputStream stream = URLResource.getResourceAsStream("/lmrs/" + NETWORK + ".xml");
265 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((OTSDEVSSimulatorInterface) simulator);
266 this.network = new OTSNetwork("ShortMerge");
267 nlp.build(stream, this.network);
268
269 addGenerator();
270
271 }
272 catch (Exception exception)
273 {
274 exception.printStackTrace();
275 }
276 }
277
278
279 @Override
280 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
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();
316 BehavioralCharacteristics bc = new BehavioralCharacteristics();
317 bc.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 mandatoryIncentives.add(new IncentiveGetInLane());
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 IncentiveHierarchal());
333 }
334 accelerationIncentives.add(new AccelerationSpeedLimitTransition());
335 accelerationIncentives.add(new AccelerationTrafficLights());
336 accelerationIncentives.add(new AccelerationConflicts());
337 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
338 new LMRSFactory(idmPlusFactory, bc, new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION,
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 BehavioralCharacteristicsFactoryByType bcFactory = new BehavioralCharacteristicsFactoryByType();
367 bcFactory.addGaussianParameter(car, ParameterTypes.FSPEED, 123.7 / 120, 12.0 / 120, stream);
368 bcFactory.addGaussianParameter(car, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
369 bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
370 bcFactory.addGaussianParameter(truck, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
371
372 Generator<Duration> headwaysA1 = new HeadwayGenerator(MAIN_DEMAND);
373 Generator<Duration> headwaysA2 = new HeadwayGenerator(MAIN_DEMAND);
374 Generator<Duration> headwaysA3 = new HeadwayGenerator(MAIN_DEMAND);
375 Generator<Duration> headwaysF = new HeadwayGenerator(RAMP_DEMAND);
376
377 SpeedGenerator speedCar = new SpeedGenerator(new Speed(160.0, SpeedUnit.KM_PER_HOUR),
378 new Speed(200.0, SpeedUnit.KM_PER_HOUR), stream);
379 SpeedGenerator speedTruck =
380 new SpeedGenerator(new Speed(80.0, SpeedUnit.KM_PER_HOUR), new Speed(95.0, SpeedUnit.KM_PER_HOUR), stream);
381 GTUTypeGenerator gtuTypeAllCar = new GTUTypeGenerator(ShortMerge.this.getSimulator());
382 GTUTypeGenerator gtuType1Lane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
383 GTUTypeGenerator gtuType3rdLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
384 gtuTypeAllCar.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
385 speedCar, 1.0);
386 gtuType1Lane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
387 speedCar, 1.0 - TRUCK_FRACTION);
388 gtuType1Lane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
389 speedTruck, TRUCK_FRACTION);
390 gtuType3rdLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
391 speedCar, 1.0 - 3 * TRUCK_FRACTION);
392 gtuType3rdLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
393 speedTruck, 3 * TRUCK_FRACTION);
394
395 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA1,
396 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
397 if (NETWORK.equals("shortWeave"))
398 {
399 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuTypeAllCar,
400 headwaysA2, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
401 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", routeGeneratorA, idGenerator, gtuType3rdLane,
402 headwaysA3, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
403 }
404 else
405 {
406 GTUTypeGenerator gtuType2ndLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
407 gtuType2ndLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
408 speedCar, 1.0 - 2 * TRUCK_FRACTION);
409 gtuType2ndLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI),
410 new GTUType("truck", TRUCK), speedTruck, 2 * TRUCK_FRACTION);
411 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuType2ndLane,
412 headwaysA2, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
413 }
414 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", routeGeneratorF, idGenerator, gtuType1Lane, headwaysF,
415 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
416
417 new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.createSI(10),
418 (OTSSimulatorInterface) this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
419
420 }
421
422
423
424
425
426
427
428 private Lane getLane(final CrossSectionLink link, final String id)
429 {
430 return (Lane) link.getCrossSectionElement(id);
431 }
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
452 final RouteGenerator routeGenerator, final IdGenerator idGenerator, final GTUTypeGenerator gtuTypeGenerator,
453 final Generator<Duration> headwayGenerator, final GTUColorer gtuColorer, final RoomChecker roomChecker,
454 final BehavioralCharacteristicsFactory bcFactory, final LaneBasedTacticalPlannerFactory<?> tacticalFactory,
455 final Time simulationTime) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
456 {
457
458 Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
459
460 initialLongitudinalPositions
461 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
462
463 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
464 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
465
466 CharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(strategicalFactory, routeGenerator,
467 idGenerator, ShortMerge.this.getSimulator(), this.network, gtuTypeGenerator, generationSpeed,
468 initialLongitudinalPositions);
469
470 new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, simulationTime, gtuColorer,
471 characteristicsGenerator, initialLongitudinalPositions, this.network, roomChecker);
472 }
473
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487 private class HeadwayGenerator implements Generator<Duration>
488 {
489
490
491 private final Frequency demand;
492
493
494
495
496 HeadwayGenerator(final Frequency demand)
497 {
498 this.demand = demand;
499 }
500
501
502 @Override
503 public Duration draw() throws ProbabilityException, ParameterException
504 {
505 return new Duration(
506 -Math.log(ShortMerge.this.getSimulator().getReplication().getStream("headwayGeneration").nextDouble())
507 / this.demand.si,
508 DurationUnit.SI);
509 }
510
511 }
512
513 }