Commit 9c2e5caf authored by Nils Richerzhagen's avatar Nils Richerzhagen
Browse files

Merge branch 'master' into 'nr/monitoring-clemens'

Merge Master into nr/monitoring-clemens



See merge request !41
parents 34fcdf6b a7d442fb
......@@ -43,7 +43,9 @@ import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
......@@ -87,7 +89,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
private List<LocationListener> listeners = new LinkedList<>();
private MovementModel movementModel;
private PlacementModel placementModel;
/**
......@@ -102,12 +104,12 @@ public class DefaultTopologyComponent implements TopologyComponent {
this.topology = topology;
this.host = host;
this.position = new PositionVector(0, 0);
this.movementModel = movementModel;
if (this.movementModel != null) {
this.movementModel.addComponent(this);
}
this.placementModel = placementModel;
if (this.placementModel != null) {
this.placementModel.addComponent(this);
......@@ -129,7 +131,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
*/
position.set(placementModel.place(this));
}
try {
final SiSComponent sis = host.getComponent(SiSComponent.class);
sis.provide().nodeState(SiSTypes.PHY_LOCATION,
......@@ -253,7 +255,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
locationListener.onLocationChanged(getHost(), getLastLocation());
}
}
@Override
public void setNewTargetLocation(double longitude, double latitude) {
movementModel.changeTargetLocation(this, longitude, latitude);
......@@ -316,6 +318,8 @@ public class DefaultTopologyComponent implements TopologyComponent {
private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0;
public LocationRequestImpl() {
// nothing to do
......@@ -323,6 +327,10 @@ public class DefaultTopologyComponent implements TopologyComponent {
protected void cancel(LocationListener listener) {
boolean removed = listeners.remove(listener);
if (listeners.isEmpty()) {
// upcoming event is no longer valid!
eventTypeSeq++;
}
assert removed;
}
......@@ -332,7 +340,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
if (listeners.isEmpty()) {
// Only start once!
lastLocation = null;
Event.scheduleImmediately(this, null, 0);
Event.scheduleImmediately(this, null, eventTypeSeq);
} else {
// Fire each new listener at least once
listener.onLocationChanged(getHost(), getLastLocation());
......@@ -356,16 +364,22 @@ public class DefaultTopologyComponent implements TopologyComponent {
@Override
public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) {
/*
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* themselves.
*/
return;
}
if (!listeners.isEmpty()) {
// Only reschedule, if at least one listener is ... listening
Location newLoc = getLastLocation();
if (lastLocation == null
|| lastLocation.distanceTo(newLoc) > 0) {
listeners.forEach((LocationListener listener) -> listener
listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(getHost(), newLoc));
lastLocation = newLoc;
}
Event.scheduleWithDelay(interval, this, null, 0);
lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
}
}
......@@ -483,15 +497,28 @@ public class DefaultTopologyComponent implements TopologyComponent {
this.onlyOnline = onlyOnline;
this.isDistanceBased = (distance > 0);
assert !isDistanceBased || phy.isBroadcastMedium();
if (phy.isBroadcastMedium()) {
// register as listener for movement
DefaultTopologyComponent.this.requestLocationUpdates(null,
LocalGraphView.this);
}
// register as listener for online/offline events
if (onlyOnline) {
getHost().getNetworkComponent().getByName(medium)
.addConnectivityListener(LocalGraphView.this);
if (phy.isBroadcastMedium() || onlyOnline) {
for (Host host : Oracle.getAllHosts()) {
if (phy.isBroadcastMedium()) {
try {
DefaultTopologyComponent dcomp = host.getComponent(
DefaultTopologyComponent.class);
dcomp.requestLocationUpdates(null,
LocalGraphView.this);
} catch (ComponentNotAvailableException e) {
continue;
}
}
if (onlyOnline) {
if (host.getNetworkComponent()
.getByName(medium) != null) {
host.getNetworkComponent().getByName(medium)
.addConnectivityListener(
LocalGraphView.this);
}
}
}
}
}
......@@ -516,7 +543,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
if (!onlyOnline || mac.isOnline()) {
INode node = currentView.createNode(mac.getHost().getId());
node.setProperty(SiSTypes.PHY_LOCATION,
topoView.getPosition(mac.getMacAddress()).clone() );
topoView.getPosition(mac.getMacAddress()).clone());
currentView.addElement(node);
}
}
......@@ -524,9 +551,11 @@ public class DefaultTopologyComponent implements TopologyComponent {
if (isDistanceBased) {
// Build neighbors solely based on an assumed range
for (MacLayer mac : topoView.getAllMacs()) {
//Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do so...
if(onlyOnline && !currentView.containsNode(mac.getHost().getId())){
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Consider all nodes as potential neighbors
......@@ -552,8 +581,10 @@ public class DefaultTopologyComponent implements TopologyComponent {
// Build neighborhoods based on underlay neighbors (1-hop)
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do so...
if(onlyOnline && !currentView.containsNode(mac.getHost().getId())){
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Rely on underlay for neighbors
......
/*
* 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.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import javax.swing.JComponent;
import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldMovementPoints;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModelViz;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.TransitionStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
*
*
*
* @author Julian Zobel
*
*
*/
public class StreetMovement implements MovementModel, EventHandler {
private final int EVENT_MOVE = 1;
private final int EVENT_INIT = 2;
protected PositionVector worldDimensions;
private Set<SimLocationActuator> moveableHosts = new LinkedHashSet<SimLocationActuator>();
private Map<SimLocationActuator, PositionVector> positions = new LinkedHashMap<SimLocationActuator, PositionVector>();
private Map<SimLocationActuator, AttractionPoint> attractionOfClients = new LinkedHashMap<SimLocationActuator, AttractionPoint>();
List<AttractionPoint> attractionPoints = new LinkedList<AttractionPoint>();
private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
private Random rand;
private double latLeft; //Values from -90 to 90; always smaller than latRight
private double latRight; //Values from -90 to 90
private double lonLeft; //Values from -180 to 180; Always smaller than lonRight
private double lonRight; //Values from -180 to 180
public StreetMovement() {
this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
this.rand = Randoms.getRandom(StreetMovement.class);
latLeft = GPSCalculation.getLatLower();
latRight = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft();
lonRight = GPSCalculation.getLonRight();
System.out.println("Scheduling first event for Init");
// scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT);
}
/**
* This Method will be not called from the Components. So we call this
* manually!
*/
public void initialize() {
if (!initialized) {
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
for (SimLocationActuator ms : moveableHosts) {
initializeStartingPosition(ms);
}
// initial move
move();
initialized = true;
}
}
/**
* Assign the given node a random attraction point and place it
* on a randomly selected position on the line between
* the assigned attraction point and another adjacent attraction point.
*
* @param ms
*/
private void initializeStartingPosition(SimLocationActuator ms) {
// set an initial attraction point
int index = rand.nextInt(attractionPoints.size());
AttractionPoint a = attractionPoints.get(index);
attractionOfClients.put(ms, a);
AttractionPoint b = this.returnNextOrLastAttractionPoint(index);
PositionVector startingPosition = this.returnRandomPositionBetweenPoints(a,b);
ms.updateCurrentLocation(startingPosition.getLongitude(), startingPosition.getLatitude());
positions.put(ms, ms.getRealPosition());
}
/**
* Returns a randomly selected point on the line between the two given attraction points
*
* @param a Attraction Point A
* @param b Attraction Point B
* @return PositionVector of a randomly selected point on the connecting line of the attraction points
*/
private PositionVector returnRandomPositionBetweenPoints(AttractionPoint a,
AttractionPoint b) {
double longMin, longMax, latMin, latMax, longNew, latNew;
// Points have different longitude, so only search for random value for longitude
if(a.getRealPosition().getLongitude() != b.getRealPosition().getLongitude()) {
if(a.getRealPosition().getLongitude() < b.getRealPosition().getLongitude()) {
longMin = a.getRealPosition().getLongitude();
longMax = b.getRealPosition().getLongitude();
} else {
longMin = b.getRealPosition().getLongitude();
longMax = a.getRealPosition().getLongitude();
}
do {
longNew = rand.nextDouble()*longMax;
} while(longNew < longMin);
assert longNew > longMin && longNew <= longMax;
return new PositionVector(longNew, a.getRealPosition().getLatitude());
}
// Points have different latitude, so only search for random value for latitude
if(a.getRealPosition().getLatitude() != b.getRealPosition().getLatitude()) {
if(a.getRealPosition().getLatitude() < b.getRealPosition().getLatitude()) {
latMin = a.getRealPosition().getLatitude();
latMax = b.getRealPosition().getLatitude();
} else {
latMin = b.getRealPosition().getLatitude();
latMax = a.getRealPosition().getLatitude();
}
do{
latNew = rand.nextDouble()*latMax;
} while(latNew < latMin);
assert latNew > latMin && latNew <= latMax;
return new PositionVector(a.getRealPosition().getLongitude(), latNew);
}
return null;
}
/**
* This default implementation relies on {@link PlacementModel}s to be
* configured in the {@link TopologyFactory}
*/
@Override
public void placeComponent(SimLocationActuator actuator) {
// not used here i guess
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) {
/*
* Set a new target AP for the current actuator
*/
attractionOfClients.put(actuator, new AttractionPoint((int) longitude, (int) latitude, ""));
}
@Override
public void addComponent(SimLocationActuator comp) {
moveableHosts.add(comp);
positions.put(comp, comp.getRealPosition());
}
@Override
public void setTimeBetweenMoveOperations(long time) {
if (time > 0) {
this.timeBetweenMoveOperation = time;
} else {
throw new ConfigurationException(
"time is negative for the Move Operations");
}
}
/**
* Move all nodes towards their assigned attraction point
*/
protected void move() {
for (Entry<SimLocationActuator, AttractionPoint> entry : attractionOfClients.entrySet()) {
SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector destination = new PositionVector(attractionCenter);
if (destination.distanceTo(ms.getRealPosition()) > ms.getMovementSpeed()) {
PositionVector newPosition = ms.getRealPosition().moveStep(destination, ms.getMovementSpeed());
ms.updateCurrentLocation(newPosition.getLongitude(), newPosition.getLatitude());
positions.put(ms, newPosition);
} else {
assignNewAttractionPoint(ms);
}
/*
* Check for negative or out of bound coordinates!
*/
assert ms.getRealPosition().getX() >= 0.0
&& ms.getRealPosition().getX() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getX();
assert ms.getRealPosition().getY() >= 0.0
&& ms.getRealPosition().getY() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getY();
}
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null,
EVENT_MOVE);
}
/**
* Assign the node a random attraction point, that is adjacent to the last one
*
* @param ms The given node
*/
private void assignNewAttractionPoint(SimLocationActuator ms) {
if(attractionOfClients.containsKey(ms)) {
boolean updownrand = rand.nextBoolean();
int index = attractionPoints.indexOf(attractionOfClients.get(ms));
if(updownrand) {
index = ((index + 1) % attractionPoints.size());
} else {
index = ((index - 1 + attractionPoints.size()) % attractionPoints.size());
}
attractionOfClients.put(ms, attractionPoints.get(index));
} else {
attractionOfClients.put(ms, attractionPoints.get(rand.nextInt(attractionPoints.size())));
}
}
/**
* Returns the next or last attraction point of the list to the given list index
*
* @param index Index of the attraction point, for which another attraction point should be returned
* @return Attraction Point
*/
private AttractionPoint returnNextOrLastAttractionPoint(int index) {
boolean updownrand = rand.nextBoolean();
if(updownrand) {
index = ((index + 1) % attractionPoints.size());
} else {
index = ((index - 1 + attractionPoints.size()) % attractionPoints.size());
}
return attractionPoints.get(index);
}
@Override
public void eventOccurred(Object content, int type) {
if (type == EVENT_INIT) {
initialize();
} else if (type == EVENT_MOVE) {
move();
}
}
protected List<AttractionPoint> getAttractionPoints() {
return attractionPoints;
}
public void setAttractionPoint(AttractionPoint point) {
this.attractionPoints.add(point);
}
}
......@@ -81,7 +81,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
hopper = new GraphHopper().forServer();
hopper.setOSMFile(osmFileLocation);
// where to store graphhopper files?
hopper.setGraphHopperLocation(graphFolderFiles);
hopper.setGraphHopperLocation(graphFolderFiles+"/"+osmFileLocation.hashCode());
hopper.setEncodingManager(new EncodingManager(movementType));
hopper.importOrLoad();
init = true;
......
......@@ -50,7 +50,7 @@ The `LocalMovementStrategy`-interface provides a method to compute routing-infor
#### RealWordlSreetsMovement ####
This class (`de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement`) does load the routing information out of a provided osm-data file. If the available data in the osm-file does not have enough information to route a node, the node will stay at its place (e.g. when the available data only covers Darmstadt, but you want to route in Frankfurt). The following values can be specified for this class:
+ OSMFileLocation: Set the path to the osm-data-file
+ OSMFileLocation: Set the path to the osm-data-file, map files of many big cities can be downloaded from https://mapzen.com/data/metro-extracts/
+ GraphFolderFiles: The routing engine stores some temporary data in this folder. If you change some of the parameters, the engine will get in trouble. Simply then delete the content of the folder before starting the simulation.
+ MovementType: The routing enginge can walk through the world as a pedestrian, by bike or by car. The possible values are {foot, bike, car}
+ NavigationalType: You can specify in which mode the routing engine should calculate the best way to the destination. Possible values are {fastest, shortest}
......
......@@ -94,8 +94,13 @@ public class NodeInfoComponentVis extends JComponent
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
boolean first = true;
for (NodeVis vis : nodes) {
vis.draw(g2);
if (first) {
first = false;
vis.drawLegend(g2);
}
}
}
......@@ -168,6 +173,9 @@ public class NodeInfoComponentVis extends JComponent
int radius = 4;
for (int dim = 0; dim < dimensions.length; dim++) {
radius += 2;
if (!activeLayers[dim]) {
continue;
}
g2.setColor(Color.DARK_GRAY);
g2.drawOval(10, 20 * (dim + 1) - 10, radius * 2, radius * 2);
g2.drawString(dimensions[dim], 30, 20 * (dim + 1));
......
......@@ -377,8 +377,7 @@ public class WifiTopologyView extends RangedTopologyView {
rxSensitivityDbm);
double satRange = interferenceHelper.calculateMaximalRadius(
maxTxPowerDbm, satDbm);
System.out.println("satRange: " + satRange + " csRange: " + csRange
+ " range: " + range);
//System.out.println("satRange: " + satRange + " csRange: " + csRange + " range: " + range);
Monitor.log(WifiTopologyView.class, Level.INFO,
"WiFi underlay ranges: satRange: " + satRange + " csRange: "
+ csRange + " range: " + range);
......
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