Commit 624ce491 authored by Benedikt Kleinmeier's avatar Benedikt Kleinmeier
Browse files

Merge branch 'psychology'

parents 5a35e1be db6d93de
Pipeline #174393 passed with stages
in 122 minutes and 11 seconds
......@@ -15,6 +15,7 @@ import org.vadere.state.scenario.Topography;
import org.vadere.state.simulation.FootStep;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.Vector2D;
import org.vadere.util.logging.Logger;
import java.util.LinkedList;
import java.util.List;
......@@ -23,7 +24,9 @@ import java.util.stream.Collectors;
/**
* A class to encapsulate the behavior of a single {@link PedestrianOSM}.
*
* This class can be used by {@link OptimalStepsModel} to react on stimuli.
* This class can be used by {@link OptimalStepsModel} to react to
* environmental stimuli (see {@link Stimulus}) and how an agent
* has categorized itself in regard to other agents (see {@link SelfCategory}).
*
* For instance:
* <pre>
......@@ -36,6 +39,8 @@ import java.util.stream.Collectors;
*/
public class OSMBehaviorController {
private static Logger logger = Logger.getLogger(OSMBehaviorController.class);
/**
* Prepare move of pedestrian inside the topography. The pedestrian object already has the new
* location (Vpoint to) stored within its position attribute. This method only informs the
......@@ -53,13 +58,13 @@ public class OSMBehaviorController {
VPoint currentPosition = pedestrian.getPosition();
VPoint nextPosition = pedestrian.getNextPosition();
// start time
// start time
double stepStartTime = pedestrian.getTimeOfNextStep();
// end time
double stepEndTime = pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep();
// end time
double stepEndTime = pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep();
assert stepEndTime >= stepStartTime && stepEndTime >= 0.0 && stepStartTime >= 0.0 : stepEndTime + "<" + stepStartTime;
assert stepEndTime >= stepStartTime && stepEndTime >= 0.0 && stepStartTime >= 0.0 : stepEndTime + "<" + stepStartTime;
if (nextPosition.equals(currentPosition)) {
pedestrian.setTimeCredit(0);
......@@ -109,7 +114,9 @@ public class OSMBehaviorController {
pedestrian.setTargets(nextTarget);
pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_DISTRACTION_STRATEGY);
} else {
// TODO: Maybe, log to console.
logger.debug(String.format("Expected: %s, Received: %s"),
Bang.class.getSimpleName(),
mostImportantStimulus.getClass().getSimpleName());
}
}
......@@ -121,39 +128,46 @@ public class OSMBehaviorController {
pedestrian.setTargets(changeTarget.getNewTargetIds());
} else {
// TODO: Maybe, log to console.
logger.debug(String.format("Expected: %s, Received: %s"),
ChangeTarget.class.getSimpleName(),
mostImportantStimulus.getClass().getSimpleName());
}
}
// TODO: Write unit tests for the critical methods below!
@Nullable
public PedestrianOSM findSwapCandidate(PedestrianOSM pedestrian, Topography topography) {
// Agents with no targets don't want to swap places.
if (pedestrian.hasNextTarget() == false) {
return null;
}
List<Pedestrian> closestPedestrians = getClosestPedestriansWhichAreCloserToTarget(pedestrian, topography);
if (closestPedestrians.size() > 0) {
for (Pedestrian closestPedestrian : closestPedestrians) {
if (closestPedestrian.hasNextTarget()) {
boolean closestPedIsCooperative = closestPedestrian.getSelfCategory() == SelfCategory.COOPERATIVE;
boolean targetOrientationDiffers = false;
List<Pedestrian> closestPedestrians = getClosestPedestriansWhichAreCloserToTarget(pedestrian, topography);
if (closestPedestrians.size() > 0) {
for (Pedestrian closestPedestrian : closestPedestrians) {
if(pedestrian.hasNextTarget()) {
boolean closestPedIsCooperative = closestPedestrian.getSelfCategory() == SelfCategory.COOPERATIVE;
boolean targetOrientationDiffers = false;
// TODO: Use "pedestrian.getTargetGradient()" instead of "calculateAngleBetweenTargets()".
double angleInRadian = calculateAngleBetweenTargets(pedestrian, closestPedestrian, topography);
if (angleInRadian == -1 || Math.toDegrees(angleInRadian) > pedestrian.getAttributes().getTargetOrientationAngleThreshold()) {
targetOrientationDiffers = true;
}
if (closestPedIsCooperative && targetOrientationDiffers) {
return (PedestrianOSM)closestPedestrian;
}
} else {
if(!closestPedestrian.hasNextTarget()) {
return (PedestrianOSM)closestPedestrian;
}
}
}
}
return null;
// TODO: Make both options configurable in JSON file.
// double angleInRadian = calculateAngleBetweenTargets(pedestrian, closestPedestrian, topography);
double angleInRadian = calculateAngleBetweenTargetGradients(pedestrian, (PedestrianOSM)closestPedestrian);
if (angleInRadian == -1 || Math.toDegrees(angleInRadian) > pedestrian.getAttributes().getTargetOrientationAngleThreshold()) {
targetOrientationDiffers = true;
}
if (closestPedIsCooperative && targetOrientationDiffers) {
return (PedestrianOSM)closestPedestrian;
}
} else {
return (PedestrianOSM)closestPedestrian;
}
}
}
return null;
}
@NotNull
......@@ -163,7 +177,7 @@ public class OSMBehaviorController {
List<Pedestrian> closestPedestrians = topography.getSpatialMap(Pedestrian.class)
.getObjects(positionOfPedestrian, pedestrian.getAttributes().getSearchRadius());
// Filter out "me" and pedestrians which are farer away from target than "me".
// Filter out "me" and pedestrians which are further away from target than "me".
closestPedestrians = closestPedestrians.stream()
.filter(candidate -> pedestrian.getId() != candidate.getId())
.filter(candidate -> pedestrian.getTargetPotential(candidate.getPosition()) < pedestrian.getTargetPotential(pedestrian.getPosition()))
......@@ -172,7 +186,10 @@ public class OSMBehaviorController {
// Sort by distance away from "me".
closestPedestrians = closestPedestrians.stream()
.sorted((pedestrian1, pedestrian2) ->
Double.compare(positionOfPedestrian.distance(pedestrian1.getPosition()), positionOfPedestrian.distance(pedestrian2.getPosition())))
Double.compare(
positionOfPedestrian.distance(pedestrian1.getPosition()),
positionOfPedestrian.distance(pedestrian2.getPosition())
))
.collect(Collectors.toList());
return closestPedestrians;
......@@ -236,7 +253,7 @@ public class OSMBehaviorController {
return vectorPedestrianToTarget;
}
private double calculateAngleBetweenTargetGradients(PedestrianOSM pedestrian1, PedestrianOSM pedestrian2) {
public double calculateAngleBetweenTargetGradients(PedestrianOSM pedestrian1, PedestrianOSM pedestrian2) {
double angleInRadian = -1;
Vector2D targetGradientPedestrian1 = pedestrian1.getTargetGradient(pedestrian1.getPosition());
......@@ -250,6 +267,13 @@ public class OSMBehaviorController {
return angleInRadian;
}
/**
* Swap two pedestrians.
*
* Watch out: This method manipulates pedestrian2 which is contained in a queue
* sorted by timeOfNextStep! The calling code must re-add pedestrian2 after
* invoking this method.
*/
public void swapPedestrians(PedestrianOSM pedestrian1, PedestrianOSM pedestrian2, Topography topography) {
VPoint newPosition = pedestrian2.getPosition().clone();
VPoint oldPosition = pedestrian1.getPosition().clone();
......@@ -257,35 +281,34 @@ public class OSMBehaviorController {
pedestrian1.setNextPosition(newPosition);
pedestrian2.setNextPosition(oldPosition);
// Use "makeStep()" to swap both pedestrians to avoid "java.lang.AssertionError:
// Number of pedestrians in LinkedCellGrid does not match number of pedestrians in topography".
double startTimeStep = pedestrian1.getTimeOfNextStep();
double durationStep = Math.max(pedestrian1.getDurationNextStep(), pedestrian2.getDurationNextStep());
double endTimeStep = startTimeStep + durationStep;
// here we interrupt the current footstep of pedestrian 2 to sync it to pedestrian 1
// this is only required for the sequential update scheme since pedestrian 2 might have done some steps in this time step and
// is ahead (with respect to the time) of pedestrian 1. We remove those steps which is not a good solution!
if(!pedestrian2.getTrajectory().isEmpty()) {
// the agent was standing still, otherwise this should not be allowed
pedestrian2.getTrajectory().adjustEndTime(startTimeStep);
}
// Synchronize movement of both pedestrians
double startTimeStep = pedestrian1.getTimeOfNextStep();
double durationStep = Math.max(pedestrian1.getDurationNextStep(), pedestrian2.getDurationNextStep());
double endTimeStep = startTimeStep + durationStep;
// We interrupt the current footstep of pedestrian 2 to sync it with
// pedestrian 1. It is only required for the sequential update scheme
// since pedestrian 2 might have done some steps in this time step and
// is ahead (with respect to the time) of pedestrian 1.
// We remove those steps which is not a good solution!
if(!pedestrian2.getTrajectory().isEmpty()) {
pedestrian2.getTrajectory().adjustEndTime(startTimeStep);
}
// Note: Here we manipulate a pedestrian which is contained in the queue sorted by timeOfNextStep!
pedestrian1.setTimeOfNextStep(startTimeStep);
pedestrian2.setTimeOfNextStep(startTimeStep);
pedestrian1.setTimeOfNextStep(startTimeStep);
pedestrian2.setTimeOfNextStep(startTimeStep);
makeStep(pedestrian1, topography, durationStep);
makeStep(pedestrian1, topography, durationStep);
makeStep(pedestrian2, topography, durationStep);
// TODO The experiment showed that speed decreased (to half of free-flow velocity).
// Therefore, use "pedestrian.getDurationNextStep() * 2".
pedestrian1.setTimeOfNextStep(endTimeStep);
pedestrian2.setTimeOfNextStep(endTimeStep);
pedestrian1.setTimeCredit(pedestrian1.getTimeCredit() - durationStep);
// assert pedestrian1.getTimeCredit() >= 0.0;
pedestrian2.setTimeCredit(pedestrian1.getTimeCredit());
// TODO:
// "makeStep()" already invokes
// "pedestrian.setTimeCredit(pedestrian.getTimeCredit() - pedestrian.getDurationNextStep())"
// => Ask BZ if is it really necessary to call it twice (and subtract duration twice)?
pedestrian1.setTimeCredit(pedestrian1.getTimeCredit() - durationStep);
pedestrian2.setTimeCredit(pedestrian1.getTimeCredit());
}
}
......@@ -46,7 +46,7 @@ public class PotentialFieldTargetGrid extends PotentialFieldTarget implements IP
public Vector2D getTargetPotentialGradient(VPoint pos, Agent ped) {
double[] gradient = { 0.0, 0.0 };
if (ped.getNextTargetId() > -1) {
if (ped.hasNextTarget()) {
InterpolationUtil.getGradientMollified(getCellGrids().get(ped.getNextTargetId()), new double[]{pos.getX(), pos.getY()}, gradient, 0.1);
}
......
package org.vadere.simulator.models.osm;
import org.junit.Test;
import org.vadere.simulator.models.SpeedAdjuster;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTargetGrid;
import org.vadere.state.attributes.Attributes;
import org.vadere.state.attributes.models.AttributesFloorField;
import org.vadere.state.attributes.models.AttributesOSM;
import org.vadere.state.attributes.scenario.AttributesAgent;
import org.vadere.state.attributes.scenario.AttributesTarget;
import org.vadere.state.psychology.cognition.SelfCategory;
import org.vadere.state.scenario.Target;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VCircle;
......@@ -18,7 +20,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.*;
public class OSMBehaviorControllerTest {
......@@ -28,10 +30,67 @@ public class OSMBehaviorControllerTest {
private PedestrianOSM pedestrian2;
private Topography topography;
private void createSameDirectionTopography() {
createTwoTargetsAndTwoPedestrians(
new VPoint(-1, 0), // target1
new VPoint(-1, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
}
private void createPerpendicularVariation1Topography() {
createTwoTargetsAndTwoPedestrians(
new VPoint(0, 1), // target1
new VPoint(-1, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
}
private void createPerpendicularVariation2Topography() {
createTwoTargetsAndTwoPedestrians(
new VPoint(1, 0), // target1
new VPoint(1, -1), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
}
private void createOppositeDirectionVariation1Topography() {
createTwoTargetsAndTwoPedestrians(
new VPoint(-1, 0), // target1
new VPoint(2, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
}
private void createOppositeDirectionVariation2Topography() {
createTwoTargetsAndTwoPedestrians(
new VPoint(-1, 0), // target1
new VPoint(2, 0), // target2
new VPoint(1, 0), // pedestrian1
new VPoint(0, 0) // pedestrian2
);
}
private void createTwoTargetsAndTwoPedestrians(VPoint target1Position, VPoint target2Position, VPoint pedestrian1Position, VPoint pedestrian2Position) {
// Create a topography with two targets.
List<Target> targets = createTwoTargets(target1Position, target2Position);
topography = new Topography();
topography.addTarget(targets.get(0));
topography.addTarget(targets.get(1));
List<PedestrianOSM> pedestrians = createTwoPedestrianOSM(pedestrian1Position, pedestrian2Position, topography);
pedestrian1 = pedestrians.get(0);
pedestrian2 = pedestrians.get(1);
topography.addElement(pedestrian1);
topography.addElement(pedestrian2);
}
private List<Target> createTwoTargets(VPoint target1Position, VPoint target2Position) {
Target target1 = new Target(new AttributesTarget());
target1.setShape(new VCircle(target1Position, 1));
target1.getAttributes().setId(1);
......@@ -40,11 +99,17 @@ public class OSMBehaviorControllerTest {
target2.setShape(new VCircle(target2Position, 1));
target2.getAttributes().setId(2);
topography.addTarget(target1);
topography.addTarget(target2);
List<Target> targets = new ArrayList<>();
targets.add(target1);
targets.add(target2);
// Create two pedestrians and assign them the two targets from above.
AttributesAgent attributesAgent = new AttributesAgent();
return targets;
}
private List<PedestrianOSM> createTwoPedestrianOSM(VPoint pedestrian1Position, VPoint pedestrian2Position, Topography topography) {
// Create helper objects which are required by a PedestrianOSM:
AttributesAgent attributesAgent1 = new AttributesAgent(1);
AttributesAgent attributesAgent2 = new AttributesAgent(2);
AttributesOSM attributesOSM = new AttributesOSM();
int seed = 1;
......@@ -54,31 +119,40 @@ public class OSMBehaviorControllerTest {
topography,
new AttributesAgent(),
attributesOSM.getTargetPotentialModel());
// Force that target potential gets calculated so that the gradient can be used later on.
double simTimeInSec = 1;
potentialFieldTargetGrid.preLoop(simTimeInSec);
pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
potentialFieldTargetGrid, null, null, null, null);
pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
potentialFieldTargetGrid, null, null, null, null);
List<SpeedAdjuster> noSpeedAdjusters = new ArrayList<>();
// Create the actual PedestrianOSM
PedestrianOSM pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent1, topography, new Random(seed),
potentialFieldTargetGrid, null, null, noSpeedAdjusters, null);
PedestrianOSM pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent2, topography, new Random(seed),
potentialFieldTargetGrid, null, null, noSpeedAdjusters, null);
pedestrian1.setPosition(pedestrian1Position);
LinkedList<Integer> targetsPedestrian1 = new LinkedList<>();
targetsPedestrian1.add(target1.getId());
targetsPedestrian1.add(topography.getTarget(1).getId());
pedestrian1.setTargets(targetsPedestrian1);
pedestrian1.setFreeFlowSpeed(1.1);
pedestrian2.setPosition(new VPoint(pedestrian2Position));
LinkedList<Integer> targetsPedestrian2 = new LinkedList<>();
targetsPedestrian2.add(target2.getId());
targetsPedestrian2.add(topography.getTarget(2).getId());
pedestrian2.setTargets(targetsPedestrian2);
pedestrian2.setFreeFlowSpeed(1.2);
List<PedestrianOSM> pedestrians = new ArrayList<>();
pedestrians.add(pedestrian1);
pedestrians.add(pedestrian2);
return pedestrians;
}
@Test
public void calculateAngleBetweenTargetsReturnsCorrectResultIfTargetAndPedestriansAreVerticalZeroQuarterCircle() {
createTwoTargetsAndTwoPedestrians(
new VPoint(-1, 0), // target1
new VPoint(-1, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
public void calculateAngleBetweenTargetsReturnsZeroIfTargetsAreInSameDirection() {
createSameDirectionTopography();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
......@@ -89,13 +163,8 @@ public class OSMBehaviorControllerTest {
}
@Test
public void calculateAngleBetweenTargetsReturnsCorrectResultIfTargetAndPedestriansAreVerticalOneQuarterCircle() {
createTwoTargetsAndTwoPedestrians(
new VPoint(0, 1), // target1
new VPoint(-1, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
public void calculateAngleBetweenTargetsReturnsPiHalfIfPedestriansWalkPerpendicularVariation1() {
createPerpendicularVariation1Topography();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
......@@ -106,34 +175,24 @@ public class OSMBehaviorControllerTest {
}
@Test
public void calculateAngleBetweenTargetsReturnsCorrectResultIfTargetAndPedestriansAreVerticalTwoQuarterCircle() {
createTwoTargetsAndTwoPedestrians(
new VPoint(-1, 0), // target1
new VPoint(2, 0), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
public void calculateAngleBetweenTargetsReturnsPiHalfIfPedestriansWalkPerpendicularVariation2() {
createPerpendicularVariation2Topography();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
double expectedAngle = Math.PI;
double expectedAngle = Math.PI / 2;
double actualAngle = controllerUnderTest.calculateAngleBetweenTargets(pedestrian1, pedestrian2, topography);
assertEquals(expectedAngle, actualAngle, ALLOWED_DOUBLE_TOLERANCE);
}
@Test
public void calculateAngleBetweenTargetsReturnsCorrectResultIfTargetAndPedestriansAreVerticalThreeQuarterCircle() {
createTwoTargetsAndTwoPedestrians(
new VPoint(1, 0), // target1
new VPoint(1, -1), // target2
new VPoint(0, 0), // pedestrian1
new VPoint(1, 0) // pedestrian2
);
public void calculateAngleBetweenTargetsReturnsPiIfPedestriansWalkInOppositeDirections() {
createOppositeDirectionVariation1Topography();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
double expectedAngle = Math.PI / 2;
double expectedAngle = Math.PI;
double actualAngle = controllerUnderTest.calculateAngleBetweenTargets(pedestrian1, pedestrian2, topography);
assertEquals(expectedAngle, actualAngle, ALLOWED_DOUBLE_TOLERANCE);
......@@ -169,9 +228,9 @@ public class OSMBehaviorControllerTest {
new AttributesAgent(),
attributesOSM.getTargetPotentialModel());
pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(seed),
potentialFieldTargetGrid, null, null, null, null);
pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(seed),
potentialFieldTargetGrid, null, null, null, null);
// Position of pedestrian1
......@@ -230,9 +289,9 @@ public class OSMBehaviorControllerTest {
new AttributesAgent(),
attributesOSM.getTargetPotentialModel());
pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
pedestrian1 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(seed),
potentialFieldTargetGrid, null, null, null, null);
pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(1),
pedestrian2 = new PedestrianOSM(new AttributesOSM(), attributesAgent, topography, new Random(seed),
potentialFieldTargetGrid, null, null, null, null);
// Position of pedestrian1
......@@ -316,4 +375,210 @@ public class OSMBehaviorControllerTest {
assertEquals(expectedAngle, actualAngle, ALLOWED_DOUBLE_TOLERANCE);
}
@Test
public void calculateAngleBetweenTargetGradientsReturnsZeroIfTargetsAreInSameDirection() {
createSameDirectionTopography();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
// TODO: Clarify with BZ where this unexpected deviation comes from.
// This error sums up for larger angles and is problematic.
double expectedAngle = 0.043;
double actualAngle = controllerUnderTest.calculateAngleBetweenTargetGradients(pedestrian1, pedestrian2);
assertEquals(expectedAngle, actualAngle, ALLOWED_DOUBLE_TOLERANCE);
}
@Test
public void swapPedestriansSetsNewPositionForBothPedestrians() {
createSameDirectionTopography();
VPoint oldPositionPed1 = pedestrian1.getPosition().clone();
VPoint oldPositionPed2 = pedestrian2.getPosition().clone();
assertNotEquals(oldPositionPed1, oldPositionPed2);
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
double simTimeInSec = 1;
pedestrian1.setTimeOfNextStep(simTimeInSec);
pedestrian2.setTimeOfNextStep(simTimeInSec);
controllerUnderTest.swapPedestrians(pedestrian1, pedestrian2, topography);
assertEquals(oldPositionPed2, pedestrian1.getPosition());
assertEquals(oldPositionPed1, pedestrian2.getPosition());
}
@Test
public void swapPedestriansUsesStartTimeOfFirstPedestrianAndMaximumOfBothStepDurations() {
createSameDirectionTopography();
double timeOfNextStepPed1 = 1;
double timeOfNextStepPed2 = 1.5;
pedestrian1.setTimeOfNextStep(timeOfNextStepPed1);
pedestrian2.setTimeOfNextStep(timeOfNextStepPed2);
double maxStepDuration = Math.max(pedestrian1.getDurationNextStep(), pedestrian2.getDurationNextStep());
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
controllerUnderTest.swapPedestrians(pedestrian1, pedestrian2, topography);
double expectedTimeOfNextStep = timeOfNextStepPed1 + maxStepDuration;
assertEquals(expectedTimeOfNextStep, pedestrian1.getTimeOfNextStep(), ALLOWED_DOUBLE_TOLERANCE);
assertEquals(expectedTimeOfNextStep, pedestrian2.getTimeOfNextStep(), ALLOWED_DOUBLE_TOLERANCE);
}
@Test
public void swapPedestriansHandlesOSMTimeCreditParametersProperly() {
createSameDirectionTopography();
double timeOfNextStepPed1 = 1;
double timeOfNextStepPed2 = 1.5;
pedestrian1.setTimeOfNextStep(timeOfNextStepPed1);
pedestrian2.setTimeOfNextStep(timeOfNextStepPed2);
double timeCreditInSecPed1 = 1;
double timeCreditInSecPed2 = 1.5;
pedestrian1.setTimeCredit(timeCreditInSecPed1);
pedestrian2.setTimeCredit(timeCreditInSecPed2);
double maxStepDuration = Math.max(pedestrian1.getDurationNextStep(), pedestrian2.getDurationNextStep());
double stepDurationPed1 = pedestrian1.getDurationNextStep();
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
controllerUnderTest.swapPedestrians(pedestrian1, pedestrian2, topography);
// For event-driven update scheme "timeOfNextStep" must be set properly.
double expectedTimeOfNextStep = timeOfNextStepPed1 + maxStepDuration;
assertEquals(expectedTimeOfNextStep, pedestrian1.getTimeOfNextStep(), ALLOWED_DOUBLE_TOLERANCE);
assertEquals(expectedTimeOfNextStep, pedestrian2.getTimeOfNextStep(), ALLOWED_DOUBLE_TOLERANCE);
// For sequential update scheme "timeCredit" must be set properly.
double expectedTimeCredit = timeCreditInSecPed1 - (stepDurationPed1 + maxStepDuration);
assertEquals(expectedTimeCredit, pedestrian1.getTimeCredit(), ALLOWED_DOUBLE_TOLERANCE);
assertEquals(expectedTimeCredit, pedestrian2.getTimeCredit(), ALLOWE