Commit f86d6489 authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

Initial Model (SUMO Integration)

parent bccf15b5
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Stream;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class SumoTraceMovementModel implements MovementModel, EventHandler {
private long timeBetweenMoveOperations;
private final List<SimLocationActuator> components;
private final Map<SimLocationActuator, Queue<Step>> movements;
private final String tracefile;
private final long timestepConversion = Time.SECOND;
private boolean initialized = false;
@XMLConfigurableConstructor({ "timeBetweenMoveOperations", "tracefile" })
public SumoTraceMovementModel(long timeBetweenMoveOperations, String tracefile) {
this.timeBetweenMoveOperations = timeBetweenMoveOperations;
this.components = new LinkedList<>();
this.movements = new LinkedHashMap<>();
this.tracefile = tracefile;
}
@Override
public final void addComponent(SimLocationActuator comp) {
components.add(comp);
}
public long getTimeBetweenMoveOperations() {
return timeBetweenMoveOperations;
}
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperations = time;
}
@Override
public void placeComponent(SimLocationActuator actuator) {
if (!initialized) {
initializeModel();
initialized = true;
}
// Initial placement
actuator.updateCurrentLocation(new PositionVector(5, 5));
}
/**
* Initializes the movement model by executing BonnMotion and parsing the
* resulting movement trace.
*/
protected void initializeModel() {
// Schedule first step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
// Read the if-file (.if)
try (Stream<String> lines = Files.lines(Paths.get(tracefile), Charset.defaultCharset())) {
lines.forEachOrdered(line -> process(line));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Initialization: done.");
}
/**
* Invoked for each line within the input file. A line consists of the
* following data, separated by a space:
*
* Node-ID Timestamp X-Coordinate Y-Coordinate
*
* @param line
*/
protected void process(String line) {
String[] step = line.split(" ");
int nodeId = Integer.valueOf(step[0]);
//assert nodeId < components.size();
long time = Long.valueOf(step[1]);
double x = Double.valueOf(step[2]);
double y = Double.valueOf(step[3]);
if (nodeId >= components.size()) {
return;
}
// TODO make SUMO trace offsets configurable.
time -= 21600;
x -= 10000;
y -= 10000;
x/=10;
y/=10;
SimLocationActuator comp = components.get(nodeId);
Queue<Step> steps = movements.get(comp);
if (steps == null) {
steps = new LinkedList<>();
movements.put(comp, steps);
}
steps.add(new Step(time, x, y));
}
@Override
public void eventOccurred(Object content, int type) {
/*
* One event for all nodes (synchronized movement), as this boosts
* simulation performance due to less recalculations in the network
* models.
*/
long currentTime = Time.getCurrentTime() / timestepConversion;
movements.forEach((component, steps) -> {
Step step = null;
Step nextStep = null;
do {
step = steps.peek();
nextStep = null;
// Valid step
if (step != null && step.timestamp <= currentTime) {
step = steps.poll();
// Look ahead, maybe we need to skip?
nextStep = steps.peek();
}
} while (step != null && nextStep != null && nextStep.timestamp < currentTime);
if (step != null) {
component.updateCurrentLocation(new PositionVector(step.x, step.y));
// System.out.println("Set component "+component.getHost().getId()+" location to "+step.x+","+step.y);
}
});
// Reschedule next step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0);
}
/**
* A Step.
*
* @author Bjoern Richerzhagen
*
*/
private class Step {
public final double x;
public final double y;
public final long timestamp;
public Step(long timestamp, double x, double y) {
this.x = x;
this.y = y;
this.timestamp = timestamp;
}
}
}
\ No newline at end of file
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