* Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
* initial version Jul 11, 2014
* @author Peter Knoppers
*/
public class IDMPlusTest implements UNITS
{
/** The network. */
private OTSNetwork network = new OTSNetwork("IDMPlus test network");
/**
* Test IDMPlus.
* @throws Exception when something goes wrong (should not happen)
*/
@SuppressWarnings({ "static-method", "checkstyle:methodlength" })
@Test
public final void computeAcceleration() throws Exception
{
// Test 1. Check a car standing still with no leaders accelerates with maximum acceleration
// cars have #10 and up
SimpleSimulator simulator = new SimpleSimulator(new Time(0, SECOND), new Duration(0, SECOND),
new Duration(3600, SECOND), new IDMPlusTestModel());
Length s0 = new Length(2, METER);
GTUFollowingModelOld carFollowingModel = new IDMPlusOld(new Acceleration(1.25, METER_PER_SECOND_2),
new Acceleration(1.5, METER_PER_SECOND_2), s0, new Duration(1, SECOND), 1d);
GTUType gtuType = CAR;
Set compatibility = new HashSet();
compatibility.add(gtuType);
LaneType laneType = new LaneType("CarLane", compatibility);
Lane lane = CarTest.makeLane(this.network, laneType);
Time initialTime = new Time(0, SECOND);
Length initialPosition = new Length(123.456, METER);
Speed initialSpeed = new Speed(0, KM_PER_HOUR);
Length length = new Length(5.0, METER);
Length width = new Length(2.0, METER);
Set initialLongitudinalPositions = new LinkedHashSet<>(1);
initialLongitudinalPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
Speed maxSpeed = new Speed(120, KM_PER_HOUR);
// AbstractLaneChangeModel laneChangeModel = new Egoistic();
BehavioralCharacteristics behavioralCharacteristicsIDM = DefaultTestParameters.create();
// fixed value for consistent testing even if the default value is changed
Length lookAhead = new Length(250, LengthUnit.SI);
// LaneBasedBehavioralCharacteristics drivingCharacteristicsIDM =
// new LaneBasedBehavioralCharacteristics(carFollowingModel, laneChangeModel);
LaneBasedIndividualGTU referenceCar10 =
new LaneBasedIndividualGTU("10", gtuType, length, width, maxSpeed, simulator, this.network);
LaneBasedStrategicalPlanner strategicalPlannerIDM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsIDM,
new LaneBasedGTUFollowingTacticalPlanner(carFollowingModel, referenceCar10), referenceCar10);
referenceCar10.init(strategicalPlannerIDM, initialLongitudinalPositions, initialSpeed);
referenceCar10.getTacticalPlanner().getPerception().perceive();
Speed speedLimit = new Speed(100, KM_PER_HOUR);
AccelerationStep cfmr = carFollowingModel.computeAccelerationStepWithNoLeader(referenceCar10, lookAhead, speedLimit);
assertEquals("Standard time slice in IDM+ is 0.5s", 0.5, cfmr.getValidUntil().getSI(), 0.0001);
assertEquals("Acceleration should be maximum", 1.25, cfmr.getAcceleration().getSI(), 0.0001);
// Create another car at exactly the stationary following distance
// Check that the follower remains stationary
Length leaderPosition = new Length(2 + referenceCar10.getLength().getSI()
+ referenceCar10.position(lane, referenceCar10.getReference(), initialTime).getSI(), METER);
Set leaderPositions = new LinkedHashSet<>(1);
leaderPositions.add(new DirectedLanePosition(lane, leaderPosition, GTUDirectionality.DIR_PLUS));
// The leader gets a car following model that makes it stay in place for a loooong time
// edit wouter schakel: not too long, cars should not exceed the lane length, i.e. 9999 to 999
FixedAccelerationModel fam =
new FixedAccelerationModel(new Acceleration(0, METER_PER_SECOND_2), new Duration(999, SECOND));
BehavioralCharacteristics behavioralCharacteristicsFAM = DefaultTestParameters.create();
// LaneBasedBehavioralCharacteristics drivingCharacteristicsFAM =
// new LaneBasedBehavioralCharacteristics(fam, laneChangeModel);
LaneBasedIndividualGTU leaderCar11 =
new LaneBasedIndividualGTU("11", gtuType, length, width, maxSpeed, simulator, this.network);
LaneBasedStrategicalPlanner strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar11), leaderCar11);
leaderCar11.init(strategicalPlannerFAM, leaderPositions, initialSpeed);
leaderCar11.getTacticalPlanner().getPerception().perceive();
HeadwayGTUSimple leader = new HeadwayGTUSimple(leaderCar11.getId(), leaderCar11.getGTUType(),
new Length(leaderPosition.getSI() - referenceCar10.getLength().getSI() - initialPosition.getSI(),
LengthUnit.SI),
leaderCar11.getLength(), leaderCar11.getSpeed(), null);
cfmr = carFollowingModel.computeAccelerationStep(referenceCar10, leaderCar11.getSpeed(), leader.getDistance(),
lookAhead, speedLimit);
assertEquals("Acceleration should be 0", 0, cfmr.getAcceleration().getSI(), 0.0001);
leaderPosition = new Length(1000 + (3 + referenceCar10.getLength().getSI()
+ referenceCar10.position(lane, referenceCar10.getFront(), initialTime).getSI()), METER);
leaderPositions = new LinkedHashSet<>(1);
leaderPositions.add(new DirectedLanePosition(lane, leaderPosition, GTUDirectionality.DIR_PLUS));
// Exercise the if statement that ignores leaders that are further ahead
behavioralCharacteristicsFAM = DefaultTestParameters.create();
// drivingCharacteristicsFAM = new LaneBasedBehavioralCharacteristics(fam, laneChangeModel);
LaneBasedIndividualGTU leaderCar12 =
new LaneBasedIndividualGTU("12", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar12), leaderCar12);
leaderCar12.init(strategicalPlannerFAM, leaderPositions, initialSpeed);
leaderCar12.getTacticalPlanner().getPerception().perceive();
// Verify that the result is independent of the order of adding in the Collection
Collection leaders = new ArrayList();
HeadwayGTUSimple leader2 = new HeadwayGTUSimple(leaderCar12.getId(), leaderCar12.getGTUType(),
new Length(leaderPosition.getSI() - referenceCar10.getLength().getSI() - initialPosition.getSI(),
LengthUnit.SI),
leaderCar12.getLength(), leaderCar12.getSpeed(), null);
leaders.add(leader2); // Put the 2nd leader in first place
leaders.add(leader);
cfmr = carFollowingModel.computeDualAccelerationStep(referenceCar10, leaders, lookAhead, speedLimit)
.getLeaderAccelerationStep();
assertEquals("Acceleration should be 0", 0, cfmr.getAcceleration().getSI(), 0.0001);
leaders.clear();
leaders.add(leader); // Put the 1st leader in first place
leaders.add(leader2);
cfmr = carFollowingModel.computeDualAccelerationStep(referenceCar10, leaders, lookAhead, speedLimit)
.getLeaderAccelerationStep();
assertEquals("Acceleration should be 0", 0, cfmr.getAcceleration().getSI(), 0.0001);
referenceCar10.destroy();
leaderCar11.destroy();
leaderCar12.destroy();
// Test 2, cars have #20 and up
LaneBasedIndividualGTU referenceCar20 =
new LaneBasedIndividualGTU("20", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerIDM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsIDM,
new LaneBasedGTUFollowingTacticalPlanner(carFollowingModel, referenceCar20), referenceCar20);
referenceCar20.init(strategicalPlannerIDM, initialLongitudinalPositions, initialSpeed);
leaders.clear();
leaderPosition = new Length(-(3 + referenceCar20.getLength().getSI())
+ referenceCar20.position(lane, referenceCar20.getFront(), initialTime).getSI(), METER);
leaderPositions = new LinkedHashSet<>(1);
leaderPositions.add(new DirectedLanePosition(lane, leaderPosition, GTUDirectionality.DIR_PLUS));
LaneBasedIndividualGTU leaderCar21 =
new LaneBasedIndividualGTU("21", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar21), leaderCar21);
leaderCar21.init(strategicalPlannerFAM, leaderPositions, initialSpeed);
referenceCar20.getTacticalPlanner().getPerception().perceive();
leaderCar21.getTacticalPlanner().getPerception().perceive();
leader = new HeadwayGTUSimple(leaderCar21.getId(), leaderCar21.getGTUType(),
new Length(leaderPosition.getSI() - referenceCar20.getLength().getSI() - initialPosition.getSI(),
LengthUnit.SI),
leaderCar21.getLength(), leaderCar21.getSpeed(), null);
leaders.add(leader);
cfmr = carFollowingModel.computeDualAccelerationStep(referenceCar20, leaders, lookAhead, speedLimit)
.getLeaderAccelerationStep();
assertEquals("Leader acceleration should be 1.25", 1.25, cfmr.getAcceleration().getSI(), 0.0001);
leaderCar21.destroy();
// Check that the returned acceleration increases with the distance to the leader
double referenceAcceleration = -1;
for (int spareDistance = 0; spareDistance <= 500; spareDistance++)
{
leaders.clear();
leaderPosition = new Length(spareDistance + (3 + referenceCar20.getLength().getSI()
+ referenceCar20.position(lane, referenceCar20.getFront(), initialTime).getSI()), METER);
leaderPositions = new LinkedHashSet<>(1);
leaderPositions.add(new DirectedLanePosition(lane, leaderPosition, GTUDirectionality.DIR_PLUS));
LaneBasedIndividualGTU leaderCar22 =
new LaneBasedIndividualGTU("0", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar22), leaderCar22);
leaderCar22.init(strategicalPlannerFAM, leaderPositions, initialSpeed);
leaderCar22.getTacticalPlanner().getPerception().perceive();
leader = new HeadwayGTUSimple(leaderCar22.getId(), leaderCar22.getGTUType(),
new Length(leaderPosition.getSI() - referenceCar20.getLength().getSI() - initialPosition.getSI(),
LengthUnit.SI),
leaderCar22.getLength(), leaderCar22.getSpeed(), null);
leaders.add(leader);
cfmr = carFollowingModel.computeDualAccelerationStep(referenceCar20, leaders, lookAhead, speedLimit)
.getFollowerAccelerationStep();
double acceleration = cfmr.getAcceleration().getSI();
// System.out.println("Acceleration with stationary leader at " + spareDistance + " is " + acceleration);
assertTrue("acceleration should not decrease when distance to leader is increased",
acceleration >= referenceAcceleration);
referenceAcceleration = acceleration;
leaderCar22.destroy();
}
assertTrue("Highest acceleration should be less than max", referenceAcceleration <= 1.25);
referenceCar20.destroy();
// Test 3. Check that the returned acceleration increases with the speed of the leader
// cars have #30 and up
LaneBasedIndividualGTU referenceCar30 =
new LaneBasedIndividualGTU("30", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerIDM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsIDM,
new LaneBasedGTUFollowingTacticalPlanner(carFollowingModel, referenceCar30), referenceCar30);
referenceCar30.init(strategicalPlannerIDM, initialLongitudinalPositions, initialSpeed);
referenceCar30.getTacticalPlanner().getPerception().perceive();
referenceAcceleration = Double.NEGATIVE_INFINITY;
leaderPosition = new Length(2 + 3 + referenceCar30.getLength().getSI()
+ referenceCar30.position(lane, referenceCar30.getFront(), initialTime).getSI(), METER);
leaderPositions = new LinkedHashSet<>(1);
leaderPositions.add(new DirectedLanePosition(lane, leaderPosition, GTUDirectionality.DIR_PLUS));
// In IDM+ the reference car must have non-zero speed for the leader speed to have any effect
initialSpeed = new Speed(2, METER_PER_SECOND);
for (int integerLeaderSpeed = 0; integerLeaderSpeed <= 40; integerLeaderSpeed++)
{
Set initialPositions = new LinkedHashSet<>(1);
initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
referenceCar30.destroy();
// behavioralCharacteristicsIDM = new BehavioralCharacteristics();
// drivingCharacteristicsIDM = new LaneBasedBehavioralCharacteristics(carFollowingModel, laneChangeModel);
referenceCar30 = new LaneBasedIndividualGTU("30", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerIDM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsIDM,
new LaneBasedGTUFollowingTacticalPlanner(carFollowingModel, referenceCar30), referenceCar30);
referenceCar30.init(strategicalPlannerIDM, initialPositions, initialSpeed);
leaders.clear();
Speed leaderSpeed = new Speed(integerLeaderSpeed, METER_PER_SECOND);
behavioralCharacteristicsFAM = DefaultTestParameters.create(); // new BehavioralCharacteristics();
// drivingCharacteristicsFAM = new LaneBasedBehavioralCharacteristics(fam, laneChangeModel);
LaneBasedIndividualGTU leaderCar31 =
new LaneBasedIndividualGTU("31", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar31), leaderCar31);
if (integerLeaderSpeed == 10)
{
System.out.println("asd");
}
leaderCar31.init(strategicalPlannerFAM, leaderPositions, leaderSpeed);
leaderCar31.getTacticalPlanner().getPerception().perceive();
leader = new HeadwayGTUSimple(leaderCar31.getId(), leaderCar31.getGTUType(),
new Length(leaderPosition.getSI() - referenceCar30.getLength().getSI() - initialPosition.getSI(),
LengthUnit.SI),
leaderCar31.getLength(), leaderCar31.getSpeed(), null);
leaders.add(leader);
// System.out.println("referenceCar: " + referenceCar);
// System.out.println("leaderCar : " + leaderCar);
cfmr = carFollowingModel.computeDualAccelerationStep(referenceCar30, leaders, lookAhead, speedLimit)
.getFollowerAccelerationStep();
double acceleration = cfmr.getAcceleration().getSI();
// System.out.println("Acceleration with leader driving " + integerLeaderSpeed + " m/s is " + acceleration);
assertTrue("acceleration should not decrease when leader speed is increased",
acceleration >= referenceAcceleration);
referenceAcceleration = acceleration;
leaderCar31.destroy();
}
assertTrue("Highest acceleration should be less than max", referenceAcceleration <= 1.25);
referenceCar30.destroy();
// Test 4. Check that a car that is 100m behind a stationary car accelerates, then decelerates and stops at
// the right point. (In IDM+ the car oscillates a while around the final position with pretty good damping.)
// Cars have #40 and up
initialPosition = new Length(100, METER);
Set initialPositions = new LinkedHashSet<>(1);
initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
initialSpeed = new Speed(0, METER_PER_SECOND);
behavioralCharacteristicsIDM = DefaultTestParameters.create(); // new BehavioralCharacteristics();
// drivingCharacteristicsIDM = new LaneBasedBehavioralCharacteristics(carFollowingModel, laneChangeModel);
LaneBasedIndividualGTU referenceCar40 =
new LaneBasedIndividualGTU("40", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerIDM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsIDM,
new LaneBasedGTUFollowingTacticalPlanner(carFollowingModel, referenceCar40), referenceCar40);
referenceCar40.init(strategicalPlannerIDM, initialPositions, initialSpeed);
referenceCar40.getTacticalPlanner().getPerception().perceive();
leaderPosition = new Length(100 + 3 + referenceCar40.getLength().getSI()
+ referenceCar40.position(lane, referenceCar40.getFront(), initialTime).getSI(), METER);
behavioralCharacteristicsFAM = DefaultTestParameters.create(); // new BehavioralCharacteristics();
// drivingCharacteristicsFAM = new LaneBasedBehavioralCharacteristics(fam, laneChangeModel);
LaneBasedIndividualGTU leaderCar41 =
new LaneBasedIndividualGTU("41", gtuType, length, width, maxSpeed, simulator, this.network);
strategicalPlannerFAM = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristicsFAM,
new LaneBasedGTUFollowingTacticalPlanner(fam, leaderCar41), leaderCar41);
leaderCar41.init(strategicalPlannerFAM, leaderPositions, initialSpeed);
leaderCar41.getTacticalPlanner().getPerception().perceive();
for (int timeStep = 0; timeStep < 200; timeStep++)
{
Time simulateUntil = new Time(0.1 * timeStep, TimeUnit.SI);
simulator.runUpTo(simulateUntil);
while (simulator.isRunning())
{
try
{
Thread.sleep(1);
// System.out.println(referenceCar40 + ", t= " + simulator.getSimulatorTime().get() + ", pos="
// + referenceCar40.getLocation());
}
catch (InterruptedException ie)
{
ie = null; // ignore
}
}
// System.out.println(String.format("step %3d, t=%s, referenceCar: %s, speed %s, leaderCar: %s", timeStep,
// simulateUntil, referenceCar, referenceCar.getSpeed(), leaderCar));
if (timeStep > 120)
{
double position = referenceCar40.position(lane, referenceCar40.getFront()).getSI();
assertEquals(
"After 20 seconds the referenceCar should now be very close to " + s0
+ " before the rear of the leader",
leaderCar41.position(lane, referenceCar40.getRear()).getSI() - s0.getSI(), position, 0.2);
assertEquals("After 20 seconds the speed of the referenceCar should be almost 0", 0,
referenceCar40.getSpeed().getSI(), 0.2);
}
}
referenceCar40.destroy();
leaderCar41.destroy();
}
}
/**
* Simulation model for IDMPlusTest.
*
* Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* $LastChangedDate: 2015-09-14 01:33:02 +0200 (Mon, 14 Sep 2015) $, @version $Revision: 1401 $, by $Author: averbraeck $,
* initial version 0 feb. 2015
* @author Peter Knoppers
*/
class IDMPlusTestModel implements OTSModelInterface
{
/** */
private static final long serialVersionUID = 20150210L;
/** {@inheritDoc} */
@Override
public void constructModel(final SimulatorInterface