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