Commit 72a1c7d9 authored by Benedikt Kleinmeier's avatar Benedikt Kleinmeier
Browse files

Implemented "TargetChangerController" and cleaned up "Simulation"

parent 2e03dd86
{
"name" : "TestTargetChangerLogsToStdout",
"name" : "Test-TargetChanger-ChangesToStaticTarget",
"description" : "",
"release" : "1.4",
"processWriters" : {
......@@ -154,19 +154,36 @@
"deletionDistance" : 0.1,
"startingWithRedLight" : false,
"nextSpeed" : -1.0
}, {
"id" : 3,
"absorbing" : true,
"shape" : {
"x" : 18.0,
"y" : 4.5,
"width" : 1.0,
"height" : 1.0,
"type" : "RECTANGLE"
},
"waitingTime" : 0.0,
"waitingTimeYellowPhase" : 0.0,
"parallelWaiters" : 0,
"individualWaiting" : true,
"deletionDistance" : 0.1,
"startingWithRedLight" : false,
"nextSpeed" : -1.0
} ],
"targetChangers" : [ {
"id" : 5,
"shape" : {
"x" : 12.5,
"y" : 5.7,
"width" : 4.9,
"height" : 3.4,
"x" : 7.9,
"y" : 0.4801097393689986,
"width" : 0.8242798353909446,
"height" : 8.97119341563786,
"type" : "RECTANGLE"
},
"reachDistance" : 0.0,
"nextTargetIsPedestrian" : false,
"nextTarget" : 2,
"nextTarget" : 3,
"probabilityToChangeTarget" : 0.0
} ],
"absorbingAreas" : [ ],
......
{
"name" : "TestTargetPedestrianHasFollower",
"description" : "",
"release" : "1.4",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepPedestrianIdOutputFile",
"filename" : "postvis.trajectories",
"processors" : [ 1, 2 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepPedestrianIdOverlapOutputFile",
"filename" : "overlaps.csv",
"processors" : [ 3 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.NoDataKeyOutputFile",
"filename" : "overlapCount.txt",
"processors" : [ 4 ]
} ],
"processors" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianPositionProcessor",
"id" : 1
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianTargetIdProcessor",
"id" : 2
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestrianOverlapProcessor",
"id" : 3
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.NumberOverlapsProcessor",
"id" : 4,
"attributesType" : "org.vadere.state.attributes.processor.AttributesNumberOverlapsProcessor",
"attributes" : {
"pedestrianOverlapProcessorId" : 3
}
} ],
"isTimestamped" : true,
"isWriteMetaData" : false
},
"scenario" : {
"mainModel" : "org.vadere.simulator.models.osm.OptimalStepsModel",
"attributesModel" : {
"org.vadere.state.attributes.models.AttributesOSM" : {
"stepCircleResolution" : 4,
"numberOfCircles" : 1,
"optimizationType" : "NELDER_MEAD",
"varyStepDirection" : true,
"movementType" : "ARBITRARY",
"stepLengthIntercept" : 0.4625,
"stepLengthSlopeSpeed" : 0.2345,
"stepLengthSD" : 0.036,
"movementThreshold" : 0.0,
"minStepLength" : 0.1,
"minimumStepLength" : true,
"maxStepDuration" : 1.7976931348623157E308,
"dynamicStepLength" : true,
"updateType" : "EVENT_DRIVEN",
"seeSmallWalls" : false,
"targetPotentialModel" : "org.vadere.simulator.models.potential.fields.PotentialFieldTargetGrid",
"pedestrianPotentialModel" : "org.vadere.simulator.models.potential.PotentialFieldPedestrianCompactSoftshell",
"obstaclePotentialModel" : "org.vadere.simulator.models.potential.PotentialFieldObstacleCompactSoftshell",
"submodels" : [ ]
},
"org.vadere.state.attributes.models.AttributesPotentialCompactSoftshell" : {
"pedPotentialIntimateSpaceWidth" : 0.45,
"pedPotentialPersonalSpaceWidth" : 1.2,
"pedPotentialHeight" : 50.0,
"obstPotentialWidth" : 0.8,
"obstPotentialHeight" : 6.0,
"intimateSpaceFactor" : 1.2,
"personalSpacePower" : 1,
"intimateSpacePower" : 1
},
"org.vadere.state.attributes.models.AttributesFloorField" : {
"createMethod" : "HIGH_ACCURACY_FAST_MARCHING",
"potentialFieldResolution" : 0.1,
"obstacleGridPenalty" : 0.1,
"targetAttractionStrength" : 1.0,
"cacheType" : "NO_CACHE",
"cacheDir" : "",
"timeCostAttributes" : {
"standardDeviation" : 0.7,
"type" : "UNIT",
"obstacleDensityWeight" : 3.5,
"pedestrianSameTargetDensityWeight" : 3.5,
"pedestrianOtherTargetDensityWeight" : 3.5,
"pedestrianWeight" : 3.5,
"queueWidthLoading" : 1.0,
"pedestrianDynamicWeight" : 6.0,
"loadingType" : "CONSTANT",
"width" : 0.2,
"height" : 1.0
}
}
},
"attributesSimulation" : {
"finishTime" : 100.0,
"simTimeStepLength" : 0.4,
"realTimeSimTimeRatio" : 0.1,
"writeSimulationData" : true,
"visualizationEnabled" : true,
"printFPS" : false,
"digitsPerCoordinate" : 2,
"useFixedSeed" : true,
"fixedSeed" : -3989740141114319444,
"simulationSeed" : 0,
"useSalientBehavior" : false
},
"topography" : {
"attributes" : {
"bounds" : {
"x" : 0.0,
"y" : 0.0,
"width" : 20.0,
"height" : 10.0
},
"boundingBoxWidth" : 0.5,
"bounded" : true,
"referenceCoordinateSystem" : null
},
"obstacles" : [ ],
"measurementAreas" : [ ],
"stairs" : [ ],
"targets" : [ {
"id" : 1,
"absorbing" : true,
"shape" : {
"x" : 18.0,
"y" : 8.0,
"width" : 1.0,
"height" : 1.0,
"type" : "RECTANGLE"
},
"waitingTime" : 0.0,
"waitingTimeYellowPhase" : 0.0,
"parallelWaiters" : 0,
"individualWaiting" : true,
"deletionDistance" : 0.1,
"startingWithRedLight" : false,
"nextSpeed" : -1.0
}, {
"id" : 2,
"absorbing" : true,
"shape" : {
"x" : 18.0,
"y" : 1.0,
"width" : 1.1,
"height" : 1.0,
"type" : "RECTANGLE"
},
"waitingTime" : 0.0,
"waitingTimeYellowPhase" : 0.0,
"parallelWaiters" : 0,
"individualWaiting" : true,
"deletionDistance" : 0.1,
"startingWithRedLight" : false,
"nextSpeed" : -1.0
} ],
"targetChangers" : [ ],
"absorbingAreas" : [ ],
"sources" : [ {
"id" : 3,
"shape" : {
"x" : 1.0,
"y" : 8.0,
"width" : 1.0,
"height" : 1.0,
"type" : "RECTANGLE"
},
"interSpawnTimeDistribution" : "org.vadere.state.scenario.ConstantDistribution",
"distributionParameters" : [ 1.0 ],
"spawnNumber" : 1,
"maxSpawnNumberTotal" : -1,
"startTime" : 0.0,
"endTime" : 0.0,
"spawnAtRandomPositions" : false,
"useFreeSpaceOnly" : true,
"targetIds" : [ 1 ],
"groupSizeDistribution" : [ 1.0 ],
"dynamicElementType" : "PEDESTRIAN"
}, {
"id" : 4,
"shape" : {
"x" : 1.0,
"y" : 0.9,
"width" : 1.1,
"height" : 1.1,
"type" : "RECTANGLE"
},
"interSpawnTimeDistribution" : "org.vadere.state.scenario.ConstantDistribution",
"distributionParameters" : [ 1.0 ],
"spawnNumber" : 1,
"maxSpawnNumberTotal" : -1,
"startTime" : 0.0,
"endTime" : 0.0,
"spawnAtRandomPositions" : false,
"useFreeSpaceOnly" : true,
"targetIds" : [ 2 ],
"groupSizeDistribution" : [ 1.0 ],
"dynamicElementType" : "PEDESTRIAN"
} ],
"dynamicElements" : [ ],
"attributesPedestrian" : {
"radius" : 0.2,
"densityDependentSpeed" : false,
"speedDistributionMean" : 0.5,
"speedDistributionStandardDeviation" : 0.1,
"minimumSpeed" : 0.5,
"maximumSpeed" : 2.2,
"acceleration" : 2.0,
"footstepHistorySize" : 4,
"searchRadius" : 1.0,
"angleCalculationType" : "USE_CENTER",
"targetOrientationAngleThreshold" : 45.0
},
"teleporter" : null,
"attributesCar" : {
"id" : -1,
"radius" : 0.2,
"densityDependentSpeed" : false,
"speedDistributionMean" : 1.34,
"speedDistributionStandardDeviation" : 0.26,
"minimumSpeed" : 0.5,
"maximumSpeed" : 2.2,
"acceleration" : 2.0,
"footstepHistorySize" : 4,
"searchRadius" : 1.0,
"angleCalculationType" : "USE_CENTER",
"targetOrientationAngleThreshold" : 45.0,
"length" : 4.5,
"width" : 1.7,
"direction" : {
"x" : 1.0,
"y" : 0.0
}
}
},
"eventInfos" : [ ]
}
}
\ No newline at end of file
......@@ -356,8 +356,10 @@ public class Simulation {
private void updateCallbacks(double simTimeInSec) {
List<Event> events = eventController.getEventsForTime(simTimeInSec);
// TODO Why are target controllers readded in each simulation loop?
// Maybe, Isabella's SIMA branch required this because pedestrians can act as targets there.
// "TargetControllers" are populated in each simulation loop because
// pedestrians can be declared as targets in each simulation loop.
// Therefore, create the necessary controller wrappers here for these
// new targets.
this.targetControllers.clear();
for (Target target : this.topographyController.getTopography().getTargets()) {
targetControllers.add(new TargetController(this.topographyController.getTopography(), target));
......@@ -390,39 +392,6 @@ public class Simulation {
salientBehaviorCognition.setSalientBehaviorForPedestrians(pedestrians, simTimeInSec);
}
// Try out if class "TargetPedestrian" still works and if it can be used by event/stimuli system.
// Check if two pedestrians are in the scenario with different targetIds. If so, make one pedestrian
// following the other.
Collection<Pedestrian> peds = topography.getElements(Pedestrian.class);
Pedestrian[] convertedPeds = new Pedestrian[peds.size()];
peds.toArray(convertedPeds);
if (addedTargetPedestrian == false && peds.size() >= 2) {
// Select target and follower candidate
Pedestrian ped1 = convertedPeds[0];
Pedestrian ped2 = convertedPeds[1];
// Configure target
int ped1TargetId = 1000;
ped1.setIdAsTarget(ped1TargetId);
// Create necessary target wrapper objects
TargetPedestrian targetPedestrian = new TargetPedestrian(ped1);
TargetController targetPedestrianController = new TargetController(topography, targetPedestrian);
targetControllers.add(targetPedestrianController);
topography.addTarget(targetPedestrian);
// Make ped2 a follower of ped1.
LinkedList<Integer> targetIdsAsList = new LinkedList<>();
targetIdsAsList.add(ped1TargetId);
ped2.setTargets(targetIdsAsList);
addedTargetPedestrian = true;
}
// Remove above code after tryout.
for (Model m : models) {
List<SourceController> stillSpawningSource = this.sourceControllers.stream().filter(s -> !s.isSourceFinished(simTimeInSec)).collect(Collectors.toList());
int pedestriansInSimulation = this.simulationState.getTopography().getPedestrianDynamicElements().getElements().size();
......
......@@ -6,20 +6,23 @@ import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.logging.Logger;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
* Change target id of an agent which enters the given {@link TargetChanger} area.
* Change target id of an agent which enters the corresponding {@link TargetChanger} area.
*
* TargetChanger's attributes contain two important parameters to control the changing behavior:
* - changeTargetProbability
* - nextTargetIsPedestrian
*
* "changeTargetProbability" defines how many percent of the agents, who enter the area,
* should change its target. If "nextTargetIsPedestrian == false", assign a new
* static target. Otherwise, randomly choose a pedestrian (with given target id) to follow.
* {@link TargetChanger}'s attributes contain two important parameters to control the changing behavior:
* <ul>
* <li>
* "changeTargetProbability": This defines how many percent of the agents,
* who enter the area, should change their target.
* </li>
* <li>
* If "nextTargetIsPedestrian == false", assign a new static target.
* Otherwise, randomly choose a pedestrian (with given target id) to follow.
* </li>
* </ul>
*/
public class TargetChangerController {
......@@ -28,14 +31,16 @@ public class TargetChangerController {
public final TargetChanger targetChanger;
private Topography topography;
private Map<Integer, Agent> processedAgents;
// Constructors
public TargetChangerController(Topography topography, TargetChanger targetChanger) {
this.targetChanger = targetChanger;
this.topography = topography;
this.processedAgents = new HashMap<>();
}
// Other Methods
// Public Methods
public void update(double simTimeInSec) {
for (DynamicElement element : getDynamicElementsNearTargetChangerArea()) {
......@@ -47,23 +52,24 @@ public class TargetChangerController {
continue;
}
if (hasAgentReachedTargetChangerArea(agent)) {
notifyListenersTargetChangerAreaReached(agent);
// TODO: Implement logic to change targets based
// on a Binomial distribution.
if (hasAgentReachedTargetChangerArea(agent) && processedAgents.containsKey(agent.getId()) == false) {
logEnteringTimeOfAgent(agent, simTimeInSec);
LinkedList<Integer> newTarget = new LinkedList<>();
newTarget.add(targetChanger.getAttributes().getNextTarget());
// TODO: First, use Binomial distribution to decide
// if target should be changed.
boolean changeTarget = true;
agent.setTargets(newTarget);
if (changeTarget) {
if (targetChanger.getAttributes().isNextTargetIsPedestrian()) {
useDynamicTargetForAgentOrUseStaticAsFallback(agent);
} else {
useStaticTargetForAgent(agent);
}
}
log.info(String.format("%s %d reached %s %d.",
agent.getClass().getSimpleName(),
agent.getId(),
targetChanger.getClass().getSimpleName(),
targetChanger.getId()));
notifyListenersTargetChangerAreaReached(agent);
processedAgents.put(agent.getId(), agent);
}
}
}
......@@ -92,6 +98,51 @@ public class TargetChangerController {
|| targetChangerShape.distance(agentPosition) < reachDistance;
}
private void logEnteringTimeOfAgent(Agent agent, double simTimeInSec) {
Map<Integer, Double> enteringTimes = targetChanger.getEnteringTimes();
Integer agentId = agent.getId();
if (enteringTimes.containsKey(agentId) == false) {
enteringTimes.put(agentId, simTimeInSec);
}
}
private void useDynamicTargetForAgentOrUseStaticAsFallback(Agent agent) {
int nextTarget = targetChanger.getAttributes().getNextTarget();
Collection<Pedestrian> allPedestrians = topography.getElements(Pedestrian.class);
List<Pedestrian> pedsWithCorrectTargetId = allPedestrians.stream()
.filter(pedestrian -> pedestrian.getTargets().contains(nextTarget))
.collect(Collectors.toList());
if (pedsWithCorrectTargetId.size() > 0) {
// Maybe, choose randomly in the long run.
Pedestrian pedToFollow = pedsWithCorrectTargetId.get(0);
agentFollowsOtherPedestrian(agent, pedToFollow);
} else {
useStaticTargetForAgent(agent);
}
}
private void agentFollowsOtherPedestrian(Agent agent, Pedestrian pedToFollow) {
// Create necessary target wrapper object.
// Watch out: The main simulation loop creates the necessary
// "TargetController" object in the next simulation step.
TargetPedestrian targetPedestrian = new TargetPedestrian(pedToFollow);
topography.addTarget(targetPedestrian);
// Make "agent" a follower of "pedToFollow".
LinkedList<Integer> nextTargetAsList = new LinkedList<>();
nextTargetAsList.add(pedToFollow.getId());
agent.setTargets(nextTargetAsList);
}
private void useStaticTargetForAgent(Agent agent) {
LinkedList<Integer> newTarget = new LinkedList<>();
newTarget.add(targetChanger.getAttributes().getNextTarget());
agent.setTargets(newTarget);
}
private void notifyListenersTargetChangerAreaReached(final Agent agent) {
for (TargetChangerListener listener : targetChanger.getTargetChangerListeners()) {
listener.reachedTargetChanger(targetChanger, agent);
......
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