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