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.NetworkException; 6 import org.opentrafficsim.road.network.lane.Lane; 7 8 /** 9 * Distraction following a distance profile. 10 * <p> 11 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 12 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 13 * </p> 14 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a> 15 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a> 16 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a> 17 */ 18 public class Distraction extends AbstractLaneBasedObject 19 { 20 21 /** */ 22 private static final long serialVersionUID = 20180405L; 23 24 /** Distraction profile. */ 25 private final DistractionProfile profile; 26 27 /** 28 * @param id id 29 * @param lane lane 30 * @param longitudinalPosition longitudinal position 31 * @param profile distraction profile 32 * @throws NetworkException on network exception 33 */ 34 public Distraction(final String id, final Lane lane, final Length longitudinalPosition, final DistractionProfile profile) 35 throws NetworkException 36 { 37 super(id, lane, longitudinalPosition, LaneBasedObject.makeLine(lane, longitudinalPosition), Length.ZERO); 38 this.profile = profile; 39 40 init(); 41 } 42 43 /** 44 * Returns the level of distraction at the given distance. 45 * @param distance negative when approaching 46 * @return level of distraction (task-demand), or {@code null} if the distraction is no longer important 47 */ 48 public Double getDistraction(final Length distance) 49 { 50 return this.profile.getDistraction(distance); 51 } 52 53 /** 54 * Describes the profile around the distraction. 55 * <p> 56 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. 57 * <br> 58 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 59 * </p> 60 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a> 61 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a> 62 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a> 63 */ 64 @FunctionalInterface 65 public interface DistractionProfile 66 { 67 /** 68 * Returns the level of distraction at the given distance. 69 * @param distance negative when approaching 70 * @return level of distraction (task-demand), or {@code null} if the distraction is no longer important 71 */ 72 Double getDistraction(Length distance); 73 } 74 75 /** 76 * Distraction profile with trapezoid shape. The constant part is from the location of the distraction downstream. 77 * <p> 78 * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. 79 * <br> 80 * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 81 * </p> 82 * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a> 83 * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a> 84 * @author <a href="https://github.com/wjschakel">Wouter Schakel</a> 85 */ 86 public static class TrapezoidProfile implements DistractionProfile 87 { 88 /** Maximum distraction. */ 89 private final double maxDistraction; 90 91 /** Distance before distraction where distraction starts to have effect. */ 92 private final Length dMin; 93 94 /** Distance beyond distraction where distraction has maximum effect. */ 95 private final Length dMed; 96 97 /** Distance beyond distraction where distraction no longer has effect. */ 98 private final Length dMax; 99 100 /** 101 * @param maxDistraction maximum distraction (task-demand) 102 * @param dMin distance before distraction where distraction starts to have effect (<0) 103 * @param dMed distance beyond distraction where distraction has maximum effect (>0) 104 * @param dMax distance beyond distraction where distraction no longer has effect (>dMed) 105 */ 106 public TrapezoidProfile(final double maxDistraction, final Length dMin, final Length dMed, final Length dMax) 107 { 108 Throw.when(dMin.si > 0 || dMed.si < 0 || dMax.si < dMed.si, IllegalArgumentException.class, 109 "dMin < 0 < dMed < dMax does not hold"); 110 Throw.when(maxDistraction < 0 || maxDistraction > 1, IllegalArgumentException.class, 111 "0 <= maxDistraction <= 1 does not hold"); 112 this.maxDistraction = maxDistraction; 113 this.dMin = dMin; 114 this.dMed = dMed; 115 this.dMax = dMax; 116 } 117 118 @Override 119 public Double getDistraction(final Length distance) 120 { 121 if (distance.si < this.dMin.si) 122 { 123 // before scope 124 return 0.0; 125 } 126 else if (distance.si < 0) 127 { 128 // increasing distraction on approach 129 return this.maxDistraction * (1.0 - distance.si / this.dMin.si); 130 } 131 else if (distance.si < this.dMed.si) 132 { 133 // max distraction at location (defined over a distance dMed) 134 return this.maxDistraction; 135 } 136 else if (distance.si < this.dMax.si) 137 { 138 // reducing distraction beyond location 139 return this.maxDistraction * (1.0 - (distance.si - this.dMed.si) / (this.dMax.si - this.dMed.si)); 140 } 141 else 142 { 143 // beyond scope 144 return null; 145 } 146 } 147 } 148 149 }