View Javadoc
1   package org.opentrafficsim.demo;
2   
3   import java.awt.Dimension;
4   import java.io.InputStream;
5   import java.rmi.RemoteException;
6   import java.util.ArrayList;
7   import java.util.HashMap;
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.base.parameters.ParameterException;
29  import org.opentrafficsim.base.parameters.ParameterSet;
30  import org.opentrafficsim.base.parameters.ParameterTypes;
31  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
32  import org.opentrafficsim.core.distributions.ConstantGenerator;
33  import org.opentrafficsim.core.distributions.Distribution;
34  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
35  import org.opentrafficsim.core.distributions.Generator;
36  import org.opentrafficsim.core.distributions.ProbabilityException;
37  import org.opentrafficsim.core.dsol.AbstractOTSModel;
38  import org.opentrafficsim.core.dsol.OTSAnimator;
39  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
40  import org.opentrafficsim.core.gtu.GTUDirectionality;
41  import org.opentrafficsim.core.gtu.GTUException;
42  import org.opentrafficsim.core.gtu.GTUType;
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.OTSNode;
48  import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
49  import org.opentrafficsim.core.network.route.Route;
50  import org.opentrafficsim.core.parameters.ParameterFactory;
51  import org.opentrafficsim.core.parameters.ParameterFactoryByType;
52  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
53  import org.opentrafficsim.demo.ShortMerge.ShortMergeModel;
54  import org.opentrafficsim.draw.core.OTSDrawingException;
55  import org.opentrafficsim.road.gtu.colorer.LmrsSwitchableColorer;
56  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
57  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
58  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
59  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
60  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
61  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
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.IncentiveKeep;
74  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
75  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
76  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
77  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
78  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
79  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
80  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
81  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
82  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
83  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
84  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
85  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
86  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
87  import org.opentrafficsim.road.network.OTSRoadNetwork;
88  import org.opentrafficsim.road.network.factory.xml.old.XmlNetworkLaneParserOld;
89  import org.opentrafficsim.road.network.lane.CrossSectionLink;
90  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
91  import org.opentrafficsim.road.network.lane.Lane;
92  import org.opentrafficsim.road.network.lane.object.SpeedSign;
93  import org.opentrafficsim.swing.gui.AnimationToggles;
94  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
95  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
96  
97  import nl.tudelft.simulation.dsol.SimRuntimeException;
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 
103 /**
104  * <p>
105  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
106  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
107  * <p>
108  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
109  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
110  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
111  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
112  */
113 public class ShortMerge extends OTSSimulationApplication<ShortMergeModel>
114 {
115     /** */
116     private static final long serialVersionUID = 20170407L;
117 
118     /** Network. */
119     static final String NETWORK = "shortMerge";
120 
121     /** Truck fraction. */
122     static final double TRUCK_FRACTION = 0.15;
123 
124     /** Left traffic fraction. */
125     static final double LEFT_FRACTION = 0.3;
126 
127     /** Main demand per lane. */
128     static final Frequency MAIN_DEMAND = new Frequency(1000, FrequencyUnit.PER_HOUR);
129 
130     /** Ramp demand. */
131     static final Frequency RAMP_DEMAND = new Frequency(500, FrequencyUnit.PER_HOUR);
132 
133     /** Synchronization. */
134     static final Synchronization SYNCHRONIZATION = Synchronization.ALIGN_GAP;
135 
136     /** Cooperation. */
137     static final Cooperation COOPERATION = Cooperation.PASSIVE_MOVING;
138 
139     /** Use additional incentives. */
140     static final boolean ADDITIONAL_INCENTIVES = true;
141 
142     /** Simulation time. */
143     public static final Time SIMTIME = Time.createSI(3600);
144 
145     /**
146      * Create a ShortMerge Swing application.
147      * @param title String; the title of the Frame
148      * @param panel OTSAnimationPanel; the tabbed panel to display
149      * @param model ShortMergeModel; the model
150      * @throws OTSDrawingException on animation error
151      */
152     public ShortMerge(final String title, final OTSAnimationPanel panel, final ShortMergeModel model) throws OTSDrawingException
153     {
154         super(model, panel);
155     }
156 
157     /** {@inheritDoc} */
158     @Override
159     protected void setAnimationToggles()
160     {
161         AnimationToggles.setTextAnimationTogglesFull(getAnimationPanel());
162         getAnimationPanel().getAnimationPanel().toggleClass(OTSLink.class);
163         getAnimationPanel().getAnimationPanel().toggleClass(OTSNode.class);
164         getAnimationPanel().getAnimationPanel().showClass(SpeedSign.class);
165     }
166 
167     /**
168      * Main program.
169      * @param args String[]; the command line arguments (not used)
170      */
171     public static void main(final String[] args)
172     {
173         demo(true);
174     }
175 
176     /**
177      * Start the demo.
178      * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false
179      */
180     public static void demo(final boolean exitOnClose)
181     {
182         try
183         {
184             OTSAnimator simulator = new OTSAnimator();
185             final ShortMergeModel otsModel = new ShortMergeModel(simulator);
186             simulator.initialize(Time.ZERO, Duration.ZERO, Duration.createSI(3600.0), otsModel);
187             OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(), new Dimension(800, 600),
188                     simulator, otsModel, new LmrsSwitchableColorer(), otsModel.getNetwork());
189             ShortMerge app = new ShortMerge("ShortMerge", animationPanel, otsModel);
190             app.setExitOnClose(exitOnClose);
191         }
192         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
193         {
194             exception.printStackTrace();
195         }
196     }
197 
198     /**
199      * <p>
200      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
201      * <br>
202      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
203      * <p>
204      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
205      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
206      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
207      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
208      */
209     static class ShortMergeModel extends AbstractOTSModel
210     {
211         /** */
212         private static final long serialVersionUID = 20170407L;
213 
214         /** The network. */
215         private OTSRoadNetwork network;
216 
217         /**
218          * @param simulator OTSSimulatorInterface; the simulator
219          */
220         ShortMergeModel(final OTSSimulatorInterface simulator)
221         {
222             super(simulator);
223         }
224 
225         /**
226          * @param network OTSRoadNetwork; set network.
227          */
228         public void setNetwork(final OTSRoadNetwork network)
229         {
230             this.network = network;
231         }
232 
233         /** {@inheritDoc} */
234         @Override
235         public void constructModel() throws SimRuntimeException
236         {
237             try
238             {
239                 InputStream stream = URLResource.getResourceAsStream("/lmrs/" + NETWORK + ".xml");
240                 XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(this.simulator);
241                 this.network = new OTSRoadNetwork("ShortMerge", true);
242                 nlp.build(stream, this.network, false);
243 
244                 addGenerator();
245 
246             }
247             catch (Exception exception)
248             {
249                 exception.printStackTrace();
250             }
251         }
252 
253         /** {@inheritDoc} */
254         @Override
255         public OTSRoadNetwork getNetwork()
256         {
257             return this.network;
258         }
259 
260         /**
261          * Create generators.
262          * @throws ParameterException on parameter exception
263          * @throws GTUException on GTU exception
264          * @throws NetworkException if not does not exist
265          * @throws ProbabilityException negative probability
266          * @throws SimRuntimeException in case of sim run time exception
267          * @throws RemoteException if no simulator
268          */
269         private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
270                 SimRuntimeException, RemoteException
271         {
272 
273             Random seedGenerator = new Random(1L);
274             Map<String, StreamInterface> streams = new HashMap<>();
275             StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
276             streams.put("headwayGeneration", stream);
277             streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
278             this.getSimulator().getReplication().setStreams(streams);
279 
280             TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
281             IdGenerator idGenerator = new IdGenerator("");
282 
283             CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
284             ParameterSet params = new ParameterSet();
285             params.setDefaultParameter(AbstractIDM.DELTA);
286 
287             Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
288             Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
289             Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
290             mandatoryIncentives.add(new IncentiveRoute());
291             if (ADDITIONAL_INCENTIVES)
292             {
293                 // mandatoryIncentives.add(new IncentiveGetInLane());
294             }
295             voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
296             voluntaryIncentives.add(new IncentiveKeep());
297             if (ADDITIONAL_INCENTIVES)
298             {
299                 voluntaryIncentives.add(new IncentiveCourtesy());
300                 voluntaryIncentives.add(new IncentiveSocioSpeed());
301             }
302             accelerationIncentives.add(new AccelerationSpeedLimitTransition());
303             accelerationIncentives.add(new AccelerationTrafficLights());
304             accelerationIncentives.add(new AccelerationConflicts());
305             LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory = new LMRSFactory(idmPlusFactory,
306                     new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION, COOPERATION, GapAcceptance.INFORMED, Tailgating.NONE,
307                     mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
308 
309             GTUType car = new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR));
310             GTUType truck = new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK));
311             Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
312             Route routeAG = !NETWORK.equals("shortWeave") ? null
313                     : this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
314             Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
315             Route routeFG = !NETWORK.equals("shortWeave") ? null
316                     : this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
317 
318             double leftFraction = NETWORK.equals("shortWeave") ? LEFT_FRACTION : 0.0;
319             List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
320             routesA.add(new FrequencyAndObject<>(1.0 - leftFraction, routeAE));
321             routesA.add(new FrequencyAndObject<>(leftFraction, routeAG));
322             List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
323             routesF.add(new FrequencyAndObject<>(1.0 - leftFraction, routeFE));
324             routesF.add(new FrequencyAndObject<>(leftFraction, routeFG));
325             Generator<Route> routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
326             Generator<Route> routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
327 
328             Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
329             Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
330 
331             CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
332             CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FF2");
333 
334             ParameterFactoryByType bcFactory = new ParameterFactoryByType();
335             bcFactory.addParameter(car, ParameterTypes.FSPEED, new DistNormal(stream, 123.7 / 120, 12.0 / 120));
336             bcFactory.addParameter(car, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
337             bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
338             bcFactory.addParameter(truck, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
339             bcFactory.addParameter(Tailgating.RHO, Tailgating.RHO.getDefaultValue());
340 
341             Generator<Duration> headwaysA1 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
342             Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
343             Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
344             Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), RAMP_DEMAND);
345 
346             // speed generators
347             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
348                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 160, 200), SpeedUnit.KM_PER_HOUR);
349             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
350                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 80, 95), SpeedUnit.KM_PER_HOUR);
351             // strategical planner factory
352             LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
353                     new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
354             // vehicle templates, with routes
355             LaneBasedTemplateGTUType carA =
356                     new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
357                             new ConstantGenerator<>(Length.createSI(4.0)), new ConstantGenerator<>(Length.createSI(2.0)),
358                             speedCar, strategicalFactory, routeGeneratorA);
359             LaneBasedTemplateGTUType carF =
360                     new LaneBasedTemplateGTUType(new GTUType("car", this.network.getGtuType(GTUType.DEFAULTS.CAR)),
361                             new ConstantGenerator<>(Length.createSI(4.0)), new ConstantGenerator<>(Length.createSI(2.0)),
362                             speedCar, strategicalFactory, routeGeneratorF);
363             LaneBasedTemplateGTUType truckA =
364                     new LaneBasedTemplateGTUType(new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
365                             new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
366                             speedTruck, strategicalFactory, routeGeneratorA);
367             LaneBasedTemplateGTUType truckF =
368                     new LaneBasedTemplateGTUType(new GTUType("truck", this.network.getGtuType(GTUType.DEFAULTS.TRUCK)),
369                             new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
370                             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          * Get lane from link by id.
412          * @param link CrossSectionLink; link
413          * @param id String; id
414          * @return lane
415          */
416         private Lane getLane(final CrossSectionLink link, final String id)
417         {
418             return (Lane) link.getCrossSectionElement(id);
419         }
420 
421         /**
422          * @param lane Lane; the reference lane for this generator
423          * @param generationSpeed Speed; the speed of the GTU
424          * @param id String; the id of the generator itself
425          * @param idGenerator IdGenerator; the generator for the ID
426          * @param distribution Distribution&lt;LaneBasedTemplateGTUType&gt;; the type generator for the GTU
427          * @param headwayGenerator Generator&lt;Duration&gt;; the headway generator for the GTU
428          * @param gtuColorer GTUColorer; the GTU colorer for animation
429          * @param roomChecker RoomChecker; the checker to see if there is room for the GTU
430          * @param bcFactory ParameterFactory; the factory to generate parameters for the GTU
431          * @param tacticalFactory LaneBasedTacticalPlannerFactory&lt;?&gt;; the generator for the tactical planner
432          * @param simulationTime Time; simulation time
433          * @param stream StreamInterface; random numbers stream
434          * @throws SimRuntimeException in case of scheduling problems
435          * @throws ProbabilityException in case of an illegal probability distribution
436          * @throws GTUException in case the GTU is inconsistent
437          * @throws ParameterException in case a parameter for the perception is missing
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             // TODO DIR_MINUS
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      * <p>
461      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
462      * <br>
463      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
464      * <p>
465      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
466      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
467      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
468      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
469      */
470     private static class HeadwayGenerator implements Generator<Duration>
471     {
472         /** the simulator. */
473         private final OTSSimulatorInterface simulator;
474 
475         /** Demand level. */
476         private final Frequency demand;
477 
478         /**
479          * @param simulator OTSSimulatorInterface; the simulator
480          * @param demand Frequency; demand
481          */
482         HeadwayGenerator(final OTSSimulatorInterface simulator, final Frequency demand)
483         {
484             this.simulator = simulator;
485             this.demand = demand;
486         }
487 
488         /** {@inheritDoc} */
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 }