Commit 4f7df0d6 authored by Benedikt Kleinmeier's avatar Benedikt Kleinmeier

Implemented "OSMBehaviorController" and use it in "UpdateSchemeEventDriven"...

Implemented "OSMBehaviorController" and use it in "UpdateSchemeEventDriven" and "UpdateSchemeSequential".
parent 9064cd9f
package org.vadere.simulator.models.osm;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
import org.vadere.state.events.types.BangEvent;
import org.vadere.state.events.types.Event;
import org.vadere.state.scenario.Target;
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 java.util.LinkedList;
/**
* A class to encapsulate the behavior of a single {@link PedestrianOSM}.
*
* This class can be used by {@link OptimalStepsModel} to react on events.
*
* For instance:
* <pre>
* ...
* if (mostImportantEvent instanceof WaitEvent) {
* osmBehaviorController.wait()
* }
* ...
* </pre>
*/
public class OSMBehaviorController {
/**
* 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
* topography object of the change in state.
*
* !IMPORTANT! this function calls movePedestrian which must be called ONLY ONCE for each
* pedestrian for each position. To allow preformat selection of a pedestrian the managing
* destructure is not idempotent (cannot be applied multiple time without changing result).
*
* @param topography manages simulation data
* @param pedestrian moving pedestrian. This object's position is already set.
* @param stepTime time in seconds used for the step.
*/
public void makeStep(@NotNull final PedestrianOSM pedestrian, @NotNull final Topography topography, final double stepTime) {
VPoint currentPosition = pedestrian.getPosition();
VPoint nextPosition = pedestrian.getNextPosition();
// start time
double timeOfNextStep = pedestrian.getTimeOfNextStep();
// end time
double entTimeOfStep = pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep();
if (nextPosition.equals(currentPosition)) {
pedestrian.setTimeCredit(0);
pedestrian.setVelocity(new Vector2D(0, 0));
} else {
pedestrian.setTimeCredit(pedestrian.getTimeCredit() - pedestrian.getDurationNextStep());
pedestrian.setPosition(nextPosition);
synchronized (topography) {
topography.moveElement(pedestrian, pedestrian.getPosition());
}
// compute velocity by forward difference
Vector2D pedVelocity = new Vector2D(nextPosition.x - currentPosition.x, nextPosition.y - currentPosition.y).multiply(1.0 / stepTime);
pedestrian.setVelocity(pedVelocity);
}
/**
* strides and foot steps have no influence on the simulation itself, i.e. they are saved to analyse trajectories
*/
pedestrian.getStrides().add(Pair.of(currentPosition.distance(nextPosition), timeOfNextStep));
pedestrian.getFootSteps().add(new FootStep(currentPosition, nextPosition, timeOfNextStep, entTimeOfStep));
}
public void wait(PedestrianOSM pedestrian) {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
}
// Watch out: A bang event changes only the "CombinedPotentialStrategy".
// I.e., a new target is set for the agent. The agent does not move here!
// Therefore, trigger only a single bang event and then use "ElapsedTimeEvent" afterwards
// to let the agent walk.
public void reactToBang(PedestrianOSM pedestrian, Topography topography) {
Event mostImportantEvent = pedestrian.getMostImportantEvent();
if (mostImportantEvent instanceof BangEvent) {
BangEvent bangEvent = (BangEvent) pedestrian.getMostImportantEvent();
Target bangOrigin = topography.getTarget(bangEvent.getOriginAsTargetId());
LinkedList<Integer> nextTarget = new LinkedList<>();
nextTarget.add(bangOrigin.getId());
pedestrian.setTargets(nextTarget);
pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_DISTRACTION_STRATEGY);
} else {
// TODO: Maybe, log to console.
}
}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.OSMBehaviorController;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
import org.vadere.simulator.models.potential.combinedPotentials.TargetDistractionStrategy;
......@@ -21,11 +22,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
private final Topography topography;
protected PriorityQueue<PedestrianOSM> pedestrianEventsQueue;
private final OSMBehaviorController osmBehaviorController;
public UpdateSchemeEventDriven(@NotNull final Topography topography) {
this.topography = topography;
this.pedestrianEventsQueue = new PriorityQueue<>(100, new ComparatorPedestrianOSM());
this.pedestrianEventsQueue.addAll(topography.getElements(PedestrianOSM.class));
osmBehaviorController = new OSMBehaviorController();
}
@Override
......@@ -47,7 +50,6 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
protected void update(@NotNull final PedestrianOSM pedestrian, final double currentTimeInSec) {
Event mostImportantEvent = pedestrian.getMostImportantEvent();
// TODO: Extract behavior to own methods (i.e. step(), wait() and escape()).
if (mostImportantEvent instanceof ElapsedTimeEvent) {
VPoint oldPosition = pedestrian.getPosition();
......@@ -59,24 +61,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
// this can cause problems if the pedestrian desired speed is 0 (see speed adjuster)
pedestrian.updateNextPosition();
double stepDuration = pedestrian.getDurationNextStep();
makeStep(topography, pedestrian, stepDuration);
osmBehaviorController.makeStep(pedestrian, topography, stepDuration);
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + stepDuration);
} else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
osmBehaviorController.wait(pedestrian);
} else if (mostImportantEvent instanceof BangEvent) {
// Watch out: For testing purposes, a bang event changes only
// the "CombinedPotentialStrategy". The agent does not move here!
// Therefore, trigger only a single bang event and then use "ElapsedTimeEvent"
BangEvent bangEvent = (BangEvent) mostImportantEvent;
Target bangOrigin = topography.getTarget(bangEvent.getOriginAsTargetId());
// TODO: Just setting a new target does not work when using "EVENT_DRIVEN".
// Maybe, we have to clear the priority queue or something else (clarify with BZ).
LinkedList<Integer> nextTarget = new LinkedList<>();
nextTarget.add(bangOrigin.getId());
pedestrian.setTargets(nextTarget);
pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_DISTRACTION_STRATEGY);
// FIXME: Just setting a new target does not work when using "EVENT_DRIVEN".
osmBehaviorController.reactToBang(pedestrian, topography);
}
}
......
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.OSMBehaviorController;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
import org.vadere.state.events.types.*;
......@@ -16,9 +17,11 @@ import java.util.List;
public class UpdateSchemeSequential implements UpdateSchemeOSM {
private final Topography topography;
private final OSMBehaviorController osmBehaviorController;
public UpdateSchemeSequential(@NotNull final Topography topography) {
this.topography = topography;
this.osmBehaviorController = new OSMBehaviorController();
}
@Override
......@@ -44,23 +47,13 @@ public class UpdateSchemeSequential implements UpdateSchemeOSM {
while (pedestrian.getTimeCredit() > pedestrian.getDurationNextStep()) {
pedestrian.updateNextPosition();
makeStep(topography, pedestrian, timeStepInSec);
osmBehaviorController.makeStep(pedestrian, topography, timeStepInSec);
}
} else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
osmBehaviorController.wait(pedestrian);
} else if (mostImportantEvent instanceof BangEvent) {
// Watch out: For testing purposes, a bang event changes only
// the "CombinedPotentialStrategy". The agent does not move here!
// Therefore, trigger only a single bang event and then use "ElapsedTimeEvent"
BangEvent bangEvent = (BangEvent) mostImportantEvent;
Target bangOrigin = topography.getTarget(bangEvent.getOriginAsTargetId());
LinkedList<Integer> nextTarget = new LinkedList<>();
nextTarget.add(bangOrigin.getId());
pedestrian.setTargets(nextTarget);
pedestrian.setCombinedPotentialStrategy(CombinedPotentialStrategy.TARGET_DISTRACTION_STRATEGY);
osmBehaviorController.reactToBang(pedestrian, topography);
}
}
......
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