View Javadoc
1   package org.opentrafficsim.road.network.lane.object;
2   
3   import org.djunits.value.vdouble.scalar.Length;
4   import org.djutils.exceptions.Throw;
5   import org.opentrafficsim.core.network.LongitudinalDirectionality;
6   import org.opentrafficsim.core.network.NetworkException;
7   import org.opentrafficsim.road.network.lane.CrossSectionElement;
8   import org.opentrafficsim.road.network.lane.Lane;
9   
10  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
11  
12  /**
13   * Distraction following a distance profile.
14   * <p>
15   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
16   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
17   * <p>
18   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 5 apr. 2018 <br>
19   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
20   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
21   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
22   */
23  public class Distraction extends AbstractLaneBasedObject
24  {
25  
26      /** */
27      private static final long serialVersionUID = 20180405L;
28  
29      /** Distraction profile. */
30      private final DistractionProfile profile;
31  
32      /**
33       * @param id String; id
34       * @param lane Lane; lane
35       * @param longitudinalPosition Length; longitudinal position
36       * @param simulator SimulatorInterface.TimeDoubleUnit; simulator
37       * @param profile DistractionProfile; distraction profile
38       * @throws NetworkException on network exception
39       */
40      public Distraction(final String id, final Lane lane, final Length longitudinalPosition,
41              final SimulatorInterface.TimeDoubleUnit simulator, final DistractionProfile profile) throws NetworkException
42      {
43          super(id, lane, LongitudinalDirectionality.DIR_PLUS, longitudinalPosition,
44                  LaneBasedObject.makeGeometry(lane, longitudinalPosition), Length.ZERO);
45          this.profile = profile;
46          
47          init();
48      }
49  
50      /** {@inheritDoc} */
51      @Override
52      public AbstractLaneBasedObject clone(final CrossSectionElement newCSE, final SimulatorInterface.TimeDoubleUnit newSimulator)
53              throws NetworkException
54      {
55          return new Distraction(getId(), (Lane) newCSE, getLongitudinalPosition(), newSimulator, this.profile);
56      }
57  
58      /**
59       * Returns the level of distraction at the given distance.
60       * @param distance Distance to distraction; negative when approaching
61       * @return Double; level of distraction (task-demand), or {@code null} if the distraction is no longer important
62       */
63      public Double getDistraction(final Length distance)
64      {
65          return this.profile.getDistraction(distance);
66      }
67  
68      /**
69       * Describes the profile around the distraction.
70       * <p>
71       * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
72       * <br>
73       * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
74       * <p>
75       * @version $Revision$, $LastChangedDate$, by $Author$, initial version 5 apr. 2018 <br>
76       * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
77       * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
78       * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
79       */
80      @FunctionalInterface
81      public interface DistractionProfile
82      {
83          /**
84           * Returns the level of distraction at the given distance.
85           * @param distance Distance to distraction; negative when approaching
86           * @return Double; level of distraction (task-demand), or {@code null} if the distraction is no longer important
87           */
88          Double getDistraction(Length distance);
89      }
90  
91      /**
92       * Distraction profile with trapezoid shape. The constant part is from the location of the distraction downstream.
93       * <p>
94       * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
95       * <br>
96       * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
97       * <p>
98       * @version $Revision$, $LastChangedDate$, by $Author$, initial version 5 apr. 2018 <br>
99       * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
100      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
101      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
102      */
103     public static class TrapezoidProfile implements DistractionProfile
104     {
105         /** Maximum distraction. */
106         private final double maxDistraction;
107 
108         /** Distance before distraction where distraction starts to have effect. */
109         private final Length dMin;
110 
111         /** Distance beyond distraction where distraction has maximum effect. */
112         private final Length dMed;
113 
114         /** Distance beyond distraction where distraction no longer has effect. */
115         private final Length dMax;
116 
117         /**
118          * @param maxDistraction double; maximum distraction (task-demand)
119          * @param dMin Length; distance before distraction where distraction starts to have effect (&lt;0)
120          * @param dMed Length; distance beyond distraction where distraction has maximum effect (&gt;0)
121          * @param dMax Length; distance beyond distraction where distraction no longer has effect (&gt;dMed)
122          */
123         public TrapezoidProfile(final double maxDistraction, final Length dMin, final Length dMed, final Length dMax)
124         {
125             Throw.when(dMin.si > 0 || dMed.si < 0 || dMax.si < dMed.si, IllegalArgumentException.class,
126                     "dMin < 0 < dMed < dMax does not hold");
127             Throw.when(maxDistraction < 0 || maxDistraction > 1, IllegalArgumentException.class,
128                     "0 <= maxDistraction <= 1 does not hold");
129             this.maxDistraction = maxDistraction;
130             this.dMin = dMin;
131             this.dMed = dMed;
132             this.dMax = dMax;
133         }
134 
135         /** {@inheritDoc} */
136         @Override
137         public Double getDistraction(final Length distance)
138         {
139             if (distance.si < this.dMin.si)
140             {
141                 // before scope
142                 return 0.0;
143             }
144             else if (distance.si < 0)
145             {
146                 // increasing distraction on approach
147                 return this.maxDistraction * (1.0 - distance.si / this.dMin.si);
148             }
149             else if (distance.si < this.dMed.si)
150             {
151                 // max distraction at location (defined over a distance dMed)
152                 return this.maxDistraction;
153             }
154             else if (distance.si < this.dMax.si)
155             {
156                 // reducing distraction beyond location
157                 return this.maxDistraction * (1.0 - (distance.si - this.dMed.si) / (this.dMax.si - this.dMed.si));
158             }
159             else
160             {
161                 // beyond scope
162                 return null;
163             }
164         }
165     }
166 
167 }