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