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