Commit dd62dfb7 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

Merge branch 'master' of

parents 96414568 d4ec9665
......@@ -44,6 +44,7 @@ VadereModelCalibration/**/output
# Operating system files
......@@ -53,3 +54,7 @@ VadereModelTests/*_private
# Vadere Cache
\ No newline at end of file
......@@ -25,6 +25,7 @@ variables:
# Stage Definitions
# Watch out: integration tests and the seed tests run after deployment, because
......@@ -81,6 +82,8 @@ stages:
- mvn -Dmaven.test.skip=true package
- python3 -m zipfile -c ${VADERE_PACKAGE_NAME_BRANCHES} VadereModelTests/ VadereGui/target/vadere-gui.jar VadereSimulator/target/vadere-console.jar
- python3 -m zipfile -c ${EIKMESH_PACKAGE_NAME_BRANCHES} VadereMeshing/ VadereMeshing/target/meshing-0.1-SNAPSHOT.jar
- master
......@@ -6,15 +6,46 @@
### Added
- single step mode in GUI: Allows the user to step through the simulation one
### Changed
## v1.2 (2019-07-13)
### Added
- VadereServer:
- Introducing TraCI server implementation for Vadere to allow remote control
of Vaderes simulation loop.
- VadereManager/target/vadere-server.jar will open a TCP socket and waits
for connection request.
- FloorField Caching:
- CellGrid based floorfields can be loaded from a persisted cache file.
- Added attributes:
- `cacheDir: ""` relative path
- Cache files will be saved in a `__cache__` directory beside (sibling) the
scenario file. With `cacheDir` it is possible to create some structure within
the cache directory. Important: If `cacheDir` is an absolute path the cache
file will not be placed in `__cache__`.
- A TXT_CACHE type will save the CellGrid in a human readable form (CSV) and
BIN_CACHE will use a simple binary format for better performance and space
- TikzGenerator:
- add configuration to show all traces of pedestrians, even if they
left the simulation. Config: PostVis -> `Show all Trajectories on Snapshot`
- add named coordinate for each scenario element. The coordinate represents the
centroid point of the polygon and can be used as a point for relative placement
of labels.
- introduced id for reference: Source `src_XXX`, Target `trg_XXX`, AbsorbingArea `absorb_XXX`
Obstacels `obs_XXX`, Stairs `str_XXX`, MeasurementArea `mrmtA_XXX`
- single step mode in GUI: Allows the user to step through the simulation one
step at a time to identify bugs.
- simplify obstacles (with undo support): Merge multiple obstacles based on the
- simplify obstacles (with undo support): Merge multiple obstacles based on the
convex hull their points create. The merge can be undon
- add features to open street map (osm) importer:
- add features to open street map (osm) importer:
- import 'open' paths as polygons with a specified width. With this it is
possible to create walls or subway entrance
- add option to include osm ids into each obstacle created
`PostVis` added functionalities:
- the PostVis works now on the basis of simulation time instead of time steps. Agents' position will be interpolated.
- the user can jump to a specific simulation time
......@@ -24,6 +55,11 @@
### Changed
- version migration ensures that new attributes in the scenario file will be added
with default values if no specific actions are defined in a Transformation class.
- TikzGenerator: style information for pedestrians are moved to dedicated style
classes to simplify changes in generated tikz files.
## v1.0 (2019-06-13)
### Added
......@@ -56,7 +92,7 @@
- `VadereConsole`: Add option `--logname <filename>` to specify the name for the log file.
Please note that the log file `log.out` is always written (because this file is configured
in the `` of each Vadere module (i.e., "gui", "meshing", ...). (c61a3946: Simulator)
- New outputprocessors
- New outputprocessors
* mainly for the BHM: QueueWidthProcessor (to evaluate queueWidth) and PedestrianBehaviorProcessor (evaluate behavior: step / tangential step / sideways step / wait)
* solely for the OSM: PedestrianFootStepProcessor (logs every step instead of the positions at each time step )
......@@ -84,7 +120,7 @@
- `GUI`:
- improved coloring
- `OutputFile`: Distinguish between indices (rows) and headers (columns), in code and with a new checkbox that when enables allow to write meta-data into output files. Furthermore, resolve naming conflicts (if they occur) in headers of output files (see #201).
- `OutputFile`: Distinguish between indices (rows) and headers (columns), in code and with a new checkbox that when enables allow to write meta-data into output files. Furthermore, resolve naming conflicts (if they occur) in headers of output files (see #201).
### Changed
......@@ -95,7 +131,7 @@
- Header in output file have now the following form "[NAME]-PID[ID]". This avoids name conflicts and makes mapping to the relevant processor easy and fast.
- Migration to Java 11 (OpenJDK).
- Removed directory `Documentation/version-control` which contained the Git hooks. The Git hooks are not required anymore. Instead, added `git rev-parse HEAD` to file `VadereSimulator/pom.xml` to create `VadereSimulator/resources/current_commit_hash.txt` during each build via `mvn compile`.
**Note:** The file `current_commit_hash.txt` is created during Maven's validation phase, i.e., before the actual build.
**Note:** The file `current_commit_hash.txt` is created during Maven's validation phase, i.e., before the actual build.
## v0.6 (2018-09-07)
package org.vadere.annotation.traci.client;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypeException;
public class ClientAnnotationProcessor extends AbstractProcessor {
private StringBuilder apiMembers;
private StringBuilder apiInit;
private StringBuilder apiMapping;
private StringBuilder apiAbstract;
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
apiMembers = new StringBuilder();
apiInit = new StringBuilder();
apiMapping = new StringBuilder();
apiAbstract = new StringBuilder();
// see SupportedAnnotationTypes (here only TraCIApi)
for (TypeElement annotation : annotations) {
Set<? extends Element> annotatedElements =
.filter(e -> e.getKind().isClass()
&& !e.getKind().equals(ElementKind.ENUM)
&& !e.getModifiers().contains(Modifier.ABSTRACT)
if (annotatedElements.isEmpty())
for (Element annotatedElement : annotatedElements) {
try {
} catch (IOException e) {
try {
TypeElement element = processingEnv.getElementUtils().
if (element == null)
} catch (IOException e) {
return true;
protected void writeAbstractTestClient() throws IOException {
JavaFileObject jFile = processingEnv.getFiler().createSourceFile("AbstractTestClient");
try (PrintWriter writer = new PrintWriter(jFile.openWriter())){
writer.append("package org.vadere.manager.client; ").println();
writer.append("import org.vadere.manager.TraCISocket;").println();
writer.append("import org.vadere.manager.client.ConsoleReader;").println();
writer.append("public abstract class AbstractTestClient {").println();
writer.append("\tpublic AbstractTestClient() { }").println();
writer.append("\tpublic void init(TraCISocket socket, ConsoleReader consoleReader){").println();
protected void writeApiClass(Element apiClass) throws IOException {
TraCiApiWrapper traCIApi = new TraCiApiWrapper(apiClass);
JavaFileObject jFile = processingEnv.getFiler().createSourceFile(;
apiMembers.append(String.format("\tprotected %s.%s %s;\n", traCIApi.packageName,,;
apiInit.append(String.format("\t\t%s = new %s.%s(socket);\n",, traCIApi.packageName,;
try (PrintWriter writer = new PrintWriter(jFile.openWriter())){
writer.append("package ").append(traCIApi.packageName).append(";").println();
for (String anImport : traCIApi.imports) {
writer.append("import ").append(anImport).append(";").println();
writer.append("import ").append(traCIApi.cmdEnum).append(";").println();
writer.append("import ").append(traCIApi.varEnum).append(";").println();
// start API class
writer.append("public class ").append(" extends ")
.append(traCIApi.extendedClassName).append(" {").println();
// constructor
writer.append("\tpublic ").append("(TraCISocket socket) {").println();
writer.append("\t\tsuper(socket, \"").append("\");").println();
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);
apiMapping.append(String.format("\t\tconsoleReader.addCommand(\"%s.%s\", \"\", this::%s_%s);\n",,,,;
apiAbstract.append(String.format("\t\tabstract public void %s_%s (String args[]) throws IOException;\n",,;
switch (apiHandler.apiType){
case "GET":
writeGET(writer, apiHandler);
case "SET":
writeSET(writer, apiHandler);
writer.append("}").println(); // end API class
protected void writeGET(PrintWriter writer, ApiHandler apiHandler){
if (apiHandler.ignoreElementId){
writer.append("\tpublic TraCIGetResponse ").append("() throws IOException {").println();
writer.append("\t\tTraCIPacket p =").append(apiHandler.cmd).append(", ").append(apiHandler.varId).append(", \"-1\");").println();
else {
writer.append("\tpublic TraCIGetResponse ").append("(String elementID) throws IOException {").println();
writer.append("\t\tTraCIPacket p =").append(apiHandler.cmd).append(", ").append(apiHandler.varId).append(", elementID);").println();
writer.append("\t\treturn (TraCIGetResponse) socket.receiveResponse();").println();
protected void writeSET(PrintWriter writer, ApiHandler apiHandler){
writer.append("\tpublic TraCIResponse ").append("(String elementId, ").append(apiHandler.dataTypeStr).append(" data) throws IOException {").println();
writer.append("\t\tTraCIPacket p =")
.append(apiHandler.cmd).append(", elementId, ").append(apiHandler.varId).append(", ").append(apiHandler.varType).append(", data);").println();
writer.append("\t\treturn socket.receiveResponse();").println();
class TraCiApiWrapper {
String name;
String singleAnnotation;
String multipleAnnotation;
String cmdEnum;
String varEnum;
String packageName;
String[] imports;
String extendedClassName;
TraCiApiWrapper(Element apiClass){
TraCIApi traCIApi = apiClass.getAnnotation(TraCIApi.class);
name =;
packageName = traCIApi.packageName();
imports = traCIApi.imports();
extendedClassName = traCIApi.extendedClassName();
try {
singleAnnotation = traCIApi.singleAnnotation().getCanonicalName();
} catch (MirroredTypeException e){
singleAnnotation = e.getTypeMirror().toString();
try {
multipleAnnotation = traCIApi.multipleAnnotation().getCanonicalName();
} catch (MirroredTypeException e){
multipleAnnotation = e.getTypeMirror().toString();
try {
cmdEnum = traCIApi.cmdEnum().getCanonicalName();
} catch (MirroredTypeException e){
cmdEnum = e.getTypeMirror().toString();
try {
varEnum = traCIApi.varEnum().getCanonicalName();
} catch (MirroredTypeException e){
varEnum = e.getTypeMirror().toString();
class ApiHandler {
String cmd;
String varId;
String varType;
String name;
String dataTypeStr;
boolean ignoreElementId;
String apiType; //SET, GET, SUB
public ApiHandler(TraCiApiWrapper traCIApi, Element method, AnnotationMirror annotationMirror){
ignoreElementId = false; //default
dataTypeStr = "";
String cmdPrefix = traCIApi.cmdEnum;
cmdPrefix = cmdPrefix.substring(cmdPrefix.lastIndexOf('.') + 1).trim();
String varPrefix = traCIApi.varEnum;
varPrefix = varPrefix.substring(varPrefix.lastIndexOf('.') + 1).trim();
Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap = annotationMirror.getElementValues();
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : valueMap.entrySet()) {
String key = entry.getKey().getSimpleName().toString();
Object value = entry.getValue().getValue();
switch (key){
case "cmd":
this.cmd = cmdPrefix+ "." + value.toString();
this.apiType = value.toString().substring(0, 3);
case "var":
this.varId = varPrefix + "." + value.toString() + ".id";
this.varType = varPrefix + "." + value.toString() + ".type";
case "name": = (String) value;
case "ignoreElementId":
this.ignoreElementId = (boolean) value;
case "dataTypeStr":
this.dataTypeStr = value.toString();
public String toString() {
return "ApiHandler{" +
"cmd='" + cmd + '\'' +
", varId='" + varId + '\'' +
", varType='" + varType + '\'' +
", name='" + name + '\'' +
", ignoreElementId=" + ignoreElementId +
", apiType='" + apiType + '\'' +
package org.vadere.annotation.traci.client;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public @interface TraCIApi {
String packageName() default "org.vadere.manager.client.traci";
String[] imports() default {
String extendedClassName() default "TraCIClientApi";
String name();
Class singleAnnotation();
Class multipleAnnotation();
Class cmdEnum();
Class varEnum();
......@@ -81,7 +81,7 @@ public class ScenarioElementView extends JPanel implements ISelectScenarioElemen
Theme syntaxTheme = Theme.load(in);
} catch (IOException e) {
logger.error("could not load theme" + e.getMessage());
logger.error("could not loadFromFilesystem theme" + e.getMessage());
txtrTextfiletextarea = textAreaLocal;
......@@ -47,7 +47,7 @@ public abstract class ActionAbstractAddScenario extends AbstractAction {
} catch (IOException e) {
logger.error(String.format("topographyError during output load: '%s'", e.getLocalizedMessage()));
logger.error(String.format("topographyError during output loadFromFilesystem: '%s'", e.getLocalizedMessage()));
} else {
......@@ -4,15 +4,19 @@ package org.vadere.gui.projectview.control;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.projectview.view.ProjectView;
import org.vadere.gui.projectview.view.VDialogManager;
import org.vadere.simulator.projects.VadereProject;
import org.vadere.util.logging.Logger;
import java.awt.event.ActionEvent;
import java.nio.file.Paths;
import java.util.ArrayList;
import javax.swing.*;
import static org.vadere.gui.projectview.control.ActionAbstractSaveProject.saveProjectUnlessUserCancels;
public class ActionCreateProject extends AbstractAction {
private static final long serialVersionUID = 1L;
......@@ -40,10 +44,16 @@ public class ActionCreateProject extends AbstractAction {
if (newProjectName == null || newProjectName.trim().length() == 0) {"invalid project name");
} else {
VadereProject project = new VadereProject(newProjectName, new ArrayList<>());
final String projectDirectory= VDialogManager.saveProjectDialog();
if(projectDirectory == null)
return; // do not create project without saving it first.
VadereProject project = new VadereProject(newProjectName, new ArrayList<>(), Paths.get(projectDirectory));
ProjectView.getMainWindow().setProjectSpecificActionsEnabled(true);"create project: " + newProjectName);
......@@ -70,17 +70,17 @@ public class ActionLoadProject extends AbstractAction {
else {
migrationOptions = MigrationOptions.reapplyFromVersion((Version)option);
// 3. load project
// 3. loadFromFilesystem project
loadProjectByPath(model, projectFilePath, migrationOptions);
} else {
// 3. load project
// 3. loadFromFilesystem project
loadProjectByPath(model, projectFilePath);
} else {"user canceled load project."));"user canceled loadFromFilesystem project."));
} catch (IOException e1) {
......@@ -109,13 +109,12 @@ public class ActionLoadProject extends AbstractAction {
public static void loadProjectByPath(ProjectViewModel projectViewModel, String projectFilePath, MigrationOptions options) {
try {
VadereProject project = IOVadere.readProjectJson(projectFilePath, options);
projectViewModel.refreshOutputTable();"refreshed output table - 2");
// select and load first scenario from list
// select and loadFromFilesystem first scenario from list
projectViewModel.setSelectedRowIndexInScenarioTable(0);"selected the first scenario");
......@@ -170,7 +169,7 @@ public class ActionLoadProject extends AbstractAction {
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "JoltMigrationAssistant assistant",
logger.error("could not load project: " + e.getMessage());
logger.error("could not loadFromFilesystem project: " + e.getMessage());
package org.vadere.gui.projectview.control;
import javax.swing.*;
import org.vadere.gui.projectview.model.ProjectViewModel;
import org.vadere.gui.projectview.view.VTable;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ActionRunSelectedScenarios extends AbstractAction {
private final ProjectViewModel model;
package org.vadere.gui.projectview.model;
import org.jetbrains.annotations.NotNull;
import org.vadere.gui.components.utils.Messages;
import org.vadere.gui.projectview.control.IOutputFileRefreshListener;
import org.vadere.gui.projectview.control.IProjectChangeListener;
......@@ -16,6 +17,12 @@ import org.vadere.util.logging.Logger;
import javax.swing.*;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
import java.util.concurrent.ExecutorService;