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