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