View Javadoc
1   package org.opentrafficsim.demo.carFollowing;
2   
3   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.TRUCK;
5   
6   import java.io.InputStream;
7   import java.rmi.RemoteException;
8   import java.util.ArrayList;
9   import java.util.HashMap;
10  import java.util.HashSet;
11  import java.util.LinkedHashSet;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Random;
15  import java.util.Set;
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.opentrafficsim.base.modelproperties.Property;
29  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
30  import org.opentrafficsim.core.distributions.Generator;
31  import org.opentrafficsim.core.distributions.ProbabilityException;
32  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
33  import org.opentrafficsim.core.dsol.OTSModelInterface;
34  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
35  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
36  import org.opentrafficsim.core.gtu.GTUDirectionality;
37  import org.opentrafficsim.core.gtu.GTUException;
38  import org.opentrafficsim.core.gtu.GTUType;
39  import org.opentrafficsim.core.gtu.animation.GTUColorer;
40  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
41  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
42  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactoryByType;
43  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
44  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
45  import org.opentrafficsim.core.idgenerator.IdGenerator;
46  import org.opentrafficsim.core.network.LongitudinalDirectionality;
47  import org.opentrafficsim.core.network.NetworkException;
48  import org.opentrafficsim.core.network.OTSLink;
49  import org.opentrafficsim.core.network.OTSNetwork;
50  import org.opentrafficsim.core.network.OTSNode;
51  import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
52  import org.opentrafficsim.core.network.route.Route;
53  import org.opentrafficsim.core.network.route.RouteGenerator;
54  import org.opentrafficsim.road.animation.AnimationToggles;
55  import org.opentrafficsim.road.gtu.animation.LmrsSwitchableColorer;
56  import org.opentrafficsim.road.gtu.generator.CharacteristicsGenerator;
57  import org.opentrafficsim.road.gtu.generator.GTUTypeGenerator;
58  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
59  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
60  import org.opentrafficsim.road.gtu.generator.SpeedGenerator;
61  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
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.IncentiveGetInLane;
74  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveHierarchal;
75  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
76  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
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.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.VoluntaryIncentive;
84  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
85  import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
86  import org.opentrafficsim.road.network.lane.CrossSectionLink;
87  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
88  import org.opentrafficsim.road.network.lane.Lane;
89  import org.opentrafficsim.road.network.lane.object.SpeedSign;
90  import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
91  import org.opentrafficsim.simulationengine.OTSSimulationException;
92  
93  import nl.tudelft.simulation.dsol.SimRuntimeException;
94  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
95  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
96  import nl.tudelft.simulation.jstats.streams.StreamInterface;
97  import nl.tudelft.simulation.language.io.URLResource;
98  
99  /**
100  * <p>
101  * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
102  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
103  * <p>
104  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
105  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
106  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
107  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
108  */
109 public class ShortMerge extends AbstractWrappableAnimation
110 {
111 
112     /** Network. */
113     static final String NETWORK = "shortMerge";
114 
115     /** Truck fraction. */
116     static final double TRUCK_FRACTION = 0.15;
117 
118     /** Left traffic fraction. */
119     static final double LEFT_FRACTION = 0.6;
120 
121     /** Main demand. */
122     static final Frequency MAIN_DEMAND = new Frequency(1200, FrequencyUnit.PER_HOUR);
123 
124     /** Ramp demand. */
125     static final Frequency RAMP_DEMAND = new Frequency(0, FrequencyUnit.PER_HOUR);
126 
127     /** Synchronization. */
128     static final Synchronization SYNCHRONIZATION = Synchronization.ACTIVE;
129 
130     /** Use additional incentives. */
131     static final boolean ADDITIONAL_INCENTIVES = true;
132 
133     /** Simulation time. */
134     public static final Time SIMTIME = Time.createSI(3600);
135 
136     /** */
137     private static final long serialVersionUID = 20170407L;
138 
139     /** The simulator. */
140     private OTSDEVSSimulatorInterface sim;
141 
142     /** {@inheritDoc} */
143     @Override
144     public String shortName()
145     {
146         return "ShortMerge";
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public String description()
152     {
153         return "Short merge to test lane change models.";
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     protected final void addAnimationToggles()
159     {
160         AnimationToggles.setTextAnimationTogglesFull(this);
161         this.toggleAnimationClass(OTSLink.class);
162         this.toggleAnimationClass(OTSNode.class);
163         showAnimationClass(SpeedSign.class);
164     }
165 
166     /** {@inheritDoc} */
167     @Override
168     protected GTUColorer getColorer()
169     {
170         return new LmrsSwitchableColorer();
171     }
172 
173     /** {@inheritDoc} */
174     @Override
175     protected OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
176     {
177         return new ShortMergeModel(colorer);
178     }
179 
180     /**
181      * @return simulator.
182      */
183     public OTSDEVSSimulatorInterface getSimulator()
184     {
185         return this.sim;
186     }
187 
188     /**
189      * @param simulator set simulator.
190      */
191     public void setSimulator(final OTSDEVSSimulatorInterface simulator)
192     {
193         this.sim = simulator;
194     }
195 
196     /**
197      * Main method.
198      * @param args args for main program
199      */
200     public static void main(final String[] args)
201     {
202 
203         ShortMerge shortMerge = new ShortMerge();
204         try
205         {
206             shortMerge.buildAnimator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMTIME.si), new ArrayList<Property<?>>(),
207                     null, true);
208         }
209         catch (Exception exception)
210         {
211             exception.printStackTrace();
212         }
213 
214     }
215 
216     /**
217      * <p>
218      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
219      * <br>
220      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
221      * <p>
222      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
223      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
224      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
225      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
226      */
227     class ShortMergeModel implements OTSModelInterface
228     {
229 
230         /**
231          * @param network set network.
232          */
233         public void setNetwork(final OTSNetwork network)
234         {
235             this.network = network;
236         }
237 
238         /** */
239         private static final long serialVersionUID = 20170407L;
240 
241         /** The network. */
242         private OTSNetwork network;
243 
244         /** Colorer. */
245         private final GTUColorer colorer;
246 
247         /**
248          * @param colorer colorer
249          */
250         ShortMergeModel(final GTUColorer colorer)
251         {
252             this.colorer = colorer;
253         }
254 
255         /** {@inheritDoc} */
256         @Override
257         public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
258                 throws SimRuntimeException, RemoteException
259         {
260             ShortMerge.this.setSimulator((OTSDEVSSimulatorInterface) simulator);
261 
262             try
263             {
264                 InputStream stream = URLResource.getResourceAsStream("/lmrs/" + NETWORK + ".xml");
265                 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((OTSDEVSSimulatorInterface) simulator);
266                 this.network = new OTSNetwork("ShortMerge");
267                 nlp.build(stream, this.network);
268 
269                 addGenerator();
270 
271             }
272             catch (Exception exception)
273             {
274                 exception.printStackTrace();
275             }
276         }
277 
278         /** {@inheritDoc} */
279         @Override
280         public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
281         {
282             return ShortMerge.this.getSimulator();
283         }
284 
285         /** {@inheritDoc} */
286         @Override
287         public OTSNetwork getNetwork()
288         {
289             return this.network;
290         }
291 
292         /**
293          * Create generators.
294          * @throws ParameterException on parameter exception
295          * @throws GTUException on GTU exception
296          * @throws NetworkException if not does not exist
297          * @throws ProbabilityException negative probability
298          * @throws SimRuntimeException in case of sim run time exception
299          * @throws RemoteException if no simulator
300          */
301         private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
302                 SimRuntimeException, RemoteException
303         {
304 
305             Random seedGenerator = new Random(1L);
306             Map<String, StreamInterface> streams = new HashMap<>();
307             StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
308             streams.put("headwayGeneration", stream);
309             streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
310             this.getSimulator().getReplication().setStreams(streams);
311 
312             TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
313             IdGenerator idGenerator = new IdGenerator("");
314 
315             CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory();
316             BehavioralCharacteristics bc = new BehavioralCharacteristics();
317             bc.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                 mandatoryIncentives.add(new IncentiveGetInLane());
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 IncentiveHierarchal());
333             }
334             accelerationIncentives.add(new AccelerationSpeedLimitTransition());
335             accelerationIncentives.add(new AccelerationTrafficLights());
336             accelerationIncentives.add(new AccelerationConflicts());
337             LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
338                     new LMRSFactory(idmPlusFactory, bc, new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION,
339                             mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
340 
341             GTUType car = new GTUType("car", CAR);
342             GTUType truck = new GTUType("truck", 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             RouteGenerator routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
358             RouteGenerator 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             BehavioralCharacteristicsFactoryByType bcFactory = new BehavioralCharacteristicsFactoryByType();
367             bcFactory.addGaussianParameter(car, ParameterTypes.FSPEED, 123.7 / 120, 12.0 / 120, stream);
368             bcFactory.addGaussianParameter(car, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
369             bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
370             bcFactory.addGaussianParameter(truck, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
371 
372             Generator<Duration> headwaysA1 = new HeadwayGenerator(MAIN_DEMAND);
373             Generator<Duration> headwaysA2 = new HeadwayGenerator(MAIN_DEMAND);
374             Generator<Duration> headwaysA3 = new HeadwayGenerator(MAIN_DEMAND);
375             Generator<Duration> headwaysF = new HeadwayGenerator(RAMP_DEMAND);
376 
377             SpeedGenerator speedCar = new SpeedGenerator(new Speed(160.0, SpeedUnit.KM_PER_HOUR),
378                     new Speed(200.0, SpeedUnit.KM_PER_HOUR), stream);
379             SpeedGenerator speedTruck =
380                     new SpeedGenerator(new Speed(80.0, SpeedUnit.KM_PER_HOUR), new Speed(95.0, SpeedUnit.KM_PER_HOUR), stream);
381             GTUTypeGenerator gtuTypeAllCar = new GTUTypeGenerator(ShortMerge.this.getSimulator());
382             GTUTypeGenerator gtuType1Lane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
383             GTUTypeGenerator gtuType3rdLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
384             gtuTypeAllCar.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
385                     speedCar, 1.0);
386             gtuType1Lane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
387                     speedCar, 1.0 - TRUCK_FRACTION);
388             gtuType1Lane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
389                     speedTruck, TRUCK_FRACTION);
390             gtuType3rdLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
391                     speedCar, 1.0 - 3 * TRUCK_FRACTION);
392             gtuType3rdLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
393                     speedTruck, 3 * TRUCK_FRACTION);
394 
395             makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA1,
396                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
397             if (NETWORK.equals("shortWeave"))
398             {
399                 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuTypeAllCar,
400                         headwaysA2, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
401                 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", routeGeneratorA, idGenerator, gtuType3rdLane,
402                         headwaysA3, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
403             }
404             else
405             {
406                 GTUTypeGenerator gtuType2ndLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
407                 gtuType2ndLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
408                         speedCar, 1.0 - 2 * TRUCK_FRACTION);
409                 gtuType2ndLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI),
410                         new GTUType("truck", TRUCK), speedTruck, 2 * TRUCK_FRACTION);
411                 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuType2ndLane,
412                         headwaysA2, this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
413             }
414             makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", routeGeneratorF, idGenerator, gtuType1Lane, headwaysF,
415                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
416 
417             new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.createSI(10),
418                     (OTSSimulatorInterface) this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
419 
420         }
421 
422         /**
423          * Get lane from link by id.
424          * @param link link
425          * @param id id
426          * @return lane
427          */
428         private Lane getLane(final CrossSectionLink link, final String id)
429         {
430             return (Lane) link.getCrossSectionElement(id);
431         }
432 
433         /**
434          * @param lane the reference lane for this generator
435          * @param generationSpeed the speed of the GTU
436          * @param id the id of the generator itself
437          * @param routeGenerator the generator for the route
438          * @param idGenerator the generator for the ID
439          * @param gtuTypeGenerator the type generator for the GTU
440          * @param headwayGenerator the headway generator for the GTU
441          * @param gtuColorer the GTU colorer for animation
442          * @param roomChecker the checker to see if there is room for the GTU
443          * @param bcFactory the factory to generate behavioral characteristics for the GTU
444          * @param tacticalFactory the generator for the tactical planner
445          * @param simulationTime simulation time
446          * @throws SimRuntimeException in case of scheduling problems
447          * @throws ProbabilityException in case of an illegal probability distribution
448          * @throws GTUException in case the GTU is inconsistent
449          * @throws ParameterException in case a parameter for the perception is missing
450          */
451         private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
452                 final RouteGenerator routeGenerator, final IdGenerator idGenerator, final GTUTypeGenerator gtuTypeGenerator,
453                 final Generator<Duration> headwayGenerator, final GTUColorer gtuColorer, final RoomChecker roomChecker,
454                 final BehavioralCharacteristicsFactory bcFactory, final LaneBasedTacticalPlannerFactory<?> tacticalFactory,
455                 final Time simulationTime) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
456         {
457 
458             Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
459             // TODO DIR_MINUS
460             initialLongitudinalPositions
461                     .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
462 
463             LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
464                     new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
465 
466             CharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(strategicalFactory, routeGenerator,
467                     idGenerator, ShortMerge.this.getSimulator(), this.network, gtuTypeGenerator, generationSpeed,
468                     initialLongitudinalPositions);
469 
470             new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, simulationTime, gtuColorer,
471                     characteristicsGenerator, initialLongitudinalPositions, this.network, roomChecker);
472         }
473 
474     }
475 
476     /**
477      * <p>
478      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
479      * <br>
480      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
481      * <p>
482      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
483      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
484      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
485      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
486      */
487     private class HeadwayGenerator implements Generator<Duration>
488     {
489 
490         /** Demand level. */
491         private final Frequency demand;
492 
493         /**
494          * @param demand demand
495          */
496         HeadwayGenerator(final Frequency demand)
497         {
498             this.demand = demand;
499         }
500 
501         /** {@inheritDoc} */
502         @Override
503         public Duration draw() throws ProbabilityException, ParameterException
504         {
505             return new Duration(
506                     -Math.log(ShortMerge.this.getSimulator().getReplication().getStream("headwayGeneration").nextDouble())
507                             / this.demand.si,
508                     DurationUnit.SI);
509         }
510 
511     }
512 
513 }