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 }