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 }