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