Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 4aa78fe7 authored by Marion Goedel's avatar Marion Goedel
Browse files

Merge branch 'master' of https://gitlab.lrz.de/vadere/vadere

parents 9e8f1624 ac7563f3
package org.vadere.simulator.control;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.system.CallbackI;
import org.vadere.simulator.models.DynamicElementFactory;
import org.vadere.state.attributes.scenario.AttributesDynamicElement;
import org.vadere.state.scenario.Source;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SingleSourceController extends SourceController {
private int numberToSpawn;
private DynamicElementFactory dynamicElementFactory;
private static final int NUMBER_OF_REPOSITION_TRIES = 10;
public SingleSourceController(Topography scenario, Source source,
DynamicElementFactory dynamicElementFactory,
AttributesDynamicElement attributesDynamicElement,
Random random) {
super(scenario, source, dynamicElementFactory, attributesDynamicElement, random);
this.dynamicElementFactory = dynamicElementFactory;
}
@Override
......@@ -25,18 +37,28 @@ public class SingleSourceController extends SourceController {
if (!isSourceFinished(simTimeInSec)) {
if (simTimeInSec >= timeOfNextEvent || numberToSpawn > 0) {
determineNumberOfSpawnsAndNextEvent(simTimeInSec);
LinkedList<VPoint> spawnPoints = new LinkedList<>();
List<VPoint> spawnPoints = new LinkedList<>();
if (sourceAttributes.isSpawnAtRandomPositions()) {
if (sourceAttributes.isUseFreeSpaceOnly()) {
spawnPoints = spawnArray.getNextFreeRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
//spawnPoints = spawnArray.getNextFreeRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
spawnPoints = getRealRandomPositions(
numberToSpawn,
random,
getDynElementsAtSource().stream()
.map(element -> element.getPosition())
.map(position -> dynamicElementFactory.getDynamicElementRequiredPlace(position))
.collect(Collectors.toList())
);
numberToSpawn -= spawnPoints.size();
assert (numberToSpawn >= 0);
} else {
spawnPoints = spawnArray.getNextRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
throw new IllegalArgumentException("use random position without free space only makes no sense.");
/*spawnPoints = spawnArray.getNextRandomSpawnPoints(numberToSpawn, random, getDynElementsAtSource());
numberToSpawn -= spawnPoints.size();
assert (numberToSpawn >= 0);
assert (numberToSpawn >= 0);*/
}
} else {
......@@ -63,6 +85,47 @@ public class SingleSourceController extends SourceController {
}
}
/**
* Computes numberToSpawn or less random positions based on the blockPedestrianShapes which contains the shapes representing the required space of each pedestrian.
* For each required position the algorithms tries {@link SingleSourceController#NUMBER_OF_REPOSITION_TRIES} times to get a feasible free position.
*
* @param numberToSpawn number of required spawn positions
* @param random random generator
* @param blockPedestrianShapes the required space of other pedestrians
* @return numberToSpawn or less random feasible positions
*/
private List<VPoint> getRealRandomPositions(final int numberToSpawn, @NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes) {
List<VPoint> randomPositions = new ArrayList<>(numberToSpawn);
for(int i = 0; i < numberToSpawn; i++) {
Optional<VPoint> optRandomPosition = getNextRandomPosition(random, blockPedestrianShapes, NUMBER_OF_REPOSITION_TRIES);
if (optRandomPosition.isPresent()) {
VPoint randomPosition = optRandomPosition.get();
blockPedestrianShapes.add(dynamicElementFactory.getDynamicElementRequiredPlace(randomPosition));
randomPositions.add(randomPosition);
}
}
return randomPositions;
}
private Optional<VPoint> getNextRandomPosition(@NotNull final Random random, @NotNull final List<VShape> blockPedestrianShapes, final int tries) {
Rectangle2D rec = source.getShape().getBounds2D();
for(int i = 0; i < tries; i++) {
VPoint randomPoint = new VPoint(rec.getMinX() + random.nextDouble() * rec.getWidth(), rec.getMinY() + random.nextDouble() * rec.getHeight());
VShape freeSpaceRequired = dynamicElementFactory.getDynamicElementRequiredPlace(randomPoint);
// no intersection with other free spaces.
if(blockPedestrianShapes.stream().noneMatch(shape -> shape.intersects(freeSpaceRequired))) {
return Optional.of(randomPoint);
}
}
return Optional.empty();
}
@Override
protected boolean isQueueEmpty() {
......
......@@ -52,8 +52,11 @@ public abstract class SourceController {
this.dynamicElementFactory = dynamicElementFactory;
this.topography = scenario;
this.random = random;
VRectangle elementBound = new VRectangle(dynamicElementFactory.getDynamicElementRequiredPlace(new VPoint(0,0)).getBounds2D());
this.spawnArray = new SpawnArray(new VRectangle(source.getShape().getBounds2D()),
new VRectangle(0, 0, (getDynamicElementShape().getRadius()) * 2 + SPAWN_BUFFER_SIZE, (getDynamicElementShape().getRadius()) * 2 + SPAWN_BUFFER_SIZE));
new VRectangle(0, 0,elementBound.getWidth() + SPAWN_BUFFER_SIZE, elementBound.getHeight() + SPAWN_BUFFER_SIZE));
timeOfNextEvent = sourceAttributes.getStartTime();
try {
......@@ -103,14 +106,7 @@ public abstract class SourceController {
return maxNumber != AttributesSource.NO_MAX_SPAWN_NUMBER_TOTAL
&& dynamicElementsCreatedTotal >= maxNumber;
}
private VCircle getDynamicElementShape() {
if (attributesDynamicElement instanceof AttributesAgent) {
return new VCircle(((AttributesAgent) attributesDynamicElement).getRadius());
}
return new VCircle(0.2);
}
abstract protected boolean isQueueEmpty();
abstract protected void determineNumberOfSpawnsAndNextEvent(double simTimeInSec);
......
package org.vadere.simulator.models;
import org.jetbrains.annotations.NotNull;
import org.vadere.state.scenario.DynamicElement;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
public interface DynamicElementFactory {
......@@ -11,5 +13,13 @@ public interface DynamicElementFactory {
* Note: Every attribute of the given element should be cloned for each individual in this
* method, because some fields are individual.
*/
public <T extends DynamicElement> DynamicElement createElement(VPoint position, int id, Class<T> type);
<T extends DynamicElement> DynamicElement createElement(VPoint position, int id, Class<T> type);
/**
* Returns the shape which represents the (free) place required by each element.
*
* @param position the position of the shape i.e. the next created {@link DynamicElement}
* @return the shape which represents the (free) place required by each element.
*/
VShape getDynamicElementRequiredPlace(@NotNull final VPoint position);
}
......@@ -6,9 +6,11 @@ import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;
import org.jetbrains.annotations.NotNull;
import org.vadere.annotation.factories.models.ModelClass;
import org.vadere.simulator.models.MainModel;
import org.vadere.simulator.models.Model;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.attributes.Attributes;
import org.vadere.state.attributes.models.AttributesBHM;
import org.vadere.state.attributes.scenario.AttributesAgent;
......@@ -17,6 +19,7 @@ import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Target;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
@ModelClass(isMainModel = true)
public class BehaviouralHeuristicsModel implements MainModel {
......@@ -70,13 +73,23 @@ public class BehaviouralHeuristicsModel implements MainModel {
AttributesAgent pedAttributes = new AttributesAgent(
this.attributesPedestrian, id > 0 ? id : pedestrianIdCounter);
PedestrianBHM pedestrian = new PedestrianBHM(topography, pedAttributes, attributesBHM, random);
PedestrianBHM pedestrian = createElement(position, pedAttributes);
pedestrian.setPosition(position);
this.pedestrianEventsQueue.add(pedestrian);
return pedestrian;
}
private PedestrianBHM createElement(VPoint position, @NotNull final AttributesAgent pedAttributes) {
PedestrianBHM pedestrian = new PedestrianBHM(topography, pedAttributes, attributesBHM, random);
pedestrian.setPosition(position);
return pedestrian;
}
@Override
public VShape getDynamicElementRequiredPlace(@NotNull final VPoint position) {
return createElement(position, new AttributesAgent(attributesPedestrian, -1)).getShape();
}
@Override
public void preLoop(final double simTimeInSec) {
this.lastSimTimeInSec = simTimeInSec;
......
......@@ -4,9 +4,11 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.jetbrains.annotations.NotNull;
import org.vadere.annotation.factories.models.ModelClass;
import org.vadere.simulator.models.MainModel;
import org.vadere.simulator.models.Model;
import org.vadere.simulator.models.bhm.PedestrianBHM;
import org.vadere.state.attributes.Attributes;
import org.vadere.state.attributes.models.AttributesBHM;
import org.vadere.state.attributes.models.AttributesBMM;
......@@ -15,6 +17,7 @@ import org.vadere.state.scenario.DynamicElement;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
/**
*
......@@ -61,14 +64,22 @@ public class BiomechanicsModel implements MainModel {
AttributesAgent pedAttributes = new AttributesAgent(
this.attributesPedestrian, id > 0 ? id : pedestrianIdCounter);
PedestrianBMM pedestrian = new PedestrianBMM(position, topography, pedAttributes,
attributesBMM, attributesBHM, random);
PedestrianBMM pedestrian = createElement(position, pedAttributes);
this.pedestriansBMM.add(pedestrian);
return pedestrian;
}
private PedestrianBMM createElement(@NotNull final VPoint position, @NotNull final AttributesAgent pedAttributes) {
PedestrianBMM pedestrian = new PedestrianBMM(position, topography, pedAttributes, attributesBMM, attributesBHM, random);
return pedestrian;
}
@Override
public VShape getDynamicElementRequiredPlace(@NotNull final VPoint position) {
return createElement(position, new AttributesAgent(attributesPedestrian, -1)).getShape();
}
@Override
public void preLoop(final double simTimeInSec) {
this.lastSimTimeInSec = simTimeInSec;
......
package org.vadere.simulator.models.gnm;
import org.jetbrains.annotations.NotNull;
import org.vadere.annotation.factories.models.ModelClass;
import org.vadere.simulator.models.Model;
import org.vadere.simulator.models.ode.IntegratorFactory;
......@@ -19,6 +20,7 @@ import org.vadere.state.scenario.Target;
import org.vadere.state.scenario.Topography;
import org.vadere.state.types.GradientProviderType;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.parallel.ParallelWorkerUtil;
import org.vadere.util.potential.gradients.GradientProvider;
......@@ -160,11 +162,21 @@ public class GradientNavigationModel extends ODEModel<Pedestrian, AttributesAgen
throw new IllegalArgumentException("GNM cannot initialize " + type.getCanonicalName());
this.pedestrianIdCounter++;
AttributesAgent pedAttributes = new AttributesAgent(elementAttributes, id > 0 ? id : pedestrianIdCounter);
Pedestrian result = new Pedestrian(pedAttributes, random);
result.setPosition(position);
Pedestrian result = create(position, pedAttributes);
return result;
}
private Pedestrian create(@NotNull final VPoint point, @NotNull final AttributesAgent attributesAgent) {
Pedestrian pedestrian = new Pedestrian(attributesAgent, random);
pedestrian.setPosition(point);
return pedestrian;
}
@Override
public VShape getDynamicElementRequiredPlace(@NotNull VPoint position) {
return create(position, new AttributesAgent(elementAttributes, -1)).getShape();
}
@Override
public List<Model> getSubmodels() {
return models;
......
package org.vadere.simulator.models.osm;
import org.jetbrains.annotations.NotNull;
import org.vadere.annotation.factories.models.ModelClass;
import org.vadere.simulator.control.factory.GroupSourceControllerFactory;
import org.vadere.simulator.control.factory.SingleSourceControllerFactory;
......@@ -19,8 +20,7 @@ import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerEvolStrat
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerGradient;
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerNelderMead;
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerPowell;
import org.vadere.simulator.models.osm.updateScheme.ParallelWorkerOSM;
import org.vadere.simulator.models.osm.updateScheme.UpdateSchemeOSM.CallMethod;
import org.vadere.simulator.models.osm.updateScheme.UpdateSchemeOSM;
import org.vadere.simulator.models.potential.PotentialFieldModel;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTarget;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTargetGrid;
......@@ -36,24 +36,20 @@ import org.vadere.state.scenario.Topography;
import org.vadere.state.types.OptimizationType;
import org.vadere.state.types.UpdateType;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.io.ListUtils;
import org.vadere.util.geometry.shapes.VShape;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ModelClass(isMainModel = true)
public class OptimalStepsModel implements MainModel, PotentialFieldModel, DynamicElementRemoveListener<Pedestrian> {
private UpdateSchemeOSM updateSchemeOSM;
private AttributesOSM attributesOSM;
private AttributesAgent attributesPedestrian;
private Random random;
......@@ -65,7 +61,6 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
private Topography topography;
private double lastSimTimeInSec;
private int pedestrianIdCounter;
private PriorityQueue<PedestrianOSM> pedestrianEventsQueue;
private ExecutorService executorService;
private List<Model> models = new LinkedList<>();
public OptimalStepsModel() {
......@@ -121,25 +116,71 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
this.speedAdjusters.add(new SpeedAdjusterWeidmann());
}
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN) {
this.pedestrianEventsQueue = new PriorityQueue<>(100,
new ComparatorPedestrianOSM());
} else {
// not needed and should not be used in this case
this.pedestrianEventsQueue = null;
}
if (attributesOSM.getUpdateType() == UpdateType.PARALLEL) {
this.executorService = Executors.newFixedThreadPool(8);
} else {
this.executorService = null;
}
this.updateSchemeOSM = createUpdateScheme(modelAttributesList, topography, attributesOSM);
this.topography.addElementAddedListener(Pedestrian.class, updateSchemeOSM);
this.topography.addElementRemovedListener(Pedestrian.class, updateSchemeOSM);
topography.addElementRemovedListener(Pedestrian.class, this);
models.add(this);
}
// Dirty quick implementation to test it! TODO: refactoring!
private UpdateSchemeOSM createUpdateScheme(
@NotNull final List<Attributes> attributesList,
@NotNull final Topography topography,
@NotNull final AttributesOSM attributesOSM) {
switch (attributesOSM.getUpdateType()) {
case PARALLEL_OPEN_CL: {
throw new UnsupportedOperationException("not jet implemented.");
/*return UpdateSchemeOSM.createOpenCLUpdateScheme(
topography,
attributesOSM,
Model.findAttributes(attributesList, AttributesFloorField.class),
//3.0,
new EikonalSolver() {
CellGrid cellGrid = null;
@Override
public void initialize() {
potentialFieldTarget.preLoop(0.4);
cellGrid = ((IPotentialFieldTargetGrid)potentialFieldTarget).getCellGrids().get(1);
}
@Override
public CellGrid getPotentialField() {
if(cellGrid == null) {
initialize();
}
return cellGrid;
}
},
new EikonalSolver() {
CellGrid cellGrid = topography.getDistanceFunctionApproximation(
Model.findAttributes(attributesList, AttributesFloorField.class).getPotentialFieldResolution()
);
@Override
public void initialize() {}
@Override
public CellGrid getPotentialField() {
return cellGrid;
}
}
);*/
}
default: return UpdateSchemeOSM.create(attributesOSM.getUpdateType(), topography, random);
}
}
private StepCircleOptimizer createStepCircleOptimizer(
AttributesOSM attributesOSM, Random random, Topography topography,
IPotentialFieldTargetGrid potentialFieldTarget) {
......@@ -193,72 +234,9 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
@Override
public void update(final double simTimeInSec) {
final double timeStepInSec = simTimeInSec - this.lastSimTimeInSec;
// event driven update
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN
&& !pedestrianEventsQueue.isEmpty()) {
while (pedestrianEventsQueue.peek().getTimeOfNextStep() < simTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll();
ped.update(timeStepInSec, simTimeInSec, CallMethod.EVENT_DRIVEN);
pedestrianEventsQueue.add(ped);
}
} else {
// time step length
// parallel update
if (attributesOSM.getUpdateType() == UpdateType.PARALLEL) {
parallelCall(timeStepInSec);
} else {
List<PedestrianOSM> pedestrians = ListUtils.select(
topography.getElements(Pedestrian.class), PedestrianOSM.class);
// random shuffle update
if (attributesOSM.getUpdateType() == UpdateType.SHUFFLE) {
Collections.shuffle(pedestrians, this.random);
}
// default is fixed order sequential update
for (PedestrianOSM pedestrian : pedestrians) {
pedestrian.update(timeStepInSec, -1, CallMethod.SEQUENTIAL);
}
}
this.lastSimTimeInSec = simTimeInSec;
}
}
private void parallelCall(double timeStepInSec) {
CallMethod[] callMethods = {CallMethod.SEEK, CallMethod.MOVE, CallMethod.CONFLICTS, CallMethod.STEPS};
List<Future<?>> futures;
for (CallMethod callMethod : callMethods) {
futures = new LinkedList<>();
for (final PedestrianOSM pedestrian : ListUtils.select(
topography.getElements(Pedestrian.class), PedestrianOSM.class)) {
Runnable worker = new ParallelWorkerOSM(callMethod, pedestrian,
timeStepInSec);
futures.add(executorService.submit(worker));
}
collectFutures(futures);
}
}
private void collectFutures(final List<Future<?>> futures) {
try {
for (Future<?> future : futures) {
future.get();
}
} catch (ExecutionException e) {
e.printStackTrace();
}
// restore interruption in order to stop simulation
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
double timeStepInSec = simTimeInSec - this.lastSimTimeInSec;
updateSchemeOSM.update(timeStepInSec, simTimeInSec);
lastSimTimeInSec = simTimeInSec;
}
/*
......@@ -273,17 +251,21 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
AttributesAgent pedAttributes = new AttributesAgent(
this.attributesPedestrian, id > 0 ? id : pedestrianIdCounter);
PedestrianOSM pedestrianOSM = createElement(position, pedAttributes);
return pedestrianOSM;
}
@Override
public VShape getDynamicElementRequiredPlace(@NotNull final VPoint position) {
return createElement(position, new AttributesAgent(attributesPedestrian, -1)).getShape();
}
private PedestrianOSM createElement(VPoint position, @NotNull final AttributesAgent attributesAgent) {
PedestrianOSM pedestrian = new PedestrianOSM(attributesOSM,
pedAttributes, topography, random, potentialFieldTarget,
attributesAgent, topography, random, potentialFieldTarget,
potentialFieldObstacle.copy(), potentialFieldPedestrian,
speedAdjusters, stepCircleOptimizer.clone());
pedestrian.setPosition(position);
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN) {
this.pedestrianEventsQueue.add(pedestrian);
}
return pedestrian;
}
......@@ -308,11 +290,7 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
}
@Override
public void elementRemoved(Pedestrian ped) {
PedestrianOSM osmPed = (PedestrianOSM) ped;
pedestrianEventsQueue.remove(osmPed);
// System.out.printf("Remove ped %s from pedestrianEventsQueue%n", ped.getId());
}
public void elementRemoved(Pedestrian ped) {}
@Override
public SourceControllerFactory getSourceControllerFactory() {
......
package org.vadere.simulator.models.osm;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.SpeedAdjuster;
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizer;
import org.vadere.simulator.models.osm.stairOptimization.StairStepOptimizer;
......@@ -34,7 +35,6 @@ public class PedestrianOSM extends Pedestrian {
private final AttributesOSM attributesOSM;
private final transient StepCircleOptimizer stepCircleOptimizer;
private final transient UpdateSchemeOSM updateScheme;
private final transient Topography topography;
private final double stepLength;
private final double stepDeviation;
......@@ -77,7 +77,6 @@ public class PedestrianOSM extends Pedestrian {
this.potentialFieldObstacle = potentialFieldObstacle;
this.potentialFieldPedestrian = potentialFieldPedestrian;
this.stepCircleOptimizer = stepCircleOptimizer;
this.updateScheme = createUpdateScheme(attributesOSM.getUpdateType(), this);
this.speedAdjusters = speedAdjusters;
this.relevantPedestrians = new HashSet<>();
......@@ -95,31 +94,12 @@ public class PedestrianOSM extends Pedestrian {
this.minStepLength = 0;
}
this.lastPosition = getPosition();
this.nextPosition = getPosition();