View Javadoc
1   package org.opentrafficsim.road.gtu.lane.perception.mental.sdm;
2   
3   import java.rmi.RemoteException;
4   import java.util.LinkedHashMap;
5   import java.util.LinkedHashSet;
6   import java.util.LinkedList;
7   import java.util.List;
8   import java.util.Map;
9   import java.util.Queue;
10  import java.util.Set;
11  
12  import org.djutils.exceptions.Throw;
13  import org.djutils.exceptions.Try;
14  import org.opentrafficsim.core.gtu.GTU;
15  import org.opentrafficsim.core.network.Network;
16  import org.opentrafficsim.core.network.OTSNetwork;
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.Fuller.Task;
20  import org.opentrafficsim.road.gtu.lane.perception.mental.Mental;
21  
22  import nl.tudelft.simulation.dsol.SimRuntimeException;
23  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
24  import nl.tudelft.simulation.event.EventInterface;
25  import nl.tudelft.simulation.event.EventListenerInterface;
26  
27  /**
28   * Stochastic Distraction Model by Manuel Lindorfer.
29   * <p>
30   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
31   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
32   * <p>
33   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 28 jun. 2018 <br>
34   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
35   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
36   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
37   */
38  public class StochasticDistractionModel implements EventListenerInterface
39  {
40  
41      /** Whether to allow multi-tasking. */
42      private final boolean allowMultiTasking;
43  
44      /** List of distractions. */
45      private final List<Distraction> distractions;
46  
47      /** Simulator. */
48      private final DEVSSimulatorInterface.TimeDoubleUnit simulator;
49  
50      /** Network. */
51      private final OTSNetwork network;
52  
53      /** Set of distracted GTUs. */
54      private final Set<String> distractedGTUs = new LinkedHashSet<>();
55  
56      /** Queue of distractions per GTU. */
57      private final Map<String, Queue<Distraction>> distractionQueues = new LinkedHashMap<>();
58  
59      /**
60       * Constructor. This model will react to GTU's being created in simulation and apply distractions.
61       * @param allowMultiTasking boolean; whether to allow multi-tasking
62       * @param distractions List&lt;Distraction&gt;; list of distractions
63       * @param simulator DEVSSimulatorInterface.TimeDoubleUnit; simulator
64       * @param network OTSNetwork; network
65       */
66      public StochasticDistractionModel(final boolean allowMultiTasking, final List<Distraction> distractions,
67              final DEVSSimulatorInterface.TimeDoubleUnit simulator, final OTSNetwork network)
68      {
69          Throw.whenNull(distractions, "List of tasks may not be null.");
70          Throw.whenNull(simulator, "Simulator may not be null.");
71          Throw.whenNull(network, "Network may not be null.");
72          this.allowMultiTasking = allowMultiTasking;
73          this.distractions = distractions;
74          this.simulator = simulator;
75          this.network = network;
76          network.addListener(this, Network.GTU_ADD_EVENT);
77          network.addListener(this, Network.GTU_REMOVE_EVENT);
78      }
79  
80      /**
81       * Start a distraction.
82       * @param gtu LaneBasedGTU; gtu to start the distraction on
83       * @param distraction Distraction; distraction
84       * @param scheduleNext boolean; whether to schedule the next distraction (not if starting from queue)
85       * @throws SimRuntimeException on time error
86       */
87      public void startDistraction(final LaneBasedGTU gtu, final Distraction distraction, final boolean scheduleNext)
88              throws SimRuntimeException
89      {
90          if (gtu.isDestroyed())
91          {
92              return;
93          }
94          String gtuId = gtu.getId();
95          if (this.allowMultiTasking || !this.distractedGTUs.contains(gtuId))
96          {
97              // start the distraction now
98              if (!this.allowMultiTasking)
99              {
100                 this.distractedGTUs.add(gtuId);
101             }
102             Task task = distraction.getTask(gtu);
103             ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).addTask(task);
104             // stop the distraction
105             this.simulator.scheduleEventRel(distraction.nextDuration(), this, this, "stopDistraction",
106                     new Object[] { gtu, task });
107         }
108         else
109         {
110             // need to queue distraction
111             if (!this.distractionQueues.containsKey(gtuId))
112             {
113                 this.distractionQueues.put(gtuId, new LinkedList<>());
114             }
115             this.distractionQueues.get(gtuId).add(distraction);
116         }
117         if (scheduleNext)
118         {
119             // schedule next distraction
120             this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, this, "startDistraction",
121                     new Object[] { gtu, distraction, true });
122         }
123     }
124 
125     /**
126      * Stops a distraction task.
127      * @param gtu LaneBasedGTU; gtu to stop the task for
128      * @param task Task; task to stop
129      * @throws SimRuntimeException on time error
130      */
131     public void stopDistraction(final LaneBasedGTU gtu, final Task task) throws SimRuntimeException
132     {
133         if (gtu.isDestroyed())
134         {
135             return;
136         }
137         String gtuId = gtu.getId();
138         ((Fuller) gtu.getTacticalPlanner().getPerception().getMental()).removeTask(task);
139         // start next distraction if any in queue
140         if (!this.allowMultiTasking)
141         {
142             this.distractedGTUs.remove(gtuId);
143             if (this.distractionQueues.containsKey(gtuId))
144             {
145                 Queue<Distraction> queue = this.distractionQueues.get(gtuId);
146                 Distraction distraction = queue.poll();
147                 startDistraction(gtu, distraction, false);
148                 if (queue.isEmpty())
149                 {
150                     this.distractionQueues.remove(gtuId);
151                 }
152             }
153         }
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public void notify(final EventInterface event) throws RemoteException
159     {
160         if (event.getType().equals(Network.GTU_ADD_EVENT))
161         {
162             // The GTU is not initialized yet, so we can't obtain the tactical planner
163             String gtuId = (String) event.getContent();
164             GTU gtu = this.network.getGTU(gtuId);
165             gtu.addListener(this, GTU.INIT_EVENT);
166         }
167         else if (event.getType().equals(GTU.INIT_EVENT))
168         {
169             String gtuId = (String) ((Object[]) event.getContent())[0];
170             LaneBasedGTU gtu = (LaneBasedGTU) this.network.getGTU(gtuId);
171             Mental mental = gtu.getTacticalPlanner().getPerception().getMental();
172             if (mental != null && mental instanceof Fuller)
173             {
174                 for (Distraction distraction : this.distractions)
175                 {
176                     if (distraction.nextExposure())
177                     {
178                         Try.execute(
179                                 () -> this.simulator.scheduleEventRel(distraction.nextInterArrival(), this, this,
180                                         "startDistraction", new Object[] { gtu, distraction, true }),
181                                 "Exception while scheduling distraction start.");
182                     }
183                 }
184             }
185         }
186         else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
187         {
188             String gtuId = (String) event.getContent();
189             if (!this.allowMultiTasking)
190             {
191                 this.distractedGTUs.remove(gtuId);
192             }
193             this.distractionQueues.remove(gtuId);
194         }
195     }
196 
197 }