View Javadoc
1   package org.opentrafficsim.ahfe;
2   
3   import java.rmi.RemoteException;
4   import java.util.HashMap;
5   import java.util.HashSet;
6   import java.util.Map;
7   import java.util.Random;
8   import java.util.Set;
9   
10  import org.djunits.unit.AccelerationUnit;
11  import org.djunits.unit.DurationUnit;
12  import org.djunits.unit.FrequencyUnit;
13  import org.djunits.unit.LengthUnit;
14  import org.djunits.unit.SpeedUnit;
15  import org.djunits.unit.TimeUnit;
16  import org.djunits.value.StorageType;
17  import org.djunits.value.ValueException;
18  import org.djunits.value.vdouble.scalar.Acceleration;
19  import org.djunits.value.vdouble.scalar.Duration;
20  import org.djunits.value.vdouble.scalar.Frequency;
21  import org.djunits.value.vdouble.scalar.Length;
22  import org.djunits.value.vdouble.scalar.Speed;
23  import org.djunits.value.vdouble.scalar.Time;
24  import org.djunits.value.vdouble.vector.FrequencyVector;
25  import org.djunits.value.vdouble.vector.TimeVector;
26  import org.djutils.exceptions.Throw;
27  import org.djutils.exceptions.Try;
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.base.parameters.Parameters;
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.OTSSimulatorInterface;
39  import org.opentrafficsim.core.gtu.GTUDirectionality;
40  import org.opentrafficsim.core.gtu.GTUException;
41  import org.opentrafficsim.core.gtu.GTUType;
42  import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
43  import org.opentrafficsim.core.gtu.perception.EgoPerception;
44  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
45  import org.opentrafficsim.core.idgenerator.IdGenerator;
46  import org.opentrafficsim.core.network.NetworkException;
47  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
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.road.gtu.generator.GeneratorPositions;
53  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
54  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
55  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
56  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
57  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
58  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
59  import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
60  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
61  import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
62  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
63  import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
64  import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
65  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation;
66  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
67  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
68  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
69  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
70  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
71  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
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.IncentiveSpeedWithCourtesy;
75  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
76  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
77  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
78  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
79  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
80  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
81  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
82  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
83  import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
84  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
85  import org.opentrafficsim.road.network.OTSRoadNetwork;
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  
90  import nl.tudelft.simulation.dsol.SimRuntimeException;
91  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
92  import nl.tudelft.simulation.jstats.distributions.DistNormal;
93  import nl.tudelft.simulation.jstats.distributions.DistUniform;
94  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
95  import nl.tudelft.simulation.jstats.streams.StreamInterface;
96  
97  /**
98   * <p>
99   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
100  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
101  * <p>
102  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017 <br>
103  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
104  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
105  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
106  */
107 
108 public final class AHFEUtil
109 {
110 
111     /**
112      * 
113      */
114     private AHFEUtil()
115     {
116         //
117     }
118 
119     /**
120      * @param network OTSRoadNetwork; the network
121      * @param gtuColorer GTUColorer; the GTU colorer
122      * @param simulator OTSSimulatorInterface; the simulator
123      * @param replication int; replication number
124      * @param anticipationStrategy String; anticipation strategy
125      * @param reactionTime Duration; reaction time
126      * @param anticipationTime Duration; anticipation time
127      * @param truckFraction double; truck fraction
128      * @param simulationTime Time; simulation time
129      * @param leftDemand Frequency; demand on left highway
130      * @param rightDemand Frequency; demand on right highway
131      * @param leftFraction double; fraction of traffic generated on left lane
132      * @param distanceError double; distance error
133      * @param speedError double; speed error
134      * @param accelerationError double; acceleration error
135      * @throws ValueException on value error
136      * @throws ParameterException on parameter error
137      * @throws GTUException on gtu error
138      * @throws ProbabilityException on probability error
139      * @throws SimRuntimeException on sim runtime error
140      */
141     @SuppressWarnings("checkstyle:parameternumber")
142     public static void createDemand(final OTSRoadNetwork network, final GTUColorer gtuColorer,
143             final OTSSimulatorInterface simulator, final int replication, final String anticipationStrategy,
144             final Duration reactionTime, final Duration anticipationTime, final double truckFraction, final Time simulationTime,
145             final Frequency leftDemand, final Frequency rightDemand, final double leftFraction, final double distanceError,
146             final double speedError, final double accelerationError)
147             throws ValueException, ParameterException, GTUException, SimRuntimeException, ProbabilityException
148     {
149 
150         Random seedGenerator = new Random(replication);
151         Map<String, StreamInterface> streams = new HashMap<>();
152         streams.put("headwayGeneration", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
153         streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
154         streams.put("perception", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
155         simulator.getReplication().setStreams(streams);
156 
157         TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
158         IdGenerator idGenerator = new IdGenerator("");
159 
160         CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
161         PerceptionFactory delayedPerceptionFactory = Try.assign(
162                 () -> new DelayedPerceptionFactory(
163                         (Anticipation) Anticipation.class.getDeclaredField(anticipationStrategy.toUpperCase()).get(null)),
164                 "Exception while obtaining anticipation value %s", anticipationStrategy);
165         ParameterSet params = new ParameterSet();
166         params.setDefaultParameter(AbstractIDM.DELTA);
167         params.setParameter(ParameterTypes.TR, reactionTime);
168         params.setParameter(DelayedNeighborsPerception.TA, anticipationTime);
169         params.setDefaultParameter(DelayedNeighborsPerception.TAUE);
170         params.setParameter(DelayedNeighborsPerception.SERROR, distanceError);
171         params.setParameter(DelayedNeighborsPerception.VERROR, speedError);
172         params.setParameter(DelayedNeighborsPerception.AERROR, accelerationError);
173         LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
174                 new LMRSFactoryAHFE(idmPlusFactory, params, delayedPerceptionFactory);
175 
176         ParameterFactoryByType bcFactory = new ParameterFactoryByType();
177         // Length lookAhead = new Length(1000.0, LengthUnit.SI);
178         // Length lookAheadStdev = new Length(250.0, LengthUnit.SI);
179         Length perception = new Length(1.0, LengthUnit.KILOMETER);
180         Acceleration b = new Acceleration(2.09, AccelerationUnit.SI);
181         GTUType gtuType = new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR));
182         bcFactory.addParameter(gtuType, ParameterTypes.FSPEED,
183                 new DistNormal(streams.get("gtuClass"), 123.7 / 120, 12.0 / 120));
184         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
185         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
186         // streams.get("gtuClass"));
187         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
188         gtuType = new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK));
189         bcFactory.addParameter(gtuType, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
190         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
191         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
192         // streams.get("gtuClass"));
193         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
194         bcFactory.addParameter(gtuType, ParameterTypes.FSPEED, 2.0);
195 
196         Route leftRoute = new Route("left");
197         Route rightRoute = new Route("right");
198         try
199         {
200             leftRoute.addNode(network.getNode("LEFTINPRE"));
201             leftRoute.addNode(network.getNode("LEFTIN"));
202             leftRoute.addNode(network.getNode("STARTCONVERGE"));
203             leftRoute.addNode(network.getNode("STARTWEAVING"));
204             leftRoute.addNode(network.getNode("NARROWING"));
205             leftRoute.addNode(network.getNode("EXIT"));
206             rightRoute.addNode(network.getNode("RIGHTINPRE"));
207             rightRoute.addNode(network.getNode("RIGHTIN"));
208             rightRoute.addNode(network.getNode("STARTWEAVING"));
209             rightRoute.addNode(network.getNode("NARROWING"));
210             rightRoute.addNode(network.getNode("EXIT"));
211         }
212         catch (NetworkException exception)
213         {
214             exception.printStackTrace();
215         }
216         Generator<Route> fixedRouteGeneratorLeft = new FixedRouteGenerator(leftRoute);
217         Generator<Route> fixedRouteGeneratorRight = new FixedRouteGenerator(rightRoute);
218 
219         LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
220                 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
221         ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
222                 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(streams.get("gtuClass"), 160, 200), SpeedUnit.KM_PER_HOUR);
223         ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
224                 new ContinuousDistDoubleScalar.Rel<>(new DistNormal(streams.get("gtuClass"), 80, 2.5), SpeedUnit.KM_PER_HOUR);
225 
226         LaneBasedTemplateGTUType carLeft = new LaneBasedTemplateGTUType(
227                 new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR)), new ConstantGenerator<>(Length.createSI(4.0)),
228                 new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, fixedRouteGeneratorLeft);
229         LaneBasedTemplateGTUType truckLeft =
230                 new LaneBasedTemplateGTUType(new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK)),
231                         new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
232                         speedTruck, strategicalFactory, fixedRouteGeneratorLeft);
233         LaneBasedTemplateGTUType carRight = new LaneBasedTemplateGTUType(
234                 new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR)), new ConstantGenerator<>(Length.createSI(4.0)),
235                 new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, fixedRouteGeneratorRight);
236         LaneBasedTemplateGTUType truckRight =
237                 new LaneBasedTemplateGTUType(new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK)),
238                         new ConstantGenerator<>(Length.createSI(15.0)), new ConstantGenerator<>(Length.createSI(2.5)),
239                         speedTruck, strategicalFactory, fixedRouteGeneratorRight);
240 
241         // GTUTypeGenerator gtuTypeGeneratorLeft = new GTUTypeGenerator(simulator, streams.get("gtuClass"));
242         // GTUTypeGenerator gtuTypeGeneratorRight = new GTUTypeGenerator(simulator, streams.get("gtuClass"));
243 
244         Distribution<LaneBasedTemplateGTUType> gtuTypeGeneratorLeftLeft = new Distribution<>(streams.get("gtuClass"));
245         Distribution<LaneBasedTemplateGTUType> gtuTypeGeneratorLeftRight = new Distribution<>(streams.get("gtuClass"));
246         Distribution<LaneBasedTemplateGTUType> gtuTypeGeneratorRightLeft = new Distribution<>(streams.get("gtuClass"));
247         Distribution<LaneBasedTemplateGTUType> gtuTypeGeneratorRightRight = new Distribution<>(streams.get("gtuClass"));
248         if (truckFraction < 1 - leftFraction)
249         {
250             double p = truckFraction / (1 - leftFraction);
251 
252             gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(1.0, carLeft));
253             gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(1.0 - p, carLeft));
254             gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(p, truckLeft));
255 
256             gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(1.0, carRight));
257             gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(1.0 - p, carRight));
258             gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(p, truckRight));
259         }
260         else
261         {
262             double p = (truckFraction - (1 - leftFraction)) / leftFraction;
263             gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(1.0 - p, carLeft));
264             gtuTypeGeneratorLeftLeft.add(new FrequencyAndObject<>(p, truckLeft));
265             gtuTypeGeneratorLeftRight.add(new FrequencyAndObject<>(1.0, truckLeft));
266 
267             gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(1.0 - p, carRight));
268             gtuTypeGeneratorRightLeft.add(new FrequencyAndObject<>(p, truckRight));
269             gtuTypeGeneratorRightRight.add(new FrequencyAndObject<>(1.0, truckRight));
270         }
271 
272         TimeVector timeVector =
273                 new TimeVector(new double[] {0, 360, 1560, 2160, 3960}, TimeUnit.BASE_SECOND, StorageType.DENSE);
274         double leftLeft = leftDemand.si * leftFraction;
275         FrequencyVector leftLeftDemandPattern = new FrequencyVector(
276                 new double[] {leftLeft * 0.5, leftLeft * 0.5, leftLeft, leftLeft, 0.0}, FrequencyUnit.SI, StorageType.DENSE);
277         double leftRight = leftDemand.si * (1 - leftFraction);
278         FrequencyVector leftRightDemandPattern =
279                 new FrequencyVector(new double[] {leftRight * 0.5, leftRight * 0.5, leftRight, leftRight, 0.0},
280                         FrequencyUnit.SI, StorageType.DENSE);
281         double rightLeft = rightDemand.si * leftFraction;
282         FrequencyVector rightLeftDemandPattern =
283                 new FrequencyVector(new double[] {rightLeft * 0.5, rightLeft * 0.5, rightLeft, rightLeft, 0.0},
284                         FrequencyUnit.SI, StorageType.DENSE);
285         double rightRight = rightDemand.si * (1 - leftFraction);
286         FrequencyVector rightRightDemandPattern =
287                 new FrequencyVector(new double[] {rightRight * 0.5, rightRight * 0.5, rightRight, rightRight, 0.0},
288                         FrequencyUnit.SI, StorageType.DENSE);
289         // This defaults to stepwise interpolation, should have been linear.
290         HeadwayGeneratorDemand leftLeftHeadways = new HeadwayGeneratorDemand(timeVector, leftLeftDemandPattern, simulator);
291         HeadwayGeneratorDemand leftRightHeadways = new HeadwayGeneratorDemand(timeVector, leftRightDemandPattern, simulator);
292         HeadwayGeneratorDemand rightLeftHeadways = new HeadwayGeneratorDemand(timeVector, rightLeftDemandPattern, simulator);
293         HeadwayGeneratorDemand rightRightHeadways = new HeadwayGeneratorDemand(timeVector, rightRightDemandPattern, simulator);
294 
295         Speed genSpeed = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
296         CrossSectionLink leftLink = (CrossSectionLink) network.getLink("LEFTINPRE");
297         CrossSectionLink rightLink = (CrossSectionLink) network.getLink("RIGHTINPRE");
298         makeGenerator(getLane(leftLink, "FORWARD1"), genSpeed, "LEFTLEFT", idGenerator, simulator, network,
299                 gtuTypeGeneratorLeftLeft, leftLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory, simulationTime,
300                 streams.get("gtuClass"));
301         makeGenerator(getLane(leftLink, "FORWARD2"), genSpeed, "LEFTRIGHT", idGenerator, simulator, network,
302                 gtuTypeGeneratorLeftRight, leftRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
303                 simulationTime, streams.get("gtuClass"));
304         makeGenerator(getLane(rightLink, "FORWARD1"), genSpeed, "RIGHTLEFT", idGenerator, simulator, network,
305                 gtuTypeGeneratorRightLeft, rightLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
306                 simulationTime, streams.get("gtuClass"));
307         makeGenerator(getLane(rightLink, "FORWARD2"), genSpeed, "RIGHTRIGHT", idGenerator, simulator, network,
308                 gtuTypeGeneratorRightRight, rightRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
309                 simulationTime, streams.get("gtuClass"));
310 
311     }
312 
313     /**
314      * Get lane from link by id.
315      * @param link CrossSectionLink; link
316      * @param id String; id
317      * @return lane
318      */
319     private static Lane getLane(final CrossSectionLink link, final String id)
320     {
321         for (Lane lane : link.getLanes())
322         {
323             if (lane.getId().equals(id))
324             {
325                 return lane;
326             }
327         }
328         throw new RuntimeException("Could not find lane " + id + " on link " + link.getId());
329     }
330 
331     /**
332      * @param lane Lane; the reference lane for this generator
333      * @param generationSpeed Speed; the speed of the GTU
334      * @param id String; the id of the generator itself
335      * @param idGenerator IdGenerator; the generator for the ID
336      * @param simulator OTSSimulatorInterface; the simulator
337      * @param network OTSRoadNetwork; the network
338      * @param distribution Distribution&lt;LaneBasedTemplateGTUType&gt;; the type generator for the GTU
339      * @param headwayGenerator HeadwayGeneratorDemand; the headway generator for the GTU
340      * @param gtuColorer GTUColorer; the GTU colorer for animation
341      * @param roomChecker RoomChecker; the checker to see if there is room for the GTU
342      * @param bcFactory ParameterFactory; the factory to generate parameters for the GTU
343      * @param tacticalFactory LaneBasedTacticalPlannerFactory&lt;?&gt;; the generator for the tactical planner
344      * @param simulationTime Time; simulation time
345      * @param stream StreamInterface; random number stream
346      * @throws SimRuntimeException in case of scheduling problems
347      * @throws ProbabilityException in case of an illegal probability distribution
348      * @throws GTUException in case the GTU is inconsistent
349      * @throws ParameterException in case a parameter for the perception is missing
350      */
351     private static void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
352             final IdGenerator idGenerator, final OTSSimulatorInterface simulator, final OTSRoadNetwork network,
353             final Distribution<LaneBasedTemplateGTUType> distribution, final HeadwayGeneratorDemand headwayGenerator,
354             final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
355             final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime, final StreamInterface stream)
356             throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
357     {
358         Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
359         // TODO DIR_MINUS
360         initialLongitudinalPositions
361                 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
362         LaneBasedTemplateGTUTypeDistribution characteristicsGenerator = new LaneBasedTemplateGTUTypeDistribution(distribution);
363         new LaneBasedGTUGenerator(id, headwayGenerator, characteristicsGenerator,
364                 GeneratorPositions.create(initialLongitudinalPositions, stream), network, simulator, roomChecker, idGenerator);
365     }
366 
367     /**
368      * <p>
369      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
370      * <br>
371      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
372      * <p>
373      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
374      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
375      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
376      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
377      */
378     private static class LMRSFactoryAHFE implements LaneBasedTacticalPlannerFactory<LMRS>
379     {
380 
381         /** Constructor for the car-following model. */
382         private final CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory;
383 
384         /** Default set of parameters for the car-following model. */
385         private final Parameters defaultCarFollowingParameters;
386 
387         /** Factory for perception. */
388         private final PerceptionFactory perceptionFactory;
389 
390         /**
391          * Constructor with car-following model class. The class should have an accessible empty constructor.
392          * @param carFollowingModelFactory CarFollowingModelFactory&lt;? extends CarFollowingModel&gt;; factory of the
393          *            car-following model
394          * @param defaultCarFollowingParameters Parameters; default set of parameters for the car-following model
395          * @param perceptionFactory PerceptionFactory; perception factory
396          * @throws GTUException if the supplied car-following model does not have an accessible empty constructor
397          */
398         LMRSFactoryAHFE(final CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory,
399                 final Parameters defaultCarFollowingParameters, final PerceptionFactory perceptionFactory) throws GTUException
400         {
401             this.carFollowingModelFactory = carFollowingModelFactory;
402             this.defaultCarFollowingParameters = defaultCarFollowingParameters;
403             this.perceptionFactory = perceptionFactory;
404         }
405 
406         /** {@inheritDoc} */
407         @Override
408         public final Parameters getParameters()
409         {
410             ParameterSet parameters = new ParameterSet();
411             parameters.setDefaultParameters(ParameterTypes.class);
412             parameters.setDefaultParameters(LmrsParameters.class);
413             this.defaultCarFollowingParameters.setAllIn(parameters);
414             return parameters;
415         }
416 
417         /** {@inheritDoc} */
418         @Override
419         public final LMRS create(final LaneBasedGTU gtu) throws GTUException
420         {
421             LMRS lmrs = new LMRS(this.carFollowingModelFactory.generateCarFollowingModel(), gtu,
422                     this.perceptionFactory.generatePerception(gtu), Synchronization.PASSIVE, Cooperation.PASSIVE,
423                     GapAcceptance.INFORMED, Tailgating.NONE);
424             lmrs.addMandatoryIncentive(new IncentiveRoute());
425             lmrs.addVoluntaryIncentive(new IncentiveSpeedWithCourtesy());
426             if (gtu.getGTUType().getId().equals("car"))
427             {
428                 lmrs.addVoluntaryIncentive(new IncentiveKeep());
429             }
430             else
431             {
432                 lmrs.addVoluntaryIncentive(new KeepRightTruck());
433             }
434             return lmrs;
435         }
436 
437         /** {@inheritDoc} */
438         @Override
439         public final String toString()
440         {
441             return "LMRSFactory [car-following=" + this.carFollowingModelFactory + "]";
442         }
443 
444     }
445 
446     /**
447      * Perception factory with delay and anticipation for neighbors.
448      * <p>
449      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
450      * <br>
451      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
452      * <p>
453      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017 <br>
454      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
455      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
456      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
457      */
458     private static class DelayedPerceptionFactory implements PerceptionFactory
459     {
460 
461         /** Anticipation form. */
462         private final Anticipation anticipation;
463 
464         /**
465          * Constructor.
466          * @param anticipation Anticipation; anticipation form.
467          */
468         DelayedPerceptionFactory(final Anticipation anticipation)
469         {
470             this.anticipation = anticipation;
471         }
472 
473         /** {@inheritDoc} */
474         @Override
475         public LanePerception generatePerception(final LaneBasedGTU gtu)
476         {
477             LanePerception perception = new CategoricalLanePerception(gtu);
478             perception.addPerceptionCategory(new DirectEgoPerception(perception));
479             // perception.addPerceptionCategory(new DirectDefaultSimplePerception(perception));
480             perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
481             // perception.addPerceptionCategory(new DirectNeighborsPerception(perception));
482             perception.addPerceptionCategory(new DelayedNeighborsPerception(perception, this.anticipation));
483             // perception.addPerceptionCategory(new DirectIntersectionPerception(perception));
484             perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
485             return perception;
486         }
487 
488         /** {@inheritDoc} */
489         @Override
490         public Parameters getParameters()
491         {
492             return new ParameterSet();
493         }
494 
495     }
496 
497     /**
498      * <p>
499      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
500      * <br>
501      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
502      * <p>
503      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mrt. 2017 <br>
504      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
505      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
506      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
507      */
508     private static class KeepRightTruck implements VoluntaryIncentive
509     {
510 
511         /**
512          * 
513          */
514         KeepRightTruck()
515         {
516         }
517 
518         /** {@inheritDoc} */
519         @Override
520         public Desire determineDesire(final Parameters parameters, final LanePerception perception,
521                 final CarFollowingModel carFollowingModel, final Desire mandatoryDesire, final Desire voluntaryDesire)
522                 throws ParameterException, OperationalPlanException
523         {
524             if (perception.getLaneStructure().getRootRecord().getRight() != null
525                     && perception.getLaneStructure().getRootRecord().getRight().getRight() != null
526                     && perception.getPerceptionCategory(EgoPerception.class).getSpeed()
527                             .gt(parameters.getParameter(ParameterTypes.VCONG)))
528             {
529                 // may not be on this lane
530                 return new Desire(0, 1);
531             }
532             if (mandatoryDesire.getRight() < 0 || voluntaryDesire.getRight() < 0
533                     || !perception.getLaneStructure().getExtendedCrossSection().contains(RelativeLane.RIGHT))
534             {
535                 // no desire to go right if more dominant incentives provide a negative desire to go right
536                 return new Desire(0, 0);
537             }
538             // keep right with dFree
539             return new Desire(0, 1.0);
540         }
541 
542     }
543 
544     /**
545      * Generates headways based on demand.
546      * <p>
547      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
548      * <br>
549      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
550      * <p>
551      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 17 nov. 2016 <br>
552      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
553      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
554      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
555      */
556     // TODO replace with ArrivalsHeadwayGenerator and Arrivals
557     private static class HeadwayGeneratorDemand implements Generator<Duration>
558     {
559 
560         /** Interpolation of demand. */
561         private final Interpolation interpolation;
562 
563         /** Vector of time. */
564         private final TimeVector timeVector;
565 
566         /** Vector of flow values. */
567         private final FrequencyVector demandVector;
568 
569         /** Simulator. */
570         private final SimulatorInterface.TimeDoubleUnit simulator;
571 
572         /** Stream name of headway generation. */
573         private static final String HEADWAY_STREAM = "headwayGeneration";
574 
575         /**
576          * @param timeVector TimeVector; a time vector
577          * @param demandVector FrequencyVector; the corresponding demand vector
578          * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator
579          */
580         public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
581                 final SimulatorInterface.TimeDoubleUnit simulator)
582         {
583             this(timeVector, demandVector, simulator, Interpolation.STEPWISE);
584         }
585 
586         /**
587          * @param timeVector TimeVector; a time vector
588          * @param demandVector FrequencyVector; the corresponding demand vector
589          * @param simulator SimulatorInterface.TimeDoubleUnit; the simulator
590          * @param interpolation Interpolation; interpolation type
591          */
592         public HeadwayGeneratorDemand(final TimeVector timeVector, final FrequencyVector demandVector,
593                 final SimulatorInterface.TimeDoubleUnit simulator, final Interpolation interpolation)
594         {
595             Throw.whenNull(timeVector, "Time vector may not be null.");
596             Throw.whenNull(demandVector, "Demand vector may not be null.");
597             Throw.whenNull(simulator, "Simulator may not be null.");
598             Throw.whenNull(interpolation, "Interpolation may not be null.");
599             Throw.whenNull(simulator.getReplication().getStream(HEADWAY_STREAM),
600                     "Could not obtain random stream '" + HEADWAY_STREAM + "'.");
601             for (int i = 0; i < timeVector.size() - 1; i++)
602             {
603                 try
604                 {
605                     Throw.when(timeVector.get(i).ge(timeVector.get(i + 1)), IllegalArgumentException.class,
606                             "Time vector is not increasing.");
607                 }
608                 catch (ValueException exception)
609                 {
610                     throw new RuntimeException(
611                             "Value out of range of time vector. Note that HeadwayGenerator does not create a safe copy.",
612                             exception);
613                 }
614             }
615             Throw.when(timeVector.size() != demandVector.size(), IllegalArgumentException.class,
616                     "Time and flow vector should be of the same size.");
617             Throw.when(timeVector.size() < 2, IllegalArgumentException.class,
618                     "Time and flow vector should be at least of size 2.");
619             this.timeVector = timeVector;
620             this.demandVector = demandVector;
621             this.simulator = simulator;
622             this.interpolation = interpolation;
623         }
624 
625         /** {@inheritDoc} */
626         @Override
627         public final Duration draw() throws ProbabilityException, ParameterException
628         {
629             Time time = this.simulator.getSimulatorTime();
630             try
631             {
632                 Throw.when(time.lt(this.timeVector.get(0)), IllegalArgumentException.class,
633                         "Cannot return a headway at time before first time in vector.");
634 
635                 // get time period of current time
636                 int i = 0;
637                 while (this.timeVector.get(i + 1).lt(time) && i < this.timeVector.size() - 1)
638                 {
639                     i++;
640                 }
641                 try
642                 {
643                     return nextArrival(i, time.minus(this.timeVector.get(i)), 1.0).minus(time);
644                 }
645                 catch (RemoteException exception)
646                 {
647                     throw new RuntimeException("Could not obtain replication.", exception);
648                 }
649             }
650             catch (ValueException exception)
651             {
652                 throw new RuntimeException(
653                         "Value out of range of time or demand vector. Note that HeadwayGenerator does not create safe copies.",
654                         exception);
655             }
656         }
657 
658         /**
659          * Recursive determination of the next arrival time. Each recursion moves to the next time period. This occurs if a
660          * randomly determined arrival falls outside of a time period, or when demand in a time period is 0.
661          * @param i int; index of time period
662          * @param start Duration; reference time from start of period i, pertains to previous arrival, or zero during recursion
663          * @param fractionRemaining double; remaining fraction of headway to apply due to time in earlier time periods
664          * @return time of next arrival
665          * @throws ValueException in case of an illegal time vector
666          * @throws RemoteException in case of not being able to retrieve the replication
667          */
668         private Time nextArrival(final int i, final Duration start, final double fractionRemaining)
669                 throws ValueException, RemoteException
670         {
671 
672             // escape if beyond specified time by infinite next arrival (= no traffic)
673             if (i == this.timeVector.size() - 1)
674             {
675                 return new Time(Double.POSITIVE_INFINITY, TimeUnit.BASE);
676             }
677 
678             // skip zero-demand periods
679             if (this.demandVector.get(i).equals(Frequency.ZERO))
680             {
681                 // after zero-demand, the next headway is a random fraction of a random headway as there is no previous arrival
682                 return nextArrival(i + 1, Duration.ZERO,
683                         this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble());
684             }
685 
686             // calculate headway from demand
687             Frequency demand;
688             if (this.interpolation.isStepWise())
689             {
690                 demand = this.demandVector.get(i);
691             }
692             else
693             {
694                 double f = start.si / (this.timeVector.get(i + 1).si - this.timeVector.get(i).si);
695                 demand = Frequency.interpolate(this.demandVector.get(i), this.demandVector.get(i + 1), f);
696             }
697             double t = -Math.log(this.simulator.getReplication().getStream(HEADWAY_STREAM).nextDouble()) / demand.si;
698 
699             // calculate arrival
700             Time arrival = new Time(this.timeVector.get(i).si + start.si + t * fractionRemaining, TimeUnit.BASE);
701 
702             // go to next period if arrival is beyond current period
703             if (arrival.gt(this.timeVector.get(i + 1)))
704             {
705                 double inStep = this.timeVector.get(i + 1).si - (this.timeVector.get(i).si + start.si);
706                 return nextArrival(i + 1, Duration.ZERO, fractionRemaining - inStep / t);
707             }
708 
709             return arrival;
710 
711         }
712 
713         /** {@inheritDoc} */
714         @Override
715         public final String toString()
716         {
717             return "HeadwayGeneratorDemand [interpolation=" + this.interpolation + ", timeVector=" + this.timeVector
718                     + ", demandVector=" + this.demandVector + ", simulator=" + this.simulator + "]";
719         }
720 
721     }
722 
723 }