View Javadoc
1   package org.opentrafficsim.ahfe;
2   
3   import java.rmi.RemoteException;
4   import java.util.LinkedHashMap;
5   import java.util.LinkedHashSet;
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.ValueRuntimeException;
17  import org.djunits.value.storage.StorageType;
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.djunits.value.vdouble.vector.base.DoubleVector;
27  import org.djutils.exceptions.Throw;
28  import org.djutils.exceptions.Try;
29  import org.opentrafficsim.base.parameters.ParameterException;
30  import org.opentrafficsim.base.parameters.ParameterSet;
31  import org.opentrafficsim.base.parameters.ParameterTypes;
32  import org.opentrafficsim.base.parameters.Parameters;
33  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
34  import org.opentrafficsim.core.distributions.ConstantGenerator;
35  import org.opentrafficsim.core.distributions.Distribution;
36  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
37  import org.opentrafficsim.core.distributions.Generator;
38  import org.opentrafficsim.core.distributions.ProbabilityException;
39  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
40  import org.opentrafficsim.core.gtu.GTUDirectionality;
41  import org.opentrafficsim.core.gtu.GTUException;
42  import org.opentrafficsim.core.gtu.GTUType;
43  import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
44  import org.opentrafficsim.core.gtu.perception.EgoPerception;
45  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
46  import org.opentrafficsim.core.idgenerator.IdGenerator;
47  import org.opentrafficsim.core.network.NetworkException;
48  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
49  import org.opentrafficsim.core.network.route.Route;
50  import org.opentrafficsim.core.parameters.ParameterFactory;
51  import org.opentrafficsim.core.parameters.ParameterFactoryByType;
52  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
53  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
54  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
55  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
56  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
57  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
58  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
59  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
60  import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
61  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
62  import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
63  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
64  import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
65  import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
66  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation;
67  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
68  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
69  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
70  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
71  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
72  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
73  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
74  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
75  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
76  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
77  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
78  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
79  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
80  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
81  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
82  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
83  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
84  import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
85  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
86  import org.opentrafficsim.road.network.OTSRoadNetwork;
87  import org.opentrafficsim.road.network.lane.CrossSectionLink;
88  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
89  import org.opentrafficsim.road.network.lane.Lane;
90  
91  import nl.tudelft.simulation.dsol.SimRuntimeException;
92  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
93  import nl.tudelft.simulation.jstats.distributions.DistNormal;
94  import nl.tudelft.simulation.jstats.distributions.DistUniform;
95  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
96  import nl.tudelft.simulation.jstats.streams.StreamInterface;
97  
98  /**
99   * <p>
100  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
101  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
102  * <p>
103  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017 <br>
104  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
105  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
106  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
107  */
108 
109 public final class AHFEUtil
110 {
111 
112     /**
113      * 
114      */
115     private AHFEUtil()
116     {
117         //
118     }
119 
120     /**
121      * @param network OTSRoadNetwork; the network
122      * @param gtuColorer GTUColorer; the GTU colorer
123      * @param simulator OTSSimulatorInterface; the simulator
124      * @param replication int; replication number
125      * @param anticipationStrategy String; anticipation strategy
126      * @param reactionTime Duration; reaction time
127      * @param anticipationTime Duration; anticipation time
128      * @param truckFraction double; truck fraction
129      * @param simulationTime Time; simulation time
130      * @param leftDemand Frequency; demand on left highway
131      * @param rightDemand Frequency; demand on right highway
132      * @param leftFraction double; fraction of traffic generated on left lane
133      * @param distanceError double; distance error
134      * @param speedError double; speed error
135      * @param accelerationError double; acceleration error
136      * @throws ValueRuntimeException on value error
137      * @throws ParameterException on parameter error
138      * @throws GTUException on gtu error
139      * @throws ProbabilityException on probability error
140      * @throws SimRuntimeException on sim runtime error
141      */
142     @SuppressWarnings("checkstyle:parameternumber")
143     public static void createDemand(final OTSRoadNetwork network, final GTUColorer gtuColorer,
144             final OTSSimulatorInterface simulator, final int replication, final String anticipationStrategy,
145             final Duration reactionTime, final Duration anticipationTime, final double truckFraction, final Time simulationTime,
146             final Frequency leftDemand, final Frequency rightDemand, final double leftFraction, final double distanceError,
147             final double speedError, final double accelerationError)
148             throws ValueRuntimeException, ParameterException, GTUException, SimRuntimeException, ProbabilityException
149     {
150 
151         Random seedGenerator = new Random(replication);
152         Map<String, StreamInterface> streams = new LinkedHashMap<>();
153         streams.put("headwayGeneration", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
154         streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
155         streams.put("perception", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
156         simulator.getReplication().setStreams(streams);
157 
158         TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
159         IdGenerator idGenerator = new IdGenerator("");
160 
161         CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
162         PerceptionFactory delayedPerceptionFactory = Try.assign(
163                 () -> new DelayedPerceptionFactory(
164                         (Anticipation) Anticipation.class.getDeclaredField(anticipationStrategy.toUpperCase()).get(null)),
165                 "Exception while obtaining anticipation value %s", anticipationStrategy);
166         ParameterSet params = new ParameterSet();
167         params.setDefaultParameter(AbstractIDM.DELTA);
168         params.setParameter(ParameterTypes.TR, reactionTime);
169         params.setParameter(DelayedNeighborsPerception.TA, anticipationTime);
170         params.setDefaultParameter(DelayedNeighborsPerception.TAUE);
171         params.setParameter(DelayedNeighborsPerception.SERROR, distanceError);
172         params.setParameter(DelayedNeighborsPerception.VERROR, speedError);
173         params.setParameter(DelayedNeighborsPerception.AERROR, accelerationError);
174         LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
175                 new LMRSFactoryAHFE(idmPlusFactory, params, delayedPerceptionFactory);
176 
177         ParameterFactoryByType bcFactory = new ParameterFactoryByType();
178         // Length lookAhead = new Length(1000.0, LengthUnit.SI);
179         // Length lookAheadStdev = new Length(250.0, LengthUnit.SI);
180         Length perception = new Length(1.0, LengthUnit.KILOMETER);
181         Acceleration b = new Acceleration(2.09, AccelerationUnit.SI);
182         GTUType gtuType = new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR));
183         bcFactory.addParameter(gtuType, ParameterTypes.FSPEED,
184                 new DistNormal(streams.get("gtuClass"), 123.7 / 120, 12.0 / 120));
185         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
186         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
187         // streams.get("gtuClass"));
188         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
189         gtuType = new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK));
190         bcFactory.addParameter(gtuType, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
191         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
192         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
193         // streams.get("gtuClass"));
194         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
195         bcFactory.addParameter(gtuType, ParameterTypes.FSPEED, 2.0);
196 
197         Route leftRoute = new Route("left");
198         Route rightRoute = new Route("right");
199         try
200         {
201             leftRoute.addNode(network.getNode("LEFTINPRE"));
202             leftRoute.addNode(network.getNode("LEFTIN"));
203             leftRoute.addNode(network.getNode("STARTCONVERGE"));
204             leftRoute.addNode(network.getNode("STARTWEAVING"));
205             leftRoute.addNode(network.getNode("NARROWING"));
206             leftRoute.addNode(network.getNode("EXIT"));
207             rightRoute.addNode(network.getNode("RIGHTINPRE"));
208             rightRoute.addNode(network.getNode("RIGHTIN"));
209             rightRoute.addNode(network.getNode("STARTWEAVING"));
210             rightRoute.addNode(network.getNode("NARROWING"));
211             rightRoute.addNode(network.getNode("EXIT"));
212         }
213         catch (NetworkException exception)
214         {
215             exception.printStackTrace();
216         }
217         Generator<Route> fixedRouteGeneratorLeft = new FixedRouteGenerator(leftRoute);
218         Generator<Route> fixedRouteGeneratorRight = new FixedRouteGenerator(rightRoute);
219 
220         LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
221                 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
222         ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
223                 new ContinuousDistDoubleScalar.Rel<>(new DistUniform(streams.get("gtuClass"), 160, 200), SpeedUnit.KM_PER_HOUR);
224         ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
225                 new ContinuousDistDoubleScalar.Rel<>(new DistNormal(streams.get("gtuClass"), 80, 2.5), SpeedUnit.KM_PER_HOUR);
226 
227         LaneBasedTemplateGTUType carLeft =
228                 new LaneBasedTemplateGTUType(new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR)),
229                         new ConstantGenerator<>(Length.instantiateSI(4.0)), new ConstantGenerator<>(Length.instantiateSI(2.0)),
230                         speedCar, strategicalFactory, fixedRouteGeneratorLeft);
231         LaneBasedTemplateGTUType truckLeft =
232                 new LaneBasedTemplateGTUType(new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK)),
233                         new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
234                         speedTruck, strategicalFactory, fixedRouteGeneratorLeft);
235         LaneBasedTemplateGTUType carRight =
236                 new LaneBasedTemplateGTUType(new GTUType("car", network.getGtuType(GTUType.DEFAULTS.CAR)),
237                         new ConstantGenerator<>(Length.instantiateSI(4.0)), new ConstantGenerator<>(Length.instantiateSI(2.0)),
238                         speedCar, strategicalFactory, fixedRouteGeneratorRight);
239         LaneBasedTemplateGTUType truckRight =
240                 new LaneBasedTemplateGTUType(new GTUType("truck", network.getGtuType(GTUType.DEFAULTS.TRUCK)),
241                         new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
242                         speedTruck, 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                 DoubleVector.instantiate(new double[] {0, 360, 1560, 2160, 3960}, TimeUnit.BASE_SECOND, StorageType.DENSE);
277         double leftLeft = leftDemand.si * leftFraction;
278         FrequencyVector leftLeftDemandPattern = DoubleVector.instantiate(
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                 DoubleVector.instantiate(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                 DoubleVector.instantiate(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                 DoubleVector.instantiate(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 OTSRoadNetwork; 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 OTSRoadNetwork 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 LinkedHashSet<>();
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-2020 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-2020 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-2020 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-2020 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         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         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 (ValueRuntimeException 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 (ValueRuntimeException 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 ValueRuntimeException 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 ValueRuntimeException, 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.DEFAULT);
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.DEFAULT);
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 }