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