Fuller.java

  1. package org.opentrafficsim.road.gtu.lane.perception.mental;

  2. import static org.opentrafficsim.base.parameters.constraint.NumericConstraint.POSITIVE;
  3. import static org.opentrafficsim.base.parameters.constraint.NumericConstraint.POSITIVEZERO;

  4. import java.util.LinkedHashMap;
  5. import java.util.LinkedHashSet;
  6. import java.util.Map;
  7. import java.util.Set;

  8. import org.djutils.exceptions.Throw;
  9. import org.djutils.exceptions.Try;
  10. import org.djutils.immutablecollections.Immutable;
  11. import org.djutils.immutablecollections.ImmutableLinkedHashSet;
  12. import org.djutils.immutablecollections.ImmutableSet;
  13. import org.opentrafficsim.base.parameters.ParameterException;
  14. import org.opentrafficsim.base.parameters.ParameterTypeDouble;
  15. import org.opentrafficsim.base.parameters.Parameters;
  16. import org.opentrafficsim.core.gtu.GTUException;
  17. import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
  18. import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
  19. import org.opentrafficsim.road.gtu.lane.perception.mental.TaskManager.SummativeTaskManager;

  20. /**
  21.  * Task-capability interface in accordance to Fuller (2011). Task demand is the sum of demands described by individual
  22.  * {@code Task}s. These take exogenous information to describe the workload in fundamental relations. Task demand is divided by
  23.  * task capability to arrive at a task saturation. Task saturation is input to {@code BehavioralAdaptation}s which alter
  24.  * parameters describing personal traits, such as desired headway and desired speed. In this way, task demand is kept at an
  25.  * equilibrium as described by Fuller.
  26.  * <p>
  27.  * A {@code BehavioralAdaptation} may also determine what the level of situational awareness is, which includes determining
  28.  * reaction time. Both situational awareness and reaction time parameters can be used in perception to model deteriorated
  29.  * perception due to a task demand imbalance.
  30.  * <p>
  31.  * Fuller, R., Driver control theory: From task difficulty homeostasis to risk allostasis, in Handbook of Traffic Psychology.
  32.  * 2011. p. 13-26
  33.  * <p>
  34.  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  35.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  36.  * <p>
  37.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 apr. 2018 <br>
  38.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  39.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  40.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  41.  */
  42. public class Fuller implements Mental
  43. {

  44.     // Parameters

  45.     /** Task capability in nominal task capability units, i.e. mean is 1. */
  46.     public static final ParameterTypeDouble TC = new ParameterTypeDouble("TC", "Task capability", 1.0, POSITIVE);

  47.     /** Critical task saturation. */
  48.     public static final ParameterTypeDouble TS_CRIT =
  49.             new ParameterTypeDouble("TScrit", "Critical task saturation", 0.8, POSITIVEZERO)
  50.             {
  51.                 /** */
  52.                 private static final long serialVersionUID = 20180403L;

  53.                 /** {@inheritDoc} */
  54.                 @Override
  55.                 public void check(final Double value, final Parameters params) throws ParameterException
  56.                 {
  57.                     Double tsMax = params.getParameterOrNull(TS_MAX);
  58.                     Throw.when(tsMax != null && value > tsMax, ParameterException.class,
  59.                             "Value for TS_CRIT should not be larger than TS_MAX.");
  60.                 }
  61.             };

  62.     /** Maximum task saturation, pertaining to maximum deterioration. */
  63.     public static final ParameterTypeDouble TS_MAX =
  64.             new ParameterTypeDouble("TSmax", "Maximum task saturation", 2.0, POSITIVEZERO)
  65.             {
  66.                 /** */
  67.                 private static final long serialVersionUID = 20180403L;

  68.                 /** {@inheritDoc} */
  69.                 @Override
  70.                 public void check(final Double value, final Parameters params) throws ParameterException
  71.                 {
  72.                     Double tsCrit = params.getParameterOrNull(TS_CRIT);
  73.                     Throw.when(tsCrit != null && value < tsCrit, ParameterException.class,
  74.                             "Value for TS_MAX should not be smaller than TS_CRIT.");
  75.                 }
  76.             };

  77.     /** Task saturation. */
  78.     public static final ParameterTypeDouble TS = new ParameterTypeDouble("TS", "Task saturation", 0.0, POSITIVEZERO);

  79.     // Properties

  80.     /** Tasks causing task demand. */
  81.     private final Set<Task> tasks;

  82.     /** Behavioral adaptations depending on task saturation. */
  83.     private final Set<BehavioralAdaptation> behavioralAdapatations;

  84.     /** Task manager. */
  85.     private final TaskManager taskManager;

  86.     /** Stored anticipation reliance per task. */
  87.     private Map<String, Double> anticipationReliances = new LinkedHashMap<>();

  88.     /** Stored task demand per task. */
  89.     private Map<String, Double> taskDemands = new LinkedHashMap<>();

  90.     /**
  91.      * Constructor with custom situational awareness.
  92.      * @param tasks Set&lt;? extends Task&gt;; tasks
  93.      * @param behavioralAdapatations Set&lt;BehavioralAdaptation&gt;; behavioralAdapatations
  94.      */
  95.     public Fuller(final Set<? extends Task> tasks, final Set<BehavioralAdaptation> behavioralAdapatations)
  96.     {
  97.         this(tasks, behavioralAdapatations, new SummativeTaskManager());
  98.     }

  99.     /**
  100.      * Constructor with custom situational awareness.
  101.      * @param tasks Set&lt;? extends Task&gt;; tasks
  102.      * @param behavioralAdapatations Set&lt;BehavioralAdaptation&gt;; behavioralAdapatations
  103.      * @param taskManager TaskManager; task manager
  104.      */
  105.     public Fuller(final Set<? extends Task> tasks, final Set<BehavioralAdaptation> behavioralAdapatations,
  106.             final TaskManager taskManager)
  107.     {
  108.         Throw.whenNull(tasks, "Tasks may not be null.");
  109.         Throw.whenNull(behavioralAdapatations, "Behavioral adaptations may not be null.");
  110.         this.tasks = new LinkedHashSet<>();
  111.         this.tasks.addAll(tasks);
  112.         this.behavioralAdapatations = behavioralAdapatations;
  113.         this.taskManager = taskManager;
  114.     }

  115.     /**
  116.      * Adds a task.
  117.      * @param task Task; task to add
  118.      */
  119.     public void addTask(final Task task)
  120.     {
  121.         this.tasks.add(task);
  122.     }

  123.     /**
  124.      * Removes a task.
  125.      * @param task Task; task to remove
  126.      */
  127.     public void removeTask(final Task task)
  128.     {
  129.         this.tasks.remove(task);
  130.     }

  131.     /**
  132.      * Returns the tasks.
  133.      * @return ImmutableSet&lt;Task&gt; tasks
  134.      */
  135.     public ImmutableSet<Task> getTasks()
  136.     {
  137.         return new ImmutableLinkedHashSet<>(this.tasks, Immutable.WRAP);
  138.     }

  139.     /** {@inheritDoc} */
  140.     @Override
  141.     public void apply(final LanePerception perception) throws ParameterException, GTUException
  142.     {
  143.         LaneBasedGTU gtu = Try.assign(() -> perception.getGtu(), "Could not obtain GTU.");
  144.         Parameters parameters = gtu.getParameters();
  145.         double taskDemand = 0.0;
  146.         // a) the fundamental diagrams of task workload are defined in the tasks
  147.         // b) sum task demand
  148.         this.taskManager.manage(this.tasks, perception, gtu, parameters);
  149.         this.anticipationReliances.clear();
  150.         this.taskDemands.clear();
  151.         for (Task task : this.tasks)
  152.         {
  153.             double ar = task.getAnticipationReliance();
  154.             double td = task.getTaskDemand();
  155.             this.anticipationReliances.put(task.getId(), ar);
  156.             this.taskDemands.put(task.getId(), td);
  157.             taskDemand += (td - ar);
  158.         }
  159.         double taskSaturation = taskDemand / parameters.getParameter(TC);
  160.         parameters.setParameter(TS, taskSaturation);
  161.         // c) behavioral adaptation
  162.         for (BehavioralAdaptation behavioralAdapatation : this.behavioralAdapatations)
  163.         {
  164.             behavioralAdapatation.adapt(parameters, taskSaturation);
  165.         }
  166.         // d) situational awareness can be implemented by one of the behavioral responses
  167.         // e) perception errors from situational awareness are included in the perception step
  168.         // f) reaction time from situational awareness are included in the perception step
  169.     }
  170.    
  171.     /**
  172.      * Returns the anticipation reliance of the given task id.
  173.      * @param taskId taskId; task id to return the anticipation reliance for.
  174.      * @return double; anticipation reliance of given task id, {@code NaN if not present}
  175.      */
  176.     public double getAnticipationReliance(final String taskId)
  177.     {
  178.          return this.anticipationReliances.getOrDefault(taskId, Double.NaN);
  179.     }
  180.    
  181.     /**
  182.      * Returns the demand of the given task id.
  183.      * @param taskId taskId; task id to return the demand for.
  184.      * @return double; demand of given task id, {@code NaN if not present}
  185.      */
  186.     public double getTaskDemand(final String taskId)
  187.     {
  188.          return this.taskDemands.getOrDefault(taskId, Double.NaN);
  189.     }

  190.     /** {@inheritDoc} */
  191.     @Override
  192.     public String toString()
  193.     {
  194.         return "Fuller [tasks=" + this.tasks + ", behavioralAdapatations=" + this.behavioralAdapatations + "]";
  195.     }

  196.     /**
  197.      * Behavioral adaptation by changing parameter values.
  198.      * <p>
  199.      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
  200.      * <br>
  201.      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  202.      * <p>
  203.      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 apr. 2018 <br>
  204.      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  205.      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  206.      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  207.      */
  208.     @FunctionalInterface
  209.     public interface BehavioralAdaptation
  210.     {
  211.         /**
  212.          * Adapt to task saturation by changing parameter values.
  213.          * @param parameters Parameters; parameters
  214.          * @param taskSaturation double; task saturation
  215.          * @throws ParameterException if a parameter is missing or out of bounds
  216.          */
  217.         void adapt(Parameters parameters, double taskSaturation) throws ParameterException;
  218.     }

  219. }