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.animation.GraphLaneUtil;
29 import org.opentrafficsim.animation.colorer.LmrsSwitchableColorer;
30 import org.opentrafficsim.animation.gtu.colorer.GtuColorer;
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.definitions.DefaultsNl;
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.GtuException;
44 import org.opentrafficsim.core.gtu.GtuType;
45 import org.opentrafficsim.core.idgenerator.IdGenerator;
46 import org.opentrafficsim.core.network.Link;
47 import org.opentrafficsim.core.network.NetworkException;
48 import org.opentrafficsim.core.network.Node;
49 import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
50 import org.opentrafficsim.core.network.route.Route;
51 import org.opentrafficsim.core.parameters.ParameterFactory;
52 import org.opentrafficsim.core.parameters.ParameterFactoryByType;
53 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
54 import org.opentrafficsim.demo.ShortMerge.ShortMergeModel;
55 import org.opentrafficsim.draw.OtsDrawingException;
56 import org.opentrafficsim.draw.graphs.GraphPath;
57 import org.opentrafficsim.draw.graphs.PlotScheduler;
58 import org.opentrafficsim.draw.graphs.TrajectoryPlot;
59 import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
60 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator;
61 import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator.RoomChecker;
62 import org.opentrafficsim.road.gtu.generator.TtcRoomChecker;
63 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuTemplate;
64 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuTemplateDistribution;
65 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
66 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIdm;
67 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
68 import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlus;
69 import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlusFactory;
70 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationConflicts;
71 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
72 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationSpeedLimitTransition;
73 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationTrafficLights;
74 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLmrsPerceptionFactory;
75 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveCourtesy;
76 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
77 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
78 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
79 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
80 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.Lmrs;
81 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory;
82 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
83 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
84 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
85 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
86 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
87 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
88 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
89 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlannerFactory;
90 import org.opentrafficsim.road.network.RoadNetwork;
91 import org.opentrafficsim.road.network.factory.xml.parser.XmlParser;
92 import org.opentrafficsim.road.network.lane.CrossSectionLink;
93 import org.opentrafficsim.road.network.lane.Lane;
94 import org.opentrafficsim.road.network.lane.LanePosition;
95 import org.opentrafficsim.road.network.lane.object.SpeedSign;
96 import org.opentrafficsim.road.network.sampling.LaneDataRoad;
97 import org.opentrafficsim.road.network.sampling.RoadSampler;
98 import org.opentrafficsim.swing.graphs.OtsPlotScheduler;
99 import org.opentrafficsim.swing.graphs.SwingPlot;
100 import org.opentrafficsim.swing.graphs.SwingTrajectoryPlot;
101 import org.opentrafficsim.swing.gui.AnimationToggles;
102 import org.opentrafficsim.swing.gui.OtsAnimationPanel;
103 import org.opentrafficsim.swing.gui.OtsSimulationApplication;
104
105 import nl.tudelft.simulation.dsol.SimRuntimeException;
106 import nl.tudelft.simulation.jstats.distributions.DistNormal;
107 import nl.tudelft.simulation.jstats.distributions.DistUniform;
108 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
109 import nl.tudelft.simulation.jstats.streams.StreamInterface;
110 import nl.tudelft.simulation.language.DsolException;
111
112
113
114
115
116
117
118
119
120
121 public class ShortMerge extends OtsSimulationApplication<ShortMergeModel>
122 {
123
124 private static final long serialVersionUID = 20170407L;
125
126
127 static final String NETWORK = "shortMerge";
128
129
130 static final double TRUCK_FRACTION = 0.15;
131
132
133 static final double LEFT_FRACTION = 0.3;
134
135
136 static final Frequency MAIN_DEMAND = new Frequency(1000, FrequencyUnit.PER_HOUR);
137
138
139 static final Frequency RAMP_DEMAND = new Frequency(500, FrequencyUnit.PER_HOUR);
140
141
142 static final Synchronization SYNCHRONIZATION = Synchronization.ALIGN_GAP;
143
144
145 static final Cooperation COOPERATION = Cooperation.PASSIVE_MOVING;
146
147
148 static final boolean ADDITIONAL_INCENTIVES = true;
149
150
151 public static final Time SIMTIME = Time.instantiateSI(3600);
152
153
154
155
156
157
158
159
160 public ShortMerge(final String title, final OtsAnimationPanel panel, final ShortMergeModel model) throws OtsDrawingException
161 {
162 super(model, panel);
163 }
164
165
166 @Override
167 protected void setAnimationToggles()
168 {
169 AnimationToggles.setTextAnimationTogglesFull(getAnimationPanel());
170 getAnimationPanel().getAnimationPanel().toggleClass(Link.class);
171 getAnimationPanel().getAnimationPanel().toggleClass(Node.class);
172 getAnimationPanel().getAnimationPanel().showClass(SpeedSign.class);
173 }
174
175
176 @Override
177 protected void addTabs()
178 {
179 GraphPath<LaneDataRoad> path;
180 try
181 {
182 Lane start = ((CrossSectionLink) getModel().getNetwork().getLink("AB")).getLanes().get(1);
183 path = GraphLaneUtil.createPath("Right lane", start);
184 }
185 catch (NetworkException exception)
186 {
187 throw new RuntimeException("Could not create a path as a lane has no set speed limit.", exception);
188 }
189 RoadSampler sampler = new RoadSampler(getModel().getNetwork());
190 GraphPath.initRecording(sampler, path);
191 PlotScheduler scheduler = new OtsPlotScheduler(getModel().getSimulator());
192 Duration updateInterval = Duration.instantiateSI(10.0);
193 SwingPlot plot = new SwingTrajectoryPlot(
194 new TrajectoryPlot("Trajectory right lane", updateInterval, scheduler, sampler.getSamplerData(), path));
195 getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "Trajectories",
196 plot.getContentPane());
197 }
198
199
200
201
202
203 public static void main(final String[] args)
204 {
205 demo(true);
206 }
207
208
209
210
211
212 public static void demo(final boolean exitOnClose)
213 {
214 try
215 {
216 OtsAnimator simulator = new OtsAnimator("ShortMerge");
217 final ShortMergeModel otsModel = new ShortMergeModel(simulator);
218 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel);
219 OtsAnimationPanel animationPanel = new OtsAnimationPanel(otsModel.getNetwork().getExtent(), new Dimension(800, 600),
220 simulator, otsModel, new LmrsSwitchableColorer(DefaultsNl.GTU_TYPE_COLORS.toMap()), otsModel.getNetwork());
221 ShortMerge app = new ShortMerge("ShortMerge", animationPanel, otsModel);
222 app.setExitOnClose(exitOnClose);
223 animationPanel.enableSimulationControlButtons();
224 }
225 catch (SimRuntimeException | NamingException | RemoteException | OtsDrawingException | IndexOutOfBoundsException
226 | DsolException exception)
227 {
228 exception.printStackTrace();
229 }
230 }
231
232
233
234
235
236
237
238
239
240
241
242 public static class ShortMergeModel extends AbstractOtsModel
243 {
244
245 private static final long serialVersionUID = 20170407L;
246
247
248 private RoadNetwork network;
249
250
251
252
253 public ShortMergeModel(final OtsSimulatorInterface simulator)
254 {
255 super(simulator);
256 }
257
258
259
260
261 public void setNetwork(final RoadNetwork network)
262 {
263 this.network = network;
264 }
265
266
267 @Override
268 public void constructModel() throws SimRuntimeException
269 {
270 try
271 {
272 URL xmlURL = URLResource.getResource("/resources/lmrs/" + NETWORK + ".xml");
273 this.network = new RoadNetwork("ShortMerge", getSimulator());
274 new XmlParser(this.network).setUrl(xmlURL).build();
275 addGenerator();
276
277 }
278 catch (Exception exception)
279 {
280 exception.printStackTrace();
281 }
282 }
283
284
285 @Override
286 public RoadNetwork getNetwork()
287 {
288 return this.network;
289 }
290
291
292
293
294
295
296
297
298
299
300 private void addGenerator() throws ParameterException, GtuException, NetworkException, ProbabilityException,
301 SimRuntimeException, RemoteException
302 {
303
304 Random seedGenerator = new Random(1L);
305 Map<String, StreamInterface> streams = new LinkedHashMap<>();
306 StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
307 streams.put("headwayGeneration", stream);
308 streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
309 getStreamInformation().addStream("headwayGeneration", stream);
310 getStreamInformation().addStream("gtuClass", streams.get("gtuClass"));
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 = DefaultsNl.CAR;
342 GtuType truck = DefaultsNl.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 Generator<Route> routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
358 Generator<Route> 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(getSimulator(), MAIN_DEMAND);
374 Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
375 Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
376 Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), 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 LaneBasedGtuTemplate carA = new LaneBasedGtuTemplate(car, new ConstantGenerator<>(Length.instantiateSI(4.0)),
388 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorA);
389 LaneBasedGtuTemplate carF = new LaneBasedGtuTemplate(car, new ConstantGenerator<>(Length.instantiateSI(4.0)),
390 new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalFactory, routeGeneratorF);
391 LaneBasedGtuTemplate truckA = new LaneBasedGtuTemplate(truck, new ConstantGenerator<>(Length.instantiateSI(15.0)),
392 new ConstantGenerator<>(Length.instantiateSI(2.5)), speedTruck, strategicalFactory, routeGeneratorA);
393 LaneBasedGtuTemplate truckF = new LaneBasedGtuTemplate(truck, new ConstantGenerator<>(Length.instantiateSI(15.0)),
394 new ConstantGenerator<>(Length.instantiateSI(2.5)), speedTruck, strategicalFactory, routeGeneratorF);
395
396 Distribution<LaneBasedGtuTemplate> gtuTypeAllCarA = new Distribution<>(streams.get("gtuClass"));
397 gtuTypeAllCarA.add(new FrequencyAndObject<>(1.0, carA));
398
399 Distribution<LaneBasedGtuTemplate> gtuType1LaneF = new Distribution<>(streams.get("gtuClass"));
400 gtuType1LaneF.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carF));
401 gtuType1LaneF.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckF));
402
403 Distribution<LaneBasedGtuTemplate> gtuType2ndLaneA = new Distribution<>(streams.get("gtuClass"));
404 gtuType2ndLaneA.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carA));
405 gtuType2ndLaneA.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckA));
406
407 Distribution<LaneBasedGtuTemplate> gtuType3rdLaneA = new Distribution<>(streams.get("gtuClass"));
408 gtuType3rdLaneA.add(new FrequencyAndObject<>(1.0 - 3 * TRUCK_FRACTION, carA));
409 gtuType3rdLaneA.add(new FrequencyAndObject<>(3 * TRUCK_FRACTION, truckA));
410
411 GtuColorer colorer = new LmrsSwitchableColorer(DefaultsNl.GTU_TYPE_COLORS.toMap());
412 makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", idGenerator, gtuTypeAllCarA, headwaysA1, colorer,
413 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
414 if (NETWORK.equals("shortWeave"))
415 {
416 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuTypeAllCarA, headwaysA2, colorer,
417 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
418 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", idGenerator, gtuType3rdLaneA, headwaysA3, colorer,
419 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
420 }
421 else
422 {
423 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuType2ndLaneA, headwaysA2, colorer,
424 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
425 }
426 makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", idGenerator, gtuType1LaneF, headwaysF, colorer,
427 roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
428
429 new SpeedSign("sign1", getLane(linkA, "FORWARD1"), Length.instantiateSI(10), this.getSimulator(),
430 new Speed(130.0, SpeedUnit.KM_PER_HOUR), DefaultsNl.VEHICLE, Duration.ZERO,
431 new Duration(24, DurationUnit.HOUR));
432
433 }
434
435
436
437
438
439
440
441 private Lane getLane(final CrossSectionLink link, final String id)
442 {
443 return (Lane) link.getCrossSectionElement(id);
444 }
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465 private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id, final IdGenerator idGenerator,
466 final Distribution<LaneBasedGtuTemplate> distribution, final Generator<Duration> headwayGenerator,
467 final GtuColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
468 final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime,
469 final StreamInterface stream)
470 throws SimRuntimeException, ProbabilityException, GtuException, ParameterException, NetworkException
471 {
472
473 Set<LanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
474
475 initialLongitudinalPositions.add(new LanePosition(lane, new Length(5.0, LengthUnit.SI)));
476 LaneBasedGtuTemplateDistribution characteristicsGenerator = new LaneBasedGtuTemplateDistribution(distribution);
477 new LaneBasedGtuGenerator(id, headwayGenerator, characteristicsGenerator,
478 GeneratorPositions.create(initialLongitudinalPositions, stream), this.network, getSimulator(), roomChecker,
479 idGenerator);
480 }
481
482 }
483
484
485
486
487
488
489
490
491
492
493
494 private static class HeadwayGenerator implements Generator<Duration>
495 {
496
497 private final OtsSimulatorInterface simulator;
498
499
500 private final Frequency demand;
501
502
503
504
505
506 HeadwayGenerator(final OtsSimulatorInterface simulator, final Frequency demand)
507 {
508 this.simulator = simulator;
509 this.demand = demand;
510 }
511
512
513 @Override
514 public Duration draw() throws ProbabilityException, ParameterException
515 {
516 return new Duration(
517 -Math.log(this.simulator.getModel().getStream("headwayGeneration").nextDouble()) / this.demand.si,
518 DurationUnit.SI);
519 }
520
521 }
522
523 }