Commit eff5d429 authored by Julian Zobel's avatar Julian Zobel 🦄
Browse files

Merge branch 'master' into 'cherry-pick-7698d9d7'

# Conflicts:
#   src/de/tud/kom/p2psim/impl/analyzer/metric/output/MetricOutputDAO.java
#   src/de/tud/kom/p2psim/impl/util/db/dao/DAO.java
parents 1c7f20ec 37020b44
...@@ -20,22 +20,13 @@ ...@@ -20,22 +20,13 @@
package de.tud.kom.p2psim.impl.topology.movement; package de.tud.kom.p2psim.impl.topology.movement;
import java.util.List;
import java.util.Random;
import com.google.common.collect.Lists;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.RandomWaypointGenerator;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
public class RandomWaypointMovement extends AbstractWaypointMovementModel { public class RandomWaypointMovement extends AbstractWaypointMovementModel {
private Random random = Randoms
.getRandom(RandomWaypointMovement.class);
@XMLConfigurableConstructor({"worldX", "worldY"}) @XMLConfigurableConstructor({"worldX", "worldY"})
public RandomWaypointMovement(double worldX, double worldY) { public RandomWaypointMovement(double worldX, double worldY) {
super(worldX, worldY); super(worldX, worldY);
...@@ -46,10 +37,12 @@ public class RandomWaypointMovement extends AbstractWaypointMovementModel { ...@@ -46,10 +37,12 @@ public class RandomWaypointMovement extends AbstractWaypointMovementModel {
if (waypointModel == null) { if (waypointModel == null) {
throw new ConfigurationException("SLAWMovementModel requires a valid waypoint model which hasn't been provided, cannot execute"); throw new ConfigurationException("SLAWMovementModel requires a valid waypoint model which hasn't been provided, cannot execute");
} }
List<Waypoint> waypoints = Lists.newArrayList(waypointModel.getWaypoints(WeakWaypoint.class));
nextDestination(component, waypoints.get(random.nextInt(waypoints.size())).getPosition(), 0); if(!(waypointModel instanceof RandomWaypointGenerator)) {
throw new ConfigurationException("RandomWaypointMovement requires RandomWaypointModel generator which hasn't been provided, cannot execute");
}
nextDestination(component, ((RandomWaypointGenerator)waypointModel).getRandomPoint(), 0);
} }
......
...@@ -40,7 +40,7 @@ import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; ...@@ -40,7 +40,7 @@ import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.scenario.simcfg2.annotations.After; import de.tud.kom.p2psim.impl.scenario.simcfg2.annotations.After;
import de.tud.kom.p2psim.impl.scenario.simcfg2.annotations.Configure; import de.tud.kom.p2psim.impl.scenario.simcfg2.annotations.Configure;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.DisplayString; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.DisplayString;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.StrongWaypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.StrongWaypoint;
......
...@@ -35,14 +35,14 @@ import de.tud.kom.p2psim.api.topology.movement.MovementModel; ...@@ -35,14 +35,14 @@ 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.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel; import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator; 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.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation; import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
/** /**
* *
...@@ -64,34 +64,21 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -64,34 +64,21 @@ public class StreetMovement implements MovementModel, EventHandler {
private Map<SimLocationActuator, PositionVector> positions = new LinkedHashMap<SimLocationActuator, PositionVector>(); private Map<SimLocationActuator, PositionVector> positions = new LinkedHashMap<SimLocationActuator, PositionVector>();
private Map<SimLocationActuator, AttractionPoint> attractionOfClients = new LinkedHashMap<SimLocationActuator, AttractionPoint>(); private Map<SimLocationActuator, IAttractionPoint> attractionOfClients = new LinkedHashMap<SimLocationActuator, IAttractionPoint>();
List<AttractionPoint> attractionPoints = new LinkedList<AttractionPoint>(); List<IAttractionPoint> attractionPoints = new LinkedList<IAttractionPoint>();
private boolean initialized = false; private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT; private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
private Random rand; private Random rand = Randoms.getRandom(StreetMovement.class);
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() { public StreetMovement() {
this.worldDimensions = Binder.getComponentOrNull(Topology.class) this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions(); .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! // scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT); Event.scheduleImmediately(this, null, EVENT_INIT);
} }
...@@ -126,10 +113,10 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -126,10 +113,10 @@ public class StreetMovement implements MovementModel, EventHandler {
private void initializeStartingPosition(SimLocationActuator ms) { private void initializeStartingPosition(SimLocationActuator ms) {
// set an initial attraction point // set an initial attraction point
int index = rand.nextInt(attractionPoints.size()); int index = rand.nextInt(attractionPoints.size());
AttractionPoint a = attractionPoints.get(index); IAttractionPoint a = attractionPoints.get(index);
attractionOfClients.put(ms, a); attractionOfClients.put(ms, a);
AttractionPoint b = this.returnNextOrLastAttractionPoint(index); IAttractionPoint b = this.returnNextOrLastAttractionPoint(index);
PositionVector startingPosition = this.returnRandomPositionBetweenPoints(a,b); PositionVector startingPosition = this.returnRandomPositionBetweenPoints(a,b);
...@@ -146,18 +133,18 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -146,18 +133,18 @@ public class StreetMovement implements MovementModel, EventHandler {
* @param b Attraction Point B * @param b Attraction Point B
* @return PositionVector of a randomly selected point on the connecting line of the attraction points * @return PositionVector of a randomly selected point on the connecting line of the attraction points
*/ */
private PositionVector returnRandomPositionBetweenPoints(AttractionPoint a, private PositionVector returnRandomPositionBetweenPoints(IAttractionPoint a,
AttractionPoint b) { IAttractionPoint b) {
double longMin, longMax, latMin, latMax, longNew, latNew; double longMin, longMax, latMin, latMax, longNew, latNew;
// Points have different longitude, so only search for random value for longitude // Points have different longitude, so only search for random value for longitude
if(a.getLongitude() != b.getLongitude()) { if(a.getLongitudeOrX() != b.getLongitudeOrX()) {
if(a.getLongitude() < b.getLongitude()) { if(a.getLongitudeOrX() < b.getLongitudeOrX()) {
longMin = a.getLongitude(); longMin = a.getLongitudeOrX();
longMax = b.getLongitude(); longMax = b.getLongitudeOrX();
} else { } else {
longMin = b.getLongitude(); longMin = b.getLongitudeOrX();
longMax = a.getLongitude(); longMax = a.getLongitudeOrX();
} }
do { do {
...@@ -165,17 +152,17 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -165,17 +152,17 @@ public class StreetMovement implements MovementModel, EventHandler {
} while(longNew < longMin); } while(longNew < longMin);
assert longNew > longMin && longNew <= longMax; assert longNew > longMin && longNew <= longMax;
return new PositionVector(longNew, a.getLatitude()); return new PositionVector(longNew, a.getLatitudeOrY());
} }
// Points have different latitude, so only search for random value for latitude // Points have different latitude, so only search for random value for latitude
if(a.getLatitude() != b.getLatitude()) { if(a.getLatitudeOrY() != b.getLatitudeOrY()) {
if(a.getLatitude() < b.getLatitude()) { if(a.getLatitudeOrY() < b.getLatitudeOrY()) {
latMin = a.getLatitude(); latMin = a.getLatitudeOrY();
latMax = b.getLatitude(); latMax = b.getLatitudeOrY();
} else { } else {
latMin = b.getLatitude(); latMin = b.getLatitudeOrY();
latMax = a.getLatitude(); latMax = a.getLatitudeOrY();
} }
do{ do{
...@@ -183,7 +170,7 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -183,7 +170,7 @@ public class StreetMovement implements MovementModel, EventHandler {
} while(latNew < latMin); } while(latNew < latMin);
assert latNew > latMin && latNew <= latMax; assert latNew > latMin && latNew <= latMax;
return new PositionVector(a.getLongitude(), latNew); return new PositionVector(a.getLongitudeOrX(), latNew);
} }
return null; return null;
...@@ -199,7 +186,7 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -199,7 +186,7 @@ public class StreetMovement implements MovementModel, EventHandler {
} }
@Override @Override
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) { public void changeTargetLocation(SimLocationActuator actuator, IAttractionPoint ap) {
/* /*
* Set a new target AP for the current actuator * Set a new target AP for the current actuator
*/ */
...@@ -227,7 +214,7 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -227,7 +214,7 @@ public class StreetMovement implements MovementModel, EventHandler {
* Move all nodes towards their assigned attraction point * Move all nodes towards their assigned attraction point
*/ */
protected void move() { protected void move() {
for (Entry<SimLocationActuator, AttractionPoint> entry : attractionOfClients.entrySet()) { for (Entry<SimLocationActuator, IAttractionPoint> entry : attractionOfClients.entrySet()) {
SimLocationActuator ms = entry.getKey(); SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = (PositionVector) entry.getValue(); PositionVector attractionCenter = (PositionVector) entry.getValue();
...@@ -288,7 +275,7 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -288,7 +275,7 @@ public class StreetMovement implements MovementModel, EventHandler {
* @param index Index of the attraction point, for which another attraction point should be returned * @param index Index of the attraction point, for which another attraction point should be returned
* @return Attraction Point * @return Attraction Point
*/ */
private AttractionPoint returnNextOrLastAttractionPoint(int index) { private IAttractionPoint returnNextOrLastAttractionPoint(int index) {
boolean updownrand = rand.nextBoolean(); boolean updownrand = rand.nextBoolean();
if(updownrand) { if(updownrand) {
...@@ -309,11 +296,11 @@ public class StreetMovement implements MovementModel, EventHandler { ...@@ -309,11 +296,11 @@ public class StreetMovement implements MovementModel, EventHandler {
} }
} }
public List<AttractionPoint> getAttractionPoints() { public List<IAttractionPoint> getAttractionPoints() {
return attractionPoints; return attractionPoints;
} }
public void setAttractionPoint(AttractionPoint point) { public void setAttractionPoint(IAttractionPoint point) {
this.attractionPoints.add(point); this.attractionPoints.add(point);
} }
} }
...@@ -33,7 +33,7 @@ import java.util.stream.Stream; ...@@ -33,7 +33,7 @@ import java.util.stream.Stream;
import de.tud.kom.p2psim.api.topology.movement.MovementModel; 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.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
......
...@@ -24,7 +24,7 @@ import java.util.Set; ...@@ -24,7 +24,7 @@ import java.util.Set;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
/** /**
* The Movement Supported Components move to one Position. It is possible to set * The Movement Supported Components move to one Position. It is possible to set
......
/*
* 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.File;
import java.io.FileNotFoundException;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.network.SimNetworkComponent;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
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.DefaultTopology;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.IAttractionBasedMovementAnalyzer;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPointViz;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionProvider;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.LifecycleComponent;
public class TracefileMovementModel implements MovementModel, EventHandler {
public static String tracefileFolder ="smarter/tracefiles/";
public static String tracefilePrefix = "smarterTraceFile-";
public static long GPS_MISSING_TRACE_THRESHOLD = 60;
public static int ZERO_TO_2 = 0;
public static int _2_to_5 = 0;
public static int _5_to_10 = 0;
public static int TEN_TO_THIRTY = 0;
public static int THIRTY_TO_SIXTY = 0;
public static int SIXTY_TO_120 = 0;
public static int _120_TO_300 = 0;
public static int _300_TO_600 = 0;
public static int ABOVE_600 = 0;
protected final int EVENT_MOVE = 1;
protected final PositionVector DEFAULT_POSITION = new PositionVector(-1000, -1000);
protected long timeBetweenMoveOperations;
protected IMapVisualization mapVisualization;
protected IAttractionProvider attractionGenerator;
protected AttractionPointViz attractionpointVisualization;
protected boolean initialized = false;
private final LinkedHashMap<SimLocationActuator, LinkedList<Step>> components;
private final static LinkedHashMap<SimLocationActuator, Integer> componentToStepSize = new LinkedHashMap<SimLocationActuator, Integer>();
private LinkedList<File> tracefiles;
private boolean first = true;
public TracefileMovementModel() {
components = new LinkedHashMap<SimLocationActuator, LinkedList<Step>>();
tracefiles = new LinkedList<File>();
}
public void initialize() {
if(initialized) {
return;
}
File folder = new File(tracefileFolder);
if (!folder.exists()) {
throw new UnsupportedOperationException("Tracefile folder not found");
}
for(File tracefile : folder.listFiles()) {
if(tracefile.getName().contains(tracefilePrefix)) {
tracefiles.add(tracefile);
}
}
if (mapVisualization != null) {
VisualizationInjector.injectComponent(mapVisualization);
}
if (attractionpointVisualization != null) {
attractionpointVisualization.setAttractionPoints(new LinkedList<>(attractionGenerator.getAttractionPoints()));
VisualizationInjector.injectComponent(attractionpointVisualization);
}
initialized = true;
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, EVENT_MOVE);
}
@Override
public void eventOccurred(Object content, int type) {
if (type == EVENT_MOVE) {
move();
}
}
private void move() {
if(first) {
components.forEach((component, steps) -> {
shutdownComponent(component);
});
}
// as the files contain the timestamp in seconds, the current time needs to be converted in seconds
long currentTime = Time.getCurrentTime() / Time.SECOND;
LinkedList<SimLocationActuator> toRemove = new LinkedList<>();
components.forEach((component, steps) -> {
Step step = steps.peek();
if (step != null) {
if(currentTime < step.timestamp) {
if(DefaultTopology.isWithinWorldBoundaries(component.getRealPosition())) {
if(currentTime + GPS_MISSING_TRACE_THRESHOLD >= step.timestamp) {
if(component.getRealPosition().distanceTo(new PositionVector(step.x, step.y)) > GPS_MISSING_TRACE_THRESHOLD * 2) {
shutdownComponent(component);
}
// do nothing for smoothing?
// TODO
else {
int stepcount = componentToStepSize.get(component);
stepcount++;
componentToStepSize.put(component, stepcount);
}
}
else {
if(DefaultTopology.isWithinWorldBoundaries(component.getRealPosition())) {
// TODO
long delta = step.timestamp - currentTime + GPS_MISSING_TRACE_THRESHOLD;
if(delta > 0 && delta <= 2) {
ZERO_TO_2++;
}
else if(delta > 2 && delta <= 5) {
_2_to_5++;
}
else if(delta > 5 && delta <= 10) {
_5_to_10++;
}
else if(delta > 10 && delta <= 30) {
TEN_TO_THIRTY++;
}
else if(delta > 30 && delta <= 60) {
THIRTY_TO_SIXTY++;
}
else if(delta > 60 && delta <= 120) {
SIXTY_TO_120++;
}
else if(delta > 120 && delta <= 300) {
_120_TO_300++;
}
else if(delta > 300 && delta <= 600) {
_300_TO_600++;
}
else if(delta > 600) {
ABOVE_600++;
}
shutdownComponent(component);
}
}
}
}
else {
step = steps.pop();
// TODO
int stepcount = componentToStepSize.get(component);
stepcount++;
componentToStepSize.put(component, stepcount);
if(!DefaultTopology.isWithinWorldBoundaries(component.getRealPosition())) {
component.updateCurrentLocation(new PositionVector(step.x, step.y));
startupComponent(component);
}
else {
component.updateCurrentLocation(new PositionVector(step.x, step.y));
}
}
}
else {
toRemove.add(component);
}
});
for (SimLocationActuator simLocationActuator : toRemove) {
components.remove(simLocationActuator);
shutdownComponent(simLocationActuator);
}
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, EVENT_MOVE);
if(first) {
// Inform analyzer of resolved movement
if(Monitor.hasAnalyzer(IAttractionBasedMovementAnalyzer.class)) {
Monitor.getOrNull(IAttractionBasedMovementAnalyzer.class).onAllNodeInitializationCompleted(components.keySet());
}
first =false;
}
}
private void shutdownComponent(SimLocationActuator node) {
SimNetworkComponent net = (SimNetworkComponent) node.getHost().getNetworkComponent();
for (SimNetInterface netI : net.getSimNetworkInterfaces()) {
if (netI.isOnline()) {
netI.goOffline();
}
}
try {
List<LifecycleComponent> comps = node.getHost().getComponents(LifecycleComponent.class);
for (LifecycleComponent lifecycleComponent : comps) {
lifecycleComponent.stopComponent();
}
} catch (Exception e) {
// TODO: handle exception
}
node.updateCurrentLocation(new PositionVector(DEFAULT_POSITION));
}
private void startupComponent(SimLocationActuator node) {
SimNetworkComponent net = (SimNetworkComponent) node.getHost().getNetworkComponent();
for (SimNetInterface netI : net.getSimNetworkInterfaces()) {
if (netI.isOffline()) {
netI.goOnline();
}
}
try {
List<LifecycleComponent> comps = node.getHost().getComponents(LifecycleComponent.class);
for (LifecycleComponent lifecycleComponent : comps) {
lifecycleComponent.startComponent();
}
} catch (Exception e) {
// TODO: handle exception
}
}
@Override
public void addComponent(SimLocationActuator actuator) {
if (!initialized) {
initialize();
}
associateTracefile(actuator);
}
private void associateTracefile(SimLocationActuator actuator) {
if(tracefiles.isEmpty()) {
throw new UnsupportedOperationException("List of tracefiles is empty, thus cannot initiate the component!");
}
if(components.containsKey(actuator)) {
throw new UnsupportedOperationException("Component was already assigned!");
}
LinkedList<Step> stepQueue = new LinkedList<Step>();
File tracefile = tracefiles.pop();
Scanner filescanner;
try {
filescanner = new Scanner(tracefile);
while(filescanner.hasNextLine()) {
String line = filescanner.nextLine();
String[] split = line.split(" ");
long timestamp = Long.valueOf(split[0]);
//double lat = Double.valueOf(split[1]);
//double lon = Double.valueOf(split[2]);
double x = Double.valueOf(split[3]);
double y = Double.valueOf(split[4]);
Step s = new Step(timestamp, x, y);
stepQueue.add(s);
}
filescanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (Exception e) {
System.err.println(tracefile.getName());
e.printStackTrace();
}
// System.out.println(actuator.getHost().getId() + " <> " + tracefile.getName());
components.put(actuator, stepQueue);
componentToStepSize.put(actuator, 0);
}
public static int getComponentStepSize(SimLocationActuator component) {
if(!componentToStepSize.containsKey(component)) {
return -1;
}
return componentToStepSize.get(component);
}
@Override
public void placeComponent(SimLocationActuator actuator) {
// Initial placement
actuator.updateCurrentLocation(new PositionVector(DEFAULT_POSITION));
}
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperations = time;
}
public void setIMapVisualization(IMapVisualization mapVisualization) {
this.mapVisualization = mapVisualization;
}
public void setAttractionPointViz(AttractionPointViz viz) {
this.attractionpointVisualization = viz;
}
public void setIAttractionGenerator(IAttractionProvider attractionGenerator) {
if (attractionGenerator == null) {
throw new ConfigurationException(
"AttractionGenerator is missing in ModularMovementModel!");
}
this.attractionGenerator = attractionGenerator;
}
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;
}
@Override
public String toString() {
return "Step @ " + timestamp + "s -> ("+x+", "+y+")";
}
}
}
...@@ -32,9 +32,9 @@ import de.tud.kom.p2psim.api.network.SimNetInterface; ...@@ -32,9 +32,9 @@ import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.topology.movement.MovementModel; 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.SimLocationActuator;
import de.tud.kom.p2psim.impl.network.routed.RoutedNetLayer; import de.tud.kom.p2psim.impl.network.routed.RoutedNetLayer;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController; import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController; import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.vehicular.DefaultVehicleInformationComponent; import de.tud.kom.p2psim.impl.vehicular.DefaultVehicleInformationComponent;
import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.EventHandler;
...@@ -60,6 +60,8 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -60,6 +60,8 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
private static VehicleMovementModel MOVEMENT; private static VehicleMovementModel MOVEMENT;
public static final int TIMESTEP_RATIO = 1;
private long timeBetweenMoveOperations; private long timeBetweenMoveOperations;
private final List<SimLocationActuator> components; private final List<SimLocationActuator> components;
...@@ -75,16 +77,11 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -75,16 +77,11 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
private final int width; private final int width;
private final int height; private final int height;
private double scenarioWidth = 0;
private double scenarioHeight = 0;
private final String sumoExe; private final String sumoExe;
private final String sumoConfigFile; private final String sumoConfigFile;
private final String sumoTrace; private final String sumoTrace;
private String sumoIntersections; private String sumoIntersections;
private final long timestepConversion = Time.SECOND;
private boolean initialized = false; private boolean initialized = false;
private VehicleController _controller; private VehicleController _controller;
...@@ -92,6 +89,8 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -92,6 +89,8 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
private double _percentageOfKnownRoutes = 1; private double _percentageOfKnownRoutes = 1;
private int _startTime;
/** /**
* Constructor for the movement model using the sumo TraCI API * Constructor for the movement model using the sumo TraCI API
* @param timeBetweenMoveOperations The time between two movement operations. * @param timeBetweenMoveOperations The time between two movement operations.
...@@ -117,6 +116,27 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -117,6 +116,27 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
this.offsetY = Integer.parseInt(offsetY); this.offsetY = Integer.parseInt(offsetY);
this.width = Integer.parseInt(width); this.width = Integer.parseInt(width);
this.height = Integer.parseInt(height); this.height = Integer.parseInt(height);
Thread current = Thread.currentThread();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
StackTraceElement[] stackTrace = current.getStackTrace();
System.out.println();
System.out.println();
for (int i = 0; i < stackTrace.length; i++) {
System.out.println(stackTrace[i]);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
});
// thread.start();
} }
/** /**
...@@ -154,6 +174,10 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -154,6 +174,10 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
_percentageOfKnownRoutes = pPercentageOfKnownRoutes; _percentageOfKnownRoutes = pPercentageOfKnownRoutes;
} }
public void setStartTime(long pStartTime) {
_startTime = (int) (pStartTime / timeBetweenMoveOperations);
}
public void setReuseComponents(boolean pReuseComponents) { public void setReuseComponents(boolean pReuseComponents) {
_reuseComponents = pReuseComponents; _reuseComponents = pReuseComponents;
...@@ -215,14 +239,15 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -215,14 +239,15 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
protected void initializeModel() { protected void initializeModel() {
// Schedule first step // Schedule first step
if (!initialized) { if (!initialized) {
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0); Event.scheduleWithDelay(timeBetweenMoveOperations * TIMESTEP_RATIO, this, null, 0);
if (sumoExe != null) { if (sumoExe != null) {
TraciSimulationController simulationController = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile); TraciSimulationController simulationController = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile, TIMESTEP_RATIO);
_controller = simulationController; _controller = simulationController;
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height); _controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_controller.init(); simulationController.setStartTime(_startTime);
_controller.nextStep(); _controller.init(timeBetweenMoveOperations);
_controller.nextStep(timeBetweenMoveOperations);
_extractor = simulationController; _extractor = simulationController;
} else { } else {
...@@ -235,15 +260,12 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -235,15 +260,12 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
_controller = simulationController; _controller = simulationController;
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height); _controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_controller.init(); _controller.init(timeBetweenMoveOperations);
_controller.nextStep(); _controller.nextStep(timeBetweenMoveOperations);
_extractor = simulationController; _extractor = simulationController;
} }
scenarioWidth = _extractor.getScenarioWidth();
scenarioHeight = _extractor.getScenarioHeight();
System.out.println("Initialization: done."); System.out.println("Initialization: done.");
} }
} }
...@@ -260,10 +282,12 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -260,10 +282,12 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
* simulation performance due to less recalculations in the network * simulation performance due to less recalculations in the network
* models. * models.
*/ */
long currentTime = Time.getCurrentTime() / timestepConversion; long currentTime = Time.getCurrentTime() / timeBetweenMoveOperations;
System.out.println("Performing movement for step " + currentTime);
while (_controller.getStep() - _controller.getStart() < currentTime) { while (_controller.getStep() - _controller.getStart() < currentTime) {
if (!_controller.nextStep()) { if (!_controller.nextStep(timeBetweenMoveOperations)) {
return; return;
} }
} }
...@@ -293,7 +317,7 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -293,7 +317,7 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
e.printStackTrace(); e.printStackTrace();
} }
component.updateCurrentLocation(new PositionVector(position.getLongitude(), position.getLatitude())); component.updateCurrentLocation(new PositionVector(position.getLongitudeOrX(), position.getLatitudeOrY()));
component.setMovementSpeed(_controller.getVehicleSpeed(vehicle)); component.setMovementSpeed(_controller.getVehicleSpeed(vehicle));
...@@ -316,7 +340,7 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -316,7 +340,7 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
} }
// Reschedule next step // Reschedule next step
Event.scheduleWithDelay(timeBetweenMoveOperations, this, null, 0); Event.scheduleWithDelay(timeBetweenMoveOperations * TIMESTEP_RATIO, this, null, 0);
} }
/** /**
...@@ -385,7 +409,9 @@ public class VehicleMovementModel implements MovementModel, EventHandler { ...@@ -385,7 +409,9 @@ public class VehicleMovementModel implements MovementModel, EventHandler {
idComponentMatcher.put(vehicle, simLocationActuator); idComponentMatcher.put(vehicle, simLocationActuator);
hostVehicleIDMatching.put(simLocationActuator.getHost().getId(), vehicle); hostVehicleIDMatching.put(simLocationActuator.getHost().getId(), vehicle);
} else { } else {
throw new RuntimeException("Unable to assign new components. Please increase node amount" + (_reuseComponents?".":" or enable the reuse of components.")); if (idComponentMatcher.size() != 0) {
throw new RuntimeException("Unable to assign new components. Please increase node amount" + (_reuseComponents?".":" or enable the reuse of components."));
}
} }
} }
return idComponentMatcher.get(vehicle); return idComponentMatcher.get(vehicle);
......
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.topology.waypoints.graph; package de.tud.kom.p2psim.impl.topology.movement.aerial;
import org.jgrapht.EdgeFactory; import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent;
/**
* Creates a simple Path from two given way points. /**
* *
* @author Fabio Zöllner */
* @version 1.0, 09.04.2012 public interface AerialMovementModelFactory {
*/ public UAVMovementModel createComponent(UAVTopologyComponent topologyComponent);
public class PathEdgeFactory implements EdgeFactory<Waypoint, Path> { }
@Override
public Path createEdge(Waypoint sourceVertex, Waypoint targetVertex) {
// Path uses the distance as weight by default
Path path = new Path(sourceVertex, targetVertex);
return path;
}
}
/*
* 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.aerial;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.impl.energy.components.ActuatorComponent;
import de.tud.kom.p2psim.impl.energy.components.StatelessActuatorComponent;
import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.db.metric.CustomMeasurement;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback;
/**
* Simplified thrust-based local movement model based on the Intel Aero UAV.
*
* The movement logic uses only straight forward movement with the maximum speed available.
*
* TODO Acceleration
* TODO Movement model for plane-like UAVs
*
* @author Julian Zobel
* @version 1.0, 11.09.2018
*/
public class MulticopterMovement implements UAVMovementModel {
private UAVTopologyComponent topologyComponent;
private double currentAngleOfAttack;
private double velocity;
private double targetVelocity;
private LinkedList<PositionVector> route = new LinkedList<>();
private Map<PositionVector, ReachedLocationCallback> locationCallbacks = new LinkedHashMap<>(); // TODO callback interface
private StatelessActuatorComponent motor;
private double mass; // kg
private double areaTop; // m^2
private double areaFront; // m^2
private double dragCoefficient;
private double maximumPitchAngleAllowed; // ° max angle
private double maximumDecentVelocityAllowed; // m/s
// TODO currently not used
private double maximumTurnAngle; // 90° per second turn angle
public MulticopterMovement(UAVTopologyComponent topologyComponent, double massTotal,
double areaTop, double areaFront, double UAVDragCoefficient, double maximumPitchAngleAllowed,
double maximumDecentVelocityAllowed, double maximumTurnAngle) {
this.topologyComponent = topologyComponent;
this.mass = massTotal;
this.areaTop = areaTop;
this.areaFront = areaFront;
this.dragCoefficient = UAVDragCoefficient;
this.maximumPitchAngleAllowed = maximumPitchAngleAllowed;
this.maximumDecentVelocityAllowed = maximumDecentVelocityAllowed;
this.maximumTurnAngle = maximumTurnAngle;
}
boolean first = true;
@Override
public void move(long timeBetweenMovementOperations) {
if(motor.isOn() && !route.isEmpty()) {
PositionVector position = new PositionVector(topologyComponent.getRealPosition());
PositionVector target = route.getFirst();
double distanceToTargetPosition = position.distanceTo(target);
// If target point is reached within a 1 meter margin, we remove that point from the list
if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < velocity)
{
target = route.removeFirst();
if(route.isEmpty()) {
// go to hover mode
topologyComponent.updateCurrentLocation(target.clone());
velocity = 0;
motor.requestThrust(hoverThrustRequired());
PositionVector direction = topologyComponent.getCurrentDirection().clone();
direction.setEntry(2, 0);
topologyComponent.updateCurrentDirection(direction);
locationReached(topologyComponent.getCurrentLocation());
return;
}
else {
// get to speed
if(targetVelocity > 0 && targetVelocity < getHorizontalMaxVelocity()) {
motor.requestThrust(estimateRequiredThrust(targetVelocity));
velocity = targetVelocity;
}
else {
motor.requestThrust(getHorizontalMaxVelocityRequiredTotalThrust());
velocity = getHorizontalMaxVelocity();
}
long timeUntilReachedLocation = (long) (distanceToTargetPosition / velocity) * Time.SECOND;
target = route.getFirst();
PositionVector directionToTarget = new PositionVector(target);
directionToTarget.subtract(position);
double timefactor = timeUntilReachedLocation / Time.SECOND;
directionToTarget.normalize();
topologyComponent.updateCurrentDirection(directionToTarget.clone());
directionToTarget.multiplyScalar(velocity * timefactor);
PositionVector newPosition = new PositionVector(position);
newPosition.add(directionToTarget);
topologyComponent.updateCurrentLocation(newPosition);
if(timeUntilReachedLocation < timeBetweenMovementOperations) {
this.move(timeBetweenMovementOperations - timeUntilReachedLocation);
}
}
}
else {
double timefactor = timeBetweenMovementOperations / Time.SECOND;
// get to speed
if(targetVelocity > 0 && targetVelocity < getHorizontalMaxVelocity()) {
motor.requestThrust(estimateRequiredThrust(targetVelocity));
velocity = targetVelocity;
}
else {
motor.requestThrust(getHorizontalMaxVelocityRequiredTotalThrust());
velocity = getHorizontalMaxVelocity();
}
PositionVector directionToTarget = new PositionVector(target);
directionToTarget.subtract(position);
directionToTarget.normalize();
if(directionToTarget.getX() != 0 || directionToTarget.getY() != 0) {
topologyComponent.updateCurrentDirection(directionToTarget.clone());
}
directionToTarget.multiplyScalar(velocity * timefactor);
PositionVector newPosition = new PositionVector(position);
newPosition.add(directionToTarget);
topologyComponent.updateCurrentLocation(newPosition);
}
}
else if(motor.isOn()) {
if(velocity != 0) {
throw new UnsupportedOperationException("no route but speed not 0?");
}
PositionVector position = new PositionVector(topologyComponent.getRealPosition());
if(position.getAltitude() == 0) {
motor.requestThrust(0);
}
else {
motor.requestThrust(hoverThrustRequired());
}
}
}
/*
*
*/
protected double verticalDescentMaxThrust() {
// m * g - 0.5 * p * C * A * v^2
return hoverThrustRequired() - 0.5 * bodyDrag(0, new PositionVector(0,0,1)) * maximumDecentVelocityAllowed * maximumDecentVelocityAllowed;
}
protected double verticalAscentMaxAcceleration() {
return (motor.getMaxThrust() - hoverThrustRequired()) / mass;
}
@Override
public double getVerticalAscentMaxVelocity() {
double maxThrust = motor.getMaxThrust();
return Math.sqrt(2.0 * (maxThrust - hoverThrustRequired()) / bodyDrag(0, new PositionVector(0,0,1)));
}
protected double hoverThrustRequired() {
return mass * GRAVITY;
}
@Override
public double getHorizontalMaxVelocity() {
double horizontalThrust = getHorizontalComponentMaxThrust();
double maxVelocity = Math.sqrt( (2.0 * horizontalThrust) / bodyDrag(maximumPitchAngleAllowed, new PositionVector(1,0,0)));
return maxVelocity;
}
protected double getHorizontalComponentMaxThrust() {
// hoverthrust / cos => amount of thrust in horizonal direction with °angle
double stableAltitudeMaximumTotalThrust = getHorizontalMaxVelocityRequiredTotalThrust();
// fraction of total thrust in horizonal (forward) direction with °angle
double maximumHorizontalThrustStableAltitude = stableAltitudeMaximumTotalThrust * Math.sin(maximumPitchAngleAllowed);
return maximumHorizontalThrustStableAltitude;
}
protected double getHorizontalMaxVelocityRequiredTotalThrust() {
return hoverThrustRequired() / Math.cos(maximumPitchAngleAllowed);
}
protected double bodyDrag(double angleRadians, PositionVector direction) {
return AIRDENSITY * dragCoefficient * areaExposedToDrag(angleRadians, direction);
}
protected double areaExposedToDrag(double angleRadians, PositionVector direction) {
Vector2D v = new Vector2D(Math.abs(direction.getX()) + Math.abs(direction.getY()), Math.abs(direction.getZ()));
v = v.normalize();
double areaExposedFront = v.getX() * (Math.sin(angleRadians) * areaTop + Math.cos(angleRadians) * areaFront );
double areaExposedTop = v.getY() * (Math.cos(angleRadians) * areaTop + Math.sin(angleRadians) * areaFront);
return areaExposedFront + areaExposedTop;
}
/*
* F_drag [N] = 0.5 * p * C_drag * A * v^2
*/
protected double currentDrag() {
return 0.5 * bodyDrag(currentAngleOfAttack, topologyComponent.getCurrentDirection()) * velocity * velocity;
}
/**
* Calculate the drag induced on the UAV with a given velocity and an angle of attack (in radians) moving forward horizontally.
*
* @param velocity
* @param angleInRadians
* @return
*/
protected double forwardDrag(double velocity, double angleInRadians) {
return 0.5 * bodyDrag(angleInRadians, new PositionVector(1,0,0)) * velocity * velocity;
}
/*
*
*/
@Override
public void setMotorControl(ActuatorComponent motor) {
this.motor = (StatelessActuatorComponent) motor;
}
@Override
public void setTargetVelocity(double v_pref) {
this.targetVelocity = v_pref;
}
@Override
public double getCurrentVelocity() {
return velocity;
}
/**
* Trigger the callback function, if there is a valid callback
*
* @param position
*/
private void locationReached(PositionVector position) {
if(locationCallbacks.containsKey(position)) {
locationCallbacks.get(position).reachedLocation();
}
}
@Override
public void setTargetLocation(PositionVector target,
ReachedLocationCallback reachedLocationCallback) {
route.clear();
route.add(target);
if(reachedLocationCallback != null)
locationCallbacks.put(target, reachedLocationCallback);
}
@Override
public void setTargetLocationRoute(LinkedList<PositionVector> route,
ReachedLocationCallback reachedLocationCallback) {
this.route.clear();
this.route.addAll(route);
if(reachedLocationCallback != null)
locationCallbacks.put(route.getLast(), reachedLocationCallback);
}
@Override
public void addTargetLocation(PositionVector target,
ReachedLocationCallback reachedLocationCallback) {
route.add(target);
if(reachedLocationCallback != null)
locationCallbacks.put(target, reachedLocationCallback);
}
@Override
public LinkedList<PositionVector> getTargetLocations() {
LinkedList<PositionVector> copy = new LinkedList<>();
for (PositionVector pv : route) {
copy.add(pv.clone());
}
return copy;
}
@Override
public void removeTargetLocations() {
route.clear();
locationCallbacks.clear();
}
@Override
public double getHorizontalMinVelocity() {
return Math.sqrt(2 * hoverThrustRequired() * Math.tan(Math.toRadians(0.25)) / bodyDrag(Math.toRadians(0.25), new PositionVector(1,0,0)));
}
@Override
public double estimatePowerConsumptionWatt(double velocity) {
if(velocity == 0) {
return motor.estimatePowerConsumptionWatt(hoverThrustRequired());
}
else if(velocity > getHorizontalMaxVelocity()) {
return -1;
}
else if(velocity < getHorizontalMinVelocity()) {
return -1;
}
else {
double requiredThrust = estimateRequiredThrust(velocity);
double wattage = motor.estimatePowerConsumptionWatt(requiredThrust);
return wattage;
}
}
protected double estimateRequiredThrust(double velocity) {
if(velocity == 0) {
return motor.estimatePowerConsumptionWatt(hoverThrustRequired());
}
else if(velocity > getHorizontalMaxVelocity()) {
return -1;
}
else if(velocity < getHorizontalMinVelocity()) {
return -1;
}
else {
double estimateAngle = estimatePitchAngleForVelocity(velocity);
double estimatedDrag = forwardDrag(velocity, estimateAngle);
double requiredThrust = Math.sqrt(hoverThrustRequired() * hoverThrustRequired() + estimatedDrag * estimatedDrag);
return requiredThrust;
}
}
/**
* Estimate the pitch angle (angle of attack) required to get the target velocity.
* Angle precision is 1/4 degree.
*
* @param velocity
* @return
*/
protected double estimatePitchAngleForVelocity(double velocity) {
int low = 0;
int high = Integer.MAX_VALUE;
double vsquared = (velocity * velocity);
for(int i = 0; i <= ((int) Math.toDegrees(maximumPitchAngleAllowed)); i++) {
double v2 = 2 * hoverThrustRequired() * Math.tan(Math.toRadians(i)) / bodyDrag(Math.toRadians(i), new PositionVector(1,0,0));
if(v2 > vsquared && i < high) {
high = i;
}
else if(v2 < vsquared && i >= low) {
low = i;
}
else if(v2 == vsquared ) {
return Math.toRadians(i);
}
}
if(high < Integer.MAX_VALUE) {
double lo = low;
double hi = high;
double nearest = -1;
double nearestDiff = Double.MAX_VALUE;
double step = (hi - lo) / 4;
for(int i = 0; i < 4; i++) {
double d = lo + i * step;
double v2 = 2 * hoverThrustRequired() * Math.tan(Math.toRadians(d)) / bodyDrag(Math.toRadians(d), new PositionVector(1,0,0));
double diff = Math.abs(((velocity * velocity) - v2));
if(diff < nearestDiff || (lo == 0 && i == 1)) {
nearestDiff = diff;
nearest = d;
}
}
return Math.toRadians(nearest);
}
return maximumPitchAngleAllowed;
}
/**
* Factory for this movement model
*
* @author Julian Zobel
* @version 1.0, 14.01.2020
*/
public static class Factory implements AerialMovementModelFactory {
private double massTotal = 1.465; // kg
private double areaTop = 0.245; // m^2
private double areaFront = 0.1; // m^2
private double UAVDragCoefficient = 0.7;
private double maximumPitchAngleAllowed = Math.toRadians(60); // ° max angle
private double maximumDecentVelocityAllowed = 5; // m/s
private double maximumTurnAngle = Math.toRadians(90); // 90° per second turn angle
public void setMassTotal(double massTotal) {
this.massTotal = massTotal;
}
public void setAreaTop(double areaTop) {
this.areaTop = areaTop;
}
public void setAreaFront(double areaFront) {
this.areaFront = areaFront;
}
public void setUAVDragCoefficient(double uAVDragCoefficient) {
UAVDragCoefficient = uAVDragCoefficient;
}
public void setMaximumPitchAngleAllowed(double maximumPitchAngleAllowed) {
this.maximumPitchAngleAllowed = Math.toRadians(maximumPitchAngleAllowed);
}
public void setMaximumDecentVelocityAllowed(
double maximumDecentVelocityAllowed) {
this.maximumDecentVelocityAllowed = maximumDecentVelocityAllowed;
}
public void setMaximumTurnAngle(double maximumTurnAngle) {
this.maximumTurnAngle = Math.toRadians(maximumTurnAngle);
}
public UAVMovementModel createComponent(UAVTopologyComponent topologyComponent) {
return new MulticopterMovement(topologyComponent, massTotal, areaTop, areaFront,
UAVDragCoefficient, maximumPitchAngleAllowed, maximumDecentVelocityAllowed, maximumTurnAngle);
}
}
// For evaluation only!
@Entity
@Table(name = "energyModel")
public static class EnergyModelPropertyMeasurement extends CustomMeasurement {
/*
* For DB performance reasons, we only store up to 15 characters of the
* topic (longer topics are truncated)
*/
@Column(nullable = false, name = "[velocity]")
final float velocity;
@Column(nullable = false, name = "[thrust]")
final float thrust;
@Column(nullable = false, name = "[ampere]")
final float ampere;
@Column(nullable = false, name = "[watt]")
final float watt;
@Column(nullable = false, name = "[wattPerMeter]")
final float wattperdistance;
public EnergyModelPropertyMeasurement(double velocity, double thrust, double ampere, double watt) {
/*
* Store all relevant fields
*/
this.velocity = (float) velocity;
this.thrust = (float) thrust;
this.ampere = (float) ampere;
this.watt = (float) watt;
if (velocity == 0) {
this.wattperdistance = -1;
} else
this.wattperdistance = this.watt / this.velocity;
}
public static EnergyModelPropertyMeasurement getPropoertyMeasurement(MulticopterMovement m, double velocity) {
double th = m.estimateRequiredThrust(velocity);
if (th == -1) {
return null;
}
double w = m.estimatePowerConsumptionWatt(velocity);
double amp = w / 14.8;
return new EnergyModelPropertyMeasurement(velocity, th, amp, w);
}
}
}
/*
* 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.aerial;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.impl.energy.components.ActuatorComponent;
import de.tud.kom.p2psim.impl.energy.components.StatefulActuatorComponent;
import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback;
/**
* Local movement for UAVs.
* This simple movement logic uses straight forward movement with the set speed (up to a max).
* Energy consumption is based on state actuators.
*
* @author Julian Zobel
* @version 1.1, 14.01.2020
*/
public class SimpleMulticopterMovement implements UAVMovementModel {
private UAVTopologyComponent topologyComponent;
private double velocity;
private double targetVelocity;
private double maximumHorizontalVelocity;
private double maximumVerticalVelocity;
// TODO currently not used
private double minimumHorizontalVelocity;
private double minimumVerticalVelocity;
private LinkedList<PositionVector> route = new LinkedList<>();
private Map<PositionVector, ReachedLocationCallback> locationCallbacks = new LinkedHashMap<>();
private StatefulActuatorComponent motor;
public SimpleMulticopterMovement(UAVTopologyComponent topologyComponent, double maximumHorizontalVelocity,
double maximumVerticalVelocity, double minimumHorizontalVelocity, double minimumVerticalVelocity) {
this.topologyComponent = topologyComponent;
this.maximumHorizontalVelocity = maximumHorizontalVelocity;
this.maximumVerticalVelocity = maximumVerticalVelocity;
this.minimumHorizontalVelocity = minimumHorizontalVelocity;
this.minimumVerticalVelocity = minimumVerticalVelocity;
}
@Override
public void move(long timeBetweenMovementOperations) {
if(motor.isOn() && !route.isEmpty()) {
PositionVector currentPosition = topologyComponent.getRealPosition();
PositionVector targetPosition = route.getFirst();
Double distanceToTargetPosition = targetPosition.distanceTo(currentPosition);
// If target point is reached within a 1 meter margin, we remove that point from the list
if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < velocity)
{
route.removeFirst();
topologyComponent.updateCurrentLocation(targetPosition); // triggers energy consumption for last distance
velocity = 0;
motor.useActuator(0);
locationReached(targetPosition);
return;
}
double timefactor = timeBetweenMovementOperations / Time.SECOND;
velocity = Math.min(distanceToTargetPosition, targetVelocity);
PositionVector direction = new PositionVector(targetPosition);
direction.subtract(currentPosition);
direction.normalize();
direction.multiplyScalar(velocity * timefactor);
PositionVector newPosition = new PositionVector(currentPosition);
newPosition.add(direction);
motor.useActuator(1);
topologyComponent.updateCurrentLocation(newPosition);
}
else if(motor.isOn()) {
if(velocity != 0) {
throw new UnsupportedOperationException("no route but speed not 0?");
}
PositionVector position = new PositionVector(topologyComponent.getRealPosition());
if(position.getAltitude() == 0) {
motor.turnOff();
}
else {
motor.useActuator(0);
}
}
}
@Override
public void setTargetVelocity(double v_pref) {
this.targetVelocity = v_pref;
}
@Override
public double getCurrentVelocity() {
return velocity;
}
/**
* Trigger the callback function, if there is a valid callback
*
* @param position
*/
private void locationReached(PositionVector position) {
if(locationCallbacks.containsKey(position)) {
locationCallbacks.get(position).reachedLocation();
}
}
@Override
public void setTargetLocation(PositionVector target,
ReachedLocationCallback reachedLocationCallback) {
route.clear();
route.add(target);
if(reachedLocationCallback != null)
locationCallbacks.put(target, reachedLocationCallback);
}
@Override
public void setTargetLocationRoute(LinkedList<PositionVector> route,
ReachedLocationCallback reachedLocationCallback) {
this.route.clear();
this.route.addAll(route);
if(reachedLocationCallback != null)
locationCallbacks.put(route.getLast(), reachedLocationCallback);
}
@Override
public void addTargetLocation(PositionVector target,
ReachedLocationCallback reachedLocationCallback) {
route.add(target);
if(reachedLocationCallback != null)
locationCallbacks.put(target, reachedLocationCallback);
}
@Override
public LinkedList<PositionVector> getTargetLocations() {
LinkedList<PositionVector> copy = new LinkedList<>();
for (PositionVector pv : route) {
copy.add(pv.clone());
}
return copy;
}
@Override
public void removeTargetLocations() {
route.clear();
locationCallbacks.clear();
}
@Override
public double estimatePowerConsumptionWatt(double velocity) {
double wattage = 0;
if(velocity == 0) {
wattage = motor.estimateEnergyConsumptionWatt(0);
}
else {
wattage = motor.estimateEnergyConsumptionWatt(1.0);
}
return wattage;
}
@Override
public void setMotorControl(ActuatorComponent motor) {
this.motor = (StatefulActuatorComponent) motor;
}
@Override
public double getVerticalAscentMaxVelocity() {
return maximumVerticalVelocity;
}
@Override
public double getHorizontalMaxVelocity() {
return maximumHorizontalVelocity;
}
@Override
public double getHorizontalMinVelocity() {
return 0;
}
/**
* Factory for this movement model
*
* @author Julian Zobel
* @version 1.0, 14.01.2020
*/
public static class Factory implements AerialMovementModelFactory {
private double maximumHorizontalVelocity = 15;
public void setMaximumHorizontalVelocity(double maximumHorizontalVelocity) {
this.maximumHorizontalVelocity = maximumHorizontalVelocity;
}
private double maximumVerticalVelocity = 5;
public void setMaximumVerticalVelocity(double maximumVerticalVelocity) {
this.maximumVerticalVelocity = maximumVerticalVelocity;
}
private double minimumHorizontalVelocity = 15;
public void setMinimumHorizontalVelocity(double minimumHorizontalVelocity) {
this.minimumHorizontalVelocity = minimumHorizontalVelocity;
}
private double minimumVerticalVelocity = 5;
public void setMinimumVerticalVelocity(double minimumVerticalVelocity) {
this.minimumVerticalVelocity = minimumVerticalVelocity;
}
public UAVMovementModel createComponent(UAVTopologyComponent topologyComponent) {
return new SimpleMulticopterMovement(topologyComponent, maximumHorizontalVelocity,
maximumVerticalVelocity, minimumHorizontalVelocity, minimumVerticalVelocity);
}
}
}
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.topology.waypoints.graph; package de.tud.kom.p2psim.impl.topology.movement.aerial;
import java.util.Set; import java.util.LinkedList;
import java.util.WeakHashMap; import java.util.List;
import org.jgrapht.EdgeFactory; import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import org.jgrapht.graph.SimpleWeightedGraph; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.SimUAVLocationActuator;
/** import de.tudarmstadt.maki.simonstrator.api.Event;
* The simple weighted edge retrievable graph caches the edges import de.tudarmstadt.maki.simonstrator.api.EventHandler;
* for later batch retrieval. import de.tudarmstadt.maki.simonstrator.api.Time;
*
* It uses the WeakHashMap to avoid unintentional references to /**
* dead objects. * Movement model container for all UAVs. This primarily triggers the local movement models of the respective UAVs.
* *
* @author Fabio Zöllner * @author Julian Zobel
* @version 1.0, 27.03.2012 * @version 1.0, 6 Sep 2018
* @param <V> Vertices */
* @param <E> Edges public class UAVMovement implements MovementModel, EventHandler {
*/
public class DefaultWeightedEdgeRetrievableGraph<V, E> extends SimpleWeightedGraph<V, E> { private List<SimUAVLocationActuator> actuators = new LinkedList<>();
private WeakHashMap<E, Object> edgeMap = new WeakHashMap<E, Object>(); protected long timeBetweenMoveOperation = Time.SECOND;
@SuppressWarnings("unchecked") public UAVMovement() {
public DefaultWeightedEdgeRetrievableGraph(EdgeFactory edgefactory) { Event.scheduleImmediately(this, null, 0);
super(edgefactory); }
}
@Override
@SuppressWarnings("unchecked") public void addComponent(SimLocationActuator actuator) {
public DefaultWeightedEdgeRetrievableGraph(Class class1) { if(!actuators.contains(actuator) && actuator instanceof SimUAVLocationActuator)
super(class1); actuators.add((SimUAVLocationActuator) actuator);
} }
/** @Override
* Add an edge to the graph by specifying the public void placeComponent(SimLocationActuator actuator) {
* start and end vertex. //
*/ }
public E addEdge(V v1, V v2) {
E e = getEdgeFactory().createEdge(v1, v2); @Override
addEdge(v1, v2, e); public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperation = time;
return e; }
}
@Override
/** public void eventOccurred(Object content, int type) {
* Add an edge to the graph by specifying the this.triggerComponentMovement();
* start and end vertex as well as the edge }
* that is connecting the two.
*/ private void triggerComponentMovement() {
public boolean addEdge(V v1, V v2, E e) { for (SimUAVLocationActuator actuator : actuators) {
edgeMap.put(e, null); actuator.getUAVMovement().move(timeBetweenMoveOperation);
}
return super.addEdge(v1, v2, e);
} Event.scheduleWithDelay(timeBetweenMoveOperation, this, null, 1);
}
/**
* Returns the set of all edges in the graph.
* }
* @return
*/
public Set<E> getAllEdges() {
return edgeMap.keySet();
}
}
...@@ -24,7 +24,7 @@ import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; ...@@ -24,7 +24,7 @@ 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.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel; import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor; import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
package de.tud.kom.p2psim.impl.topology.movement.local; package de.tud.kom.p2psim.impl.topology.movement.local;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Left;
......
...@@ -37,8 +37,8 @@ import com.graphhopper.util.shapes.GHPoint3D; ...@@ -37,8 +37,8 @@ import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation; import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
......
...@@ -26,35 +26,44 @@ import java.util.LinkedList; ...@@ -26,35 +26,44 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.UUID; import java.util.UUID;
import com.graphhopper.GHRequest; import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse; import com.graphhopper.GHResponse;
import com.graphhopper.GraphHopper; import com.graphhopper.GraphHopper;
import com.graphhopper.PathWrapper; import com.graphhopper.PathWrapper;
import com.graphhopper.reader.osm.GraphHopperOSM;
import com.graphhopper.routing.util.EdgeFilter; import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.EncodingManager; import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.routing.util.TraversalMode; import com.graphhopper.routing.util.TraversalMode;
import com.graphhopper.routing.weighting.BlockAreaWeighting;
import com.graphhopper.storage.index.LocationIndex; import com.graphhopper.storage.index.LocationIndex;
import com.graphhopper.storage.index.QueryResult; import com.graphhopper.storage.index.QueryResult;
import com.graphhopper.util.DistanceCalc2D; import com.graphhopper.util.DistanceCalc2D;
import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.Instruction; import com.graphhopper.util.Instruction;
import com.graphhopper.util.InstructionList; import com.graphhopper.util.InstructionList;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.Parameters.Routing;
import com.graphhopper.util.PointList; import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint; import com.graphhopper.util.shapes.GHPoint;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation; import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModelViz;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.RouteSensorComponent; import de.tud.kom.p2psim.impl.topology.movement.modularosm.RouteSensorComponent;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.RandomAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException; import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* This movement strategy uses the data from osm and navigates the nodes throught streets to the destination * This movement strategy uses the data from osm and navigates the nodes throught streets to the destination
...@@ -64,9 +73,20 @@ import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableExcep ...@@ -64,9 +73,20 @@ import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableExcep
* *
* @author Martin Hellwig * @author Martin Hellwig
* @version 1.0, 07.07.2015 * @version 1.0, 07.07.2015
*
* - added a possibility to allow the usage of alternative routes
* - set the probability for this alternatives
* - allow a dynamic reload of graphhopper files when switching routing algorithms
* - allow to define blocked areas, that are not used for routing
*
* @author Julian Zobel
* @version 02.04.2020
*
*/ */
public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
private Random random = Randoms.getRandom(RealWorldStreetsMovement.class);
private static PositionVector worldDimensions; private static PositionVector worldDimensions;
private GraphHopper hopper; private GraphHopper hopper;
private LocationIndex index; private LocationIndex index;
...@@ -81,11 +101,15 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -81,11 +101,15 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
private String movementType; //car, bike or foot private String movementType; //car, bike or foot
private String defaultMovement; private String defaultMovement;
private String navigationalType; //fastest, private String navigationalType; //fastest,
private String blockedAreas; // default null
private static double latLower; //Values from -90 to 90; always smaller than latUpper private static double latLower; //Values from -90 to 90; always smaller than latUpper
private static double latUpper; //Values from -90 to 90 private static double latUpper; //Values from -90 to 90
private static double lonLeft; //Values from -180 to 180; Always smaller than lonRight private static double lonLeft; //Values from -180 to 180; Always smaller than lonRight
private static double lonRight; //Values from -180 to 180 private static double lonRight; //Values from -180 to 180
private boolean uniqueFolders; private boolean uniqueFolders;
private boolean allowAlternativeRoutes = false;
private double probabilityForAlternativeRoute = 0.0;
/** /**
* Tolerance in meters (if the node reached a waypoint up to "tolerance" * Tolerance in meters (if the node reached a waypoint up to "tolerance"
...@@ -93,6 +117,12 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -93,6 +117,12 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
*/ */
private double tolerance = 1; private double tolerance = 1;
@XMLConfigurableConstructor({"blockedAreas"})
public RealWorldStreetsMovement(String blockedAreas) {
this();
this.setBlockedAreas(blockedAreas);
}
public RealWorldStreetsMovement() { public RealWorldStreetsMovement() {
worldDimensions = Binder.getComponentOrNull(Topology.class) worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions(); .getWorldDimensions();
...@@ -100,13 +130,12 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -100,13 +130,12 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
latUpper = GPSCalculation.getLatUpper(); latUpper = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft(); lonLeft = GPSCalculation.getLonLeft();
lonRight = GPSCalculation.getLonRight(); lonRight = GPSCalculation.getLonRight();
} }
private void init() { private void init() {
hopper = new GraphHopper().forServer(); hopper = new GraphHopperOSM().forServer();
hopper.setOSMFile(osmFileLocation); hopper.setDataReaderFile(osmFileLocation);
// where to store graphhopper files? // where to store graphhopper files?
if (uniqueFolders) { if (uniqueFolders) {
Monitor.log(RealWorldStreetsMovement.class, Level.WARN, Monitor.log(RealWorldStreetsMovement.class, Level.WARN,
...@@ -118,12 +147,27 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -118,12 +147,27 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
hopper.setGraphHopperLocation(graphFolderFiles + "/" hopper.setGraphHopperLocation(graphFolderFiles + "/"
+ osmFileLocation.hashCode() + movementType); + osmFileLocation.hashCode() + movementType);
} }
hopper.setEncodingManager(new EncodingManager(movementType)); hopper.setEncodingManager(EncodingManager.create(movementType));
hopper.importOrLoad();
// if we have blocked areas defined, the CH in Graphhopper needs to be disabled!
// this also requires a new import
if((blockedAreas != null && !blockedAreas.isEmpty()) || allowAlternativeRoutes) {
hopper.setCHEnabled(false);
}
// try to load a cached import. If the cached import was with a different CH_ENABLED setting then now specified, this will fail.
// in this case, clean cache and re-import.
try {
hopper.importOrLoad();
} catch (Exception e) {
System.err.println("[RealWorldStreetMovement] GraphHopper graph file must be imported again!");
hopper.clean();
hopper.importOrLoad();
}
index = hopper.getLocationIndex(); index = hopper.getLocationIndex();
init = true; init = true;
} }
@Override @Override
public Either<PositionVector, Boolean> nextPosition( public Either<PositionVector, Boolean> nextPosition(
...@@ -168,7 +212,22 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -168,7 +212,22 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
setWeighting(navigationalType). setWeighting(navigationalType).
setVehicle(movementType). setVehicle(movementType).
setLocale(Locale.GERMANY); setLocale(Locale.GERMANY);
GHResponse rsp = hopper.route(req);
// blocks one or multiple given areas from being used by the routing
// https://github.com/graphhopper/graphhopper/blob/master/docs/web/api-doc.md#flexible
if(blockedAreas != null && !blockedAreas.isEmpty()) {
req.getHints().put(Routing.BLOCK_AREA, blockedAreas);
}
if(allowAlternativeRoutes) {
// see: https://discuss.graphhopper.com/t/alternative-routes/424/11
req.setAlgorithm(Parameters.Algorithms.ALT_ROUTE);
req.getHints().put(Parameters.Algorithms.AltRoute.MAX_WEIGHT, "2.0"); // how much longer can alternatives be?
req.getHints().put(Parameters.Algorithms.AltRoute.MAX_PATHS, "5"); // how much alternatives should be returned at max?
}
GHResponse rsp = hopper.route(req);
//If the requested point is not in the map data, simple return the destination as next point //If the requested point is not in the map data, simple return the destination as next point
if(rsp.hasErrors()) { if(rsp.hasErrors()) {
Monitor.log(this.getClass(), Monitor.Level.ERROR, "Routing request for Host %s with starting point (" + Monitor.log(this.getClass(), Monitor.Level.ERROR, "Routing request for Host %s with starting point (" +
...@@ -181,7 +240,20 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -181,7 +240,20 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
currentRoutes.put(comp, trajectory); currentRoutes.put(comp, trajectory);
} else { } else {
PointList pointList = rsp.getBest().getPoints(); PointList pointList = rsp.getBest().getPoints();
// alternatives for routing are allowed for distances bigger than 50
if(allowAlternativeRoutes && rsp.hasAlternatives() && rsp.getBest().getDistance() > 50) {
// alternative route is taken with a certain chance
if(random.nextDouble() <= probabilityForAlternativeRoute) {
List<PathWrapper> paths = rsp.getAll();
int pick = random.nextInt(paths.size() - 1) + 1;
pointList = rsp.getAll().get(pick).getPoints();
}
}
//PointList pointList = rsp.getBest().getPoints();
if (isCalculateRouteSegments()) { if (isCalculateRouteSegments()) {
/* /*
...@@ -223,8 +295,9 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -223,8 +295,9 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
RouteSegmentImpl segment = null; RouteSegmentImpl segment = null;
PointList points = instr.getPoints(); PointList points = instr.getPoints();
String name = instr.getName(); String name = instr.getName();
if (name.isEmpty()) { if (name.isEmpty()) {
name = Integer.toString(instr.getPoints().toGHPoint(0).hashCode()); name = Integer.toString(instr.getPoints().get(0).hashCode());
//name = Integer.toString(instr.getPoints().toGHPoint(0).hashCode()); @deprecated for old GraphHopper version
} }
for (GHPoint point : points) { for (GHPoint point : points) {
if (segment == null) { if (segment == null) {
...@@ -399,4 +472,19 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -399,4 +472,19 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
public void setCreateUniqueFolders(boolean uniqueFolders) { public void setCreateUniqueFolders(boolean uniqueFolders) {
this.uniqueFolders = uniqueFolders; this.uniqueFolders = uniqueFolders;
} }
public void setBlockedAreas(String blockedAreas) {
if(!blockedAreas.isEmpty()) {
this.blockedAreas = blockedAreas;
}
}
public void setAllowAlternativeRoutes(boolean allowAlternativeRoutes) {
this.allowAlternativeRoutes = allowAlternativeRoutes;
}
public void setProbabilityForAlternativeRoute(double p) {
this.probabilityForAlternativeRoute = p;
}
} }
...@@ -29,7 +29,7 @@ import com.graphhopper.util.PointList; ...@@ -29,7 +29,7 @@ import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint3D; import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route; import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor; import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
......
...@@ -23,7 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.local; ...@@ -23,7 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.local;
import java.util.List; import java.util.List;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint;
......
...@@ -24,9 +24,11 @@ import java.util.ArrayList; ...@@ -24,9 +24,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import org.jgrapht.graph.DefaultWeightedEdge;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path; import de.tud.kom.p2psim.impl.topology.waypoints.graph.PathEdge;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
...@@ -114,7 +116,7 @@ public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy ...@@ -114,7 +116,7 @@ public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy
Waypoint closestWaypointToDestination = waypointModel Waypoint closestWaypointToDestination = waypointModel
.getClosestWaypoint(finalDestination, WeakWaypoint.class); .getClosestWaypoint(finalDestination, WeakWaypoint.class);
List<Path> shortestPath = waypointModel.getShortestPath( List<PathEdge> shortestPath = waypointModel.getShortestPath(
closestWaypointToCurrentPosition, closestWaypointToDestination); closestWaypointToCurrentPosition, closestWaypointToDestination);
List<Waypoint> waypointList = buildWaypointList( List<Waypoint> waypointList = buildWaypointList(
...@@ -133,13 +135,13 @@ public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy ...@@ -133,13 +135,13 @@ public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy
* @return * @return
*/ */
protected List<Waypoint> buildWaypointList(Waypoint start, protected List<Waypoint> buildWaypointList(Waypoint start,
List<Path> shortestPath) { List<PathEdge> shortestPath) {
List<Waypoint> waypointList = new ArrayList<Waypoint>(); List<Waypoint> waypointList = new ArrayList<Waypoint>();
Waypoint lastWaypoint = start; Waypoint lastWaypoint = start;
waypointList.add(start); waypointList.add(start);
for (Path p : shortestPath) { for (PathEdge p : shortestPath) {
lastWaypoint = p.getOtherEnd(lastWaypoint); lastWaypoint = p.getOtherEnd(lastWaypoint);
waypointList.add(lastWaypoint); waypointList.add(lastWaypoint);
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
package de.tud.kom.p2psim.impl.topology.movement.modularosm; package de.tud.kom.p2psim.impl.topology.movement.modularosm;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
...@@ -134,7 +135,35 @@ public class GPSCalculation { ...@@ -134,7 +135,35 @@ public class GPSCalculation {
public void setLonCenter(double lonCenter) { public void setLonCenter(double lonCenter) {
this.lonCenter = lonCenter; this.lonCenter = lonCenter;
} }
/**
* Projects the gps coordinates in the given gps window to the world-coordinates given in world-dimensions
* @param lat
* @param lon
* @return The projected position in world-dimensions
*/
public static PositionVector transformGPSWindowToOwnWorld(double lat, double lon) {
double x = getWorldDimensionsX() * (lon - getLonLeft())/(getLonRight() - getLonLeft());
//Invert the y value, because in Java Swing we start drawing in the upper left corner instead in the lower left one
double y = getWorldDimensionsY() - getWorldDimensionsY() * (lat - getLatLower())/(getLatUpper() - getLatLower());
return new PositionVector(x, y);
}
/**
* Checks if the given latitute and longitude is within the simulated GPS area.
*
* @param lat
* @param lon
* @return True if within the GPS area, false otherwise.
*/
public static boolean isWithinGPSBoundaries(double lat, double lon) {
if(lat > getLatLower() && lat < getLatUpper() &&
lon > getLonLeft() && lon < getLonRight()) {
return true;
}
else return false;
}
/** /**
* Formula http://wiki.openstreetmap.org/wiki/Zoom_levels * Formula http://wiki.openstreetmap.org/wiki/Zoom_levels
* *
......
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.topology.waypoints.graph; package de.tud.kom.p2psim.impl.topology.movement.modularosm;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import org.jgrapht.EdgeFactory; import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.Analyzer;
import org.jgrapht.graph.DefaultDirectedWeightedGraph; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
/** public interface IAttractionBasedMovementAnalyzer extends Analyzer {
* The simple weighted edge retrievable graph caches the edges
* for later batch retrieval. public void onAllNodeInitializationCompleted(Set<SimLocationActuator> nodes);
*
* It uses the WeakHashMap to avoid unintentional references to public void onAttractionPointAdded(IAttractionPoint attractionpoint);
* dead objects.
* public void onAttractionPointRemoved(IAttractionPoint attractionpoint);
* @author Fabio Zöllner
* @version 1.0, 27.03.2012 public void onUpdateAttractionAssignment(SimLocationActuator node, IAttractionPoint attractionpoint);
* @param <V> Vertices
* @param <E> Edges
*/ public void onNodeReachedAttractionPoint(SimLocationActuator node, IAttractionPoint attractionpoint);
public class DefaultDirectedWeightedEdgeRetrievableGraph<V, E> extends DefaultDirectedWeightedGraph<V, E> {
private WeakHashMap<E, Object> edgeMap = new WeakHashMap<E, Object>(); }
@SuppressWarnings("unchecked")
public DefaultDirectedWeightedEdgeRetrievableGraph(EdgeFactory edgefactory) {
super(edgefactory);
}
@SuppressWarnings("unchecked")
public DefaultDirectedWeightedEdgeRetrievableGraph(Class class1) {
super(class1);
}
public E addEdge(V v1, V v2) {
E e = getEdgeFactory().createEdge(v1, v2);
addEdge(v1, v2, e);
return e;
}
public boolean addEdge(V v1, V v2, E e) {
edgeMap.put(e, null);
return super.addEdge(v1, v2, e);
}
public Set<E> getAllEdges() {
return edgeMap.keySet();
}
}
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