IDM.java
package org.opentrafficsim.road.gtu.lane.tactical.following;
import java.util.SortedMap;
import org.djunits.unit.AccelerationUnit;
import org.djunits.unit.LengthUnit;
import org.djunits.value.vdouble.scalar.Acceleration;
import org.djunits.value.vdouble.scalar.Length;
import org.djunits.value.vdouble.scalar.Length.Rel;
import org.djunits.value.vdouble.scalar.Speed;
import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterException;
import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterTypeDouble;
import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterTypes;
import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
/**
* Implementation of the IDM.
* See <a href=https://en.wikipedia.org/wiki/Intelligent_driver_model>https://en.wikipedia.org/wiki/Intelligent_driver_model</a>
* @author Wouter Schakel
*/
public class IDM extends AbstractCarFollowingModel {
/** Speed limit adherence factor. */
public static final ParameterTypeDouble DELTA = new ParameterTypeDouble("delta",
"Acceleration flattening exponent towards desired speed.", 4.0) {
public void check(double value) throws ParameterException {
ParameterException.failIf(value<=0, "Parameter of type delta may not have a negative or zero value.");
}
};
/** {@inheritDoc} */
public Speed desiredSpeed(LaneBasedGTU gtu, Speed speedLimit, boolean enforcement, Speed maximumVehicleSpeed)
throws ParameterException {
if (!enforcement) {
speedLimit = speedLimit.multiplyBy(gtu.getBehavioralCharacteristics().getParameter(ParameterTypes.FSPEED));
}
return speedLimit.le(maximumVehicleSpeed) ? speedLimit : maximumVehicleSpeed;
}
/** {@inheritDoc} */
public Rel desiredHeadway(LaneBasedGTU gtu, Speed speed) throws ParameterException {
return gtu.getBehavioralCharacteristics().getLengthParameter(ParameterTypes.S0).plus(
speed.multiplyBy(gtu.getBehavioralCharacteristics().getTimeParameter(ParameterTypes.T)));
}
/** {@inheritDoc} */
public String getName() {
return "IDM";
}
/** {@inheritDoc} */
public String getLongName() {
return "Intelligent Driver Model";
}
/** {@inheritDoc} */
protected Acceleration followingAcceleration(LaneBasedGTU gtu, Speed speed, Speed desiredSpeed, Rel desiredHeadway,
SortedMap<Rel, Speed> leaders) throws ParameterException {
Acceleration a = gtu.getBehavioralCharacteristics().getAccelerationParameter(ParameterTypes.A);
double delta = gtu.getBehavioralCharacteristics().getParameter(DELTA);
double sStar = dynamicDesiredHeadway(gtu, speed, desiredHeadway, leaders.get(leaders.firstKey())).si;
return new Acceleration(a.si * (1-Math.pow(speed.si/desiredSpeed.si, delta)-
(sStar/leaders.firstKey().si)*(sStar/leaders.firstKey().si)), AccelerationUnit.SI);
}
/**
* Determines the dynamic desired headway, which is non-negative.
* @param gtu GTU for which the dynamic desired headway is calculated.
* @param speed Current speed.
* @param desiredHeadway Desired speed.
* @param leaderSpeed Speed of the leading vehicle.
* @return Dynamic desired headway.
* @throws ParameterException x
*/
protected Length.Rel dynamicDesiredHeadway(LaneBasedGTU gtu, Speed speed, Rel desiredHeadway, Speed leaderSpeed)
throws ParameterException {
double sStar = desiredHeadway.si + dynamicHeadwayTerm(gtu, speed, leaderSpeed).si;
/*
* Due to a power of 2 in the IDM, negative values of sStar are not allowed. A negative sStar means that the
* leader is faster to such an extent, that the equilibrium headway (s0+vT) is completely compensated by the
* dynamic part in sStar. This might occur if a much faster leader changes lane closely in front. The
* compensation is limited to the equilibrium headway (i.e. sStar = 0), which means the driver wants to follow
* with acceleration. Note that usually the free term determines acceleration in such cases.
*/
return new Length.Rel(sStar>=0 ? sStar : 0, LengthUnit.SI);
}
/**
* Determines the dynamic headway term. May be used on individual leaders for multi-anticipative following.
* @param gtu GTU for which the dynamic desired headway term is calculated.
* @param speed Current speed.
* @param leaderSpeed Speed of the leading vehicle.
* @return Dynamic headway term.
* @throws ParameterException x
*/
protected Length.Rel dynamicHeadwayTerm(LaneBasedGTU gtu, Speed speed, Speed leaderSpeed) throws ParameterException {
Acceleration a = gtu.getBehavioralCharacteristics().getAccelerationParameter(ParameterTypes.A);
Acceleration b = gtu.getBehavioralCharacteristics().getAccelerationParameter(ParameterTypes.B);
return new Length.Rel(speed.si*(speed.si-leaderSpeed.si) / (2*Math.sqrt(a.si + b.si)), LengthUnit.SI);
}
}