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.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.FrequencyUnit;
18 import org.djunits.unit.LengthUnit;
19 import org.djunits.unit.SpeedUnit;
20 import org.djunits.unit.TimeUnit;
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.core.distributions.Distribution.FrequencyAndObject;
29 import org.opentrafficsim.core.distributions.Generator;
30 import org.opentrafficsim.core.distributions.ProbabilityException;
31 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
32 import org.opentrafficsim.core.dsol.OTSModelInterface;
33 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
34 import org.opentrafficsim.core.gtu.GTUDirectionality;
35 import org.opentrafficsim.core.gtu.GTUException;
36 import org.opentrafficsim.core.gtu.GTUType;
37 import org.opentrafficsim.core.gtu.animation.GTUColorer;
38 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
39 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
40 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactoryByType;
41 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
42 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
43 import org.opentrafficsim.core.idgenerator.IdGenerator;
44 import org.opentrafficsim.core.network.NetworkException;
45 import org.opentrafficsim.core.network.OTSLink;
46 import org.opentrafficsim.core.network.OTSNetwork;
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.network.route.RouteGenerator;
51 import org.opentrafficsim.road.animation.AnimationToggles;
52 import org.opentrafficsim.road.gtu.generator.CharacteristicsGenerator;
53 import org.opentrafficsim.road.gtu.generator.GTUTypeGenerator;
54 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
55 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
56 import org.opentrafficsim.road.gtu.generator.SpeedGenerator;
57 import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
58 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
59 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
60 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
61 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
62 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
64 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
65 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
66 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
67 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
68 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
69 import org.opentrafficsim.road.network.lane.CrossSectionLink;
70 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
71 import org.opentrafficsim.road.network.lane.Lane;
72 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
73 import org.opentrafficsim.simulationengine.OTSSimulationException;
74
75 import nl.tudelft.simulation.dsol.SimRuntimeException;
76 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
77 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
78 import nl.tudelft.simulation.jstats.streams.StreamInterface;
79 import nl.tudelft.simulation.language.io.URLResource;
80
81
82
83
84
85
86
87
88
89
90
91 public class ShortMerge extends AbstractWrappableAnimation
92 {
93
94
95 public static final Time SIMTIME = Time.createSI(3600);
96
97
98 private static final long serialVersionUID = 20170407L;
99
100
101 private OTSDEVSSimulatorInterface sim;
102
103
104 @Override
105 public String shortName()
106 {
107 return "ShortMerge";
108 }
109
110
111 @Override
112 public String description()
113 {
114 return "Short merge to test lane change models.";
115 }
116
117
118 @Override
119 protected final void addAnimationToggles()
120 {
121 AnimationToggles.setTextAnimationTogglesFull(this);
122 this.toggleAnimationClass(OTSLink.class);
123 this.toggleAnimationClass(OTSNode.class);
124 }
125
126
127 @Override
128 protected OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
129 {
130 return new ShortMergeModel(colorer);
131 }
132
133
134
135
136 public OTSDEVSSimulatorInterface getSimulator()
137 {
138 return this.sim;
139 }
140
141
142
143
144 public void setSimulator(final OTSDEVSSimulatorInterface simulator)
145 {
146 this.sim = simulator;
147 }
148
149
150
151
152
153 public static void main(final String[] args)
154 {
155
156 ShortMerge shortMerge = new ShortMerge();
157 try
158 {
159 shortMerge.buildAnimator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMTIME.si), new ArrayList<Property<?>>(),
160 null, true);
161 }
162 catch (Exception exception)
163 {
164 exception.printStackTrace();
165 }
166
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180 class ShortMergeModel implements OTSModelInterface
181 {
182
183
184
185
186 public void setNetwork(final OTSNetwork network)
187 {
188 this.network = network;
189 }
190
191
192 private static final long serialVersionUID = 20170407L;
193
194
195 private OTSNetwork network;
196
197
198 private final GTUColorer colorer;
199
200
201
202
203 ShortMergeModel(final GTUColorer colorer)
204 {
205 this.colorer = colorer;
206 }
207
208
209 @Override
210 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
211 throws SimRuntimeException, RemoteException
212 {
213 ShortMerge.this.setSimulator((OTSDEVSSimulatorInterface) simulator);
214
215 try
216 {
217 InputStream stream = URLResource.getResourceAsStream("/lmrs/shortMerge.xml");
218 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((OTSDEVSSimulatorInterface) simulator);
219 this.network = new OTSNetwork("ShortMerge");
220 nlp.build(stream, this.network);
221
222 addGenerator();
223
224 }
225 catch (Exception exception)
226 {
227 exception.printStackTrace();
228 }
229 }
230
231
232 @Override
233 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
234 {
235 return ShortMerge.this.getSimulator();
236 }
237
238
239 @Override
240 public OTSNetwork getNetwork()
241 {
242 return this.network;
243 }
244
245
246
247
248
249
250
251
252
253
254 private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
255 SimRuntimeException, RemoteException
256 {
257
258 Random seedGenerator = new Random(1L);
259 Map<String, StreamInterface> streams = new HashMap<>();
260 StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
261 streams.put("headwayGeneration", stream);
262 streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
263 this.getSimulator().getReplication().setStreams(streams);
264
265 TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, TimeUnit.SI));
266 IdGenerator idGenerator = new IdGenerator("");
267
268 CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory();
269 BehavioralCharacteristics bc = new BehavioralCharacteristics();
270 bc.setDefaultParameter(AbstractIDM.DELTA);
271
272 LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
273 new LMRSFactory(idmPlusFactory, bc, new DefaultLMRSPerceptionFactory());
274
275 GTUType car = new GTUType("car", CAR);
276 GTUType truck = new GTUType("truck", TRUCK);
277 Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
278 Route routeAG = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
279 Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
280 Route routeFG = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
281
282 List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
283 routesA.add(new FrequencyAndObject<>(0.2, routeAE));
284 routesA.add(new FrequencyAndObject<>(0.8, routeAG));
285 List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
286 routesF.add(new FrequencyAndObject<>(0.2, routeFE));
287 routesF.add(new FrequencyAndObject<>(0.8, routeFG));
288 RouteGenerator routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
289 RouteGenerator routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
290
291 Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
292 Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
293
294 CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
295 CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FB");
296
297 BehavioralCharacteristicsFactoryByType bcFactory = new BehavioralCharacteristicsFactoryByType();
298 bcFactory.addGaussianParameter(car, ParameterTypes.FSPEED, 123.7 / 120, 12.0 / 120, stream);
299 bcFactory.addGaussianParameter(car, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
300 bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
301 bcFactory.addGaussianParameter(truck, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
302
303 Generator<Duration> headwaysA1 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
304 Generator<Duration> headwaysA2 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
305 Generator<Duration> headwaysA3 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
306 Generator<Duration> headwaysF = new HeadwayGenerator(new Frequency(600, FrequencyUnit.PER_HOUR));
307
308 SpeedGenerator speedCar = new SpeedGenerator(new Speed(160.0, SpeedUnit.KM_PER_HOUR),
309 new Speed(200.0, SpeedUnit.KM_PER_HOUR), stream);
310 SpeedGenerator speedTruck =
311 new SpeedGenerator(new Speed(80.0, SpeedUnit.KM_PER_HOUR), new Speed(95.0, SpeedUnit.KM_PER_HOUR), stream);
312 GTUTypeGenerator gtuTypeAllCar = new GTUTypeGenerator(ShortMerge.this.getSimulator());
313 GTUTypeGenerator gtuType1Lane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
314 GTUTypeGenerator gtuType3rdLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
315 gtuTypeAllCar.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
316 speedCar, 1.0);
317 gtuType1Lane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
318 speedCar, 0.9);
319 gtuType1Lane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
320 speedTruck, 0.1);
321 gtuType3rdLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
322 speedCar, 0.7);
323 gtuType3rdLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
324 speedTruck, 0.3);
325
326 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA1,
327 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
328 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA2,
329 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
330 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", routeGeneratorA, idGenerator, gtuType3rdLane, headwaysA3,
331 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
332 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", routeGeneratorF, idGenerator, gtuType1Lane, headwaysF,
333 this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
334
335 }
336
337
338
339
340
341
342
343 private Lane getLane(final CrossSectionLink link, final String id)
344 {
345 for (Lane lane : link.getLanes())
346 {
347 if (lane.getId().equals(id))
348 {
349 return lane;
350 }
351 }
352 throw new RuntimeException("Could not find lane " + id + " on link " + link.getId());
353 }
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
374 final RouteGenerator routeGenerator, final IdGenerator idGenerator, final GTUTypeGenerator gtuTypeGenerator,
375 final Generator<Duration> headwayGenerator, final GTUColorer gtuColorer, final RoomChecker roomChecker,
376 final BehavioralCharacteristicsFactory bcFactory, final LaneBasedTacticalPlannerFactory<?> tacticalFactory,
377 final Time simulationTime) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
378 {
379 Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
380
381 initialLongitudinalPositions
382 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
383
384 LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
385 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
386
387 CharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(strategicalFactory, routeGenerator,
388 idGenerator, ShortMerge.this.getSimulator(), this.network, gtuTypeGenerator, generationSpeed,
389 initialLongitudinalPositions);
390
391 new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, simulationTime, gtuColorer,
392 characteristicsGenerator, initialLongitudinalPositions, this.network, roomChecker);
393 }
394
395 }
396
397
398
399
400
401
402
403
404
405
406
407
408 private class HeadwayGenerator implements Generator<Duration>
409 {
410
411
412 private final Frequency demand;
413
414
415
416
417 HeadwayGenerator(final Frequency demand)
418 {
419 this.demand = demand;
420 }
421
422
423 @Override
424 public Duration draw() throws ProbabilityException, ParameterException
425 {
426 return new Duration(
427 -Math.log(ShortMerge.this.getSimulator().getReplication().getStream("headwayGeneration").nextDouble())
428 / this.demand.si,
429 TimeUnit.SI);
430 }
431
432 }
433
434 }