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

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; package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.OSMBehaviorController;
import org.vadere.simulator.models.osm.PedestrianOSM; import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy; import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
import org.vadere.simulator.models.potential.combinedPotentials.TargetDistractionStrategy; import org.vadere.simulator.models.potential.combinedPotentials.TargetDistractionStrategy;
...@@ -21,11 +22,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM { ...@@ -21,11 +22,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
private final Topography topography; private final Topography topography;
protected PriorityQueue<PedestrianOSM> pedestrianEventsQueue; protected PriorityQueue<PedestrianOSM> pedestrianEventsQueue;
private final OSMBehaviorController osmBehaviorController;
public UpdateSchemeEventDriven(@NotNull final Topography topography) { public UpdateSchemeEventDriven(@NotNull final Topography topography) {
this.topography = topography; this.topography = topography;
this.pedestrianEventsQueue = new PriorityQueue<>(100, new ComparatorPedestrianOSM()); this.pedestrianEventsQueue = new PriorityQueue<>(100, new ComparatorPedestrianOSM());
this.pedestrianEventsQueue.addAll(topography.getElements(PedestrianOSM.class)); this.pedestrianEventsQueue.addAll(topography.getElements(PedestrianOSM.class));
osmBehaviorController = new OSMBehaviorController();
} }
@Override @Override
...@@ -47,7 +50,6 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM { ...@@ -47,7 +50,6 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
protected void update(@NotNull final PedestrianOSM pedestrian, final double currentTimeInSec) { protected void update(@NotNull final PedestrianOSM pedestrian, final double currentTimeInSec) {
Event mostImportantEvent = pedestrian.getMostImportantEvent(); Event mostImportantEvent = pedestrian.getMostImportantEvent();
// TODO: Extract behavior to own methods (i.e. step(), wait() and escape()).
if (mostImportantEvent instanceof ElapsedTimeEvent) { if (mostImportantEvent instanceof ElapsedTimeEvent) {
VPoint oldPosition = pedestrian.getPosition(); VPoint oldPosition = pedestrian.getPosition();
...@@ -59,24 +61,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM { ...@@ -59,24 +61,13 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
// this can cause problems if the pedestrian desired speed is 0 (see speed adjuster) // this can cause problems if the pedestrian desired speed is 0 (see speed adjuster)
pedestrian.updateNextPosition(); pedestrian.updateNextPosition();
double stepDuration = pedestrian.getDurationNextStep(); double stepDuration = pedestrian.getDurationNextStep();
makeStep(topography, pedestrian, stepDuration); osmBehaviorController.makeStep(pedestrian, topography, stepDuration);
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + stepDuration); pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + stepDuration);
} else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) { } else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep()); osmBehaviorController.wait(pedestrian);
} else if (mostImportantEvent instanceof BangEvent) { } else if (mostImportantEvent instanceof BangEvent) {
// Watch out: For testing purposes, a bang event changes only // FIXME: Just setting a new target does not work when using "EVENT_DRIVEN".
// the "CombinedPotentialStrategy". The agent does not move here! osmBehaviorController.reactToBang(pedestrian, topography);
// 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);
} }
} }
......
package org.vadere.simulator.models.osm.updateScheme; package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.OSMBehaviorController;
import org.vadere.simulator.models.osm.PedestrianOSM; import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy; import org.vadere.simulator.models.potential.combinedPotentials.CombinedPotentialStrategy;
import org.vadere.state.events.types.*; import org.vadere.state.events.types.*;
...@@ -16,9 +17,11 @@ import java.util.List; ...@@ -16,9 +17,11 @@ import java.util.List;
public class UpdateSchemeSequential implements UpdateSchemeOSM { public class UpdateSchemeSequential implements UpdateSchemeOSM {
private final Topography topography; private final Topography topography;
private final OSMBehaviorController osmBehaviorController;
public UpdateSchemeSequential(@NotNull final Topography topography) { public UpdateSchemeSequential(@NotNull final Topography topography) {
this.topography = topography; this.topography = topography;
this.osmBehaviorController = new OSMBehaviorController();
} }
@Override @Override
...@@ -44,23 +47,13 @@ public class UpdateSchemeSequential implements UpdateSchemeOSM { ...@@ -44,23 +47,13 @@ public class UpdateSchemeSequential implements UpdateSchemeOSM {
while (pedestrian.getTimeCredit() > pedestrian.getDurationNextStep()) { while (pedestrian.getTimeCredit() > pedestrian.getDurationNextStep()) {
pedestrian.updateNextPosition(); pedestrian.updateNextPosition();
makeStep(topography, pedestrian, timeStepInSec); osmBehaviorController.makeStep(pedestrian, topography, timeStepInSec);
} }
} else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) { } else if (mostImportantEvent instanceof WaitEvent || mostImportantEvent instanceof WaitInAreaEvent) {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep()); osmBehaviorController.wait(pedestrian);
} else if (mostImportantEvent instanceof BangEvent) { } else if (mostImportantEvent instanceof BangEvent) {
// Watch out: For testing purposes, a bang event changes only osmBehaviorController.reactToBang(pedestrian, topography);
// 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);
} }
} }
......
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