Commit 0e00dd07 authored by Benedikt Kleinmeier's avatar Benedikt Kleinmeier
Browse files

In "OSMBehaviorController", removed evasion code (instead use BHM to...

In "OSMBehaviorController", removed evasion code (instead use BHM to demonstrate evasion cognition which already provides evasion methods)
parent cedd2873
Pipeline #344883 failed with stages
in 96 minutes and 31 seconds
......@@ -34,8 +34,8 @@ public class CounterflowCognitionModel implements ICognitionModel {
if (neighborCloserToTarget != null) {
if (TopographyHelper.walkingDirectionDiffers(pedestrian, neighborCloserToTarget, topography)) {
pedestrian.setSelfCategory(SelfCategory.EVADE);
} else if (neighborCloserToTarget.getSelfCategory() == SelfCategory.EVADE) {
pedestrian.setSelfCategory(SelfCategory.EVADE); // Imitate behavior
} else if (neighborCloserToTarget.getSelfCategory() == SelfCategory.EVADE) { // Imitate behavior
pedestrian.setSelfCategory(SelfCategory.EVADE);
}
}
}
......
......@@ -183,7 +183,10 @@ public class PedestrianBHM extends Pedestrian {
makeStep();
} else if (selfCategory == SelfCategory.WAIT) {
// do nothing
} else {
} else if (selfCategory == SelfCategory.EVADE) {
// TODO: Force tangential or sideways evasion using BHM's internal methods.
}
else {
throw new IllegalArgumentException("Unsupported SelfCategory: " + selfCategory);
}
......
package org.vadere.simulator.models.osm;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.math.exception.OutOfRangeException;
import org.apache.commons.math3.distribution.BinomialDistribution;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
......@@ -18,10 +15,10 @@ import org.vadere.state.scenario.ScenarioElement;
import org.vadere.state.scenario.Target;
import org.vadere.state.scenario.Topography;
import org.vadere.state.simulation.FootStep;
import org.vadere.util.geometry.shapes.*;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.Vector2D;
import org.vadere.util.logging.Logger;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;
import java.util.List;
......@@ -45,26 +42,6 @@ public class OSMBehaviorController {
// Static Variables
private static Logger logger = Logger.getLogger(OSMBehaviorController.class);
private static final int BINOMIAL_DISTRIBUTION_SUCCESS_VALUE = 1;
// Member Variables
BinomialDistribution evasionDirectionDistribution;
// Constructors
public OSMBehaviorController() {
evasionDirectionDistribution = createEvasionDistribution(0, 0.8);
}
private BinomialDistribution createEvasionDistribution(int seed, double evadeRightProbability) {
if (evadeRightProbability < 0 || evadeRightProbability > 1) {
throw new OutOfRangeException(evadeRightProbability, 0, 1);
}
JDKRandomGenerator randomGenerator = new JDKRandomGenerator();
randomGenerator.setSeed(seed);
return new BinomialDistribution(randomGenerator, BINOMIAL_DISTRIBUTION_SUCCESS_VALUE, evadeRightProbability);
}
// Methods
public void makeStepToTarget(@NotNull final PedestrianOSM pedestrian, @NotNull final Topography topography) {
......@@ -162,118 +139,6 @@ public class OSMBehaviorController {
pedestrian.setTimeOfNextStep(stepEndTime);
}
/**
* 1. Use TargetAttractionAndEvasionStrategy to weight agents a little less
* 2. Use gradient to get walking direction of pedestrian
* 3. Sample "evasionDirectionDistribution" to evaluate evasion direction (right or left)
* 4. Call updateNextPosition() with adapted reachable area (use gradient and evasion direction for this)
* 5. Restore TargetAttractionStrategy
*
* @param pedestrian The pedestrian to evade
* @param topography The topography to be able to move the pedestrian within the topography
* @param timeStepInSec The current simulation time in second
*/
public void evade(PedestrianOSM pedestrian, Topography topography, double timeStepInSec) {
// pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_ATTRACTION_AND_EVASION_STRATEGY);
boolean evadeRight = evasionDirectionDistribution.sample() == BINOMIAL_DISTRIBUTION_SUCCESS_VALUE;
VShape reachableArea = createCircularReachableAreaInEvasionDirectionByTargetCentroid(pedestrian, evadeRight, topography);
// TODO Use pedestrian.updateNextPosition(reachableArea) only and do not set position hard
// to avoid zig-zag trajectories.
// TODO If evasion region is outside topography, use smaller rotation angle (< 45° deg)
// to force that agents evade only once and then keep their lane.
/*
if (topographyContainsReachableArea(topography, reachableArea)) {
pedestrian.setNextPosition(reachableArea.getCentroid());
} else {
*/
pedestrian.updateNextPosition(reachableArea);
// }
makeStep(pedestrian, topography, pedestrian.getDurationNextStep());
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
// pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_ATTRACTION_STRATEGY);
}
public VShape createCircularReachableAreaInEvasionDirectionByTargetCentroid(PedestrianOSM pedestrian, boolean evadeRight, Topography topography) {
VPoint nextPosition = pedestrian.getPosition();
if (pedestrian.hasNextTarget()) {
Target currentTarget = topography.getTarget(pedestrian.getNextTargetId());
VPoint vectorToTarget = TopographyHelper.calculateVectorPedestrianToTarget(pedestrian, currentTarget);
double evasionAngleRad = (evadeRight) ? -Math.toRadians(45) : +Math.toRadians(45);
VPoint nextWalkingDirection = vectorToTarget.rotate(evasionAngleRad);
VPoint nextPositionNormedToZero = nextWalkingDirection.norm().scalarMultiply(pedestrian.getDesiredStepSize());
nextPosition = nextPositionNormedToZero.add(pedestrian.getPosition());
}
VCircle reachableArea = new VCircle(nextPosition, pedestrian.getRadius() * 1.5);
return reachableArea;
}
public VShape createCircularReachableAreaInEvasionDirection(PedestrianOSM pedestrian, boolean evadeRight) {
Vector2D targetGradient = pedestrian.getTargetGradient(pedestrian.getPosition());
Vector2D pedestrianWalkingDirection = targetGradient.rotate(Math.toRadians(180));
double evasionAngleRad = (evadeRight) ? -Math.toRadians(45) : +Math.toRadians(45);
Vector2D nextWalkingDirection = pedestrianWalkingDirection.rotate(evasionAngleRad);
VPoint nextPositionNormedToZero = nextWalkingDirection.norm().scalarMultiply(pedestrian.getDesiredStepSize());
VPoint nextPosition = nextPositionNormedToZero.add(pedestrian.getPosition());
VCircle reachableArea = new VCircle(nextPosition, pedestrian.getRadius());
return reachableArea;
}
private boolean topographyContainsReachableArea(Topography topography, VShape reachableArea) {
Rectangle2D.Double bounds = topography.getBounds();
double boundsWidth = topography.getBoundingBoxWidth();
Rectangle2D.Double validArea = new Rectangle2D.Double(bounds.x + boundsWidth, bounds.y + boundsWidth, bounds.width - 2 * boundsWidth, bounds.height - 2 * boundsWidth);
boolean reachableAreaInsideBoundary = validArea.contains(reachableArea.getCentroid().x, reachableArea.getCentroid().y);
return reachableAreaInsideBoundary;
}
// TODO: Maybe, remove this method because low-level (optimization) code expects "reachableArea" to be of type "VCircle". :/
/**
* Use an isosceles triangle as reachable area where the isosceles legs represent pedestrian's step length
* and the angle between both legs is 30° deg. Both legs meet at pedestrian's current position.
* This triangle is rotated by using the targetGradient plus/minus some evasion offset of 45° deg.
*
* @param pedestrian The pedestrian to derive current position and walking direction (by using the gradient)
* @param evadeRight Decides if the isosceles triangle should be rotated by +45° deg or -45° deg
* @return The new reachable area for the pedestrian as isosceles triangle
*/
public VShape createIsoscelesTriangleAsReachableArea(PedestrianOSM pedestrian, boolean evadeRight) {
double legAngleInRadians = Math.toRadians(15);
double stepSize = pedestrian.getDesiredStepSize();
double xCoord = stepSize * Math.cos(legAngleInRadians);
double yCoord = stepSize * Math.sin(legAngleInRadians);
Vector2D p1 = new Vector2D(0, 0);
Vector2D p2 = new Vector2D(xCoord, yCoord);
Vector2D p3 = new Vector2D(xCoord, -yCoord);
Vector2D targetGradient = pedestrian.getTargetGradient(pedestrian.getPosition());
Vector2D pedestrianWalkingDirection = targetGradient.rotate(Math.toRadians(180));
double walkingAngleRad = pedestrianWalkingDirection.angleToZero();
double evasionAngleRad = (evadeRight) ? -Math.toRadians(45) : +Math.toRadians(45);
double nextWalkingAngleRad = walkingAngleRad + evasionAngleRad;
Vector2D p1Rotated = p1.rotate(nextWalkingAngleRad);
Vector2D p2Rotated = p2.rotate(nextWalkingAngleRad);
Vector2D p3Rotated = p3.rotate(nextWalkingAngleRad);
VPoint base = pedestrian.getPosition();
VTriangle rotatedTriangleCounterClockwise = new VTriangle(base.add(p1Rotated), base.add(p3Rotated), base.add(p2Rotated));
return rotatedTriangleCounterClockwise;
}
/**
* Maximize distance to the threat (a threat) and increase speed.
*
......
......@@ -366,10 +366,6 @@ public class PedestrianOSM extends Pedestrian {
this.combinedPotentialStrategy = new TargetAttractionStrategy(this.potentialFieldTarget,
this.potentialFieldObstacle,
this.potentialFieldPedestrian);
} else if (newStrategy == CombinedPotentialStrategy.TARGET_ATTRACTION_AND_EVASION_STRATEGY) {
this.combinedPotentialStrategy = new TargetAttractionAndEvasionStrategy(this.potentialFieldTarget,
this.potentialFieldObstacle,
this.potentialFieldPedestrian);
} else if (newStrategy == CombinedPotentialStrategy.TARGET_REPULSION_STRATEGY) {
this.combinedPotentialStrategy = new TargetRepulsionStrategy(this.potentialFieldTarget,
this.potentialFieldObstacle,
......
......@@ -62,8 +62,6 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
} else {
osmBehaviorController.makeStepToTarget(pedestrian, topography);
}
} else if (selfCategory == SelfCategory.EVADE) {
osmBehaviorController.evade(pedestrian, topography, timeStepInSec);
} else if (selfCategory == SelfCategory.INSIDE_THREAT_AREA) {
osmBehaviorController.changeToTargetRepulsionStrategyAndIncreaseSpeed(pedestrian, topography);
osmBehaviorController.makeStepToTarget(pedestrian, topography);
......
......@@ -8,6 +8,5 @@ package org.vadere.simulator.models.potential.combinedPotentials;
*/
public enum CombinedPotentialStrategy {
TARGET_ATTRACTION_STRATEGY,
TARGET_ATTRACTION_AND_EVASION_STRATEGY,
TARGET_REPULSION_STRATEGY
}
package org.vadere.simulator.models.potential.combinedPotentials;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTarget;
import org.vadere.simulator.models.potential.fields.PotentialFieldAgent;
import org.vadere.simulator.models.potential.fields.PotentialFieldObstacle;
import org.vadere.state.scenario.Agent;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.Collection;
/**
* Combine potential so that agents are attracted by targets
* but other agents are less weighted.
*/
public class TargetAttractionAndEvasionStrategy implements ICombinedPotentialStrategy {
private IPotentialFieldTarget potentialFieldTarget;
private PotentialFieldObstacle potentialFieldObstacle;
private PotentialFieldAgent potentialFieldAgent;
public TargetAttractionAndEvasionStrategy(IPotentialFieldTarget potentialFieldTarget, PotentialFieldObstacle potentialFieldObstacle, PotentialFieldAgent potentialFieldAgent) {
this.potentialFieldTarget = potentialFieldTarget;
this.potentialFieldObstacle = potentialFieldObstacle;
this.potentialFieldAgent = potentialFieldAgent;
}
@Override
public double getValue(IPoint newPos, Agent thisAgent, Collection<? extends Agent> otherAgents) {
double targetPotential = potentialFieldTarget.getPotential(newPos, thisAgent);
double obstaclePotential = potentialFieldObstacle.getObstaclePotential(newPos, thisAgent);
double agentPotential = potentialFieldAgent.getAgentPotential(newPos, thisAgent, otherAgents);
agentPotential = agentPotential * 0.8;
return targetPotential + agentPotential + obstaclePotential;
}
}
......@@ -14,8 +14,6 @@ import org.vadere.state.scenario.Target;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.geometry.shapes.VTriangle;
import java.util.ArrayList;
import java.util.LinkedList;
......@@ -385,28 +383,4 @@ public class OSMBehaviorControllerTest {
assertEquals(expectedTimeOfNextStep, pedestrian1.getTimeOfNextStep(), ALLOWED_DOUBLE_TOLERANCE);
}
@Test
public void createIsoscelesTriangleAsReachableAreaReturnsTriangleTypes() {
createOppositeDirectionVariation1Topography();
boolean evadeRight = true;
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
for (int i = 0; i < 5; i++) {
VShape reachableArea = controllerUnderTest.createIsoscelesTriangleAsReachableArea(pedestrian1, evadeRight);
assertTrue(reachableArea instanceof VTriangle);
}
}
@Test
public void createCircularReachableAreaInEvasionDirectionWorksProperly() {
createOppositeDirectionVariation1Topography();
boolean evadeRight = true;
OSMBehaviorController controllerUnderTest = new OSMBehaviorController();
// Ped1 walks from (0,0) to (-1,0) => walking direction (gradient) is roughly (-1, 0).
VShape reachableArea = controllerUnderTest.createCircularReachableAreaInEvasionDirection(pedestrian2, evadeRight);
// TODO Assert that coordinates match roughly the expectation.
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment