StochasticDistractionModel.java

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

  2. import java.rmi.RemoteException;
  3. import java.util.LinkedHashMap;
  4. import java.util.LinkedHashSet;
  5. import java.util.LinkedList;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Queue;
  9. import java.util.Set;

  10. import org.djutils.event.Event;
  11. import org.djutils.event.EventListener;
  12. import org.djutils.exceptions.Throw;
  13. import org.djutils.exceptions.Try;
  14. import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
  15. import org.opentrafficsim.core.gtu.Gtu;
  16. import org.opentrafficsim.core.network.Network;
  17. import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
  18. import org.opentrafficsim.road.gtu.lane.perception.mental.Fuller;
  19. import org.opentrafficsim.road.gtu.lane.perception.mental.Mental;
  20. import org.opentrafficsim.road.gtu.lane.perception.mental.Task;
  21. import org.opentrafficsim.road.network.RoadNetwork;

  22. import nl.tudelft.simulation.dsol.SimRuntimeException;

  23. /**
  24.  * Stochastic Distraction Model by Manuel Lindorfer.
  25.  * <p>
  26.  * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  27.  * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
  28.  * </p>
  29.  * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
  30.  * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
  31.  * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
  32.  */
  33. public class StochasticDistractionModel implements EventListener
  34. {

  35.     /** Whether to allow multi-tasking. */
  36.     private final boolean allowMultiTasking;

  37.     /** List of distractions. */
  38.     private final List<Distraction> distractions;

  39.     /** Simulator. */
  40.     private final OtsSimulatorInterface simulator;

  41.     /** Network. */
  42.     private final RoadNetwork network;

  43.     /** Set of distracted GTUs. */
  44.     private final Set<String> distractedGTUs = new LinkedHashSet<>();

  45.     /** Queue of distractions per GTU. */
  46.     private final Map<String, Queue<Distraction>> distractionQueues = new LinkedHashMap<>();

  47.     /**
  48.      * Constructor. This model will react to GTU's being created in simulation and apply distractions.
  49.      * @param allowMultiTasking whether to allow multi-tasking
  50.      * @param distractions list of distractions
  51.      * @param simulator simulator
  52.      * @param network network
  53.      */
  54.     public StochasticDistractionModel(final boolean allowMultiTasking, final List<Distraction> distractions,
  55.             final OtsSimulatorInterface simulator, final RoadNetwork network)
  56.     {
  57.         Throw.whenNull(distractions, "List of tasks may not be null.");
  58.         Throw.whenNull(simulator, "Simulator may not be null.");
  59.         Throw.whenNull(network, "Network may not be null.");
  60.         this.allowMultiTasking = allowMultiTasking;
  61.         this.distractions = distractions;
  62.         this.simulator = simulator;
  63.         this.network = network;
  64.         network.addListener(this, Network.GTU_ADD_EVENT);
  65.         network.addListener(this, Network.GTU_REMOVE_EVENT);
  66.     }

  67.     /**
  68.      * Start a distraction.
  69.      * @param gtu gtu to start the distraction on
  70.      * @param distraction distraction
  71.      * @param scheduleNext whether to schedule the next distraction (not if starting from queue)
  72.      * @throws SimRuntimeException on time error
  73.      */
  74.     public void startDistraction(final LaneBasedGtu gtu, final Distraction distraction, final boolean scheduleNext)
  75.             throws SimRuntimeException
  76.     {
  77.         if (gtu.isDestroyed())
  78.         {
  79.             return;
  80.         }
  81.         String gtuId = gtu.getId();
  82.         if (this.allowMultiTasking || !this.distractedGTUs.contains(gtuId))
  83.         {
  84.             // start the distraction now
  85.             if (!this.allowMultiTasking)
  86.             {
  87.                 this.distractedGTUs.add(gtuId);
  88.             }
  89.             Task task = distraction.getTask(gtu);
  90.             ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).addTask(task);
  91.             // stop the distraction
  92.             this.simulator.scheduleEventRel(distraction.nextDuration(), this, "stopDistraction", new Object[] {gtu, task});
  93.         }
  94.         else
  95.         {
  96.             // need to queue distraction
  97.             if (!this.distractionQueues.containsKey(gtuId))
  98.             {
  99.                 this.distractionQueues.put(gtuId, new LinkedList<>());
  100.             }
  101.             this.distractionQueues.get(gtuId).add(distraction);
  102.         }
  103.         if (scheduleNext)
  104.         {
  105.             // schedule next distraction
  106.             this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, "startDistraction",
  107.                     new Object[] {gtu, distraction, true});
  108.         }
  109.     }

  110.     /**
  111.      * Stops a distraction task.
  112.      * @param gtu gtu to stop the task for
  113.      * @param task task to stop
  114.      * @throws SimRuntimeException on time error
  115.      */
  116.     public void stopDistraction(final LaneBasedGtu gtu, final Task task) throws SimRuntimeException
  117.     {
  118.         if (gtu.isDestroyed())
  119.         {
  120.             return;
  121.         }
  122.         String gtuId = gtu.getId();
  123.         ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).removeTask(task);
  124.         // start next distraction if any in queue
  125.         if (!this.allowMultiTasking)
  126.         {
  127.             this.distractedGTUs.remove(gtuId);
  128.             if (this.distractionQueues.containsKey(gtuId))
  129.             {
  130.                 Queue<Distraction> queue = this.distractionQueues.get(gtuId);
  131.                 Distraction distraction = queue.poll();
  132.                 startDistraction(gtu, distraction, false);
  133.                 if (queue.isEmpty())
  134.                 {
  135.                     this.distractionQueues.remove(gtuId);
  136.                 }
  137.             }
  138.         }
  139.     }

  140.     @Override
  141.     public void notify(final Event event) throws RemoteException
  142.     {
  143.         if (event.getType().equals(Network.GTU_ADD_EVENT))
  144.         {
  145.             // The GTU is not initialized yet, so we can't obtain the tactical planner
  146.             String gtuId = (String) event.getContent();
  147.             Gtu gtu = this.network.getGTU(gtuId);
  148.             gtu.addListener(this, Gtu.MOVE_EVENT);
  149.         }
  150.         else if (event.getType().equals(Gtu.MOVE_EVENT))
  151.         {
  152.             String gtuId = (String) ((Object[]) event.getContent())[0];
  153.             LaneBasedGtu gtu = (LaneBasedGtu) this.network.getGTU(gtuId);
  154.             Mental mental = gtu.getTacticalPlanner().getPerception().getMental();
  155.             if (mental != null && mental instanceof Fuller)
  156.             {
  157.                 for (Distraction distraction : this.distractions)
  158.                 {
  159.                     if (distraction.nextExposure())
  160.                     {
  161.                         Try.execute(
  162.                                 () -> this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, "startDistraction",
  163.                                         new Object[] {gtu, distraction, true}),
  164.                                 "Exception while scheduling distraction start.");
  165.                     }
  166.                 }
  167.             }
  168.             gtu.removeListener(this, Gtu.MOVE_EVENT);
  169.         }
  170.         else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
  171.         {
  172.             String gtuId = (String) event.getContent();
  173.             if (!this.allowMultiTasking)
  174.             {
  175.                 this.distractedGTUs.remove(gtuId);
  176.             }
  177.             this.distractionQueues.remove(gtuId);
  178.         }
  179.     }

  180. }