Commit 311a863c authored by Stefan Schuhbäck's avatar Stefan Schuhbäck
Browse files

add random point provider

parent 18e09ac6
Pipeline #176705 failed with stages
in 82 minutes and 59 seconds
......@@ -10,6 +10,7 @@ import org.vadere.util.logging.Logger;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;
import tech.tablesaw.api.Table;
......@@ -25,6 +26,7 @@ public class OfflineSimulation {
private final Path outputDir;
private final OfflineTopographyController topographyController;
private final Topography topography;
private final Random random;
public OfflineSimulation(final Table pedestriansByStep, final Scenario vadere,
......@@ -33,7 +35,9 @@ public class OfflineSimulation {
this.vadere = vadere;
this.outputDir = outputDir;
this.topography = vadere.getTopography();
this.topographyController = new OfflineTopographyController(topography);
long seed = vadere.getAttributesSimulation().getSimulationSeed();
this.random = new Random(seed);
this.topographyController = new OfflineTopographyController(topography, random);
this.trajectories = null;
this.simulationStates = null;
......
package org.vadere.simulator.control;
import org.vadere.simulator.context.VadereContext;
import org.vadere.simulator.models.potential.fields.IPotentialField;
import org.vadere.simulator.models.potential.fields.PotentialFieldDistancesBruteForce;
import org.vadere.simulator.utils.cache.ScenarioCache;
import org.vadere.state.attributes.models.AttributesFloorField;
......@@ -9,18 +8,20 @@ import org.vadere.state.scenario.Car;
import org.vadere.state.scenario.Obstacle;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.data.cellgrid.CellGridReachablePointProvider;
import org.vadere.util.geometry.shapes.VRectangle;
import java.util.function.Function;
import java.util.Random;
import java.util.stream.Collectors;
public class OfflineTopographyController {
private final Topography topography;
protected final Random random;
public OfflineTopographyController(final Topography topography) {
public OfflineTopographyController(final Topography topography, final Random random) {
this.topography = topography;
this.random = random;
}
protected void update(double simTimeInSec) {
......@@ -42,13 +43,14 @@ public class OfflineTopographyController {
// add distance function
ScenarioCache cache = (ScenarioCache) VadereContext.get(topography).getOrDefault("cache", ScenarioCache.empty());
IPotentialField distanceField = new PotentialFieldDistancesBruteForce(
PotentialFieldDistancesBruteForce distanceField = new PotentialFieldDistancesBruteForce(
topography.getObstacles().stream().map(obs -> obs.getShape()).collect(Collectors.toList()),
new VRectangle(topography.getBounds()),
new AttributesFloorField(), cache);
Function<IPoint, Double> obstacleDistance = p -> distanceField.getPotential(p, null);
this.topography.setObstacleDistanceFunction(obstacleDistance);
this.topography.setObstacleDistanceFunction(distanceField);
this.topography.setReachablePointProvider(CellGridReachablePointProvider.createUniform(
distanceField.getCellGrid(), random));
}
/**
......
......@@ -158,7 +158,7 @@ public class Simulation {
}
private void createControllers(Topography topography, MainModel mainModel, Random random) {
this.topographyController = new TopographyController(topography, mainModel);
this.topographyController = new TopographyController(topography, mainModel, random);
for (Source source : topography.getSources()) {
SourceController sc = this.sourceControllerFactory
......
......@@ -6,14 +6,15 @@ import org.vadere.state.scenario.TargetPedestrian;
import org.vadere.state.scenario.Topography;
import java.util.LinkedList;
import java.util.Random;
public class TopographyController extends OfflineTopographyController {
private final Topography topography;
private final DynamicElementFactory dynamicElementFactory;
public TopographyController(Topography topography, DynamicElementFactory dynamicElementFactory) {
super(topography);
public TopographyController(Topography topography, DynamicElementFactory dynamicElementFactory, final Random random) {
super(topography, random);
this.topography = topography;
this.dynamicElementFactory = dynamicElementFactory;
}
......
......@@ -7,6 +7,7 @@ import org.vadere.simulator.utils.cache.ICellGridCacheObject;
import org.vadere.simulator.utils.cache.ScenarioCache;
import org.vadere.state.attributes.models.AttributesFloorField;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.ObstacleDistanceFunction;
import org.vadere.util.data.cellgrid.CellGrid;
import org.vadere.util.data.cellgrid.CellState;
import org.vadere.util.data.cellgrid.PathFindingTag;
......@@ -29,7 +30,7 @@ import java.util.Collection;
*
* Note: This can be computational expensive if there are many and or complex obstacles.
*/
public class PotentialFieldDistancesBruteForce implements IPotentialField {
public class PotentialFieldDistancesBruteForce implements IPotentialField, ObstacleDistanceFunction {
private static Logger logger = Logger.getLogger(PotentialFieldDistancesBruteForce.class);
private final CellGrid cellGrid;
......@@ -93,4 +94,14 @@ public class PotentialFieldDistancesBruteForce implements IPotentialField {
public double getPotential(@NotNull IPoint pos, @Nullable Agent agent) {
return cellGrid.getInterpolatedValueAt(pos).getLeft();
}
public CellGrid getCellGrid(){
return cellGrid;
}
@Override
public double getDistance(IPoint point) {
return getPotential(point, null);
}
}
package org.vadere.state.scenario;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.math.IDistanceFunction;
public interface ObstacleDistanceFunction extends IDistanceFunction {
double getDistance(IPoint point);
@Override
default Double apply(IPoint point) {
return getDistance(point);
}
}
......@@ -17,6 +17,7 @@ import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VPolygon;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.logging.Logger;
import org.vadere.util.random.IReachablePointProvider;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
......@@ -39,7 +40,8 @@ public class Topography implements DynamicElementMover{
/** Transient to prevent JSON serialization. */
private static Logger logger = Logger.getLogger(Topography.class);
private Function<IPoint, Double> obstacleDistanceFunction;
private ObstacleDistanceFunction obstacleDistanceFunction;
private IReachablePointProvider reachablePointProvider;
/** A possible empty string identifying a context object. */
private String contextId;
......@@ -147,7 +149,12 @@ public class Topography implements DynamicElementMover{
this.cars = new DynamicElementContainer<>(bounds, CELL_SIZE);
recomputeCells = false;
this.obstacleDistanceFunction = p -> obstacles.stream().map(obs -> obs.getShape()).map(shape -> shape.distance(p)).min(Double::compareTo).orElse(Double.MAX_VALUE);
this.obstacleDistanceFunction = point -> obstacles.stream()
.map(Obstacle::getShape)
.map(shape -> shape.distance(point))
.min(Double::compareTo)
.orElse(Double.MAX_VALUE);
this.dynamicElementIdCounter = new AtomicInteger(1);
this.contextId = "";
}
......@@ -200,10 +207,22 @@ public class Topography implements DynamicElementMover{
}
public double distanceToObstacle(@NotNull IPoint point) {
return this.obstacleDistanceFunction.apply(point);
return this.obstacleDistanceFunction.getDistance(point);
}
public ObstacleDistanceFunction getObstacleDistanceFunction() {
return obstacleDistanceFunction;
}
public IReachablePointProvider getReachablePointProvider() {
return reachablePointProvider;
}
public void setReachablePointProvider(@NotNull IReachablePointProvider reachablePointProvider) {
this.reachablePointProvider = reachablePointProvider;
}
public void setObstacleDistanceFunction(@NotNull Function<IPoint, Double> obstacleDistanceFunction) {
public void setObstacleDistanceFunction(@NotNull ObstacleDistanceFunction obstacleDistanceFunction) {
this.obstacleDistanceFunction = obstacleDistanceFunction;
}
......
package org.vadere.util.data.cellgrid;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.random.ConstantIntegerPointProvider;
import org.vadere.util.random.IPointOffsetProvider;
import org.vadere.util.random.IReachablePointProvider;
import org.vadere.util.random.RandomIPointProvider;
import org.vadere.util.random.UniformIntegerIPointSupplier;
import org.vadere.util.random.UniformPointOffsetDouble;
import java.util.Random;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class CellGridReachablePointProvider implements IReachablePointProvider {
private final CellGrid cellGrid;
private RandomIPointProvider randomPointProvider;
private ConstantIntegerPointProvider constPointProvider;
private IPointOffsetProvider offsetProvider;
public static CellGridReachablePointProvider createUniform(final CellGrid cellGrid, final Random random){
IPointOffsetProvider offset = new UniformPointOffsetDouble(random, 0.5);
RandomIPointProvider pointSupplier = new UniformIntegerIPointSupplier(random,
cellGrid.getNumPointsX()-1, cellGrid.getNumPointsY()-1);
return new CellGridReachablePointProvider(cellGrid, pointSupplier, offset);
}
private CellGridReachablePointProvider(CellGrid cellGrid, RandomIPointProvider pointSupplier, IPointOffsetProvider offset) {
this.cellGrid = cellGrid;
this.randomPointProvider = pointSupplier;
this.offsetProvider = offset;
this.constPointProvider = new ConstantIntegerPointProvider(cellGrid.numPointsX -1, cellGrid.numPointsY-1);
}
private IPoint get(RandomIPointProvider provider, Predicate<Double> obstacleDistPredicate, IPointOffsetProvider offsetProvider){
boolean legalState;
CellState state;
IPoint p;
do {
p = provider.nextPoint();
state = cellGrid.getValue((int)p.getX(), (int)p.getY());
legalState = state.tag == PathFindingTag.Reachable && obstacleDistPredicate.test(state.potential);
} while (!legalState);
return offsetProvider.applyOffset(p);
}
@Override
public void setRandomIPointProvider(RandomIPointProvider provider) {
this.randomPointProvider = provider;
}
@Override
public RandomIPointProvider getRandomIPointProvider() {
return randomPointProvider;
}
@Override
public void setIPointOffsetProvider(IPointOffsetProvider provider) {
this.offsetProvider = provider;
}
@Override
public IPointOffsetProvider getIPointOffsetProvider() {
return offsetProvider;
}
@Override
public Stream<IPoint> stream(Predicate<Double> obstacleDistPredicate) {
return Stream.generate(() -> get(constPointProvider, obstacleDistPredicate, offsetProvider));
}
@Override
public Stream<IPoint> randomStream(Predicate<Double> obstacleDistPredicate) {
return Stream.generate(() -> get(randomPointProvider, obstacleDistPredicate, offsetProvider));
}
}
package org.vadere.util.random;
import com.google.common.base.Supplier;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
public class ConstantIntegerPointProvider implements RandomIPointProvider {
private Supplier<IPoint> iPointSupplier;
private int xUpperBound;
private int yUpperBound;
public ConstantIntegerPointProvider(int xUpperBound, int yUpperBound){
this.xUpperBound = xUpperBound;
this.yUpperBound = yUpperBound;
this.iPointSupplier = new Supplier<IPoint>() {
int x;
int y;
@Override
public IPoint get() {
if (x == xUpperBound){
x = 0;
y = y == yUpperBound ? 0 : ++y;
} else {
x++;
}
return new VPoint(x, y);
}
};
}
@Override
public double getSupportUpperBoundX() {
return xUpperBound;
}
@Override
public double getSupportLowerBoundX() {
return 0;
}
@Override
public double getSupportUpperBoundY() {
return yUpperBound;
}
@Override
public double getSupportLowerBoundY() {
return 0;
}
@Override
public IPoint nextPoint() {
return iPointSupplier.get();
}
}
package org.vadere.util.random;
import org.vadere.util.geometry.shapes.IPoint;
public interface IPointOffsetProvider {
static IPointOffsetProvider noOffset(){
return new IPointOffsetProvider() {
@Override
public IPoint applyOffset(IPoint point) {
return point;
}
@Override
public IPoint applyOffset(IPoint point, double maxOffset) {
return point;
}
};
}
IPoint applyOffset(IPoint point);
IPoint applyOffset(IPoint point, double maxOffset);
}
package org.vadere.util.random;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.function.Predicate;
import java.util.stream.Stream;
public interface IReachablePointProvider {
void setRandomIPointProvider(RandomIPointProvider provider);
RandomIPointProvider getRandomIPointProvider();
void setIPointOffsetProvider(IPointOffsetProvider provider);
IPointOffsetProvider getIPointOffsetProvider();
Stream<IPoint> randomStream(Predicate<Double> obstacleDistPredicate);
Stream<IPoint> stream(Predicate<Double> obstacleDistPredicate);
}
package org.vadere.util.random;
import org.vadere.util.geometry.shapes.IPoint;
import java.util.stream.Stream;
public interface RandomIPointProvider {
double getSupportUpperBoundX();
double getSupportLowerBoundX();
double getSupportUpperBoundY();
double getSupportLowerBoundY();
IPoint nextPoint();
}
package org.vadere.util.random;
import org.apache.commons.math3.distribution.IntegerDistribution;
import org.apache.commons.math3.distribution.UniformIntegerDistribution;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import java.util.Random;
public class UniformIntegerIPointSupplier implements RandomIPointProvider {
private IntegerDistribution xDist;
private IntegerDistribution yDist;
public UniformIntegerIPointSupplier(final Random random, int xUpperBound, int yUpperBound){
xDist = new UniformIntegerDistribution(new JDKRandomGenerator(random.nextInt()), 0, xUpperBound);
yDist = new UniformIntegerDistribution(new JDKRandomGenerator(random.nextInt()), 0, yUpperBound);
}
@Override
public double getSupportUpperBoundX() {
return xDist.getSupportUpperBound();
}
@Override
public double getSupportLowerBoundX() {
return xDist.getSupportLowerBound();
}
@Override
public double getSupportUpperBoundY() {
return yDist.getSupportUpperBound();
}
@Override
public double getSupportLowerBoundY() {
return yDist.getSupportLowerBound();
}
@Override
public IPoint nextPoint() {
return new VPoint(xDist.sample(), yDist.sample());
}
}
package org.vadere.util.random;
import org.apache.commons.math3.distribution.RealDistribution;
import org.apache.commons.math3.distribution.UniformRealDistribution;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import java.util.Random;
public class UniformPointOffsetDouble implements IPointOffsetProvider {
private RealDistribution radiusDist;
private RealDistribution angleDist;
private double maxOffsetRadius;
public UniformPointOffsetDouble(final Random random, double maxOffsetRadius){
this.maxOffsetRadius = maxOffsetRadius;
this.radiusDist = new UniformRealDistribution(new JDKRandomGenerator(random.nextInt()), 0, 1.0);
this.angleDist = new UniformRealDistribution(new JDKRandomGenerator(random.nextInt()), 0, 2*Math.PI);
}
@Override
public IPoint applyOffset(IPoint point) {
return applyOffset(point, maxOffsetRadius);
}
@Override
public IPoint applyOffset(IPoint point, double maxOffset) {
double radius = maxOffset*radiusDist.sample();
double angle = angleDist.sample();
VPoint offset = new VPoint(radius*Math.cos(angle), radius*Math.sin(angle));
return point.add(offset);
}
}
......@@ -2,6 +2,7 @@ package org.vadere.util.data.cellgrid;
import org.junit.Assert;
import org.junit.Test;
import org.vadere.util.random.IPointOffsetProvider;
import java.io.File;
import java.io.IOException;
......@@ -60,6 +61,29 @@ public class CellGridTest {
compare(cellGrid.asTable(), cellGrid);
}
@Test
public void randomFreeSpace(){
Random rnd = new Random(4);
CellGrid cellGrid = new CellGrid(3.0, 3.0, 1.0, new CellState(), 0.0, 0.0);
cellGrid.setValue(0, 0, new CellState(1.0, PathFindingTag.Reachable));
cellGrid.setValue(0, 1, new CellState(2.0, PathFindingTag.Reachable));
cellGrid.setValue(0, 2, new CellState(3.0, PathFindingTag.Reachable));
cellGrid.setValue(0, 3, new CellState(4.0, PathFindingTag.Reachable));
cellGrid.setValue(1, 0, new CellState(1.0, PathFindingTag.Reachable));
cellGrid.setValue(1, 1, new CellState(2.0, PathFindingTag.Reachable));
cellGrid.setValue(1, 2, new CellState(3.0, PathFindingTag.Reachable));
cellGrid.setValue(1, 3, new CellState(4.0, PathFindingTag.Reachable));
CellGridReachablePointProvider provider = CellGridReachablePointProvider.createUniform(cellGrid, rnd);
provider.setIPointOffsetProvider(IPointOffsetProvider.noOffset());
// provider.stream(aDouble -> true).limit(9).forEach(System.out::println);
System.out.println("------");
provider.randomStream(aDouble -> aDouble < 2).limit(50).forEach(System.out::println);
}
private void compare(Table t, CellGrid cellGrid){
for (int row = 0; row < cellGrid.numPointsY; row++) {
for (int col = 0; col < cellGrid.numPointsX; col++) {
......
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