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 (<0)
118 * @param dMed Length; distance beyond distraction where distraction has maximum effect (>0)
119 * @param dMax Length; distance beyond distraction where distraction no longer has effect (>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 }