Commit 362e4036 authored by Christina Maria Mayr's avatar Christina Maria Mayr
Browse files

Merge branch 'target_changer_prob_list' into 'master'

Set simulation finish time dynamically

See merge request !127
parents 2d5d4900 bbd98c0b
Pipeline #257448 passed with stages
in 218 minutes and 7 seconds
{
"name" : "Liddle_osm_v4_clone_1",
"description" : "",
"release" : "1.12",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
"filename" : "postvis.traj",
"processors" : [ 1, 2 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepPedestrianIdOverlapOutputFile",
"filename" : "overlap.csv",
"processors" : [ 3 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.NoDataKeyOutputFile",
"filename" : "overlapCount.txt",
"processors" : [ 4 ]
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.TimestepPedestriansNearbyIdOutputFile",
"filename" : "pedsNearby.txt",
"processors" : [ 5 ]
} ],
"processors" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.FootStepProcessor",
"id" : 1
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.FootStepTargetIDProcessor",
"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
}
}, {
"type" : "org.vadere.simulator.projects.dataprocessing.processor.PedestriansNearbyProcessor",
"id" : 5,
"attributesType" : "org.vadere.state.attributes.processor.AttributesPedestrianNearbyProcessor",
"attributes" : {
"maxDistanceForANearbyPedestrian" : 1.5,
"sampleEveryNthStep" : 1,
"allowedAbsenceTimestepsIfContactReturns" : 2,
"minTimespanOfContactTimesteps" : 5,
"printContactTrajectories" : false,
"printForPostVis" : false
}
} ],
"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" : false,
"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" : 1.5,
"pedPotentialPersonalSpaceWidth" : 2.25,
"pedPotentialHeight" : 200.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" : 60.0,
"simTimeStepLength" : 0.4,
"realTimeSimTimeRatio" : 0.5,
"writeSimulationData" : true,
"visualizationEnabled" : true,
"printFPS" : false,
"digitsPerCoordinate" : 2,
"useFixedSeed" : false,
"fixedSeed" : 1,
"simulationSeed" : 0
},
"attributesPsychology" : {
"usePsychologyLayer" : false,
"psychologyLayer" : {
"perception" : "SimplePerceptionModel",
"cognition" : "CooperativeCognitionModel"
}
},
"topography" : {
"attributes" : {
"bounds" : {
"x" : 0.0,
"y" : 0.0,
"width" : 40.0,
"height" : 15.0
},
"boundingBoxWidth" : 0.5,
"bounded" : true,
"referenceCoordinateSystem" : null
},
"obstacles" : [ {
"shape" : {
"x" : 3.0,
"y" : 9.0,
"width" : 5.0,
"height" : 6.0,
"type" : "RECTANGLE"
},
"id" : 1
}, {
"shape" : {
"x" : 3.0,
"y" : 0.0,
"width" : 5.0,
"height" : 8.0,
"type" : "RECTANGLE"
},
"id" : 2
} ],
"measurementAreas" : [ {
"shape" : {
"x" : 8.5,
"y" : 6.0,
"width" : 1.0,
"height" : 3.0,
"type" : "RECTANGLE"
},
"id" : 1
}, {
"shape" : {
"x" : 8.0,
"y" : 5.6,
"width" : 2.0,
"height" : 4.0,
"type" : "RECTANGLE"
},
"id" : 2
} ],
"stairs" : [ ],
"targets" : [ {
"id" : 1,
"absorbing" : true,
"shape" : {
"x" : 1.0,
"y" : 6.8,
"width" : 1.4,
"height" : 1.4,
"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" : 19.0,
"y" : 1.0,
"width" : 20.0,
"height" : 13.0,
"type" : "RECTANGLE"
},
"interSpawnTimeDistribution" : "org.vadere.state.scenario.ConstantDistribution",
"distributionParameters" : [ 1.0 ],
"spawnNumber" : 70,
"maxSpawnNumberTotal" : -1,
"startTime" : 0.0,
"endTime" : 0.0,
"spawnAtRandomPositions" : true,
"spawnAtGridPositionsCA" : false,
"useFreeSpaceOnly" : true,
"targetIds" : [ 1 ],
"groupSizeDistribution" : [ 1.0 ],
"dynamicElementType" : "PEDESTRIAN",
"attributesPedestrian" : null
} ],
"dynamicElements" : [ ],
"attributesPedestrian" : {
"radius" : 0.195,
"densityDependentSpeed" : false,
"speedDistributionMean" : 1.34,
"speedDistributionStandardDeviation" : 0.26,
"minimumSpeed" : 0.01,
"maximumSpeed" : 5.0,
"acceleration" : 2.0,
"footstepHistorySize" : 4,
"searchRadius" : 1.0,
"walkingDirectionCalculation" : "BY_TARGET_CENTER",
"walkingDirectionSameIfAngleLessOrEqual" : 45.0
},
"teleporter" : null,
"attributesCar" : null
},
"stimulusInfos" : [ ]
}
}
\ No newline at end of file
......@@ -74,9 +74,13 @@ public class RemoteManager implements RunnableFinishedListener {
throw new TraCIException("Cannot create Scenario from given file.");
}
if (simCfg != null) {
scenario.getAttributesSimulation().setFixedSeed(simCfg.getSeed());
scenario.getAttributesSimulation().setUseFixedSeed(true);
logger.infof("received seed from traci client '%s'", Long.toString(simCfg.getSeed()));
if (simCfg.isUseVadereSeed()){
logger.infof("use Vadere Seed. (ignoring traci seed)", Long.toString(simCfg.getSeed()));
} else {
scenario.getAttributesSimulation().setFixedSeed(simCfg.getSeed());
scenario.getAttributesSimulation().setUseFixedSeed(true);
logger.infof("received seed from traci client '%s'", Long.toString(simCfg.getSeed()));
}
}
currentSimulationRun = new RemoteScenarioRun(scenario, outputDir, this, scenarioPath, scenarioCache);
}
......@@ -143,6 +147,10 @@ public class RemoteManager implements RunnableFinishedListener {
return true;
}
public double getSimulationStoppedEarlyAtTime(){
return currentSimulationRun.getSimulationStoppedEarlyAtTime();
}
public boolean isClientCloseCommandReceived() {
return clientCloseCommandReceived;
}
......
......@@ -17,6 +17,7 @@ public class RemoteScenarioRun extends ScenarioRun implements RemoteRunListener
private final ReentrantLock lock;
private List<Subscription> subscriptions;
private boolean lastSimulationStep;
private double simulationStoppedEarlyAtTime;
public RemoteScenarioRun(Scenario scenario, Path outputDir, RunnableFinishedListener scenarioFinishedListener, Path scenarioPath, ScenarioCache scenarioCache) {
......@@ -25,6 +26,7 @@ public class RemoteScenarioRun extends ScenarioRun implements RemoteRunListener
this.waitForLoopEnd = new Object();
this.lock = new ReentrantLock();
this.lastSimulationStep = false;
this.simulationStoppedEarlyAtTime = Double.MAX_VALUE;
addRemoteManagerListener(this);
}
......@@ -72,8 +74,16 @@ public class RemoteScenarioRun extends ScenarioRun implements RemoteRunListener
}
}
@Override
public void simulationStoppedEarlyListener(double time) {
simulationStoppedEarlyAtTime = time;
}
public boolean isLastSimulationStep() {
return lastSimulationStep;
}
public double getSimulationStoppedEarlyAtTime() {
return simulationStoppedEarlyAtTime;
}
}
......@@ -98,6 +98,15 @@ public class ControlCommandHandler extends CommandHandler<ControlVar> {
});
cmd.setResponse(response);
// check RemoteManager if simulation is ended prematurely. This can happen if the
// a finish state is reached earlier than the given simulation time. In this case
// inform the TraCI client about this instead of giving it the Subscription results.
if (remoteManager.getSimulationStoppedEarlyAtTime() != Double.MAX_VALUE){
double stoppedAtTime = remoteManager.getSimulationStoppedEarlyAtTime();
logger.infof("Stop simulation at %f. Inform TraCI client with simEndReach Response.", stoppedAtTime);
cmd.setResponse(TraCISimTimeResponse.simEndReached());
}
logger.debug("process_simStep done.");
return cmd;
}
......
......@@ -22,10 +22,11 @@ public class SimulationCfg {
private String outputScalarFile;
private String outputVecFile;
private long seed;
private boolean useVadereSeed;
public SimulationCfg(CompoundObject obj) {
if (obj.size() != 9) {
throw new TraCIException("Expected at least 9 elements");
if (obj.size() != 10) {
throw new TraCIException("Expected at least 10 elements");
}
configName = (String) obj.getData(0, TraCIDataType.STRING);
experiment = (String) obj.getData(1, TraCIDataType.STRING);
......@@ -36,6 +37,12 @@ public class SimulationCfg {
outputScalarFile = (String) obj.getData(6, TraCIDataType.STRING);
outputVecFile = (String) obj.getData(7, TraCIDataType.STRING);
seed = Long.valueOf((int) obj.getData(8, TraCIDataType.INTEGER));
int useVadereSeedVal = (Integer) obj.getData(9, TraCIDataType.U_BYTE);
if (useVadereSeedVal == 1){
useVadereSeed = true;
} else {
useVadereSeed = false;
}
}
public static CompoundObject asCompoundObject(String configName,
......@@ -46,11 +53,13 @@ public class SimulationCfg {
String repetition,
String outputScalarFile,
String outputVecFile,
long seed) {
long seed,
boolean useVadereSeed) {
return CompoundObjectBuilder.builder()
.rest()
.add(TraCIDataType.STRING, 8)
.add(TraCIDataType.INTEGER)
.add(TraCIDataType.U_BYTE)
.build(configName,
experiment,
dateTime,
......@@ -59,7 +68,8 @@ public class SimulationCfg {
repetition,
outputScalarFile,
outputVecFile,
seed);
seed,
useVadereSeed);
}
public String outputPath() {
......@@ -151,25 +161,34 @@ public class SimulationCfg {
this.seed = seed;
}
public boolean isUseVadereSeed() {
return useVadereSeed;
}
public void setUseVadereSeed(boolean useVadereSeed) {
this.useVadereSeed = useVadereSeed;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SimulationCfg that = (SimulationCfg) o;
return seed == that.seed &&
configName.equals(that.configName) &&
experiment.equals(that.experiment) &&
dateTime.equals(that.dateTime) &&
resultRootDir.equals(that.resultRootDir) &&
iterationVariables.equals(that.iterationVariables) &&
repetition.equals(that.repetition) &&
outputScalarFile.equals(that.outputScalarFile) &&
outputVecFile.equals(that.outputVecFile);
useVadereSeed == that.useVadereSeed &&
Objects.equals(configName, that.configName) &&
Objects.equals(experiment, that.experiment) &&
Objects.equals(dateTime, that.dateTime) &&
Objects.equals(resultRootDir, that.resultRootDir) &&
Objects.equals(iterationVariables, that.iterationVariables) &&
Objects.equals(repetition, that.repetition) &&
Objects.equals(outputScalarFile, that.outputScalarFile) &&
Objects.equals(outputVecFile, that.outputVecFile);
}
@Override
public int hashCode() {
return Objects.hash(configName, experiment, dateTime, resultRootDir, iterationVariables, repetition, outputScalarFile, outputVecFile, seed);
return Objects.hash(configName, experiment, dateTime, resultRootDir, iterationVariables, repetition, outputScalarFile, outputVecFile, seed, useVadereSeed);
}
@Override
......@@ -184,6 +203,7 @@ public class SimulationCfg {
", outputScalarFile='" + outputScalarFile + '\'' +
", outputVecFile='" + outputVecFile + '\'' +
", seed=" + seed +
", useVadereSeed=" + useVadereSeed +
'}';
}
}
......@@ -61,6 +61,7 @@ public class ControlCommandHandlerTest extends CommandHandlerTest {
TraCISimStepCommand rawCmd = (TraCISimStepCommand) getFirstCommand(TraCISimStepCommand.build(targetTime));
RemoteManager rm = mock(RemoteManager.class, Mockito.RETURNS_DEEP_STUBS);
when(rm.nextStep(targetTime)).thenReturn(true);
when(rm.getSimulationStoppedEarlyAtTime()).thenReturn(Double.MAX_VALUE);
TraCICommand cmd = ctrCmdHandler.process_simStep(rawCmd, rm);
testTraCICommand(cmd, traciCmd, cmdType);
......
......@@ -9,4 +9,9 @@ public interface RemoteRunListener {
void simulationStepFinishedListener();
void lastSimulationStepFinishedListener();
/**
* Notify RemoteManger about early shutdown. This is used to gracefully stop TraCI connection.
*/
void simulationStoppedEarlyListener(double time);
}
......@@ -288,6 +288,22 @@ public class Simulation {
c.postUpdate(simTimeInSec);
}
double stopTime = runTimeInSec;
if (this.simulationState.isSimStop()) {
// get stopTime if the simulation should finish before finish time. New finish time = stop time
stopTime = this.simTimeInSec;
}
if (stopTime + startTimeInSec > simTimeInSec + 1e-7) {
// do nothing here. This is done after the Remote Control Hook
} else {
// inform Remote Control Hook that simulation is stopped before
// static runTimeInSec is reached.
isRunSimulation = false;
remoteRunListeners.forEach(e-> e.simulationStoppedEarlyListener(simTimeInSec));
if (stopTime < runTimeInSec) {
logger.info("Run simulation until time t=" + stopTime +"s is reached."); }
}
// Single step hook
// Remote Control Hook
......@@ -315,14 +331,11 @@ public class Simulation {
}
}
if (runTimeInSec + startTimeInSec > simTimeInSec + 1e-7) {
if (stopTime + startTimeInSec > simTimeInSec + 1e-7) {
simTimeInSec += Math.min(attributesSimulation.getSimTimeStepLength(), runTimeInSec + startTimeInSec - simTimeInSec);
} else {
isRunSimulation = false;
}
//remove comment to fasten simulation for evacuation simulations
//if (topography.getElements(Pedestrian.class).size() == 0){
// isRunSimulation = false;
......
......@@ -16,6 +16,7 @@ public class SimulationState {
private final int step;
private final String name;
private final MainModel mainModel;
private boolean simStop = false;
protected SimulationState(final String name,
final Topography topography,
......@@ -29,7 +30,6 @@ public class SimulationState {
this.step = step;
this.scenarioStore = scenarioStore;
this.mainModel = mainModel;
}
@Deprecated
......@@ -75,4 +75,12 @@ public class SimulationState {
public Optional<MainModel> getMainModel() {
return Optional.ofNullable(mainModel);
}
public void setSimStop(boolean stop){
this.simStop = stop;
}
public boolean isSimStop() {
return simStop;
}
}
package org.vadere.simulator.control.simulation;
public class SimulationStop {
}
......@@ -45,6 +45,8 @@ public abstract class DataProcessor<K extends DataKey<K>, V> {
private int lastStep;
private boolean stopSimBeforeSimFinish;
protected DataProcessor() {
this(new String[] { });
}
......@@ -54,6 +56,7 @@ public abstract class DataProcessor<K extends DataKey<K>, V> {
this.data = new TreeMap<>(); // TreeMap to avoid sorting data later
this.lastStep = 0;
this.stopSimBeforeSimFinish = false;
}
......@@ -116,10 +119,13 @@ public abstract class DataProcessor<K extends DataKey<K>, V> {
public final void update(final SimulationState state) {
int step = state.getStep();
if (this.lastStep < step) {
if (this.lastStep < step) {
this.doUpdate(state);
this.lastStep = step;
}
// stop simulation if a criteria defined in your data processor is fulfilled
state.setSimStop(this.stopSimBeforeSimFinish);
}
public Optional<Model> getSubModel(SimulationState state, Class clazz){
......@@ -152,6 +158,10 @@ public abstract class DataProcessor<K extends DataKey<K>, V> {
return getClass().getSimpleName();
}
public void setStopSimBeforeSimFinish(boolean stopSimBeforeSimFinish) {
this.stopSimBeforeSimFinish = stopSimBeforeSimFinish;
}
@Override
public String toString() {
return id + ": " + getSimpleProcessorTypeName();
......
......@@ -5,6 +5,7 @@ import org.vadere.simulator.control.simulation.SimulationState;
import org.vadere.simulator.projects.dataprocessing.ProcessorManager;
import org.vadere.simulator.projects.dataprocessing.datakey.EventtimePedestrianIdKey;
import org.vadere.simulator.projects.dataprocessing.datakey.TimestepKey;
import org.vadere.state.attributes.AttributesSimulation;
import org.vadere.state.attributes.processor.AttributesPedStimulusCountingProcessor;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.simulation.InformationDegree;
......@@ -19,6 +20,7 @@ public class PedStimulusCountingProcessor extends DataProcessor<TimestepKey, Inf
private Predicate<Pedestrian> filter_by_stimuli;
private Pattern filter_pattern = null;
private double stopIfPercentageIsInformed = 0.95;
public PedStimulusCountingProcessor() {
super("numberPedsInformed", "numberPedsAll", "percentageInformed");
......@@ -37,6 +39,8 @@ public class PedStimulusCountingProcessor extends DataProcessor<TimestepKey, Inf
filter_by_stimuli = ped -> ped.getKnowledgeBase().knowsAbout(getAttributes().getInformationFilter());
}
stopIfPercentageIsInformed = attr.getStopIfPercentageIsInformed();
}
@Override
......@@ -47,10 +51,16 @@ public class PedStimulusCountingProcessor extends DataProcessor<TimestepKey, Inf
int numberPedsAll = (int) peds.stream().filter(p-> p.getFootstepHistory().getFootSteps().size() > 1).count();
numberPedsAll = Math.max(numberPedsAll,numberPedsInformed);
InformationDegree informationDegree = new InformationDegree(numberPedsInformed, numberPedsAll);
// force stop before simulation time defined in json is reached.