AbstractCarFollowingModel.java

package org.opentrafficsim.road.gtu.lane.tactical.following;

import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

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.djunits.value.vdouble.scalar.Time.Abs;
import org.opentrafficsim.core.gtu.GTUException;
import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterException;
import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;

/**
 * Implements free, single-leader and multi-anticipative methods as forwards to a new multi-anticipative method with
 * desired headway and speed pre-calculated. The information forwarded to the new method implies a leader at infinite
 * headway for free acceleration, and a single vehicle in the set for single-leader acceleration. As a result, 
 * implementations of this class only need to implement a single, and simpler, method covering different calls to the 
 * car-following model. The headway towards the first vehicle being followed is guaranteed to be positive.
 * TODO: do not implement GTUFollowingModelOld
 * @author Wouter Schakel
 */
public abstract class AbstractCarFollowingModel implements CarFollowingModel, GTUFollowingModelOld  {

	/** {@inheritDoc} */
	public Acceleration freeAcceleration(LaneBasedGTU gtu, Speed speed, Speed speedLimit, boolean enforcement, 
			Speed maximumVehicleSpeed) throws ParameterException {
		// Fill map with a single leader at infinite headway and the same speed.
		SortedMap<Length.Rel, Speed> leaders = new TreeMap<Length.Rel, Speed>();
		leaders.put(new Length.Rel(Double.POSITIVE_INFINITY, LengthUnit.SI), speed);
		return followingAcceleration(gtu, speed, this.desiredSpeed(gtu, speedLimit, enforcement, maximumVehicleSpeed), 
				this.desiredHeadway(gtu, speed), leaders);
	}

	/** {@inheritDoc} */
	public Acceleration followingAcceleration(LaneBasedGTU gtu, Speed speed, Speed speedLimit, boolean enforcement, 
			Speed maximumVehicleSpeed, Length.Rel headway, Speed leaderSpeed) throws ParameterException {
		// Catch negative headway
		if (headway.si<=0) {
			// The car-following model is undefined for this case, return 'inappropriate' acceleration. Whatever uses
			// the car-following model has to figure out what to do in this situation. E.g. limit deceleration to an
			// extent depending on the circumstances, or divert from a certain behavior. 
			return new Acceleration(Double.NEGATIVE_INFINITY, AccelerationUnit.SI);
		}
		// Fill map with the single leader.
		SortedMap<Length.Rel, Speed> leaders = new TreeMap<Length.Rel, Speed>();
		leaders.put(headway, leaderSpeed);
		return followingAcceleration(gtu, speed, this.desiredSpeed(gtu, speedLimit, enforcement, maximumVehicleSpeed), 
				this.desiredHeadway(gtu, speed), leaders);
	}

	/** {@inheritDoc} */
	public Acceleration followingAcceleration(LaneBasedGTU gtu, Speed speed, Speed speedLimit, boolean enforcement, 
			Speed maximumVehicleSpeed, SortedMap<Length.Rel, Speed> leaders) throws ParameterException {
		// Catch negative headway
		if (leaders.firstKey().si<=0) {
			// The car-following model is undefined for this case, return 'inappropriate' acceleration. Whatever uses
			// the car-following model has to figure out what to do in this situation. E.g. limit deceleration to an
			// extent depending on the circumstances, or divert from a certain behavior. 
			return new Acceleration(Double.NEGATIVE_INFINITY, AccelerationUnit.SI);
		}
		// Forward to method with desired speed and headway predetermined by this car-following model.
		return followingAcceleration(gtu, speed, this.desiredSpeed(gtu, speedLimit, enforcement, maximumVehicleSpeed), 
				this.desiredHeadway(gtu, speed), leaders);
	}
	
	/**
	 * Multi-anticipative determination of car-following acceleration. The implementation should be able to deal with
	 * the current speed being higher than the desired speed. The tactical planner determines whether multi-anticipative 
	 * car-following is applied, including to how many leaders and within what distance, by including these vehicles in 
	 * the set. The car-following model itself may however only respond to the first vehicle.
	 * @param gtu GTU for which the acceleration is calculated.
	 * @param speed Current speed.
	 * @param desiredSpeed Desired speed.
	 * @param desiredHeadway Desired headway.
	 * @param leaders Set of leader headways (guaranteed positive) and speeds, ordered by headway (closest first).
     * @throws ParameterException If parameter exception occurs.
	 * @return Car-following acceleration.
	 */
	protected abstract Acceleration followingAcceleration(LaneBasedGTU gtu, Speed speed, Speed desiredSpeed, 
			Length.Rel desiredHeadway, SortedMap<Length.Rel, Speed> leaders) throws ParameterException;

	
	// TODO: Remove methods below
	
	@Override
	public AccelerationStep computeAccelerationStep(LaneBasedGTU gtu,
			Speed leaderSpeed, Rel headway, Rel maxDistance, Speed speedLimit)
			throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccelerationStep computeAccelerationStep(LaneBasedGTU gtu,
			Speed leaderSpeed, Rel headway, Rel maxDistance, Speed speedLimit,
			org.djunits.value.vdouble.scalar.Time.Rel stepSize)
			throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Acceleration computeAcceleration(Speed followerSpeed,
			Speed followerMaximumSpeed, Speed leaderSpeed, Rel headway,
			Speed speedLimit) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Acceleration computeAcceleration(Speed followerSpeed,
			Speed followerMaximumSpeed, Speed leaderSpeed, Rel headway,
			Speed speedLimit, org.djunits.value.vdouble.scalar.Time.Rel stepSize) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccelerationStep computeAccelerationStep(Speed followerSpeed,
			Speed leaderSpeed, Rel headway, Speed speedLimit, Abs currentTime) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccelerationStep computeAccelerationStep(Speed followerSpeed,
			Speed leaderSpeed, Rel headway, Speed speedLimit, Abs currentTime,
			org.djunits.value.vdouble.scalar.Time.Rel stepSize) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public DualAccelerationStep computeDualAccelerationStep(LaneBasedGTU gtu,
			Collection<HeadwayGTU> otherGtuHeadways, Rel maxDistance,
			Speed speedLimit) throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public DualAccelerationStep computeDualAccelerationStep(LaneBasedGTU gtu,
			Collection<HeadwayGTU> otherGtuHeadways, Rel maxDistance,
			Speed speedLimit, org.djunits.value.vdouble.scalar.Time.Rel stepSize)
			throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccelerationStep computeAccelerationStepWithNoLeader(
			LaneBasedGTU gtu, Rel maxDistance, Speed speedLimit)
			throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccelerationStep computeAccelerationStepWithNoLeader(
			LaneBasedGTU gtu, Rel maxDistance, Speed speedLimit,
			org.djunits.value.vdouble.scalar.Time.Rel stepSize)
			throws GTUException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Rel minimumHeadway(Speed followerSpeed, Speed leaderSpeed,
			Rel precision, Rel maxDistance, Speed speedLimit,
			Speed followerMaximumSpeed) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Acceleration getMaximumSafeDeceleration() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public org.djunits.value.vdouble.scalar.Time.Rel getStepSize() {
		// TODO Auto-generated method stub
		return null;
	}

	
}