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