View Javadoc
1   package org.opentrafficsim.ahfe;
2   
3   import java.awt.Color;
4   import java.io.IOException;
5   import java.io.InputStream;
6   import java.util.ArrayList;
7   import java.util.LinkedHashSet;
8   import java.util.List;
9   import java.util.Set;
10  
11  import javax.naming.NamingException;
12  import javax.xml.parsers.ParserConfigurationException;
13  
14  import org.djunits.unit.FrequencyUnit;
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.Length;
22  import org.djunits.value.vdouble.scalar.Speed;
23  import org.djunits.value.vdouble.vector.FrequencyVector;
24  import org.djunits.value.vdouble.vector.TimeVector;
25  import org.djutils.exceptions.Throw;
26  import org.djutils.exceptions.Try;
27  import org.djutils.io.URLResource;
28  import org.opentrafficsim.base.parameters.ParameterException;
29  import org.opentrafficsim.base.parameters.ParameterSet;
30  import org.opentrafficsim.base.parameters.ParameterTypeDouble;
31  import org.opentrafficsim.base.parameters.ParameterTypeDuration;
32  import org.opentrafficsim.base.parameters.ParameterTypes;
33  import org.opentrafficsim.base.parameters.Parameters;
34  import org.opentrafficsim.base.parameters.constraint.DualBound;
35  import org.opentrafficsim.base.parameters.constraint.NumericConstraint;
36  import org.opentrafficsim.core.animation.gtu.colorer.AccelerationGTUColorer;
37  import org.opentrafficsim.core.animation.gtu.colorer.SpeedGTUColorer;
38  import org.opentrafficsim.core.animation.gtu.colorer.SwitchableGTUColorer;
39  import org.opentrafficsim.core.distributions.Distribution;
40  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
41  import org.opentrafficsim.core.distributions.Generator;
42  import org.opentrafficsim.core.distributions.ProbabilityException;
43  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
44  import org.opentrafficsim.core.geometry.OTSGeometryException;
45  import org.opentrafficsim.core.gtu.AbstractGTU;
46  import org.opentrafficsim.core.gtu.GTUException;
47  import org.opentrafficsim.core.gtu.GTUType;
48  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterFactoryByType;
49  import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
50  import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
51  import org.opentrafficsim.core.network.NetworkException;
52  import org.opentrafficsim.core.network.Node;
53  import org.opentrafficsim.core.network.OTSNetwork;
54  import org.opentrafficsim.core.perception.HistoryManagerDEVS;
55  import org.opentrafficsim.core.units.distributions.ContinuousDistSpeed;
56  import org.opentrafficsim.draw.core.OTSDrawingException;
57  import org.opentrafficsim.draw.factory.DefaultAnimationFactory;
58  import org.opentrafficsim.kpi.interfaces.LaneDataInterface;
59  import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
60  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
61  import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
62  import org.opentrafficsim.road.gtu.colorer.DesiredHeadwayColorer;
63  import org.opentrafficsim.road.gtu.colorer.DesiredSpeedColorer;
64  import org.opentrafficsim.road.gtu.colorer.FixedColor;
65  import org.opentrafficsim.road.gtu.colorer.GTUTypeColorer;
66  import org.opentrafficsim.road.gtu.colorer.IncentiveColorer;
67  import org.opentrafficsim.road.gtu.colorer.ReactionTimeColorer;
68  import org.opentrafficsim.road.gtu.colorer.SynchronizationColorer;
69  import org.opentrafficsim.road.gtu.colorer.TaskColorer;
70  import org.opentrafficsim.road.gtu.colorer.TaskSaturationColorer;
71  import org.opentrafficsim.road.gtu.colorer.TotalDesireColorer;
72  import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
73  import org.opentrafficsim.road.gtu.generator.od.ODApplier;
74  import org.opentrafficsim.road.gtu.generator.od.ODOptions;
75  import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD;
76  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
77  import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
78  import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
79  import org.opentrafficsim.road.gtu.lane.perception.PerceptionCollectable;
80  import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
81  import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
82  import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
83  import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
84  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Anticipation;
85  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
86  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.Estimation;
87  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType.PerceivedHeadwayGtuType;
88  import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.NeighborsPerception;
89  import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU;
90  import org.opentrafficsim.road.gtu.lane.perception.mental.AbstractTask;
91  import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationHeadway;
92  import org.opentrafficsim.road.gtu.lane.perception.mental.AdaptationSituationalAwareness;
93  import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
94  import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller.BehavioralAdaptation;
95  import org.opentrafficsim.road.gtu.lane.perception.mental.Task;
96  import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager;
97  import org.opentrafficsim.road.gtu.lane.plan.operational.LaneOperationalPlanBuilder;
98  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
99  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
100 import org.opentrafficsim.road.gtu.lane.tactical.following.DesiredSpeedModel;
101 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
102 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
103 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
104 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveCourtesy;
105 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveGetInLane;
106 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
107 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
108 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
109 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeed;
110 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
111 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveStayRight;
112 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
113 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.SocioDesiredSpeed;
114 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
115 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
116 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
117 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
118 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
119 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
120 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
121 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
122 import org.opentrafficsim.road.gtu.strategical.od.Categorization;
123 import org.opentrafficsim.road.gtu.strategical.od.Category;
124 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
125 import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
126 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
127 import org.opentrafficsim.road.network.factory.xml.old.XmlNetworkLaneParserOld;
128 import org.opentrafficsim.road.network.lane.CrossSectionLink;
129 import org.opentrafficsim.road.network.lane.object.Distraction;
130 import org.opentrafficsim.road.network.lane.object.Distraction.TrapezoidProfile;
131 import org.opentrafficsim.road.network.sampling.LinkData;
132 import org.opentrafficsim.road.network.sampling.RoadSampler;
133 import org.opentrafficsim.road.network.sampling.data.TimeToCollision;
134 import org.opentrafficsim.swing.script.AbstractSimulationScript;
135 import org.xml.sax.SAXException;
136 
137 import nl.tudelft.simulation.dsol.SimRuntimeException;
138 import nl.tudelft.simulation.jstats.distributions.DistLogNormal;
139 import nl.tudelft.simulation.jstats.distributions.DistNormal;
140 import nl.tudelft.simulation.jstats.distributions.DistTriangular;
141 import nl.tudelft.simulation.jstats.streams.StreamInterface;
142 
143 // TODO: network is not colored correctly; missing links and stripes
144 
145 /**
146  * Distraction simulation.
147  * <p>
148  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
149  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
150  * <p>
151  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 9 apr. 2018 <br>
152  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
153  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
154  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
155  */
156 public final class AnticipationRelianceScript extends AbstractSimulationScript
157 {
158 
159     /** Car-following task parameter. */
160     static final ParameterTypeDuration HEXP = new ParameterTypeDuration("Hexp",
161             "Exponential decay of car-following task by headway.", Duration.createSI(4.0), NumericConstraint.POSITIVE);
162 
163     /** Fraction of primary task that can be reduced by anticipation reliance. */
164     static final ParameterTypeDouble ALPHA = new ParameterTypeDouble("alpha",
165             "Fraction of primary task that can be reduced by anticipation reliance.", 0.8, DualBound.UNITINTERVAL);
166 
167     /** Fraction of auxiliary tasks that can be reduced by anticipation reliance. */
168     static final ParameterTypeDouble BETA = new ParameterTypeDouble("beta",
169             "Fraction of auxiliary tasks that can be reduced by anticipation reliance.", 0.6, DualBound.UNITINTERVAL);
170 
171     /** Distance to not consider at start of the network. */
172     private static Length ignoreStart = Length.createSI(2900); // Not 100m on pre-link, so 3000 total
173 
174     /** Distance to not consider at end of the network. */
175     private static Length ignoreEnd = Length.createSI(1000);
176 
177     /** Sampler. */
178     private RoadSampler sampler;
179 
180     /**
181      * Main method.
182      * @param args String[]; command line arguments
183      */
184     public static void main(final String[] args)
185     {
186         // Long start = System.currentTimeMillis();
187         AnticipationRelianceScript script = new AnticipationRelianceScript(args);
188         // script.setProperty("autorun", true);
189         script.start();
190         // Long end = System.currentTimeMillis();
191         // System.out.println("That took " + (end - start) / 1000 + "s.");
192     }
193 
194     /**
195      * Constructor.
196      * @param properties String[]; properties as name-value pairs
197      */
198     private AnticipationRelianceScript(final String[] properties)
199     {
200         super("Distraction", "Distraction simulation", properties);
201         setGtuColorer(SwitchableGTUColorer.builder().addActiveColorer(new FixedColor(Color.BLUE, "Blue"))
202                 .addColorer(new TaskColorer("car-following")).addColorer(new TaskColorer("lane-changing"))
203                 .addColorer(new TaskSaturationColorer()).addColorer(new ReactionTimeColorer(Duration.createSI(1.0)))
204                 .addColorer(GTUTypeColorer.DEFAULT).addColorer(new SpeedGTUColorer(new Speed(150, SpeedUnit.KM_PER_HOUR)))
205                 .addColorer(
206                         new DesiredSpeedColorer(new Speed(50, SpeedUnit.KM_PER_HOUR), new Speed(150, SpeedUnit.KM_PER_HOUR)))
207                 .addColorer(new AccelerationGTUColorer(Acceleration.createSI(-6.0), Acceleration.createSI(2)))
208                 .addColorer(new SynchronizationColorer())
209                 .addColorer(new DesiredHeadwayColorer(Duration.createSI(0.56), Duration.createSI(2.4)))
210                 .addColorer(new TotalDesireColorer()).addColorer(new IncentiveColorer(IncentiveRoute.class))
211                 .addColorer(new IncentiveColorer(IncentiveSpeedWithCourtesy.class))
212                 .addColorer(new IncentiveColorer(IncentiveSpeed.class)).addColorer(new IncentiveColorer(IncentiveKeep.class))
213                 .addColorer(new IncentiveColorer(IncentiveGetInLane.class))
214                 .addColorer(new IncentiveColorer(IncentiveCourtesy.class))
215                 .addColorer(new IncentiveColorer(IncentiveSocioSpeed.class)).build());
216     }
217 
218     /** {@inheritDoc} */
219     @Override
220     protected void setDefaultProperties()
221     {
222         setProperty("fTruck", 0.05);
223         setProperty("leftDemand", 3500);
224         setProperty("rightDemand", 3200);
225         setProperty("sampler", true);
226         setProperty("warmupTime", 360);
227         setProperty("simulationTime", 3960);
228         setProperty("scenario", "test");
229 
230         setProperty("strategies", true);
231         setProperty("adaptation", false);
232         setProperty("alpha", 0.8); // max. lane-change reduction
233         setProperty("beta", 0.6); // max. car-following reduction
234         setProperty("fractionUnderestimation", 0.75);
235     }
236 
237     /** {@inheritDoc} */
238     @Override
239     protected void onSimulationEnd()
240     {
241         if (this.sampler != null)
242         {
243             this.sampler.writeToFile(getProperty("outputDir") + getProperty("scenario") + ".csv");
244         }
245     }
246 
247     /** {@inheritDoc} */
248     @Override
249     protected OTSNetwork setupSimulation(final OTSSimulatorInterface sim) throws Exception
250     {
251         AbstractGTU.ALIGNED = false;
252         LaneOperationalPlanBuilder.INSTANT_LANE_CHANGES = true;
253 
254         // Network
255         InputStream stream = URLResource.getResourceAsStream("/AHFE/Network.xml");
256         XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(sim);
257         OTSNetwork network = new OTSNetwork("Distraction");
258         try
259         {
260             nlp.build(stream, network, false);
261         }
262         catch (NetworkException | ParserConfigurationException | SAXException | IOException | NamingException | GTUException
263                 | OTSGeometryException | ValueException | ParameterException | SimRuntimeException exception)
264         {
265             exception.printStackTrace();
266         }
267         new Distraction("distraction", ((CrossSectionLink) network.getLink("END")).getLanes().get(0), Length.createSI(1000),
268                 sim, new TrapezoidProfile(0.2, Length.createSI(-400), Length.createSI(200), Length.createSI(400)));
269 
270         // OD
271         List<Node> origins = new ArrayList<>();
272         origins.add(network.getNode("LEFTINPRE"));
273         origins.add(network.getNode("RIGHTINPRE"));
274         List<Node> destinations = new ArrayList<>();
275         destinations.add(network.getNode("EXIT"));
276         Categorization categorization = new Categorization("Distraction", GTUType.class);
277         TimeVector globalTime =
278                 new TimeVector(new double[] { 0, 360, 1560, 2160, 3960 }, TimeUnit.BASE_SECOND, StorageType.DENSE);
279         ODMatrix od = new ODMatrix("Distraction", origins, destinations, categorization, globalTime, Interpolation.LINEAR);
280         Category carCategory = new Category(categorization, GTUType.CAR);
281         Category truckCategory = new Category(categorization, GTUType.TRUCK);
282         double fTruck = getDoubleProperty("fTruck");
283         double demandLeft = getDoubleProperty("leftDemand");
284         double demandRight = getDoubleProperty("rightDemand");
285         FrequencyVector leftDemandPatternCar = getDemand(demandLeft * (1.0 - fTruck));
286         FrequencyVector leftDemandPatternTruck = getDemand(demandLeft * fTruck);
287         FrequencyVector rightDemandPatternCar = getDemand(demandRight * (1.0 - fTruck));
288         FrequencyVector rightDemandPatternTruck = getDemand(demandRight * fTruck);
289         od.putDemandVector(network.getNode("LEFTINPRE"), network.getNode("EXIT"), carCategory, leftDemandPatternCar);
290         od.putDemandVector(network.getNode("LEFTINPRE"), network.getNode("EXIT"), truckCategory, leftDemandPatternTruck);
291         od.putDemandVector(network.getNode("RIGHTINPRE"), network.getNode("EXIT"), carCategory, rightDemandPatternCar);
292         od.putDemandVector(network.getNode("RIGHTINPRE"), network.getNode("EXIT"), truckCategory, rightDemandPatternTruck);
293         ODOptions odOptions = new ODOptions().set(ODOptions.GTU_TYPE,
294                 new DefaultGTUCharacteristicsGeneratorOD(new DistractionFactorySupplier()));
295         ODApplier.applyOD(network, od, sim, odOptions);
296 
297         // History
298         sim.getReplication().setHistoryManager(new HistoryManagerDEVS(sim, Duration.createSI(2.0), Duration.createSI(1.0)));
299 
300         // Sampler
301         this.sampler = new RoadSampler(sim);
302         this.sampler.registerExtendedDataType(new TimeToCollision());
303         LinkData linkData = new LinkData((CrossSectionLink) network.getLink("LEFTIN"));
304         registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
305         linkData = new LinkData((CrossSectionLink) network.getLink("RIGHTIN"));
306         registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
307         linkData = new LinkData((CrossSectionLink) network.getLink("CONVERGE"));
308         registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
309         linkData = new LinkData((CrossSectionLink) network.getLink("WEAVING"));
310         registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
311         linkData = new LinkData((CrossSectionLink) network.getLink("END"));
312         registerLinkToSampler(linkData, Length.ZERO, linkData.getLength().minus(ignoreEnd));
313 
314         // return
315         return network;
316     }
317 
318     /**
319      * Register a link to the sampler, so data is sampled there.
320      * @param linkData LinkData; link data
321      * @param startDistance Length; start distance on link
322      * @param endDistance Length; end distance on link
323      */
324     private void registerLinkToSampler(final LinkData linkData, final Length startDistance, final Length endDistance)
325     {
326         for (LaneDataInterface laneData : linkData.getLaneDatas())
327         {
328             Length start = laneData.getLength().multiplyBy(startDistance.si / linkData.getLength().si);
329             Length end = laneData.getLength().multiplyBy(endDistance.si / linkData.getLength().si);
330             this.sampler
331                     .registerSpaceTimeRegion(new SpaceTimeRegion(new KpiLaneDirection(laneData, KpiGtuDirectionality.DIR_PLUS),
332                             start, end, getTimeProperty("warmupTime"), getTimeProperty("simulationTime")));
333         }
334     }
335 
336     /**
337      * Compose demand vector.
338      * @param demand double; maximum demand value
339      * @return FrequencyVector demand vector
340      * @throws ValueException on value exception
341      */
342     private static FrequencyVector getDemand(final double demand) throws ValueException
343     {
344         return new FrequencyVector(new double[] { demand * 0.5, demand * 0.5, demand, demand, 0.0 }, FrequencyUnit.PER_HOUR,
345                 StorageType.DENSE);
346     }
347 
348     /** {@inheritDoc} */
349     @Override
350     protected void animateNetwork(final OTSNetwork net)
351     {
352         try
353         {
354             DefaultAnimationFactory.animateXmlNetwork(net, getSimulator(), getGtuColorer());
355         }
356         catch (OTSDrawingException exception)
357         {
358             throw new RuntimeException("Exception while creating network animation.", exception);
359         }
360     }
361 
362     /////////////////////
363     ////// FACTORY //////
364     /////////////////////
365 
366     /**
367      * Supplier of strategical factory.
368      * <p>
369      * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
370      * <br>
371      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
372      * <p>
373      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 9 apr. 2018 <br>
374      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
375      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
376      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
377      */
378     private class DistractionFactorySupplier implements StrategicalPlannerFactorySupplierOD
379     {
380 
381         /** Factory cars. */
382         private LaneBasedStrategicalRoutePlannerFactory factoryCar = null;
383 
384         /** Factory trucks. */
385         private LaneBasedStrategicalRoutePlannerFactory factoryTruck = null;
386 
387         /** */
388         DistractionFactorySupplier()
389         {
390         }
391 
392         /** {@inheritDoc} */
393         @Override
394         public LaneBasedStrategicalPlannerFactory<?> getFactory(final Node origin, final Node destination,
395                 final Category category, final StreamInterface randomStream) throws GTUException
396         {
397             if (this.factoryCar == null)
398             {
399                 boolean strategies = getBooleanProperty("strategies");
400 
401                 // car-following model, with different desired speed models
402                 CarFollowingModelFactory<IDMPlus> cfFactoryCar = new IdmPlusFactoryAR(
403                         () -> strategies ? new SocioDesiredSpeed(AbstractIDM.DESIRED_SPEED) : AbstractIDM.DESIRED_SPEED);
404                 CarFollowingModelFactory<IDMPlus> cfFactoryTruck = new IdmPlusFactoryAR(() -> AbstractIDM.DESIRED_SPEED);
405 
406                 // perception factory with estimation distribution (i.e. over- vs. underestimation)
407                 Distribution<Estimation> estimation;
408                 try
409                 {
410                     estimation = new Distribution<>(randomStream);
411                     estimation.add(
412                             new FrequencyAndObject<>(getDoubleProperty("fractionUnderestimation"), Estimation.UNDERESTIMATION));
413                     estimation.add(new FrequencyAndObject<>(1.0 - getDoubleProperty("fractionUnderestimation"),
414                             Estimation.OVERESTIMATION));
415                 }
416                 catch (ProbabilityException ex)
417                 {
418                     throw new GTUException("Random stream is null.", ex);
419                 }
420                 PerceptionFactory perceptionFactory = new LmrsPerceptionFactoryAR(estimation);
421 
422                 // tailgating
423                 Tailgating tailgating = getBooleanProperty("strategies") ? Tailgating.PRESSURE : Tailgating.NONE;
424 
425                 // incentives
426                 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
427                 mandatoryIncentives.add(new IncentiveRoute());
428                 Set<VoluntaryIncentive> voluntaryIncentivesCar = new LinkedHashSet<>();
429                 Set<VoluntaryIncentive> voluntaryIncentivesTruck = new LinkedHashSet<>();
430                 voluntaryIncentivesCar.add(new IncentiveSpeedWithCourtesy());
431                 voluntaryIncentivesCar.add(new IncentiveKeep());
432                 if (strategies)
433                 {
434                     voluntaryIncentivesCar.add(new IncentiveSocioSpeed());
435                 }
436                 voluntaryIncentivesTruck.addAll(voluntaryIncentivesCar);
437                 voluntaryIncentivesTruck.add(new IncentiveStayRight());
438 
439                 // acceleration incentives (none, nothing on the freeway)
440                 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
441 
442                 // parameter factory
443                 ParameterFactoryByType params = new ParameterFactoryByType();
444                 params.addParameter(GTUType.CAR, ParameterTypes.FSPEED,
445                         new DistNormal(randomStream, 123.7 / 120.0, 12.0 / 120.0));
446                 params.addParameter(GTUType.TRUCK, ParameterTypes.A, Acceleration.createSI(0.4));
447                 if (strategies)
448                 {
449                     params.addParameter(Tailgating.RHO, 0.0);
450                     params.addParameter(GTUType.CAR, LmrsParameters.SOCIO, new DistTriangular(randomStream, 0.0, 0.25, 1.0));
451                     params.addParameter(GTUType.TRUCK, LmrsParameters.SOCIO, 1.0);
452                     params.addParameter(GTUType.CAR, LmrsParameters.VGAIN,
453                             new ContinuousDistSpeed(new DistLogNormal(randomStream, 3.3789, 0.4), SpeedUnit.KM_PER_HOUR));
454                     params.addParameter(GTUType.TRUCK, LmrsParameters.VGAIN, new Speed(50.0, SpeedUnit.KM_PER_HOUR));
455                     params.addParameter(ParameterTypes.TMAX, Duration.createSI(1.6));
456                 }
457 
458                 // factories
459                 this.factoryCar = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(cfFactoryCar, perceptionFactory,
460                         Synchronization.PASSIVE, Cooperation.PASSIVE, GapAcceptance.INFORMED, tailgating, mandatoryIncentives,
461                         voluntaryIncentivesCar, accelerationIncentives), params);
462                 this.factoryTruck = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(cfFactoryTruck,
463                         perceptionFactory, Synchronization.PASSIVE, Cooperation.PASSIVE, GapAcceptance.INFORMED, tailgating,
464                         mandatoryIncentives, voluntaryIncentivesTruck, accelerationIncentives), params);
465             }
466             return category.get(GTUType.class).isOfType(GTUType.TRUCK) ? this.factoryTruck : this.factoryCar;
467         }
468     }
469 
470     ////////////////////////////////////
471     ////// FACTORY HELPER CLASSES //////
472     ////////////////////////////////////
473 
474     /** Car-following task. */
475     private class CarFollowingTaskAR extends AbstractTask
476     {
477         /** Constructor. */
478         CarFollowingTaskAR()
479         {
480             super("car-following");
481         }
482 
483         /** {@inheritDoc} */
484         @Override
485         public double calculateTaskDemand(final LanePerception perception, final LaneBasedGTU gtuCF,
486                 final Parameters parameters) throws ParameterException, GTUException
487         {
488             try
489             {
490                 NeighborsPerception neighbors = perception.getPerceptionCategory(NeighborsPerception.class);
491                 PerceptionCollectable<HeadwayGTU, LaneBasedGTU> leaders = neighbors.getLeaders(RelativeLane.CURRENT);
492                 return leaders.isEmpty() ? 0.0 : Math.exp(-leaders.first().getDistance().si
493                         / (perception.getGtu().getSpeed().si * parameters.getParameter(HEXP).si));
494             }
495             catch (OperationalPlanException ex)
496             {
497                 throw new GTUException(ex);
498             }
499         }
500     }
501 
502     /** Lane change task. */
503     private class LaneChangeTaskAR extends AbstractTask
504     {
505         /** Constructor. */
506         LaneChangeTaskAR()
507         {
508             super("lane-changing");
509         }
510 
511         /** {@inheritDoc} */
512         @Override
513         public double calculateTaskDemand(final LanePerception perception, final LaneBasedGTU gtuLC,
514                 final Parameters parameters) throws ParameterException, GTUException
515         {
516             return Math.max(0.0,
517                     Math.max(parameters.getParameter(LmrsParameters.DLEFT), parameters.getParameter(LmrsParameters.DRIGHT)));
518         }
519     }
520 
521     /** LMRS perception factory with AR. */
522     private class LmrsPerceptionFactoryAR extends DefaultLMRSPerceptionFactory
523     {
524         /** Estimation distribution. */
525         private final Distribution<Estimation> estimation;
526 
527         /**
528          * Constructor.
529          * @param estimation Distribution&lt;Estimation&gt;; estimation distribution
530          */
531         LmrsPerceptionFactoryAR(final Distribution<Estimation> estimation)
532         {
533             this.estimation = estimation;
534         }
535 
536         /** {@inheritDoc} */
537         @Override
538         public LanePerception generatePerception(final LaneBasedGTU gtu)
539         {
540             Set<Task> tasks = new LinkedHashSet<>();
541             tasks.add(new CarFollowingTaskAR());
542             tasks.add(new LaneChangeTaskAR());
543 
544             Set<BehavioralAdaptation> behavioralAdapatations = new LinkedHashSet<>();
545             behavioralAdapatations.add(new AdaptationSituationalAwareness());
546             if (getBooleanProperty("adaptation"))
547             {
548                 // TODO: weak anticipation / behavioral adaptation
549             }
550             @SuppressWarnings("synthetic-access")
551             Fuller fuller = new Fuller(tasks, behavioralAdapatations, new TaskManagerAR());
552             LanePerception perception = new CategoricalLanePerception(gtu, fuller);
553             perception.addPerceptionCategory(new DirectEgoPerception<>(perception));
554             perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
555             Estimation est = Try.assign(() -> this.estimation.draw(), "Probability exception while drawing estimation.");
556             perception.addPerceptionCategory(
557                     new DirectNeighborsPerception(perception, new PerceivedHeadwayGtuType(est, Anticipation.CONSTANT_SPEED)));
558             perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
559             return perception;
560         }
561 
562         /** {@inheritDoc} */
563         @Override
564         public Parameters getParameters() throws ParameterException
565         {
566             Parameters params = super.getParameters();
567             params.setParameter(HEXP, Duration.createSI(4.0));
568             params.setParameter(ALPHA, getDoubleProperty("alpha"));
569             params.setParameter(BETA, getDoubleProperty("beta"));
570             params.setParameter(Fuller.TC, 1.0);
571             params.setParameter(Fuller.TS_CRIT, 0.8);
572             params.setParameter(Fuller.TS_MAX, 2.0);
573             params.setParameter(AdaptationSituationalAwareness.SA, 1.0);
574             params.setParameter(AdaptationSituationalAwareness.SA_MAX, 1.0);
575             params.setParameter(AdaptationSituationalAwareness.SA_MIN, 0.5);
576             params.setParameter(AdaptationSituationalAwareness.TR_MAX, Duration.createSI(2.0));
577             params.setParameter(ParameterTypes.TR, Duration.ZERO);
578             params.setParameter(AdaptationHeadway.BETA_T, 1.0);
579             return params;
580         }
581     }
582 
583     /** Task manager for AR. */
584     private class TaskManagerAR implements TaskManager
585     {
586         /** {@inheritDoc} */
587         @Override
588         public void manage(final Set<Task> tasksMan, final LanePerception perception, final LaneBasedGTU gtu,
589                 final Parameters parameters) throws ParameterException, GTUException
590         {
591             Task primary = null;
592             Set<Task> auxiliaryTasks = new LinkedHashSet<>();
593             for (Task task : tasksMan)
594             {
595                 if (task.getId().equals("lane-changing"))
596                 {
597                     primary = task;
598                 }
599                 else
600                 {
601                     auxiliaryTasks.add(task);
602                 }
603             }
604             Throw.whenNull(primary, "There is no task with id 'lane-changing'.");
605             double primaryTaskDemand = primary.calculateTaskDemand(perception, gtu, parameters);
606             primary.setTaskDemand(primaryTaskDemand);
607             // max AR is alpha of TD, actual AR approaches 0 for increasing TD
608             double alpha = parameters.getParameter(ALPHA);
609             double beta = parameters.getParameter(BETA);
610             primary.setAnticipationReliance(alpha * primaryTaskDemand * (1.0 - primaryTaskDemand));
611             for (Task auxiliary : auxiliaryTasks)
612             {
613                 double auxiliaryTaskLoad = auxiliary.calculateTaskDemand(perception, gtu, parameters);
614                 auxiliary.setTaskDemand(auxiliaryTaskLoad);
615                 // max AR is beta of TD, actual AR approaches 0 as primary TD approaches 0
616                 auxiliary.setAnticipationReliance(beta * auxiliaryTaskLoad * primaryTaskDemand);
617             }
618         }
619     }
620 
621     /** Car-following model factory. */
622     private class IdmPlusFactoryAR implements CarFollowingModelFactory<IDMPlus>
623     {
624         /** Generator for desired speed model. */
625         private final Generator<DesiredSpeedModel> desiredSpeedModelGenerator;
626 
627         /**
628          * Constructor.
629          * @param desiredSpeedModelGenerator Generator&lt;DesiredSpeedModel&gt;; generator for desired speed model
630          */
631         IdmPlusFactoryAR(final Generator<DesiredSpeedModel> desiredSpeedModelGenerator)
632         {
633             this.desiredSpeedModelGenerator = desiredSpeedModelGenerator;
634         }
635 
636         /** {@inheritDoc} */
637         @Override
638         public Parameters getParameters() throws ParameterException
639         {
640             ParameterSet parameters = new ParameterSet();
641             parameters.setDefaultParameters(AbstractIDM.class);
642             return parameters;
643         }
644 
645         /** {@inheritDoc} */
646         @Override
647         public IDMPlus generateCarFollowingModel()
648         {
649             return new IDMPlus(AbstractIDM.HEADWAY,
650                     Try.assign(() -> this.desiredSpeedModelGenerator.draw(), "Unexpected exception."));
651         }
652     }
653 
654 }