Commit f9cbb1b6 authored by Stefan Schuhbaeck's avatar Stefan Schuhbaeck
Browse files

Merge branch 'controller' into 'master'

Controller

See merge request !153
parents 3aaac6d8 00f626d2
Pipeline #434715 passed with stages
in 126 minutes and 26 seconds
{
"name" : "mf_base",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "mf_detailed",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "mf_underground",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "roVerTest001",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "roVerTest002",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "scenario001",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "scenario002",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
{
"name" : "separation_slow_fast",
"description" : "",
"release" : "1.12",
"release" : "1.15",
"processWriters" : {
"files" : [ {
"type" : "org.vadere.simulator.projects.dataprocessing.outputfile.EventtimePedestrianIdOutputFile",
......
......@@ -23,7 +23,9 @@ import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypeException;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
@SupportedAnnotationTypes("org.vadere.annotation.traci.client.TraCIApi")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
......@@ -58,14 +60,34 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
if (annotatedElements.isEmpty())
continue;
StringBuilder pythonConstants = new StringBuilder();
for (Element annotatedElement : annotatedElements) {
try {
writeApiClass(annotatedElement);
writePythonBinding(annotatedElement, pythonConstants);
} catch (IOException e) {
e.printStackTrace();
}
}
String fileName = "pythonapi/VadereConstants.py";
try {
FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", fileName);
try (PrintWriter w = new PrintWriter(file.openWriter())) {
w.println("#");
w.println("# Generated source file. DO NOT CHANGE!");
w.println("");
w.println("from . constants import *");
w.println("from . vadere_vars import *");
w.println("");
w.append(pythonConstants.toString());
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
TypeElement element = processingEnv.getElementUtils().
......@@ -104,6 +126,130 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
}
private String qq(String s){
return "\"" + s + "\"";
}
private String q(String s){
return "'" + s + "'";
}
private String t(int i){
return " ".repeat(i*4);
}
private void writePythonBinding(Element apiClass, StringBuilder pythonConstants) throws IOException {
TraCiApiWrapper traCIApi = new TraCiApiWrapper(apiClass);
String fileName = "pythonapi/Vadere" + traCIApi.name + ".py";
FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", fileName);
pythonConstants.append("# Command constants for Vadere").append(traCIApi.name).append("\n");
pythonConstants.append(traCIApi.cmdGetVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdGet)).append("\n");
pythonConstants.append(traCIApi.cmdResponseGetVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdResponseGet)).append("\n");
pythonConstants.append(traCIApi.cmdSetVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdSet)).append("\n");
pythonConstants.append(traCIApi.cmdSubVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdSub)).append("\n");
pythonConstants.append(traCIApi.cmdResponseSubVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdResponseSub)).append("\n");
pythonConstants.append(traCIApi.cmdCtxVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdCtx)).append("\n");
pythonConstants.append(traCIApi.cmdResponseCtxVarName).append(" = 0x").append(Integer.toHexString(traCIApi.cmdResponseCtx)).append("\n\n");
try (PrintWriter w = new PrintWriter(file.openWriter())) {
w.println("#");
w.println("# Generated source file. DO NOT CHANGE!");
w.println("");
w.println("from .domain import Domain");
w.println("from . import VadereConstants as tc");
w.println("\n");
w.println("class Vadere" + traCIApi.name + "(Domain):");
w.println(t(1) + "def __init__(self):");
w.append(t(2)).append("Domain.__init__(self, ").append(qq(traCIApi.domainName)).append(",")
.append("tc.").append(traCIApi.cmdGetVarName).append(", tc.").append(traCIApi.cmdSetVarName).append(", \n").append(t(8))
.append("tc.").append(traCIApi.cmdSubVarName).append(", tc.").append(traCIApi.cmdResponseSubVarName).append(", \n").append(t(8))
.append("tc.").append(traCIApi.cmdCtxVarName).append(", tc.").append(traCIApi.cmdResponseCtxVarName).append(")\n\n");
for (Element element : apiClass.getEnclosedElements()) {
List<? extends AnnotationMirror> anMirrors = element.getAnnotationMirrors();
if (anMirrors != null){
for (AnnotationMirror anMirror : anMirrors) {
String anName = anMirror.getAnnotationType().asElement().getSimpleName().toString();
String singeAn = traCIApi.singleAnnotation
.substring(traCIApi.singleAnnotation.lastIndexOf(".") + 1).trim();
if (anName.equals(singeAn)){
ApiHandler apiHandler = new ApiHandler(traCIApi, element, anMirror);
switch (apiHandler.apiType){
case "GET":
writePythonGET(w, apiHandler);
break;
case "SET":
writePythonSET(w, apiHandler);
break;
}
}
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void writePythonGET(PrintWriter w, ApiHandler apiHandler) {
if (apiHandler.dataTypeStr.isEmpty()){
// standard GET command without additional data
if (apiHandler.ignoreElementId){
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self):").println();
w.append(t(2)).append("return self._getUniversal(").append(apiHandler.varIdPython).append(", ").append(qq("")).append(")").println();
}
else {
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self, element_id):").println();
w.append(t(2)).append("return self._getUniversal(").append(apiHandler.varIdPython).append(", element_id)").println();
}
} else {
// extended GET command which accepts any kind of data based on the standard traci data types
if (apiHandler.ignoreElementId){
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self, data):").println();
w.append(t(2)).append("return self._getUniversal(").append(apiHandler.varIdPython).append(", ").append(qq("")).append(", data)").println();
} else {
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self, element_id, data):").println();
w.append(t(2)).append("return self._getUniversal(").append(apiHandler.varIdPython).append(", element_id, data)").println();
}
}
w.println();
}
private void writePythonSET(PrintWriter w, ApiHandler apiHandler) {
if (apiHandler.ignoreElementId) {
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self");
if (apiHandler.dataTypeStr.length() > 0){
w.append(", data");
}
w.append("):").println();
w.append(t(2)).append("self._setCmd(").append(apiHandler.varIdPython).append(", ").append(qq("")).append(", ").append(qq(apiHandler.dataTypeStrPython()));
if (apiHandler.dataTypeStr.length() > 0){
w.append(", data)");
} else {
w.append(", None)");
}
} else {
w.append(t(1)).append("def ").append(apiHandler.namePython).append("(self, element_id");
if (apiHandler.dataTypeStr.length() > 0){
w.append(", data");
}
w.append("):").println();
w.append(t(2)).append("self._setCmd(").append(apiHandler.varIdPython).append(", element_id").append(", ").append(qq(apiHandler.dataTypeStrPython()));
if (apiHandler.dataTypeStr.length() > 0){
w.append(", data)");
} else {
w.append(", None)");
}
}
w.println();
w.println();
}
protected void writeApiClass(Element apiClass) throws IOException {
TraCiApiWrapper traCIApi = new TraCiApiWrapper(apiClass);
JavaFileObject jFile = processingEnv.getFiler().createSourceFile(traCIApi.name);
......@@ -226,6 +372,7 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
class TraCiApiWrapper {
String name;
String nameShort;
String domainName;
String singleAnnotation;
String multipleAnnotation;
String cmdEnum;
......@@ -233,6 +380,23 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
String packageName;
String[] imports;
String extendedClassName;
String varShort;
int cmdGet;
int cmdResponseGet;
int cmdSet; // no Response needed.
int cmdSub;
int cmdResponseSub;
int cmdCtx;
int cmdResponseCtx;
String varName;
String cmdGetVarName;
String cmdResponseGetVarName;
String cmdSetVarName; // no Response needed.
String cmdSubVarName;
String cmdResponseSubVarName;
String cmdCtxVarName;
String cmdResponseCtxVarName;
TraCiApiWrapper(Element apiClass){
TraCIApi traCIApi = apiClass.getAnnotation(TraCIApi.class);
......@@ -241,10 +405,29 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
name = traCIApi.name();
nameShort = traCIApi.nameShort();
nameShort = nameShort.isEmpty() ? name : nameShort;
domainName = "v_" + name.substring(0, name.length()-3).toLowerCase();
packageName = traCIApi.packageName();
imports = traCIApi.imports();
extendedClassName = traCIApi.extendedClassName();
cmdGet = traCIApi.cmdGet();
cmdResponseGet = cmdGet + 16;
cmdSet = traCIApi.cmdSet();
cmdSub = traCIApi.cmdSub();
cmdResponseSub = traCIApi.cmdResponseSub();
cmdCtx = traCIApi.cmdCtx();
cmdResponseCtx = traCIApi.cmdResponseCtx();
varName = traCIApi.var();
cmdGetVarName = "CMD_GET_" + varName + "_VARIABLE";
cmdResponseGetVarName= "RESPONSE_GET_" + varName + "_VARIABLE";
cmdSetVarName = "CMD_SET_" + varName + "_VARIABLE";
cmdSubVarName = "CMD_SUBSCRIBE_" + varName + "_VARIABLE";
cmdResponseSubVarName = "RESPONSE_SUBSCRIBE_" + varName + "_VARIABLE";
cmdCtxVarName = "CMD_SUBSCRIBE_" + varName + "_CONTEXT";
cmdResponseCtxVarName = "RESPONSE_SUBSCRIBE_" + varName + "_CONTEXT";
try {
singleAnnotation = traCIApi.singleAnnotation().getCanonicalName();
} catch (MirroredTypeException e){
......@@ -275,8 +458,10 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
String cmd;
String varId;
String varIdPython;
String varType;
String name;
String namePython;
String dataTypeStr;
boolean ignoreElementId;
String apiType; //SET, GET, SUB
......@@ -301,10 +486,12 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
break;
case "var":
this.varId = varPrefix + "." + value.toString() + ".id";
this.varIdPython = "tc.VAR_" + value.toString();
this.varType = varPrefix + "." + value.toString() + ".type";
break;
case "name":
this.name = (String) value;
this.namePython = toSnakeCase(this.name);
break;
case "ignoreElementId":
this.ignoreElementId = (boolean) value;
......@@ -315,6 +502,44 @@ public class ClientAnnotationProcessor extends AbstractProcessor {
}
}
private String toSnakeCase(String input){
StringBuilder out = new StringBuilder();
boolean firstUpper = true;
for (int i = 0; i < input.length(); i++){
char ch = input.charAt(i);
if (Character.isUpperCase(ch)){
if (firstUpper) {
out.append('_');
}
out.append(Character.toLowerCase(ch));
firstUpper = false;
} else {
out.append(ch);
firstUpper = true;
}
}
return out.toString();
}
public String dataTypeStrPython(){
switch (dataTypeStr) {
case "Double":
return "d";
case "Integer":
return "i";
case "String":
return "s";
case "ArrayList<String>":
return "l";
case "ArrayList<Double>":
return "f";
case "VPoint":
return "o";
}
return "Error";
}
@Override
public String toString() {
return "ApiHandler{" +
......
......@@ -30,4 +30,11 @@ public @interface TraCIApi {
Class multipleAnnotation();
Class cmdEnum();
Class varEnum();
String var();
int cmdGet();
int cmdSet();
int cmdSub();
int cmdResponseSub();
int cmdCtx();
int cmdResponseCtx();
}
......@@ -22,6 +22,7 @@ public class ClientHandler implements Runnable {
private final TraCISocket traCISocket;
private CommandExecutor cmdExecutor;
private RemoteManager remoteManager;
private String scenarioString;
public ClientHandler(ServerSocket serverSocket, TraCISocket traCISocket, Path basedir, boolean guiSupport) {
......@@ -29,12 +30,21 @@ public class ClientHandler implements Runnable {
this.traCISocket = traCISocket;
this.remoteManager = new RemoteManager(basedir, guiSupport);
this.cmdExecutor = new CommandExecutor(remoteManager);
this.scenarioString = ""; // traci will provide the scenario
}
public void setScenario(String scenarioString) {
this.scenarioString = scenarioString;
}
@Override
public void run() {
try {
if (!scenarioString.equals("")){
// scenario provided in command line. Load it and then wait for traci commands
remoteManager.loadScenario(this.scenarioString);
remoteManager.startSimulation();
}
handleClient();
} catch (EOFException eof) {
logger.infof("EOF. Client closed socket");
......
package org.vadere.manager;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.Namespace;
......@@ -35,7 +34,7 @@ public class Manager {
logger.infof("Start Server(%s) with Loglevel: %s", VadereServer.currentVersion.getVersionString(), logger.getLevel().toString());
AbstractVadereServer server;
if (ns.getBoolean("singleClient")) {
server = new VadereSingleClientServer(serverSocket, Paths.get(ns.getString("output-dir")), ns.getBoolean("guiMode"), ns.getBoolean("trace"));
server = new VadereSingleClientServer(serverSocket, Paths.get(ns.getString("output-dir")), ns.getBoolean("guiMode"), ns.getBoolean("trace"), ns.getString("scenario"));
} else {
ExecutorService pool = Executors.newFixedThreadPool(ns.getInt("clientNum"));
server = new VadereServer(serverSocket, pool, Paths.get(ns.getString("output-dir")), ns.getBoolean("guiMode"), ns.getBoolean("trace"));
......@@ -130,5 +129,11 @@ public class Manager {
.dest("output-dir") // set name in namespace
.type(String.class)
.help("Supply output directory as base directory for received scenarios.");
parser.addArgument("--scenario")
.required(false)
.dest("scenario") // set name in namespace
.type(String.class)
.help("Supply path to scenario. This will start this scenario and waits for first simstep command");
}
}
......@@ -8,6 +8,8 @@ import org.vadere.simulator.entrypoints.ScenarioFactory;
import org.vadere.simulator.projects.RunnableFinishedListener;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.utils.cache.ScenarioCache;
import org.vadere.state.traci.TraCIException;
import org.vadere.state.traci.TraCIExceptionInternal;
import org.vadere.util.io.IOUtils;
import org.vadere.util.logging.Logger;
......
......@@ -6,6 +6,7 @@ import org.vadere.simulator.control.simulation.ScenarioRun;
import org.vadere.simulator.projects.RunnableFinishedListener;
import org.vadere.simulator.projects.Scenario;
import org.vadere.simulator.utils.cache.ScenarioCache;
import org.vadere.state.traci.TraCIException;
import java.nio.file.Path;
import java.util.List;
......
......@@ -13,6 +13,12 @@ import org.vadere.util.logging.Logger;
import java.util.Arrays;
/**
* Wrapper around a given TraCIValueSubscriptionCommand to execute the
* subscription
* todo: merge multiple subscription so no unnecessary duplicates are send send
*/
public class Subscription {
private static Logger logger = Logger.getLogger(Subscription.class);
......@@ -30,6 +36,13 @@ public class Subscription {
}
public void executeSubscription(RemoteManager remoteManager) {
// todo check if subscription is still valid.
// markForRemoval();
// if (markedForRemoval){
// return;
// }
TraCISubscriptionResponse subResponse = new TraCISubscriptionResponse(
new StatusResponse(valueSubscriptionCommand.getTraCICmd(), TraCIStatusResponse.OK, ""),
responseIdentifier, valueSubscriptionCommand.getElementIdentifier(), valueSubscriptionCommand.getNumberOfVariables());
......@@ -62,6 +75,12 @@ public class Subscription {
}
}
public void markIfOld(double simTime){
if (this.valueSubscriptionCommand.getEndTime() >= simTime){
markForRemoval();
}
}
public void markForRemoval() {
this.markedForRemoval = true;
}
......
......@@ -222,8 +222,8 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
// personapi
@Override
public void personapi_getIDList(String[] args) throws IOException {
TraCIResponse res = personapi.getIDList();
public void personapi_getIdList(String[] args) throws IOException {
TraCIResponse res = personapi.getIdList();
printGet(res);
}
......@@ -258,8 +258,8 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
}
@Override
public void personapi_getIDCount(String[] args) throws IOException {
TraCIResponse res = personapi.getIDCount();
public void personapi_getIdCount(String[] args) throws IOException {
TraCIResponse res = personapi.getIdCount();
printGet(res);
}
......@@ -624,6 +624,11 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
System.out.println(res.toString());
}
@Override
public void simulationapi_getDataProcessorValue(String[] args) throws IOException {
}
@Override
public void simulationapi_getNetworkBound(String[] args) throws IOException {
......@@ -632,7 +637,7 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
// vadere api
@Override
public void vadereapi_addStimulusInfos(String[] args) throws IOException {
public void miscapi_addStimulusInfos(String[] args) throws IOException {
if (args.length < 2) {
System.out.println("command needs argument json file");
}
......@@ -644,18 +649,18 @@ public class TestClient extends org.vadere.manager.client.AbstractTestClient imp
} catch (IOException e) {
e.printStackTrace();
}
TraCIResponse res = vadereapi.addStimulusInfos(data);
TraCIResponse res = miscapi.addStimulusInfos(data);
System.out.println(res.toString());
}
@Override
public void vadereapi_getAllStimulusInfos(String[] args) throws IOException {
TraCIResponse res = vadereapi.getAllStimulusInfos();
public void miscapi_getAllStimulusInfos(String[] args) throws IOException {
TraCIResponse res = miscapi.getAllStimulusInfos();
System.out.println(res.toString());
}