1 package org.opentrafficsim.road.gtu.following; 2 3 /** 4 * IDMPlus implements the <i>Integrated Lane Change Model with Relaxation and Synchronization</i> as published by Wouter J. 5 * Schakel, Bart van Arem, Member, IEEE, and Bart D. Netten. 2012. <br> 6 * There are two nasty type setting errors in equation 7 in this published version of the paper. Both times an equals sign 7 * (<cite>=</cite>) after <cite>a<sub>gain</sub></cite> should <b>not</b> be there. 8 * <p> 9 * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 10 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 11 * <p> 12 * @version $Revision: 1408 $, $LastChangedDate: 2015-09-24 15:17:25 +0200 (Thu, 24 Sep 2015) $, by $Author: pknoppers $, 13 * initial version Jul 4, 2014 <br> 14 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 15 */ 16 public class IDMPlus extends AbstractGTUFollowingModel 17 { 18 /** Preferred net longitudinal distance when stopped [m]. */ 19 private final Length.Rel s0; 20 21 /** Longitudinal acceleration [m/s^2]. */ 22 private final Acceleration.Abs a; 23 24 /** Longitudinal deceleration [m/s^2]. (Should be a positive value even though it is a <b>de</b>celeration.) */ 25 private final Acceleration.Abs b; 26 27 /** Safe time headway. */ 28 private final Time.Rel tSafe; 29 30 /** 31 * Mean speed limit adherence (1.0: mean free speed equals the speed limit; 1.1: mean free speed equals 110% of the speed 32 * limit, etc.). 33 */ 34 private final double delta; 35 36 /** 37 * Time slot size used by IDMPlus by (not defined in the paper, but 0.5s is a reasonable trade-off between computational 38 * speed and accuracy). 39 */ 40 private final Time.Rel stepSize = new Time.Rel(0.5, SECOND); 41 42 /** 43 * Construct a new IDM+ car following model with reasonable values (reasonable for passenger cars). <br> 44 * These values are from <b>Integrated Lane Change Model with Relaxation and Synchronization</b> by Wouter J. Schakel, 45 * Victor L. Knoop, and Bart van Arem, published in Transportation Research Record: Journal of the Transportation Research 46 * Board, No. 2316, Transportation Research Board of the National Academies, Washington, D.C., 2012, pp. 47–57. 47 */ 48 public IDMPlus() 49 { 50 this.a = new Acceleration.Abs(1.56, METER_PER_SECOND_2); 51 this.b = new Acceleration.Abs(2.09, METER_PER_SECOND_2); 52 this.s0 = new Length.Rel(3, METER); 53 this.tSafe = new Time.Rel(1.2, SECOND); 54 this.delta = 1d; 55 } 56 57 /** 58 * Construct a new IDMPlus car following model. 59 * @param a DoubleScalar.Abs<AccelerationUnit>; the maximum acceleration of a stationary vehicle (normal value is 1 60 * m/s/s) 61 * @param b DoubleScalar.Abs<AccelerationUnit>; the maximum deemed-safe deceleration (this is a positive value) 62 * @param s0 DoubleScalar.Rel<LengthUnit>; the minimum stationary headway 63 * @param tSafe DoubleScalar.Rel<TimeUnit>; the minimum time-headway 64 * @param delta double; the speed limit adherence (1.0; mean free speed equals the speed limit; 1.1: mean free speed equals 65 * 110% of the speed limit; etc.) 66 */ 67 public IDMPlus(final Acceleration.Abs a, final Acceleration.Abs b, final Length.Rel s0, final Time.Rel tSafe, 68 final double delta) 69 { 70 this.a = a; 71 this.b = b; 72 this.s0 = s0; 73 this.tSafe = tSafe; 74 this.delta = delta; 75 } 76 77 /** 78 * Desired speed (taking into account the urge to drive a little faster or slower than the posted speed limit). 79 * @param speedLimit DoubleScalarAbs<SpeedUnit>; the speed limit 80 * @param followerMaximumSpeed DoubleScalar.Abs<SpeedUnit>; the maximum speed that the follower can drive 81 * @return DoubleScalarRel<SpeedUnit>; the desired speed 82 */ 83 private Speed.Rel vDes(final Speed.Abs speedLimit, final Speed.Abs followerMaximumSpeed) 84 { 85 return new Speed.Rel(Math.min(this.delta * speedLimit.getSI(), followerMaximumSpeed.getSI()), METER_PER_SECOND); 86 } 87 88 /** {@inheritDoc} */ 89 public final Acceleration.Abs computeAcceleration(final Speed.Abs followerSpeed, final Speed.Abs followerMaximumSpeed, 90 final Speed.Abs leaderSpeed, final Length.Rel headway, final Speed.Abs speedLimit) 91 { 92 double leftComponent = 1 - Math.pow(followerSpeed.getSI() / vDes(speedLimit, followerMaximumSpeed).getSI(), 4); 93 if (Double.isNaN(leftComponent)) 94 { 95 leftComponent = 0; 96 } 97 // if (leftComponent < 0) 98 // { 99 // System.out.println("leftComponent is " + leftComponent); 100 // } 101 Acceleration.Rel logWeightedAccelerationTimes2 = 102 new Acceleration.Rel(Math.sqrt(this.a.getSI() * this.b.getSI()), METER_PER_SECOND_2).multiplyBy(2); 103 // don't forget the times 2 104 105 Speed.Rel dV = followerSpeed.minus(leaderSpeed); 106 // System.out.println("dV is " + dV); 107 // System.out.println(" v is " + gtu.speed(thisEvaluationTime)); 108 // System.out.println("s0 is " + this.s0); 109 Length.Rel sStar = 110 this.s0.plus(followerSpeed.toRel().multiplyBy(this.tSafe)).plus( 111 dV.multiplyBy(followerSpeed.toRel().divideBy(logWeightedAccelerationTimes2))); 112 113 /*- 114 this.s0.plus(Calc.speedTimesTime(followerSpeed, this.tSafe)).plus( 115 Calc.speedTimesTime(dV, Calc.speedDividedByAcceleration(followerSpeed, logWeightedAccelerationTimes2))); 116 */ 117 if (sStar.getSI() < 0) 118 { 119 // Negative value should be treated as 0? This is NOT in the LMRS paper 120 // Without this "fix" a higher speed of the leader may cause a lower acceleration (which is crazy) 121 sStar = new Length.Rel(0, METER); 122 } 123 // System.out.println("s* is " + sStar); 124 125 double rightComponent = 1 - Math.pow(sStar.getSI() / headway.getSI(), 2); 126 // if (rightComponent < 0) 127 // { 128 // System.out.println("rightComponent is " + rightComponent); 129 // } 130 Acceleration.Abs newAcceleration = new Acceleration.Abs(this.a).multiplyBy(Math.min(leftComponent, rightComponent)); 131 // System.out.println("newAcceleration is " + newAcceleration); 132 if (newAcceleration.getSI() * this.stepSize.getSI() + followerSpeed.getSI() < 0) 133 { 134 // System.out.println("Preventing follower from driving backwards " + follower); 135 newAcceleration = new Acceleration.Abs(-followerSpeed.getSI() / this.stepSize.getSI(), METER_PER_SECOND_2); 136 } 137 // System.out.println("newAcceleration is " + newAcceleration); 138 return newAcceleration; 139 } 140 141 /** {@inheritDoc} */ 142 @Override 143 public final Time.Rel getStepSize() 144 { 145 return new Time.Rel(this.stepSize); 146 } 147 148 /** {@inheritDoc} */ 149 @Override 150 public final Acceleration.Abs maximumSafeDeceleration() 151 { 152 return this.b; 153 } 154 155 /** {@inheritDoc} */ 156 @Override 157 public final String getName() 158 { 159 return "IDM+"; 160 } 161 162 /** {@inheritDoc} */ 163 @Override 164 public final String getLongName() 165 { 166 return String.format("%s (a=%.1fm/s\u00b2, b=%.1fm/s\u00b2, s0=%.1fm, tSafe=%.1fs, delta=%.2f)", getName(), 167 this.a.getSI(), this.b.getSI(), this.s0.getSI(), this.tSafe.getSI(), this.delta); 168 } 169 170 }