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