Commit d0970313 authored by Christina Maria Mayr's avatar Christina Maria Mayr
Browse files

Merge branch 'external_input' into 'master'

External input

See merge request !154
parents 27bc882f 7782e542
Pipeline #494384 passed with stages
in 128 minutes and 43 seconds
......@@ -487,6 +487,16 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
}
@Override
public void simulationapi_init_control(final String[] args) throws IOException {
}
@Override
public void simulationapi_apply_control(final String[] args) throws IOException {
}
@Override
public void simulationapi_setSimConfig(String[] args) throws IOException {
System.out.println("not implemented");
......
......@@ -2,22 +2,21 @@ package org.vadere.manager.traci.commandHandler;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import org.vadere.annotation.traci.client.TraCIApi;
import org.vadere.manager.RemoteManager;
import org.vadere.manager.traci.TraCICmd;
import org.vadere.state.traci.TraCIDataType;
import org.vadere.manager.traci.commandHandler.annotation.PersonHandler;
import org.vadere.manager.traci.commandHandler.annotation.PersonHandlers;
import org.vadere.manager.traci.commandHandler.variables.PersonVar;
import org.vadere.manager.traci.commands.TraCICommand;
import org.vadere.manager.traci.commands.TraCIGetCommand;
import org.vadere.manager.traci.commands.TraCISetCommand;
import org.vadere.state.traci.CompoundObject;
import org.vadere.manager.traci.response.TraCIGetResponse;
import org.vadere.simulator.control.simulation.SimulationState;
import org.vadere.state.psychology.perception.types.KnowledgeItem;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.traci.CompoundObject;
import org.vadere.state.traci.TraCIDataType;
import org.vadere.state.util.StateJsonConverter;
import org.vadere.util.geometry.Vector3D;
import org.vadere.util.geometry.shapes.VPoint;
......@@ -25,11 +24,7 @@ import org.vadere.util.logging.Logger;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
......
......@@ -3,11 +3,7 @@ package org.vadere.manager.traci.commandHandler;
import org.apache.commons.math3.util.Pair;
import org.vadere.annotation.traci.client.TraCIApi;
import org.vadere.manager.RemoteManager;
import org.vadere.state.traci.CompoundObjectProvider;
import org.vadere.state.traci.TraCICommandCreationException;
import org.vadere.state.traci.TraCIException;
import org.vadere.manager.traci.TraCICmd;
import org.vadere.state.traci.TraCIDataType;
import org.vadere.manager.traci.commandHandler.annotation.SimulationHandler;
import org.vadere.manager.traci.commandHandler.annotation.SimulationHandlers;
import org.vadere.manager.traci.commandHandler.variables.SimulationVar;
......@@ -16,16 +12,20 @@ import org.vadere.manager.traci.commands.TraCIGetCommand;
import org.vadere.manager.traci.commands.TraCISetCommand;
import org.vadere.manager.traci.commands.get.TraCIGetCacheHashCommand;
import org.vadere.manager.traci.commands.get.TraCIGetCompoundPayload;
import org.vadere.state.traci.CompoundObject;
import org.vadere.manager.traci.compound.object.CoordRef;
import org.vadere.manager.traci.compound.object.PointConverter;
import org.vadere.manager.traci.compound.object.SimulationCfg;
import org.vadere.manager.traci.response.TraCIGetResponse;
import org.vadere.simulator.control.external.models.ControlModel;
import org.vadere.simulator.control.external.models.ControlModelBuilder;
import org.vadere.simulator.control.external.models.IControlModel;
import org.vadere.simulator.control.external.reaction.ReactionModel;
import org.vadere.simulator.entrypoints.ScenarioFactory;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.utils.cache.ScenarioCache;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.ReferenceCoordinateSystem;
import org.vadere.state.traci.*;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.logging.Logger;
......@@ -34,10 +34,7 @@ import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
/**
......@@ -66,6 +63,7 @@ public class SimulationCommandHandler extends CommandHandler<SimulationVar> {
private Pair<Double, Set<Integer>> allPrevious; // time at witch the given ids were send over traci
private Pair<Double, List<String>> departedCache; // time at witch the given ids were send over traci
private Pair<Double, List<String>> arrivedCache; // time at witch the given ids were send over traci
private HashMap<String, IControlModel> iControlModelHashMap;
static {
instance = new SimulationCommandHandler();
......@@ -77,6 +75,7 @@ public class SimulationCommandHandler extends CommandHandler<SimulationVar> {
allPrevious = Pair.create(-1.0, new HashSet<>()); // never called.
departedCache = Pair.create(-1.0, new ArrayList<>());
arrivedCache = Pair.create(-1.0, new ArrayList<>());
iControlModelHashMap = new HashMap<>();
}
@Override
......@@ -165,8 +164,84 @@ public class SimulationCommandHandler extends CommandHandler<SimulationVar> {
});
return cmd;
}
@SimulationHandler(cmd = TraCICmd.SET_SIMULATION_STATE, var = SimulationVar.EXTERNAL_INPUT_INIT,
name = "init_control", ignoreElementId = true )
public TraCICommand process_init_control(TraCISetCommand cmd, RemoteManager remoteManager) {
String controlModelName, controlModelType;
String reactionModelParameter;
try {
CompoundObject cfg = (CompoundObject) cmd.getVariableValue();
controlModelName = (String) cfg.getData(0, TraCIDataType.STRING);
controlModelType = (String) cfg.getData(1, TraCIDataType.STRING);
reactionModelParameter = (String) cfg.getData(2, TraCIDataType.STRING);
ReactionModel reactionModel = new ReactionModel(reactionModelParameter);
if (!iControlModelHashMap.containsKey(controlModelName)) {
IControlModel controlModel = ControlModelBuilder.getModel(controlModelType);
controlModel.setReactionModel(reactionModel);
iControlModelHashMap.put(controlModelName, controlModel);
}
logger.infof("Received ControlInitCommand:");
logger.infof(cfg.toString());
cmd.setOK();
} catch (TraCIException e) {
logger.errorf("cannot parse ControlInitCommand object. Err: %s", e.getMessage());
cmd.setErr(String.format("cannot parse ControlInitCommand object. Err: %s", e.getMessage()));
}
return cmd;
}
@SimulationHandler(cmd = TraCICmd.SET_SIMULATION_STATE, var = SimulationVar.EXTERNAL_INPUT,
name = "apply_control", ignoreElementId = true )
public TraCICommand process_apply_control(TraCISetCommand cmd, RemoteManager remoteManager) {
int packet_size, specify_id;
String msg_content, model_name;
try {
CompoundObject cfg = (CompoundObject) cmd.getVariableValue();
//remoteManager.setSimCfg(cfg);
packet_size = (int) cfg.getData(0,TraCIDataType.INTEGER);
specify_id = Integer.parseInt((String) cfg.getData(1,TraCIDataType.STRING));
model_name = (String) cfg.getData(2,TraCIDataType.STRING);
msg_content = (String) cfg.getData(3,TraCIDataType.STRING);
if (!iControlModelHashMap.containsKey(model_name)) {
logger.infof("Model" + model_name + " not found. Try to initialize from model name.");
IControlModel controlModel = ControlModelBuilder.getModel(model_name);
iControlModelHashMap.put(model_name, controlModel);
}
IControlModel controlModel = iControlModelHashMap.get(model_name);
remoteManager.accessState((manager, state) -> {
int i;
controlModel.update(state.getScenarioStore().getTopography(), state.getSimTimeInSec(), msg_content, specify_id);
});
logger.infof("Received ControlCommand:");
logger.infof(cfg.toString());
cmd.setOK();
} catch (TraCIException ex) {
logger.errorf("cannot parse ControlCommand object. Err: %s", ex.getMessage());
cmd.setErr(String.format("cannot parse ControlCommand object. Err: %s", ex.getMessage()));
}
return cmd;
}
@SimulationHandler(cmd = TraCICmd.SET_SIMULATION_STATE, var = SimulationVar.SIM_CONFIG,
name = "setSimConfig", ignoreElementId = true)
......
......@@ -35,7 +35,7 @@ public enum PersonVar {
VEHICLE(0xc3, TraCIDataType.STRING), // get
ADD(0x80, TraCIDataType.STRING),
REMOVE_STAGE(0xc5, TraCIDataType.INTEGER), // set
TARGET_LIST(0xfe, TraCIDataType.STRING_LIST), // get, set
TARGET_LIST(0xfe, TraCIDataType.STRING_LIST), // get, set
INFORMATION_ITEM(0xfd, TraCIDataType.COMPOUND_OBJECT)
;
......
......@@ -27,6 +27,8 @@ public enum SimulationVar {
CACHE_HASH(0x7d, TraCIDataType.STRING),
SIM_CONFIG(0x7e, TraCIDataType.COMPOUND_OBJECT),
DATA_PROCESSOR(0x7f, TraCIDataType.COMPOUND_OBJECT),
EXTERNAL_INPUT(0x20, TraCIDataType.COMPOUND_OBJECT),
EXTERNAL_INPUT_INIT(0x21, TraCIDataType.COMPOUND_OBJECT),
;
public int id;
......
package org.vadere.manager.traci.commandHandler;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.vadere.manager.RemoteManager;
import org.vadere.manager.TestRemoteManager;
import org.vadere.manager.traci.TraCICmd;
import org.vadere.manager.traci.commandHandler.variables.PersonVar;
import org.vadere.manager.traci.commands.TraCISetCommand;
import org.vadere.manager.traci.commands.get.TraCIGetCompoundPayload;
import org.vadere.state.attributes.scenario.AttributesAgent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.state.traci.CompoundObject;
import org.vadere.state.traci.CompoundObjectBuilder;
import org.vadere.state.traci.TraCIDataType;
import org.vadere.manager.traci.commandHandler.variables.SimulationVar;
import org.vadere.manager.traci.commands.TraCICommand;
import org.vadere.manager.traci.commands.TraCIGetCommand;
import org.vadere.manager.traci.commands.get.TraCIGetCacheHashCommand;
import org.vadere.state.traci.TraCIException;
import org.vadere.util.io.IOUtils;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
......@@ -94,4 +110,49 @@ public class SimulationCommandHandlerTest extends CommandHandlerTest {
testGetValue(ret, varID, varType, elementID, retVal);
}
@Test
public void process_apply_control() {
SimulationVar var = SimulationVar.EXTERNAL_INPUT;
int varID = var.id;
TraCIDataType varType = var.type;
String elementID = "-1";
// set up control command
CompoundObject data = CompoundObjectBuilder.builder()
.add(TraCIDataType.INTEGER) // packet size
.add(TraCIDataType.STRING) // sending node
.add(TraCIDataType.STRING) // model name
.add(TraCIDataType.STRING) // command
.build(-1, "10", "RouteChoice" , "{'time': 8.0}");
TraCISetCommand cmd = (TraCISetCommand) getFirstCommand(TraCISetCommand.build(
TraCICmd.SET_SIMULATION_STATE, elementID, varID, varType, data));
Pedestrian p = new Pedestrian(new AttributesAgent(10), new Random(1));
RemoteManager rm = new TestRemoteManager() {
@Override
protected void mockIt() {
Topography topo = mock(Topography.class, Mockito.RETURNS_DEEP_STUBS);
Pedestrian pedEl1 = new Pedestrian(new AttributesAgent(), new Random());
LinkedList<Integer> t = new LinkedList<>();
t.add(1);
pedEl1.setTargets(t);
when(topo.getPedestrianDynamicElements().getElement(0)).thenReturn(pedEl1);
when(simState.getSimTimeInSec()).thenReturn(4.0);
}
};
try {
TraCICommand ret = simCmdHandler.process_apply_control(cmd, rm);
fail();
} catch (Exception e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
package org.vadere.simulator.control.external.models;
import org.json.JSONObject;
import org.vadere.simulator.control.external.reaction.ReactionModel;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.util.logging.Logger;
import rx.Subscription;
import java.util.LinkedList;
import java.util.stream.Collectors;
public abstract class ControlModel implements IControlModel {
public static Logger logger = Logger.getLogger(Subscription.class);
public Topography topography;
public Double simTime;
private CtlCommand command;
protected ReactionModel reactionModel;
public ControlModel(){
simTime = 0.0;
this.reactionModel = new ReactionModel();
}
public ControlModel(ReactionModel reactionModel){
simTime = 0.0;
this.reactionModel = reactionModel;
}
public abstract void applyPedControl(Pedestrian ped, JSONObject command);
public void update(Topography topo, Double time, String commandStr, Integer pedId) {
topography = topo;
simTime = time;
command = new CtlCommand(commandStr);
for (int i : get_pedIds(pedId)){
Pedestrian ped = topography.getPedestrianDynamicElements().getElement(i);
if (isInfoInTime() && isPedInDefinedArea(ped)){
this.applyPedControl(ped, command.getPedCommand());
this.setAction(ped);
}
}
}
public void update(Topography topography, Double time, String command) {
update(topography,time,command,-1);
}
private LinkedList<Integer> get_pedIds(Integer pedId)
{
LinkedList<Integer> pedIds = new LinkedList<>();
if (pedId == -1){
pedIds.addAll(topography.getPedestrianDynamicElements().getElements().stream().map(Pedestrian::getId).collect(Collectors.toList()));
}
else{
pedIds.add(pedId);
}
return pedIds;
}
boolean isPedInDefinedArea(Pedestrian ped) {
if (command.isSpaceBounded()) {
return command.getSpace().contains(ped.getPosition());
}
else{
return true;
}
}
boolean isInfoInTime(){
return command.getExecTime() >= simTime;
}
public abstract boolean isPedReact();
public void setAction(Pedestrian ped){
if (isPedReact()){
triggerRedRaction(ped);
}
}
protected abstract void triggerRedRaction(Pedestrian ped);
public void setReactionModel(ReactionModel reactionModel){
this.reactionModel = reactionModel;
}
}
package org.vadere.simulator.control.external.models;
import org.vadere.simulator.control.psychology.cognition.models.ICognitionModel;
import org.vadere.util.reflection.DynamicClassInstantiator;
/**
* This class encapsulates the creation of a concrete {@link ControlModel}
* defined and updated by an external control unit handled by TraCI.
*
* The user provides the simple class name, no fully qualified classname.
*/
public class ControlModelBuilder {
public static final String MODEL_CONTAINER = ".";
public static IControlModel getModel(String ClassName) {
String classSearchPath = ControlModel.class.getPackageName();
String fullyQualifiedClassName = classSearchPath + MODEL_CONTAINER + ClassName;
DynamicClassInstantiator<ICognitionModel> instantiator = new DynamicClassInstantiator<>();
IControlModel controlModel = (IControlModel) instantiator.createObject(fullyQualifiedClassName);
return controlModel;
}
}
\ No newline at end of file
package org.vadere.simulator.control.external.models;
import org.json.JSONException;
import org.json.JSONObject;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VShape;
public class CtlCommand {
JSONObject rawCommand;
VCircle space;
Double time;
JSONObject pedCommand;
public CtlCommand(JSONObject command){
rawCommand = command;
};
public CtlCommand(String command){
rawCommand = new JSONObject(command);
};
public String getModelName(){
return rawCommand.getString("model");
}
public double getExecTime(){
double time = Double.POSITIVE_INFINITY;
try {
time = rawCommand.getDouble("time");
} catch (JSONException e) {
e.printStackTrace();
}
return time;
}
public VCircle getSpace(){
// only radius
VShape shape;
double x = 0;
double y = 0;
double radius = 0;
try {
JSONObject space = rawCommand.getJSONObject("space");
x = space.getDouble("x");
y = space.getDouble("y");
radius = space.getDouble("radius");
if (radius>=0) {
this.space = new VCircle(x, y, radius);
}
} catch (JSONException e) {
e.printStackTrace();
}
return this.space;
}
public boolean isSpaceBounded(){
return (getSpace() != null);
}
public JSONObject getPedCommand(){
try{
pedCommand = rawCommand.getJSONObject("command");
} catch (JSONException e) {
e.printStackTrace();
}
return pedCommand;
}
}
package org.vadere.simulator.control.external.models;
import org.vadere.simulator.control.external.reaction.ReactionModel;
import org.vadere.state.scenario.Topography;
/**
* This class encapsulates the creation of a concrete {@link IControlModel}
* which is defined by the user in the crowd guidance simulator over TraCI.
*
* The user provides the simple class name.
* I.e., no fully qualified classname.
*/
public interface IControlModel {
void update(Topography topo, Double time, String commandStr, Integer pedId);
void update(Topography topography, Double time, String command);
void setReactionModel(ReactionModel reactionModel);
}
package org.vadere.simulator.control.external.models;
import org.apache.commons.math3.distribution.EnumeratedIntegerDistribution;
import org.apache.commons.math3.random.JDKRandomGenerator;
import org.apache.commons.math3.random.RandomGenerator;
import org.json.JSONArray;
import org.json.JSONObject;
import org.vadere.simulator.control.external.reaction.ReactionModel;
import org.vadere.state.scenario.Pedestrian;
import java.util.LinkedList;
import java.util.Random;