View Javadoc
1   package ahfe;
2   
3   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.TRUCK;
5   
6   import java.util.HashMap;
7   import java.util.HashSet;
8   import java.util.Map;
9   import java.util.Random;
10  import java.util.Set;
11  
12  import org.djunits.unit.AccelerationUnit;
13  import org.djunits.unit.DurationUnit;
14  import org.djunits.unit.FrequencyUnit;
15  import org.djunits.unit.LengthUnit;
16  import org.djunits.unit.SpeedUnit;
17  import org.djunits.unit.TimeUnit;
18  import org.djunits.value.StorageType;
19  import org.djunits.value.ValueException;
20  import org.djunits.value.vdouble.scalar.Acceleration;
21  import org.djunits.value.vdouble.scalar.Duration;
22  import org.djunits.value.vdouble.scalar.Frequency;
23  import org.djunits.value.vdouble.scalar.Length;
24  import org.djunits.value.vdouble.scalar.Speed;
25  import org.djunits.value.vdouble.scalar.Time;
26  import org.djunits.value.vdouble.vector.FrequencyVector;
27  import org.djunits.value.vdouble.vector.TimeVector;
28  import org.opentrafficsim.core.distributions.ProbabilityException;
29  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
30  import org.opentrafficsim.core.gtu.GTUDirectionality;
31  import org.opentrafficsim.core.gtu.GTUException;
32  import org.opentrafficsim.core.gtu.GTUType;
33  import org.opentrafficsim.core.gtu.animation.GTUColorer;
34  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
35  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
36  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactoryByType;
37  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
38  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
39  import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
40  import org.opentrafficsim.core.gtu.perception.EgoPerception;
41  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
42  import org.opentrafficsim.core.idgenerator.IdGenerator;
43  import org.opentrafficsim.core.network.NetworkException;
44  import org.opentrafficsim.core.network.OTSNetwork;
45  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
46  import org.opentrafficsim.core.network.route.Route;
47  import org.opentrafficsim.core.network.route.RouteGenerator;
48  import org.opentrafficsim.road.gtu.generator.CharacteristicsGenerator;
49  import org.opentrafficsim.road.gtu.generator.GTUTypeGenerator;
50  import org.opentrafficsim.road.gtu.generator.HeadwayGeneratorDemand;
51  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
52  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
53  import org.opentrafficsim.road.gtu.generator.SpeedGenerator;
54  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
55  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
56  import org.opentrafficsim.road.gtu.lane.perception.CategorialLanePerception;
57  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
58  import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
59  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
60  import org.opentrafficsim.road.gtu.lane.perception.categories.DelayedNeighborsPerception;
61  import org.opentrafficsim.road.gtu.lane.perception.categories.DelayedNeighborsPerception.Anticipation;
62  import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
63  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
64  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
65  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
66  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
67  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
68  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
69  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
70  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
71  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
72  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
73  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
74  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
75  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
76  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
77  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
78  import org.opentrafficsim.road.network.lane.CrossSectionLink;
79  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
80  import org.opentrafficsim.road.network.lane.Lane;
81  
82  import nl.tudelft.simulation.dsol.SimRuntimeException;
83  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
84  import nl.tudelft.simulation.jstats.streams.StreamInterface;
85  
86  /**
87   * <p>
88   * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
89   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
90   * <p>
91   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017 <br>
92   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
93   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
94   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
95   */
96  
97  public final class AHFEUtil
98  {
99  
100     /**
101      * 
102      */
103     private AHFEUtil()
104     {
105         //
106     }
107 
108     /**
109      * @param network the network
110      * @param gtuColorer the GTU colorer
111      * @param simulator the simulator
112      * @param replication replication number
113      * @param anticipationStrategy anticipation strategy
114      * @param reactionTime reaction time
115      * @param anticipationTime anticipation time
116      * @param truckFraction truck fraction
117      * @param simulationTime simulation time
118      * @param leftDemand demand on left highway
119      * @param rightDemand demand on right highway
120      * @param leftFraction fraction of traffic generated on left lane
121      * @param distanceError distance error
122      * @param speedError speed error
123      * @param accelerationError acceleration error
124      * @throws ValueException on value error
125      * @throws ParameterException on parameter error
126      * @throws GTUException on gtu error
127      * @throws ProbabilityException on probability error
128      * @throws SimRuntimeException on sim runtime error
129      */
130     @SuppressWarnings("checkstyle:parameternumber")
131     public static void createDemand(final OTSNetwork network, final GTUColorer gtuColorer,
132             final OTSDEVSSimulatorInterface simulator, final int replication, final String anticipationStrategy,
133             final Duration reactionTime, final Duration anticipationTime, final double truckFraction, final Time simulationTime,
134             final Frequency leftDemand, final Frequency rightDemand, final double leftFraction, final double distanceError,
135             final double speedError, final double accelerationError)
136             throws ValueException, ParameterException, GTUException, SimRuntimeException, ProbabilityException
137     {
138 
139         Random seedGenerator = new Random(replication);
140         Map<String, StreamInterface> streams = new HashMap<>();
141         streams.put("headwayGeneration", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
142         streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
143         streams.put("perception", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
144         simulator.getReplication().setStreams(streams);
145 
146         TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
147         IdGenerator idGenerator = new IdGenerator("");
148 
149         CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory();
150         PerceptionFactory delayedPerceptionFactory =
151                 new DelayedPerceptionFactory(Anticipation.valueOf(anticipationStrategy.toUpperCase()));
152         BehavioralCharacteristics bc = new BehavioralCharacteristics();
153         bc.setDefaultParameter(AbstractIDM.DELTA);
154         bc.setParameter(ParameterTypes.TR, reactionTime);
155         bc.setParameter(DelayedNeighborsPerception.TA, anticipationTime);
156         bc.setDefaultParameter(DelayedNeighborsPerception.TAUE);
157         bc.setParameter(DelayedNeighborsPerception.SERROR, distanceError);
158         bc.setParameter(DelayedNeighborsPerception.VERROR, speedError);
159         bc.setParameter(DelayedNeighborsPerception.AERROR, accelerationError);
160         LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
161                 new LMRSFactoryAHFE(idmPlusFactory, bc, delayedPerceptionFactory);
162 
163         BehavioralCharacteristicsFactoryByType bcFactory = new BehavioralCharacteristicsFactoryByType();
164         // Length lookAhead = new Length(1000.0, LengthUnit.SI);
165         // Length lookAheadStdev = new Length(250.0, LengthUnit.SI);
166         Length perception = new Length(1.0, LengthUnit.KILOMETER);
167         Acceleration b = new Acceleration(2.09, AccelerationUnit.SI);
168         GTUType gtuType = new GTUType("car", CAR);
169         bcFactory.addGaussianParameter(gtuType, ParameterTypes.FSPEED, 123.7 / 120, 12.0 / 120, streams.get("gtuClass"));
170         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
171         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
172         // streams.get("gtuClass"));
173         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
174         gtuType = new GTUType("truck", TRUCK);
175         bcFactory.addParameter(gtuType, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
176         bcFactory.addParameter(gtuType, ParameterTypes.B, b);
177         // bcFactory.addGaussianParameter(gtuType, ParameterTypes.LOOKAHEAD, lookAhead, lookAheadStdev,
178         // streams.get("gtuClass"));
179         bcFactory.addParameter(gtuType, ParameterTypes.PERCEPTION, perception);
180         bcFactory.addParameter(gtuType, ParameterTypes.FSPEED, 2.0);
181 
182         Route leftRoute = new Route("left");
183         Route rightRoute = new Route("right");
184         try
185         {
186             leftRoute.addNode(network.getNode("LEFTINPRE"));
187             leftRoute.addNode(network.getNode("LEFTIN"));
188             leftRoute.addNode(network.getNode("STARTCONVERGE"));
189             leftRoute.addNode(network.getNode("STARTWEAVING"));
190             leftRoute.addNode(network.getNode("NARROWING"));
191             leftRoute.addNode(network.getNode("EXIT"));
192             rightRoute.addNode(network.getNode("RIGHTINPRE"));
193             rightRoute.addNode(network.getNode("RIGHTIN"));
194             rightRoute.addNode(network.getNode("STARTWEAVING"));
195             rightRoute.addNode(network.getNode("NARROWING"));
196             rightRoute.addNode(network.getNode("EXIT"));
197         }
198         catch (NetworkException exception)
199         {
200             exception.printStackTrace();
201         }
202         RouteGenerator fixedRouteGeneratorLeft = new FixedRouteGenerator(leftRoute);
203         RouteGenerator fixedRouteGeneratorRight = new FixedRouteGenerator(rightRoute);
204 
205         SpeedGenerator speedCar = new SpeedGenerator(new Speed(160.0, SpeedUnit.KM_PER_HOUR),
206                 new Speed(200.0, SpeedUnit.KM_PER_HOUR), streams.get("gtuClass"));
207         // TODO gaussian 85 +/- 2.5 for match with default LMRS
208         SpeedGenerator speedTruck = new SpeedGenerator(new Speed(80.0, SpeedUnit.KM_PER_HOUR),
209                 new Speed(95.0, SpeedUnit.KM_PER_HOUR), streams.get("gtuClass"));
210         GTUTypeGenerator gtuTypeGeneratorLeft = new GTUTypeGenerator(simulator);
211         GTUTypeGenerator gtuTypeGeneratorRight = new GTUTypeGenerator(simulator);
212         if (truckFraction < 1 - leftFraction)
213         {
214             gtuTypeGeneratorLeft.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI),
215                     new GTUType("car", CAR), speedCar, 1.0);
216             double p = truckFraction / (1 - leftFraction);
217             gtuTypeGeneratorRight.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI),
218                     new GTUType("car", CAR), speedCar, 1.0 - p);
219             gtuTypeGeneratorRight.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI),
220                     new GTUType("truck", TRUCK), speedTruck, p);
221         }
222         else
223         {
224             double p = (truckFraction - (1 - leftFraction)) / leftFraction;
225             gtuTypeGeneratorLeft.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI),
226                     new GTUType("car", CAR), speedCar, 1.0 - p);
227             gtuTypeGeneratorLeft.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI),
228                     new GTUType("truck", TRUCK), speedTruck, p);
229             gtuTypeGeneratorRight.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI),
230                     new GTUType("truck", TRUCK), speedTruck, 1.0);
231         }
232 
233         TimeVector timeVector = new TimeVector(new double[] { 0, 360, 1560, 2160, 3960 }, TimeUnit.BASE_SECOND, StorageType.DENSE);
234         double leftLeft = leftDemand.si * leftFraction;
235         FrequencyVector leftLeftDemandPattern = new FrequencyVector(
236                 new double[] { leftLeft * 0.5, leftLeft * 0.5, leftLeft, leftLeft, 0.0 }, FrequencyUnit.SI, StorageType.DENSE);
237         double leftRight = leftDemand.si * (1 - leftFraction);
238         FrequencyVector leftRightDemandPattern =
239                 new FrequencyVector(new double[] { leftRight * 0.5, leftRight * 0.5, leftRight, leftRight, 0.0 },
240                         FrequencyUnit.SI, StorageType.DENSE);
241         double rightLeft = rightDemand.si * leftFraction;
242         FrequencyVector rightLeftDemandPattern =
243                 new FrequencyVector(new double[] { rightLeft * 0.5, rightLeft * 0.5, rightLeft, rightLeft, 0.0 },
244                         FrequencyUnit.SI, StorageType.DENSE);
245         double rightRight = rightDemand.si * (1 - leftFraction);
246         FrequencyVector rightRightDemandPattern =
247                 new FrequencyVector(new double[] { rightRight * 0.5, rightRight * 0.5, rightRight, rightRight, 0.0 },
248                         FrequencyUnit.SI, StorageType.DENSE);
249         // This defaults to stepwise interpolation, should have been linear.
250         HeadwayGeneratorDemand leftLeftHeadways = new HeadwayGeneratorDemand(timeVector, leftLeftDemandPattern, simulator);
251         HeadwayGeneratorDemand leftRightHeadways = new HeadwayGeneratorDemand(timeVector, leftRightDemandPattern, simulator);
252         HeadwayGeneratorDemand rightLeftHeadways = new HeadwayGeneratorDemand(timeVector, rightLeftDemandPattern, simulator);
253         HeadwayGeneratorDemand rightRightHeadways = new HeadwayGeneratorDemand(timeVector, rightRightDemandPattern, simulator);
254 
255         Speed genSpeed = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
256         CrossSectionLink leftLink = (CrossSectionLink) network.getLink("LEFTINPRE");
257         CrossSectionLink rightLink = (CrossSectionLink) network.getLink("RIGHTINPRE");
258         makeGenerator(getLane(leftLink, "FORWARD1"), genSpeed, "LEFTLEFT", fixedRouteGeneratorLeft, idGenerator, simulator,
259                 network, gtuTypeGeneratorLeft, leftLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
260                 simulationTime);
261         makeGenerator(getLane(leftLink, "FORWARD2"), genSpeed, "LEFTRIGHT", fixedRouteGeneratorLeft, idGenerator, simulator,
262                 network, gtuTypeGeneratorRight, leftRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
263                 simulationTime);
264         makeGenerator(getLane(rightLink, "FORWARD1"), genSpeed, "RIGHTLEFT", fixedRouteGeneratorRight, idGenerator, simulator,
265                 network, gtuTypeGeneratorLeft, rightLeftHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
266                 simulationTime);
267         makeGenerator(getLane(rightLink, "FORWARD2"), genSpeed, "RIGHTRIGHT", fixedRouteGeneratorRight, idGenerator, simulator,
268                 network, gtuTypeGeneratorRight, rightRightHeadways, gtuColorer, roomChecker, bcFactory, tacticalFactory,
269                 simulationTime);
270 
271     }
272 
273     /**
274      * Get lane from link by id.
275      * @param link link
276      * @param id id
277      * @return lane
278      */
279     private static Lane getLane(final CrossSectionLink link, final String id)
280     {
281         for (Lane lane : link.getLanes())
282         {
283             if (lane.getId().equals(id))
284             {
285                 return lane;
286             }
287         }
288         throw new RuntimeException("Could not find lane " + id + " on link " + link.getId());
289     }
290 
291     /**
292      * @param lane the reference lane for this generator
293      * @param generationSpeed the speed of the GTU
294      * @param id the id of the generator itself
295      * @param routeGenerator the generator for the route
296      * @param idGenerator the generator for the ID
297      * @param simulator the simulator
298      * @param network the network
299      * @param gtuTypeGenerator the type generator for the GTU
300      * @param headwayGenerator the headway generator for the GTU
301      * @param gtuColorer the GTU colorer for animation
302      * @param roomChecker the checker to see if there is room for the GTU
303      * @param bcFactory the factory to generate behavioral characteristics for the GTU
304      * @param tacticalFactory the generator for the tactical planner
305      * @param simulationTime simulation time
306      * @throws SimRuntimeException in case of scheduling problems
307      * @throws ProbabilityException in case of an illegal probability distribution
308      * @throws GTUException in case the GTU is inconsistent
309      * @throws ParameterException in case a parameter for the perception is missing
310      */
311     private static void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
312             final RouteGenerator routeGenerator, final IdGenerator idGenerator, final OTSDEVSSimulatorInterface simulator,
313             final OTSNetwork network, final GTUTypeGenerator gtuTypeGenerator, final HeadwayGeneratorDemand headwayGenerator,
314             final GTUColorer gtuColorer, final RoomChecker roomChecker, final BehavioralCharacteristicsFactory bcFactory,
315             final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime)
316             throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
317     {
318         Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
319         // TODO DIR_MINUS
320         initialLongitudinalPositions
321                 .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
322 
323         LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
324                 new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
325 
326         CharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(strategicalFactory, routeGenerator,
327                 idGenerator, simulator, network, gtuTypeGenerator, generationSpeed, initialLongitudinalPositions);
328 
329         new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, simulationTime, gtuColorer,
330                 characteristicsGenerator, initialLongitudinalPositions, network, roomChecker);
331     }
332 
333     /**
334      * <p>
335      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
336      * <br>
337      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
338      * <p>
339      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
340      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
341      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
342      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
343      */
344     private static class LMRSFactoryAHFE implements LaneBasedTacticalPlannerFactory<LMRS>
345     {
346 
347         /** Constructor for the car-following model. */
348         private final CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory;
349 
350         /** Default set of parameters for the car-following model. */
351         private final BehavioralCharacteristics defaultCarFollowingBehavioralCharacteristics;
352 
353         /** Factory for perception. */
354         private final PerceptionFactory perceptionFactory;
355 
356         /**
357          * Constructor with car-following model class. The class should have an accessible empty constructor.
358          * @param carFollowingModelFactory factory of the car-following model
359          * @param defaultCarFollowingBehavioralCharacteristics default set of parameters for the car-following model
360          * @param perceptionFactory perception factory
361          * @throws GTUException if the supplied car-following model does not have an accessible empty constructor
362          */
363         LMRSFactoryAHFE(final CarFollowingModelFactory<? extends CarFollowingModel> carFollowingModelFactory,
364                 final BehavioralCharacteristics defaultCarFollowingBehavioralCharacteristics,
365                 final PerceptionFactory perceptionFactory) throws GTUException
366         {
367             this.carFollowingModelFactory = carFollowingModelFactory;
368             this.defaultCarFollowingBehavioralCharacteristics = defaultCarFollowingBehavioralCharacteristics;
369             this.perceptionFactory = perceptionFactory;
370         }
371 
372         /** {@inheritDoc} */
373         @Override
374         public final BehavioralCharacteristics getDefaultBehavioralCharacteristics()
375         {
376             BehavioralCharacteristics behavioralCharacteristics = new BehavioralCharacteristics();
377             behavioralCharacteristics.setDefaultParameters(ParameterTypes.class);
378             behavioralCharacteristics.setDefaultParameters(LmrsParameters.class);
379             behavioralCharacteristics.setAll(this.defaultCarFollowingBehavioralCharacteristics);
380             return behavioralCharacteristics;
381         }
382 
383         /** {@inheritDoc} */
384         @Override
385         public final LMRS create(final LaneBasedGTU gtu) throws GTUException
386         {
387             LMRS lmrs = new LMRS(this.carFollowingModelFactory.generateCarFollowingModel(), gtu,
388                     this.perceptionFactory.generatePerception(gtu), Synchronization.PASSIVE);
389             lmrs.addMandatoryIncentive(new IncentiveRoute());
390             lmrs.addVoluntaryIncentive(new IncentiveSpeedWithCourtesy());
391             if (gtu.getGTUType().getId().equals("car"))
392             {
393                 lmrs.addVoluntaryIncentive(new IncentiveKeep());
394             }
395             else
396             {
397                 lmrs.addVoluntaryIncentive(new KeepRightTruck());
398             }
399             return lmrs;
400         }
401 
402         /** {@inheritDoc} */
403         public final String toString()
404         {
405             return "LMRSFactory [car-following=" + this.carFollowingModelFactory + "]";
406         }
407 
408     }
409 
410     /**
411      * Perception factory with delay and anticipation for neighbors.
412      * <p>
413      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
414      * <br>
415      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
416      * <p>
417      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2017 <br>
418      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
419      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
420      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
421      */
422     private static class DelayedPerceptionFactory implements PerceptionFactory
423     {
424 
425         /** Anticipation form. */
426         private final Anticipation anticipation;
427 
428         /**
429          * Constructor.
430          * @param anticipation anticipation form.
431          */
432         DelayedPerceptionFactory(final Anticipation anticipation)
433         {
434             this.anticipation = anticipation;
435         }
436 
437         /** {@inheritDoc} */
438         @Override
439         public LanePerception generatePerception(final LaneBasedGTU gtu)
440         {
441             LanePerception perception = new CategorialLanePerception(gtu);
442             perception.addPerceptionCategory(new DirectEgoPerception(perception));
443             // perception.addPerceptionCategory(new DirectDefaultSimplePerception(perception));
444             perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
445             // perception.addPerceptionCategory(new DirectNeighborsPerception(perception));
446             perception.addPerceptionCategory(new DelayedNeighborsPerception(perception, this.anticipation));
447             // perception.addPerceptionCategory(new DirectIntersectionPerception(perception));
448             return perception;
449         }
450 
451     }
452 
453     /**
454      * <p>
455      * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
456      * <br>
457      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
458      * <p>
459      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mrt. 2017 <br>
460      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
461      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
462      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
463      */
464     private static class KeepRightTruck implements VoluntaryIncentive
465     {
466 
467         /**
468          * 
469          */
470         KeepRightTruck()
471         {
472         }
473 
474         /** {@inheritDoc} */
475         @Override
476         public Desire determineDesire(final BehavioralCharacteristics behavioralCharacteristics,
477                 final LanePerception perception, final CarFollowingModel carFollowingModel, final Desire mandatoryDesire,
478                 final Desire voluntaryDesire) throws ParameterException, OperationalPlanException
479         {
480             if (perception.getLaneStructure().getRootLSR().getRight() != null
481                     && perception.getLaneStructure().getRootLSR().getRight().getRight() != null
482                     && perception.getPerceptionCategory(EgoPerception.class).getSpeed()
483                             .gt(behavioralCharacteristics.getParameter(ParameterTypes.VCONG)))
484             {
485                 // may not be on this lane
486                 return new Desire(0, 1);
487             }
488             if (mandatoryDesire.getRight() < 0 || voluntaryDesire.getRight() < 0
489                     || !perception.getLaneStructure().getCrossSection().contains(RelativeLane.RIGHT))
490             {
491                 // no desire to go right if more dominant incentives provide a negative desire to go right
492                 return new Desire(0, 0);
493             }
494             // keep right with dFree
495             return new Desire(0, 1.0);
496         }
497 
498     }
499 
500 }