1 package org.opentrafficsim.road.gtu.lane.tactical.util; 2 3 import java.util.SortedMap; 4 import java.util.SortedSet; 5 import java.util.TreeMap; 6 7 import org.djunits.unit.AccelerationUnit; 8 import org.djunits.unit.SpeedUnit; 9 import org.djunits.value.vdouble.scalar.Acceleration; 10 import org.djunits.value.vdouble.scalar.Length; 11 import org.djunits.value.vdouble.scalar.Speed; 12 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics; 13 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException; 14 import org.opentrafficsim.road.gtu.lane.perception.headway.HeadwayGTU; 15 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel; 16 import org.opentrafficsim.road.network.speed.SpeedLimitInfo; 17 18 import nl.tudelft.simulation.language.Throw; 19 20 /** 21 * Static methods regarding car-following for composition in tactical planners. 22 * <p> 23 * Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 24 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>. 25 * <p> 26 * @version $Revision$, $LastChangedDate$, by $Author$, initial version May 23, 2016 <br> 27 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 28 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a> 29 */ 30 public final class CarFollowingUtil 31 { 32 33 /** 34 * Do not instantiate. 35 */ 36 private CarFollowingUtil() 37 { 38 // 39 } 40 41 /** 42 * Follow a set of headway GTUs. 43 * @param carFollowingModel car-following model 44 * @param behavioralCharacteristics behavioral characteristics 45 * @param speed current speed 46 * @param speedLimitInfo speed limit info 47 * @param leaders leaders 48 * @return acceleration for following the leader 49 * @throws ParameterException if a parameter is not given or out of bounds 50 */ 51 public static Acceleration followLeaders(final CarFollowingModel carFollowingModel, 52 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final SpeedLimitInfo speedLimitInfo, 53 final SortedSet<HeadwayGTU> leaders) throws ParameterException 54 { 55 SortedMap<Length, Speed> leaderMap = new TreeMap<>(); 56 for (HeadwayGTU headwayGTU : leaders) 57 { 58 leaderMap.put(headwayGTU.getDistance(), headwayGTU.getSpeed()); 59 } 60 return carFollowingModel.followingAcceleration(behavioralCharacteristics, speed, speedLimitInfo, leaderMap); 61 } 62 63 /** 64 * Follow a set of headway GTUs. 65 * @param carFollowingModel car-following model 66 * @param behavioralCharacteristics behavioral characteristics 67 * @param speed current speed 68 * @param speedLimitInfo speed limit info 69 * @param distance distance 70 * @param leaderSpeed speed of the leader 71 * @return acceleration for following the leader 72 * @throws ParameterException if a parameter is not given or out of bounds 73 */ 74 public static Acceleration followSingleLeader(final CarFollowingModel carFollowingModel, 75 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final SpeedLimitInfo speedLimitInfo, 76 final Length distance, final Speed leaderSpeed) throws ParameterException 77 { 78 SortedMap<Length, Speed> leaders = new TreeMap<>(); 79 leaders.put(distance, leaderSpeed); 80 return carFollowingModel.followingAcceleration(behavioralCharacteristics, speed, speedLimitInfo, leaders); 81 } 82 83 /** 84 * Stop within given distance. 85 * @param carFollowingModel car-following model 86 * @param behavioralCharacteristics behavioral characteristics 87 * @param speed current speed 88 * @param speedLimitInfo speed limit info 89 * @param distance distance to stop over 90 * @return acceleration to stop over distance 91 * @throws ParameterException if a parameter is not given or out of bounds 92 */ 93 public static Acceleration stop(final CarFollowingModel carFollowingModel, 94 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final SpeedLimitInfo speedLimitInfo, 95 final Length distance) throws ParameterException 96 { 97 SortedMap<Length, Speed> leaderMap = new TreeMap<>(); 98 leaderMap.put(distance, Speed.ZERO); 99 return carFollowingModel.followingAcceleration(behavioralCharacteristics, speed, speedLimitInfo, leaderMap); 100 } 101 102 /** 103 * Return constant acceleration in order to stop in specified distance. The car-following model is used to determine the 104 * stopping distance (i.e. distance remaining at stand still, e.g. 1-3m). 105 * @param carFollowingModel car-following model 106 * @param behavioralCharacteristics behavioral characteristics 107 * @param speed current speed 108 * @param distance distance to stop over 109 * @return constant acceleration in order to stop in specified distance 110 * @throws ParameterException on missing parameter 111 */ 112 public static Acceleration constantAccelerationStop(final CarFollowingModel carFollowingModel, 113 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final Length distance) 114 throws ParameterException 115 { 116 Length s0 = carFollowingModel.desiredHeadway(behavioralCharacteristics, Speed.ZERO); 117 return new Acceleration(-0.5 * speed.si * speed.si / (distance.si - s0.si), AccelerationUnit.SI); 118 } 119 120 /** 121 * Calculate free acceleration. 122 * @param carFollowingModel car-following model 123 * @param behavioralCharacteristics behavioral characteristics 124 * @param speed current speed 125 * @param speedLimitInfo speed limit info 126 * @return acceleration free acceleration 127 * @throws ParameterException if a parameter is not given or out of bounds 128 */ 129 public static Acceleration freeAcceleration(final CarFollowingModel carFollowingModel, 130 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final SpeedLimitInfo speedLimitInfo) 131 throws ParameterException 132 { 133 SortedMap<Length, Speed> leaderMap = new TreeMap<>(); 134 return carFollowingModel.followingAcceleration(behavioralCharacteristics, speed, speedLimitInfo, leaderMap); 135 } 136 137 /** 138 * Returns an acceleration based on the car-following model in order to adjust the speed to a given value at some location 139 * ahead. This is done by placing a virtual vehicle somewhere near the location. Both the location and speed of this virtual 140 * vehicle are dynamically adjusted to resemble a car-following situation. To explain, first consider the situation where a 141 * virtual vehicle is placed at the target speed and such that the equilibrium headway is in line with the location: 142 * 143 * <pre> 144 * 145 * ___ location of target speed --)| ___ 146 * |___|(--------------s--------------) (--h--)|___| ))) vTar 147 * </pre> 148 * 149 * Here, {@code s} is the distance to the target speed, and {@code h} is the desired headway if the vehicle would drive at 150 * the target speed {@code vTar}.<br> 151 * <br> 152 * In this way car-following models will first underestimate the required deceleration, as the virtual vehicle is actually 153 * stationary and does not move with {@code vTar} at all. Because of this underestimation, strong deceleration is required 154 * later. This behavior is not in line with the sensitivity parameters of the car-following model.<br> 155 * <br> 156 * To correct for the fact that the virtual vehicle is actually not moving, the speed difference should be larger, i.e. the 157 * speed of the virtual vehicle {@code vTar'} should be lower. We require: 158 * <ul> 159 * <li>if {@code v = vTar} then {@code vTar' = vTar}, otherwise there is an incentive to accelerate or decelerate for no 160 * good reason</li> 161 * <li>if {@code vTar ~ 0} then {@code vTar' ~ 0}, as car-following models are suitable for stopping and need no additional 162 * incentive to decelerate in such cases</li> 163 * <li>if {@code 0 < vTar < v} then {@code vTar' < vTar}, introducing additional deceleration to compensate for the fact 164 * that the virtual vehicle does not move 165 * </ul> 166 * These requirements are met by {@code vTar' = vTar * (vTar/v) = vTar^2/v}.<br> 167 * <br> 168 * Furthermore, if {@code v < vTar} we get {@code vTar' > vTar} leading to additional acceleration. Acceleration is then 169 * appropriate, and possibly limited by a free term in the car-following model.<br> 170 * <br> 171 * The virtual vehicle is thus placed with speed {@code vTar'} at a distance {@code s + h'} where {@code h'} is the desired 172 * headway if the vehicle would drive at speed {@code vTar'}. Both {@code vTar'} and {@code h'} depend on the current speed 173 * of the vehicle, so the virtual vehicle in this case actually moves, but not with {@code vTar}.<br> 174 * <br> 175 * This approach has been tested with the IDM+ to deliver decelerations in line with the parameters. On a plane with initial 176 * speed ranging from 0 to 33.33m/s and a target speed in 300m also ranging from 0 to 33.33m/s, strongest deceleration is 177 * equal to the car-following model stopping from 33.33m/s to a stand-still vehicle in 300m (+ stopping distance of 3m). 178 * Throughout the plane the maximum deceleration of each scenario is close to this value, unless the initial speed is so 179 * low, and the target speed is so high, that such levels of deceleration are never required.<br> 180 * <br> 181 * @param carFollowingModel car-following model to use 182 * @param behavioralCharacteristics behavioral characteristics 183 * @param speed current speed 184 * @param speedLimitInfo info regarding the desired speed for car-following 185 * @param distance distance to the location of the target speed 186 * @param targetSpeed target speed 187 * @return acceleration acceleration based on the car-following model in order to adjust the speed 188 * @throws ParameterException if parameter exception occurs 189 * @throws NullPointerException if any input is null 190 * @throws IllegalArgumentException if the distance or target speed is not at least 0 191 */ 192 public static Acceleration approachTargetSpeed(final CarFollowingModel carFollowingModel, 193 final BehavioralCharacteristics behavioralCharacteristics, final Speed speed, final SpeedLimitInfo speedLimitInfo, 194 final Length distance, final Speed targetSpeed) throws ParameterException 195 { 196 Throw.whenNull(behavioralCharacteristics, "Behavioral characteristics may not be null."); 197 Throw.whenNull(speed, "Speed may not be null."); 198 Throw.whenNull(speedLimitInfo, "Speed limit info may not be null."); 199 Throw.whenNull(distance, "Distance may not be null"); 200 Throw.whenNull(targetSpeed, "Target speed may not be null"); 201 Throw.when(distance.si < 0, IllegalArgumentException.class, "Distance must be at least 0."); 202 Throw.when(targetSpeed.si < 0, IllegalArgumentException.class, "Target speed must be at least 0."); 203 // adjust speed of virtual vehicle to add deceleration incentive as the virtual vehicle does not move 204 Speed virtualSpeed; 205 if (speed.si > 0) 206 { 207 virtualSpeed = new Speed(targetSpeed.si * targetSpeed.si / speed.si, SpeedUnit.SI); 208 } 209 else 210 { 211 virtualSpeed = new Speed(Double.MAX_VALUE, SpeedUnit.SI); 212 } 213 // set distance in line with equilibrium headway at virtual speed 214 Length virtualDistance = distance.plus(carFollowingModel.desiredHeadway(behavioralCharacteristics, virtualSpeed)); 215 // calculate acceleration towards virtual vehicle with car-following model 216 SortedMap<Length, Speed> leaders = new TreeMap<>(); 217 leaders.put(virtualDistance, virtualSpeed); 218 return carFollowingModel.followingAcceleration(behavioralCharacteristics, speed, speedLimitInfo, leaders); 219 } 220 221 }