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

Removed deprecated `Position`-Interface

parent db566de9
...@@ -9,12 +9,12 @@ import java.io.UnsupportedEncodingException; ...@@ -9,12 +9,12 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.util.positioning.GeoSpherePosition; import de.tud.kom.p2psim.impl.util.positioning.GeoSpherePosition;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class AppJobberPositioning implements PositioningStrategy { public class AppJobberPositioning implements PositioningStrategy {
...@@ -25,7 +25,7 @@ public class AppJobberPositioning implements PositioningStrategy { ...@@ -25,7 +25,7 @@ public class AppJobberPositioning implements PositioningStrategy {
private Random rnd = Randoms.getRandom(AppJobberPositioning.class); private Random rnd = Randoms.getRandom(AppJobberPositioning.class);
@Override @Override
public Position getPosition( public Location getPosition(
SimHost host, SimHost host,
NetMeasurementDB db, NetMeasurementDB db,
NetMeasurementDB.Host hostMeta) { NetMeasurementDB.Host hostMeta) {
......
...@@ -24,12 +24,12 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning; ...@@ -24,12 +24,12 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.common.GNPToolkit; import de.tud.kom.p2psim.impl.network.modular.common.GNPToolkit;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
* Applies the (virtual) GNP position as the host's position * Applies the (virtual) GNP position as the host's position
...@@ -40,7 +40,7 @@ import de.tud.kom.p2psim.impl.topology.PositionVector; ...@@ -40,7 +40,7 @@ import de.tud.kom.p2psim.impl.topology.PositionVector;
public class GNPPositioning implements PositioningStrategy { public class GNPPositioning implements PositioningStrategy {
@Override @Override
public Position getPosition(SimHost host, NetMeasurementDB db, public Location getPosition(SimHost host, NetMeasurementDB db,
NetMeasurementDB.Host hostMeta) { NetMeasurementDB.Host hostMeta) {
if (hostMeta == null) if (hostMeta == null)
...@@ -51,7 +51,7 @@ public class GNPPositioning implements PositioningStrategy { ...@@ -51,7 +51,7 @@ public class GNPPositioning implements PositioningStrategy {
} }
public static class GNPPosition extends PositionVector implements Position { public static class GNPPosition extends PositionVector {
private List<Double> coords; private List<Double> coords;
...@@ -63,7 +63,7 @@ public class GNPPositioning implements PositioningStrategy { ...@@ -63,7 +63,7 @@ public class GNPPositioning implements PositioningStrategy {
} }
@Override @Override
public double getDistance(Position netPosition) { public double distanceTo(Location netPosition) {
if (!(netPosition instanceof PositionVector)) if (!(netPosition instanceof PositionVector))
throw new AssertionError( throw new AssertionError(
"Can not calculate distances between different position classes: " "Can not calculate distances between different position classes: "
......
...@@ -21,12 +21,12 @@ ...@@ -21,12 +21,12 @@
package de.tud.kom.p2psim.impl.network.modular.st.positioning; package de.tud.kom.p2psim.impl.network.modular.st.positioning;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.common.GeoToolkit; import de.tud.kom.p2psim.impl.network.modular.common.GeoToolkit;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
* Applies a geographical position as defined by the GeoIP project. * Applies a geographical position as defined by the GeoIP project.
...@@ -49,8 +49,7 @@ public class GeographicalPositioning implements PositioningStrategy { ...@@ -49,8 +49,7 @@ public class GeographicalPositioning implements PositioningStrategy {
} }
public class GeographicalPosition extends PositionVector implements public class GeographicalPosition extends PositionVector {
Position {
private double latitude; private double latitude;
private double longitude; private double longitude;
...@@ -70,7 +69,7 @@ public class GeographicalPositioning implements PositioningStrategy { ...@@ -70,7 +69,7 @@ public class GeographicalPositioning implements PositioningStrategy {
* *
*/ */
@Override @Override
public double getDistance(Position netPosition) { public double distanceTo(Location netPosition) {
if (!(netPosition instanceof PositionVector)) if (!(netPosition instanceof PositionVector))
throw new AssertionError( throw new AssertionError(
"Can not calculate the distance between two different position classes: " "Can not calculate the distance between two different position classes: "
...@@ -80,12 +79,6 @@ public class GeographicalPositioning implements PositioningStrategy { ...@@ -80,12 +79,6 @@ public class GeographicalPositioning implements PositioningStrategy {
return GeoToolkit.getDistance(this.latitude, this.longitude, return GeoToolkit.getDistance(this.latitude, this.longitude,
other.getEntry(1), other.getEntry(0)); other.getEntry(1), other.getEntry(0));
} }
@Override
public double getAngle(Position target) {
throw new AssertionError(
"getAngle is not defined for this Position-Type");
}
@Override @Override
public int getTransmissionSize() { public int getTransmissionSize() {
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
package de.tud.kom.p2psim.impl.network.modular.st.positioning; package de.tud.kom.p2psim.impl.network.modular.st.positioning;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.topology.placement.PositionDistribution; import de.tud.kom.p2psim.impl.topology.placement.PositionDistribution;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
* Positioning on a 2D-Plane, used for all Movement-Enabled Routing-Scenarios * Positioning on a 2D-Plane, used for all Movement-Enabled Routing-Scenarios
...@@ -42,7 +42,7 @@ public class PlanePositioning implements PositioningStrategy { ...@@ -42,7 +42,7 @@ public class PlanePositioning implements PositioningStrategy {
} }
@Override @Override
public Position getPosition( public Location getPosition(
SimHost host, SimHost host,
NetMeasurementDB db, NetMeasurementDB db,
de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Host hostMeta) { de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Host hostMeta) {
......
...@@ -22,13 +22,13 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning; ...@@ -22,13 +22,13 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning;
import java.util.Random; import java.util.Random;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.network.simple.SimpleSubnet; import de.tud.kom.p2psim.impl.network.simple.SimpleSubnet;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
* Implementation of the <code>NetPosition</code> interface representing a two * Implementation of the <code>NetPosition</code> interface representing a two
...@@ -48,7 +48,7 @@ public class SimpleEuclidianPositioning implements PositioningStrategy { ...@@ -48,7 +48,7 @@ public class SimpleEuclidianPositioning implements PositioningStrategy {
* @see de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy#getPosition(de.tud.kom.p2psim.api.common.Host, de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB, de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Host) * @see de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy#getPosition(de.tud.kom.p2psim.api.common.Host, de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB, de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB.Host)
*/ */
@Override @Override
public Position getPosition( public Location getPosition(
SimHost host, SimHost host,
NetMeasurementDB db, NetMeasurementDB db,
NetMeasurementDB.Host hostMeta) { NetMeasurementDB.Host hostMeta) {
...@@ -59,7 +59,7 @@ public class SimpleEuclidianPositioning implements PositioningStrategy { ...@@ -59,7 +59,7 @@ public class SimpleEuclidianPositioning implements PositioningStrategy {
} }
public class SimpleEuclidianPosition extends PositionVector implements Position { public class SimpleEuclidianPosition extends PositionVector {
private double xPos; private double xPos;
...@@ -93,7 +93,8 @@ public class SimpleEuclidianPositioning implements PositioningStrategy { ...@@ -93,7 +93,8 @@ public class SimpleEuclidianPositioning implements PositioningStrategy {
* de.tud.kom.p2psim.api.network.NetPosition#getDistance(de.tud.kom. * de.tud.kom.p2psim.api.network.NetPosition#getDistance(de.tud.kom.
* p2psim .api.network.NetPosition) * p2psim .api.network.NetPosition)
*/ */
public double getDistance(Position ep) { @Override
public double distanceTo(Location ep) {
double xDiff = 0; double xDiff = 0;
double yDiff = 0; double yDiff = 0;
SimpleEuclidianPosition point = (SimpleEuclidianPosition) ep; SimpleEuclidianPosition point = (SimpleEuclidianPosition) ep;
...@@ -118,11 +119,6 @@ public class SimpleEuclidianPositioning implements PositioningStrategy { ...@@ -118,11 +119,6 @@ public class SimpleEuclidianPositioning implements PositioningStrategy {
return Math.pow(Math.pow(xDiff, 2) + Math.pow(yDiff, 2), 0.5); return Math.pow(Math.pow(xDiff, 2) + Math.pow(yDiff, 2), 0.5);
} }
@Override
public double getAngle(Position target) {
throw new AssertionError("getAngle is not defined for this Position-Type");
}
@Override @Override
public int getTransmissionSize() { public int getTransmissionSize() {
return 16; // 2 * double return 16; // 2 * double
......
...@@ -23,12 +23,12 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning; ...@@ -23,12 +23,12 @@ package de.tud.kom.p2psim.impl.network.modular.st.positioning;
import java.util.Random; import java.util.Random;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy; import de.tud.kom.p2psim.impl.network.modular.st.PositioningStrategy;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
* Applies a uniformly-distributed random position on a 2-or multi-dimensional * Applies a uniformly-distributed random position on a 2-or multi-dimensional
...@@ -48,7 +48,7 @@ public class TorusPositioning implements PositioningStrategy { ...@@ -48,7 +48,7 @@ public class TorusPositioning implements PositioningStrategy {
Random rand = Randoms.getRandom(TorusPosition.class); Random rand = Randoms.getRandom(TorusPosition.class);
@Override @Override
public Position getPosition(SimHost host, NetMeasurementDB db, public Location getPosition(SimHost host, NetMeasurementDB db,
NetMeasurementDB.Host hostMeta) { NetMeasurementDB.Host hostMeta) {
double[] rawPos = getRawTorusPositionFor(host); double[] rawPos = getRawTorusPositionFor(host);
...@@ -93,7 +93,7 @@ public class TorusPositioning implements PositioningStrategy { ...@@ -93,7 +93,7 @@ public class TorusPositioning implements PositioningStrategy {
this.halfTorusDimensionSize = torusDimensionSize * 0.5d; this.halfTorusDimensionSize = torusDimensionSize * 0.5d;
} }
public class TorusPosition extends PositionVector implements Position { public class TorusPosition extends PositionVector {
TorusPosition(double[] rawPos) { TorusPosition(double[] rawPos) {
...@@ -101,7 +101,7 @@ public class TorusPositioning implements PositioningStrategy { ...@@ -101,7 +101,7 @@ public class TorusPositioning implements PositioningStrategy {
} }
@Override @Override
public double getDistance(Position netPosition) { public double distanceTo(Location netPosition) {
if (!(netPosition instanceof PositionVector)) if (!(netPosition instanceof PositionVector))
throw new AssertionError( throw new AssertionError(
"Can not calculate distances between different position classes: " "Can not calculate distances between different position classes: "
......
...@@ -28,7 +28,6 @@ import java.util.Map; ...@@ -28,7 +28,6 @@ import java.util.Map;
import de.tud.kom.p2psim.api.analyzer.ConnectivityAnalyzer; import de.tud.kom.p2psim.api.analyzer.ConnectivityAnalyzer;
import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason; import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason;
import de.tud.kom.p2psim.api.analyzer.NetlayerAnalyzer; import de.tud.kom.p2psim.api.analyzer.NetlayerAnalyzer;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent; import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.linklayer.LinkLayer; import de.tud.kom.p2psim.api.linklayer.LinkLayer;
...@@ -57,6 +56,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.network.Bandwidth; ...@@ -57,6 +56,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.network.Bandwidth;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetID; import de.tudarmstadt.maki.simonstrator.api.component.network.NetID;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface; import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent; import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener; import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener;
/** /**
...@@ -548,7 +548,7 @@ public class RoutedNetLayer implements SimNetworkComponent, NetworkComponent, ...@@ -548,7 +548,7 @@ public class RoutedNetLayer implements SimNetworkComponent, NetworkComponent,
} }
@Override @Override
public Position getNetPosition() { public Location getNetPosition() {
return host.getTopologyComponent().getRealPosition(); return host.getTopologyComponent().getRealPosition();
} }
......
...@@ -19,11 +19,10 @@ ...@@ -19,11 +19,10 @@
*/ */
package de.tud.kom.p2psim.impl.network.simple; package de.tud.kom.p2psim.impl.network.simple;
import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason; import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.network.BandwidthImpl; import de.tud.kom.p2psim.api.network.BandwidthImpl;
import de.tud.kom.p2psim.api.network.NetMessage; import de.tud.kom.p2psim.api.network.NetMessage;
...@@ -34,105 +33,106 @@ import de.tud.kom.p2psim.impl.transport.AbstractTransMessage; ...@@ -34,105 +33,106 @@ import de.tud.kom.p2psim.impl.transport.AbstractTransMessage;
import de.tudarmstadt.maki.simonstrator.api.Message; import de.tudarmstadt.maki.simonstrator.api.Message;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetID; import de.tudarmstadt.maki.simonstrator.api.component.network.NetID;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class SimpleNetLayer extends AbstractNetLayer {
public class SimpleNetLayer extends AbstractNetLayer {
private double currentDownBandwidth;
private double currentDownBandwidth;
private double currentUpBandwidth;
private double currentUpBandwidth;
private final SimpleSubnet subNet;
private final SimpleSubnet subNet;
public SimpleNetLayer(SimHost host, SimpleSubnet subNet, SimpleNetID netID,
Position netPosition, BandwidthImpl bandwidth) { public SimpleNetLayer(SimHost host, SimpleSubnet subNet, SimpleNetID netID,
super(host, netID, bandwidth, netPosition, null); Location netPosition, BandwidthImpl bandwidth) {
this.subNet = subNet; super(host, netID, bandwidth, netPosition, null);
subNet.registerNetLayer(this); this.subNet = subNet;
} subNet.registerNetLayer(this);
}
public boolean isSupported(TransProtocol transProtocol) {
if (transProtocol.equals(TransProtocol.UDP)) public boolean isSupported(TransProtocol transProtocol) {
return true; if (transProtocol.equals(TransProtocol.UDP))
else return true;
return false; else
} return false;
}
public void send(Message msg, NetID receiver, NetProtocol netProtocol) {
// outer if-else-block is used to avoid sending although the host is public void send(Message msg, NetID receiver, NetProtocol netProtocol) {
// offline // outer if-else-block is used to avoid sending although the host is
if (this.isOnline()) { // offline
TransProtocol usedTransProtocol = ((AbstractTransMessage) msg) if (this.isOnline()) {
.getProtocol(); TransProtocol usedTransProtocol = ((AbstractTransMessage) msg)
if (this.isSupported(usedTransProtocol)) { .getProtocol();
if (this.isSupported(usedTransProtocol)) {
NetMessage netMsg = new SimpleNetMessage(msg, receiver, NetMessage netMsg = new SimpleNetMessage(msg, receiver,
getLocalInetAddress(), getLocalInetAddress(),
netProtocol); netProtocol);
if (hasAnalyzer) { if (hasAnalyzer) {
netAnalyzerProxy netAnalyzerProxy
.netMsgEvent(netMsg, getHost(), Reason.SEND); .netMsgEvent(netMsg, getHost(), Reason.SEND);
} }
subNet.send(netMsg); subNet.send(netMsg);
} else { } else {
throw new IllegalArgumentException("Transport protocol " throw new IllegalArgumentException("Transport protocol "
+ usedTransProtocol + usedTransProtocol
+ " not supported by this NetLayer implementation."); + " not supported by this NetLayer implementation.");
} }
} else { } else {
int assignedMsgId = subNet.determineTransMsgNumber(msg); int assignedMsgId = subNet.determineTransMsgNumber(msg);
Monitor.log(SimpleNetLayer.class, Monitor.Level.DEBUG, Monitor.log(SimpleNetLayer.class, Monitor.Level.DEBUG,
"During send: Assigning MsgId " + assignedMsgId "During send: Assigning MsgId " + assignedMsgId
+ " to dropped message"); + " to dropped message");
((AbstractTransMessage) msg).setCommId(assignedMsgId); ((AbstractTransMessage) msg).setCommId(assignedMsgId);
NetMessage netMsg = new SimpleNetMessage(msg, receiver, NetMessage netMsg = new SimpleNetMessage(msg, receiver,
getLocalInetAddress(), getLocalInetAddress(),
netProtocol); netProtocol);
if (hasAnalyzer) { if (hasAnalyzer) {
netAnalyzerProxy.netMsgEvent(netMsg, getHost(), Reason.DROP); netAnalyzerProxy.netMsgEvent(netMsg, getHost(), Reason.DROP);
} }
} }
} }
@Override @Override
public String toString() { public String toString() {
return "NetLayer(netID=" + getLocalInetAddress() + ", " return "NetLayer(netID=" + getLocalInetAddress() + ", "
+ (isOffline() ? "online" : "offline") + ")"; + (isOffline() ? "online" : "offline") + ")";
} }
@Override @Override
public int hashCode() { public int hashCode() {
final int PRIME = 31; final int PRIME = 31;
int result = 1; int result = 1;
long temp; long temp;
temp = Double.doubleToLongBits(currentDownBandwidth); temp = Double.doubleToLongBits(currentDownBandwidth);
result = PRIME * result + (int) (temp ^ (temp >>> 32)); result = PRIME * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(currentUpBandwidth); temp = Double.doubleToLongBits(currentUpBandwidth);
result = PRIME * result + (int) (temp ^ (temp >>> 32)); result = PRIME * result + (int) (temp ^ (temp >>> 32));
result = PRIME * result + ((subNet == null) ? 0 : subNet.hashCode()); result = PRIME * result + ((subNet == null) ? 0 : subNet.hashCode());
return result; return result;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj)
return true; return true;
if (obj == null) if (obj == null)
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
final SimpleNetLayer other = (SimpleNetLayer) obj; final SimpleNetLayer other = (SimpleNetLayer) obj;
if (Double.doubleToLongBits(currentDownBandwidth) != Double if (Double.doubleToLongBits(currentDownBandwidth) != Double
.doubleToLongBits(other.currentDownBandwidth)) .doubleToLongBits(other.currentDownBandwidth))
return false; return false;
if (Double.doubleToLongBits(currentUpBandwidth) != Double if (Double.doubleToLongBits(currentUpBandwidth) != Double
.doubleToLongBits(other.currentUpBandwidth)) .doubleToLongBits(other.currentUpBandwidth))
return false; return false;
if (subNet == null) { if (subNet == null) {
if (other.subNet != null) if (other.subNet != null)
return false; return false;
} else if (!subNet.equals(other.subNet)) } else if (!subNet.equals(other.subNet))
return false; return false;
return true; return true;
} }
} }
...@@ -28,7 +28,6 @@ import java.util.Random; ...@@ -28,7 +28,6 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import de.tud.kom.p2psim.api.common.HostProperties; import de.tud.kom.p2psim.api.common.HostProperties;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.linklayer.mac.MacAddress; import de.tud.kom.p2psim.api.linklayer.mac.MacAddress;
import de.tud.kom.p2psim.api.linklayer.mac.MacLayer; import de.tud.kom.p2psim.api.linklayer.mac.MacLayer;
...@@ -178,7 +177,7 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -178,7 +177,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
@Override @Override
public void positionChanged() { public void positionChanged() {
for (PositionListener listener : positionListener) { for (PositionListener listener : positionListener) {
if (listener.getPosition().getDistance(position) < listener if (listener.getPosition().distanceTo(position) < listener
.getRadius()) { .getRadius()) {
listener.reachedPosition(); listener.reachedPosition();
} }
...@@ -212,14 +211,6 @@ public class DefaultTopologyComponent implements TopologyComponent { ...@@ -212,14 +211,6 @@ public class DefaultTopologyComponent implements TopologyComponent {
return position; return position;
} }
@Override
public Position getPosition(PositionAccuracy accuracy) {
/*
* TODO :)
*/
return position;
}
@Override @Override
public Topology getTopology() { public Topology getTopology() {
return topology; return topology;
......
...@@ -25,7 +25,6 @@ import java.util.Arrays; ...@@ -25,7 +25,6 @@ import java.util.Arrays;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import de.tud.kom.p2psim.api.common.Position;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/** /**
...@@ -50,7 +49,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; ...@@ -50,7 +49,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, 04/25/2011 * @version 1.0, 04/25/2011
*/ */
public class PositionVector implements Position, Location { public class PositionVector implements Location {
private int dimensions; private int dimensions;
...@@ -255,55 +254,6 @@ public class PositionVector implements Position, Location { ...@@ -255,55 +254,6 @@ public class PositionVector implements Position, Location {
return result; return result;
} }
@Override
public double getDistance(Position position) {
if (position instanceof PositionVector) {
PositionVector pv = (PositionVector) position;
if (pv.getDimensions() == getDimensions()) {
double dist = 0;
for (int i = 0; i < dimensions; i++) {
// faster as Math.pow
dist += (pv.getEntry(i) - getEntry(i))
* (pv.getEntry(i) - getEntry(i));
}
return Math.sqrt(dist);
} else {
throw new AssertionError(
"Can not compute distance between Vectors of different length!");
}
} else {
throw new AssertionError("Incompatible Types!");
}
}
@Override
public double getAngle(Position target) {
if (target instanceof PositionVector) {
PositionVector t = (PositionVector) target;
/*
* Calculates the angle using atan2 - this implies that the first
* two dimensions in your vector are the plane you are interested
* in.
*/
return Math.atan2(t.getEntry(1) - this.getEntry(1), t.getEntry(0)
- this.getEntry(0));
} else {
throw new AssertionError(
"Can only calculate an Angle on elements of type position vector");
}
}
@Override
public Position getTarget(double distance, double angle) {
/*
* The call to "clone" ensures correct typing
*/
PositionVector newPos = clone();
newPos.setEntry(0, newPos.getEntry(0) + distance * Math.cos(angle));
newPos.setEntry(1, newPos.getEntry(1) + distance * Math.sin(angle));
return newPos;
}
@Override @Override
public int getTransmissionSize() { public int getTransmissionSize() {
return getDimensions() * 8; return getDimensions() * 8;
...@@ -496,13 +446,39 @@ public class PositionVector implements Position, Location { ...@@ -496,13 +446,39 @@ public class PositionVector implements Position, Location {
@Override @Override
public double distanceTo(Location dest) { public double distanceTo(Location dest) {
assert (dest instanceof PositionVector); if (dest instanceof PositionVector) {
return this.getDistance((PositionVector) dest); PositionVector pv = (PositionVector) dest;
if (pv.getDimensions() == getDimensions()) {
double dist = 0;
for (int i = 0; i < dimensions; i++) {
// faster as Math.pow
dist += (pv.getEntry(i) - getEntry(i))
* (pv.getEntry(i) - getEntry(i));
}
return Math.sqrt(dist);
} else {
throw new AssertionError(
"Can not compute distance between Vectors of different length!");
}
} else {
throw new AssertionError("Incompatible Types!");
}
} }
@Override @Override
public float bearingTo(Location dest) { public float bearingTo(Location dest) {
assert (dest instanceof PositionVector); if (dest instanceof PositionVector) {
return (float) ((this.getAngle((PositionVector) dest) - (Math.PI / 2)) * 180 / Math.PI); PositionVector t = (PositionVector) dest;
/*
* Calculates the angle using atan2 - this implies that the first
* two dimensions in your vector are the plane you are interested
* in.
*/
return (float) Math.atan2(t.getEntry(1) - this.getEntry(1),
t.getEntry(0) - this.getEntry(0));
} else {
throw new AssertionError(
"Can only calculate an Angle on elements of type position vector");
}
} }
} }
...@@ -39,6 +39,7 @@ import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB; ...@@ -39,6 +39,7 @@ import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.topology.movement.AbstractWaypointMovementModel; import de.tud.kom.p2psim.impl.topology.movement.AbstractWaypointMovementModel;
import de.tud.kom.p2psim.impl.topology.placement.GNPPlacement; import de.tud.kom.p2psim.impl.topology.placement.GNPPlacement;
import de.tud.kom.p2psim.impl.topology.views.latency.GNPLatency; import de.tud.kom.p2psim.impl.topology.views.latency.GNPLatency;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Host; import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
...@@ -88,7 +89,8 @@ public class TopologyFactory implements HostComponentFactory { ...@@ -88,7 +89,8 @@ public class TopologyFactory implements HostComponentFactory {
@XMLConfigurableConstructor({ "worldX", "worldY" }) @XMLConfigurableConstructor({ "worldX", "worldY" })
public TopologyFactory(double worldX, double worldY) { public TopologyFactory(double worldX, double worldY) {
topo = new DefaultTopology(new PositionVector(worldX, worldY)); topo = new DefaultTopology(new PositionVector(worldX, worldY));
de.tud.kom.p2psim.impl.topology.Topology.setTopology(topo); // Make the topology component available globally
Binder.registerComponent(topo);
} }
@Override @Override
......
...@@ -26,11 +26,12 @@ import java.util.List; ...@@ -26,11 +26,12 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.MovementListener; import de.tud.kom.p2psim.api.topology.movement.MovementListener;
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.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology; 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;
...@@ -87,7 +88,8 @@ public abstract class AbstractMovementModel implements MovementModel { ...@@ -87,7 +88,8 @@ public abstract class AbstractMovementModel implements MovementModel {
@Override @Override
public void addComponent(MovementSupported component) { public void addComponent(MovementSupported component) {
if (worldDimensions == null) { if (worldDimensions == null) {
worldDimensions = Topology.getWorldDimension(); worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
} }
components.add(component); components.add(component);
} }
......
/* /*
* Copyright (c) 2005-2011 KOM - Multimedia Communications Lab * Copyright (c) 2005-2011 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.movement; package de.tud.kom.p2psim.impl.topology.movement;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import de.tud.kom.p2psim.api.topology.movement.MovementListener; import de.tud.kom.p2psim.api.topology.movement.MovementListener;
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.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
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.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.PositionVector;
import de.tud.kom.p2psim.impl.topology.events.ScaleWorldEvent; import de.tud.kom.p2psim.impl.topology.events.ScaleWorldEvent;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.geo.maps.MapLoader; import de.tud.kom.p2psim.impl.util.geo.maps.MapLoader;
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.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
/** /**
* The AbstractWaypointMovementModel can be used to implement movement models * The AbstractWaypointMovementModel can be used to implement movement models
* based on way point data. It uses an implementation of LocalMovementStrategy * based on way point data. It uses an implementation of LocalMovementStrategy
* for the movement between selected way points. * for the movement between selected way points.
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 27.03.2012 * @version 1.0, 27.03.2012
*/ */
public abstract class AbstractWaypointMovementModel implements MovementModel { public abstract class AbstractWaypointMovementModel implements MovementModel {
private Set<MovementSupported> components = new LinkedHashSet<MovementSupported>(); private Set<MovementSupported> components = new LinkedHashSet<MovementSupported>();
protected PositionVector worldDimensions; protected PositionVector worldDimensions;
protected WeakHashMap<MovementSupported, PositionVector> destinations; protected WeakHashMap<MovementSupported, PositionVector> destinations;
protected WeakHashMap<MovementSupported, Long> pauseTimes; protected WeakHashMap<MovementSupported, Long> pauseTimes;
protected WeakHashMap<MovementSupported, Long> pauseInProgressTimes; protected WeakHashMap<MovementSupported, Long> pauseInProgressTimes;
private List<MovementListener> listeners; private List<MovementListener> listeners;
protected WaypointModel waypointModel; protected WaypointModel waypointModel;
protected LocalMovementStrategy localMovementStrategy; protected LocalMovementStrategy localMovementStrategy;
private int configurationCounter = 100; private int configurationCounter = 100;
private long timeBetweenMovement = 1 * Time.SECOND; private long timeBetweenMovement = 1 * Time.SECOND;
private double speedLimit = 1; private double speedLimit = 1;
private double unscaledSpeedLimit = speedLimit; private double unscaledSpeedLimit = speedLimit;
private Random rnd = Randoms.getRandom(AbstractWaypointMovementModel.class); private Random rnd = Randoms.getRandom(AbstractWaypointMovementModel.class);
public AbstractWaypointMovementModel(double worldX, double worldY) { public AbstractWaypointMovementModel(double worldX, double worldY) {
worldDimensions = new PositionVector(worldX, worldY); worldDimensions = new PositionVector(worldX, worldY);
listeners = new LinkedList<MovementListener>(); listeners = new LinkedList<MovementListener>();
destinations = new WeakHashMap<MovementSupported, PositionVector>(); destinations = new WeakHashMap<MovementSupported, PositionVector>();
pauseTimes = new WeakHashMap<MovementSupported, Long>(); pauseTimes = new WeakHashMap<MovementSupported, Long>();
pauseInProgressTimes = new WeakHashMap<MovementSupported, Long>(); pauseInProgressTimes = new WeakHashMap<MovementSupported, Long>();
// Simulator.registerAtEventBus(this); // Simulator.registerAtEventBus(this);
} }
@Configure() @Configure()
@After(required = { WaypointModel.class, MapLoader.class }) @After(required = { WaypointModel.class, MapLoader.class })
public boolean configure() { public boolean configure() {
if (this.waypointModel == null && configurationCounter > 0) { if (this.waypointModel == null && configurationCounter > 0) {
configurationCounter--; configurationCounter--;
return false; return false;
} }
if (this.waypointModel == null) { if (this.waypointModel == null) {
Monitor.log( Monitor.log(
AbstractWaypointMovementModel.class, AbstractWaypointMovementModel.class,
Level.INFO, Level.INFO,
"No waypoint model has been configured. Thus the movement speed won't be adjusted for the scale of the waypoint model."); "No waypoint model has been configured. Thus the movement speed won't be adjusted for the scale of the waypoint model.");
} }
// //
// if (waypointModel.getScaleFactor() != 1.0) { // if (waypointModel.getScaleFactor() != 1.0) {
// Simulator.postEvent(new ScaleWorldEvent(waypointModel // Simulator.postEvent(new ScaleWorldEvent(waypointModel
// .getScaleFactor())); // .getScaleFactor()));
// } // }
return true; return true;
} }
@Subscribe @Subscribe
public void scaleWorld(ScaleWorldEvent event) { public void scaleWorld(ScaleWorldEvent event) {
double scaleFactor = event.getFactor(); double scaleFactor = event.getFactor();
speedLimit = unscaledSpeedLimit * scaleFactor; speedLimit = unscaledSpeedLimit * scaleFactor;
Monitor.log( Monitor.log(
AbstractWaypointMovementModel.class, AbstractWaypointMovementModel.class,
Level.INFO, Level.INFO,
"Movement speed of the local movement strategy has been adjusted for the waypoint model scale and is now " "Movement speed of the local movement strategy has been adjusted for the waypoint model scale and is now "
+ speedLimit + "m/s"); + speedLimit + "m/s");
} }
/** /**
* Gets called periodically (after timeBetweenMoveOperations) or by an * Gets called periodically (after timeBetweenMoveOperations) or by an
* application and should be used to recalculate positions * application and should be used to recalculate positions
*/ */
public void move() { public void move() {
long nrOfSteps = timeBetweenMovement / Time.SECOND; long nrOfSteps = timeBetweenMovement / Time.SECOND;
for (int i = 0; i < nrOfSteps; i++) { for (int i = 0; i < nrOfSteps; i++) {
step(); step();
} }
notifyRoundEnd(); notifyRoundEnd();
} }
private void step() { private void step() {
Set<MovementSupported> comps = getComponents(); Set<MovementSupported> comps = getComponents();
for (MovementSupported mcomp : comps) { for (MovementSupported mcomp : comps) {
if (!mcomp.movementActive()) { if (!mcomp.movementActive()) {
continue; continue;
} }
Long currentPause = pauseInProgressTimes.get(mcomp); Long currentPause = pauseInProgressTimes.get(mcomp);
if (currentPause != null) { if (currentPause != null) {
if (Time.getCurrentTime() >= currentPause) { if (Time.getCurrentTime() >= currentPause) {
Monitor.log(AbstractWaypointMovementModel.class, Monitor.log(AbstractWaypointMovementModel.class,
Level.DEBUG, "Pause time ended..."); Level.DEBUG, "Pause time ended...");
pauseInProgressTimes.remove(mcomp); pauseInProgressTimes.remove(mcomp);
} else } else
continue; continue;
} }
PositionVector dst = getDestination(mcomp); PositionVector dst = getDestination(mcomp);
// If the movement model gave null as a destination no move is // If the movement model gave null as a destination no move is
// executed // executed
if (dst == null) { if (dst == null) {
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"No destination before reachedPosition check... continuing"); "No destination before reachedPosition check... continuing");
continue; continue;
} }
// If the position has been reached last round // If the position has been reached last round
// set pause active and get a new destination // set pause active and get a new destination
if (reachedPosition(mcomp, dst)) { if (reachedPosition(mcomp, dst)) {
pauseAndGetNextPosition(mcomp); pauseAndGetNextPosition(mcomp);
continue; continue;
} }
// Ask the local movement strategy for the next position. // Ask the local movement strategy for the next position.
// It may return the next position or a boolean with true to notify // It may return the next position or a boolean with true to notify
// the // the
// movement model that it can't get any closer to the current way // movement model that it can't get any closer to the current way
// point. // point.
Either<PositionVector, Boolean> either = localMovementStrategy Either<PositionVector, Boolean> either = localMovementStrategy
.nextPosition(mcomp, dst); .nextPosition(mcomp, dst);
if (either.hasLeft()) { if (either.hasLeft()) {
mcomp.getRealPosition().replace(either.getLeft()); mcomp.getRealPosition().replace(either.getLeft());
notifyPositionChange(mcomp); notifyPositionChange(mcomp);
} else { } else {
if (either.getRight().booleanValue()) { if (either.getRight().booleanValue()) {
pauseAndGetNextPosition(mcomp); pauseAndGetNextPosition(mcomp);
continue; continue;
} else { } else {
// Pause this round // Pause this round
continue; continue;
} }
} }
} }
} }
/** /**
* Sets the pause time for the given component and calls nextPosition on it. * Sets the pause time for the given component and calls nextPosition on it.
* *
* @param comp * @param comp
*/ */
private void pauseAndGetNextPosition(MovementSupported comp) { private void pauseAndGetNextPosition(MovementSupported comp) {
Long pt = pauseTimes.get(comp) * Time.SECOND; Long pt = pauseTimes.get(comp) * Time.SECOND;
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Position reached... pause time is " + pt); "Position reached... pause time is " + pt);
if (pt != null) { if (pt != null) {
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Simulator time: " + Time.getCurrentTime()); "Simulator time: " + Time.getCurrentTime());
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Pause time: " + pt); "Pause time: " + pt);
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Added up: " + (Time.getCurrentTime() + pt)); "Added up: " + (Time.getCurrentTime() + pt));
pauseInProgressTimes.put(comp, Time.getCurrentTime() + pt); pauseInProgressTimes.put(comp, Time.getCurrentTime() + pt);
} }
nextPosition(comp); nextPosition(comp);
} }
/** /**
* Checks if the given component has reached its destination * Checks if the given component has reached its destination
* *
* @param comp * @param comp
* @param dst * @param dst
* @return Returns true if the destination was reached * @return Returns true if the destination was reached
*/ */
private boolean reachedPosition(MovementSupported comp, PositionVector dst) { private boolean reachedPosition(MovementSupported comp, PositionVector dst) {
PositionVector pos = comp.getRealPosition(); PositionVector pos = comp.getRealPosition();
double distance = pos.getDistance(dst); double distance = pos.distanceTo(dst);
// FIXME: Better detection? // FIXME: Better detection?
return (distance < getSpeedLimit() * 2); return (distance < getSpeedLimit() * 2);
} }
/** /**
* Returns the current destination of the given component and calls * Returns the current destination of the given component and calls
* nextPosition if it hasn't been set yet. * nextPosition if it hasn't been set yet.
* *
* @param comp * @param comp
* @return * @return
*/ */
private PositionVector getDestination(MovementSupported comp) { private PositionVector getDestination(MovementSupported comp) {
PositionVector dst = destinations.get(comp); PositionVector dst = destinations.get(comp);
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Pos: " Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Pos: "
+ comp.getRealPosition()); + comp.getRealPosition());
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Dst: " Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Dst: "
+ dst); + dst);
if (dst == null) { if (dst == null) {
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"No destination, calling nextPosition()"); "No destination, calling nextPosition()");
nextPosition(comp); nextPosition(comp);
dst = destinations.get(comp); dst = destinations.get(comp);
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"New destination is: " + dst); "New destination is: " + dst);
} }
return dst; return dst;
} }
/** /**
* This method can be called by the concrete implementation to let the * This method can be called by the concrete implementation to let the
* AbstractWaypointMovementModel know the next destination and pause time. * AbstractWaypointMovementModel know the next destination and pause time.
* *
* @param comp * @param comp
* @param destination * @param destination
* @param pauseTime * @param pauseTime
*/ */
protected void nextDestination(MovementSupported comp, protected void nextDestination(MovementSupported comp,
PositionVector destination, long pauseTime) { PositionVector destination, long pauseTime) {
destinations.put(comp, destination); destinations.put(comp, destination);
pauseTimes.put(comp, pauseTime); pauseTimes.put(comp, pauseTime);
} }
/** /**
* Is to be implemented by the concrete movement model and will be called by * Is to be implemented by the concrete movement model and will be called by
* the AbstractWaypointMovementModel to ask the concrete implementation for * the AbstractWaypointMovementModel to ask the concrete implementation for
* a new destination. * a new destination.
* *
* @param component * @param component
*/ */
public abstract void nextPosition(MovementSupported component); public abstract void nextPosition(MovementSupported component);
/** /**
* Get all participating Components * Get all participating Components
* *
* @return * @return
*/ */
protected Set<MovementSupported> getComponents() { protected Set<MovementSupported> getComponents() {
return components; return components;
} }
/** /**
* Add a component to this movement-Model (used to keep global information * Add a component to this movement-Model (used to keep global information
* about all participants in a movement model). Each Component acts as a * about all participants in a movement model). Each Component acts as a
* callback upon movement of this component * callback upon movement of this component
* *
* @param component * @param component
*/ */
@Override @Override
public void addComponent(MovementSupported component) { public void addComponent(MovementSupported component) {
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"AbstractMovementModel: Adding component to the movement model"); "AbstractMovementModel: Adding component to the movement model");
components.add(component); components.add(component);
} }
@Override @Override
public void addMovementListener(MovementListener listener) { public void addMovementListener(MovementListener listener) {
if (!listeners.contains(listener)) { if (!listeners.contains(listener)) {
listeners.add(listener); listeners.add(listener);
} }
} }
@Override @Override
public void removeMovementListener(MovementListener listener) { public void removeMovementListener(MovementListener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
/** /**
* Notify Listeners * Notify Listeners
*/ */
protected void notifyRoundEnd() { protected void notifyRoundEnd() {
for (MovementListener listener : listeners) { for (MovementListener listener : listeners) {
listener.afterComponentsMoved(); listener.afterComponentsMoved();
} }
} }
protected void notifyPositionChange(MovementSupported comp) { protected void notifyPositionChange(MovementSupported comp) {
for (MovementListener listener : listeners) { for (MovementListener listener : listeners) {
listener.afterComponentMoved(comp); listener.afterComponentMoved(comp);
} }
comp.positionChanged(); comp.positionChanged();
} }
/** /**
* Get a valid delta-Vector (does not cross world-boundaries and does not * Get a valid delta-Vector (does not cross world-boundaries and does not
* exceed moveSpeedLimit) * exceed moveSpeedLimit)
* *
* @param oldPosition * @param oldPosition
* @return * @return
*/ */
protected PositionVector getRandomDelta(PositionVector oldPosition) { protected PositionVector getRandomDelta(PositionVector oldPosition) {
return getRandomDelta(oldPosition, getSpeedLimit()); return getRandomDelta(oldPosition, getSpeedLimit());
} }
/** /**
* Get a valid delta-Vector, where each abs(entry) must not exceed maxLength * Get a valid delta-Vector, where each abs(entry) must not exceed maxLength
* *
* @param oldPosition * @param oldPosition
* @param maxLength * @param maxLength
* @return * @return
*/ */
protected PositionVector getRandomDelta(PositionVector oldPosition, protected PositionVector getRandomDelta(PositionVector oldPosition,
double maxLength) { double maxLength) {
double[] delta = new double[oldPosition.getDimensions()]; double[] delta = new double[oldPosition.getDimensions()];
for (int i = 0; i < oldPosition.getDimensions(); i++) { for (int i = 0; i < oldPosition.getDimensions(); i++) {
int tries = 0; int tries = 0;
do { do {
delta[i] = getRandomDouble(-maxLength, maxLength); delta[i] = getRandomDouble(-maxLength, maxLength);
if (++tries > 50) { if (++tries > 50) {
delta[i] = 0; delta[i] = 0;
break; break;
} }
// delta[i] = (r.nextInt(2 * getMoveSpeedLimit() + 1) - // delta[i] = (r.nextInt(2 * getMoveSpeedLimit() + 1) -
// getMoveSpeedLimit()); // getMoveSpeedLimit());
} while (oldPosition.getEntry(i) + delta[i] > getWorldDimension(i) } while (oldPosition.getEntry(i) + delta[i] > getWorldDimension(i)
|| oldPosition.getEntry(i) + delta[i] < 0); || oldPosition.getEntry(i) + delta[i] < 0);
} }
PositionVector deltaVector = new PositionVector(delta); PositionVector deltaVector = new PositionVector(delta);
return deltaVector; return deltaVector;
} }
/** /**
* Returns if this is a valid position within the boundaries * Returns if this is a valid position within the boundaries
* *
* @return * @return
*/ */
protected boolean isValidPosition(PositionVector vector) { protected boolean isValidPosition(PositionVector vector) {
for (int i = 0; i < vector.getDimensions(); i++) { for (int i = 0; i < vector.getDimensions(); i++) {
if (vector.getEntry(i) > getWorldDimension(i) if (vector.getEntry(i) > getWorldDimension(i)
|| vector.getEntry(i) < 0) { || vector.getEntry(i) < 0) {
return false; return false;
} }
} }
return true; return true;
} }
/** /**
* Returns a random int between from and to, including both interval ends! * Returns a random int between from and to, including both interval ends!
* *
* @param from * @param from
* @param to * @param to
* @return * @return
*/ */
protected int getRandomInt(int from, int to) { protected int getRandomInt(int from, int to) {
int intervalSize = Math.abs(to - from); int intervalSize = Math.abs(to - from);
return (rnd.nextInt(intervalSize + 1) + from); return (rnd.nextInt(intervalSize + 1) + from);
} }
protected double getRandomDouble(double from, double to) { protected double getRandomDouble(double from, double to) {
double intervalSize = Math.abs(to - from); double intervalSize = Math.abs(to - from);
return (rnd.nextDouble() * intervalSize + from); return (rnd.nextDouble() * intervalSize + from);
} }
/** /**
* Move models can periodically calculate new positions and notify * Move models can periodically calculate new positions and notify
* listeners, if a position changed. Here you can specify the interval * listeners, if a position changed. Here you can specify the interval
* between these notifications/calculations. If this is set to zero, there * between these notifications/calculations. If this is set to zero, there
* is no periodical execution, which may be useful if you want to call * is no periodical execution, which may be useful if you want to call
* move() from within an application. * move() from within an application.
* *
* @param timeBetweenMoveOperations * @param timeBetweenMoveOperations
*/ */
public void setTimeBetweenMoveOperations(long timeBetweenMoveOperations) { public void setTimeBetweenMoveOperations(long timeBetweenMoveOperations) {
this.timeBetweenMovement = timeBetweenMoveOperations; this.timeBetweenMovement = timeBetweenMoveOperations;
if (timeBetweenMoveOperations > 0) { if (timeBetweenMoveOperations > 0) {
reschedule(); reschedule();
} }
} }
protected void reschedule() { protected void reschedule() {
Event.scheduleWithDelay(timeBetweenMovement, new PeriodicMove(), this, Event.scheduleWithDelay(timeBetweenMovement, new PeriodicMove(), this,
0); 0);
} }
@Deprecated @Deprecated
public void setSpeedLimit(double speedLimit) { public void setSpeedLimit(double speedLimit) {
this.speedLimit = speedLimit; this.speedLimit = speedLimit;
this.unscaledSpeedLimit = speedLimit; this.unscaledSpeedLimit = speedLimit;
} }
@Deprecated @Deprecated
public double getSpeedLimit() { public double getSpeedLimit() {
return speedLimit; return speedLimit;
} }
public void setWorldX(double dimension) { public void setWorldX(double dimension) {
this.worldDimensions.setEntry(0, dimension); this.worldDimensions.setEntry(0, dimension);
} }
public void setWorldY(double dimension) { public void setWorldY(double dimension) {
this.worldDimensions.setEntry(1, dimension); this.worldDimensions.setEntry(1, dimension);
} }
public double getWorldDimension(int dim) { public double getWorldDimension(int dim) {
return worldDimensions.getEntry(dim); return worldDimensions.getEntry(dim);
} }
public void setWorldZ(double dimension) { public void setWorldZ(double dimension) {
this.worldDimensions.setEntry(2, dimension); this.worldDimensions.setEntry(2, dimension);
} }
public void setWaypointModel(WaypointModel model) { public void setWaypointModel(WaypointModel model) {
this.waypointModel = model; this.waypointModel = model;
if (localMovementStrategy != null) if (localMovementStrategy != null)
localMovementStrategy.setWaypointModel(getWaypointModel()); localMovementStrategy.setWaypointModel(getWaypointModel());
} }
public WaypointModel getWaypointModel() { public WaypointModel getWaypointModel() {
return this.waypointModel; return this.waypointModel;
} }
public void setLocalMovementStrategy(LocalMovementStrategy strategy) { public void setLocalMovementStrategy(LocalMovementStrategy strategy) {
strategy.setWaypointModel(getWaypointModel()); strategy.setWaypointModel(getWaypointModel());
this.localMovementStrategy = strategy; this.localMovementStrategy = strategy;
} }
/** /**
* Triggers the periodic move * Triggers the periodic move
* *
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, 20.03.2012 * @version 1.0, 20.03.2012
*/ */
protected class PeriodicMove implements EventHandler { protected class PeriodicMove implements EventHandler {
@Override @Override
public void eventOccurred(Object content, int type) { public void eventOccurred(Object content, int type) {
move(); move();
reschedule(); reschedule();
} }
} }
} }
...@@ -27,26 +27,19 @@ import java.util.LinkedHashMap; ...@@ -27,26 +27,19 @@ import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.Set; import java.util.Set;
import org.jfree.data.io.CSV;
import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.network.SimNetInterface; import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.MovementInformation; import de.tud.kom.p2psim.api.topology.movement.MovementInformation;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.network.gnp.topology.Host;
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.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModel; import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint; import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.FixedAssignmentStrategy; import de.tud.kom.p2psim.impl.topology.movement.modular.transition.FixedAssignmentStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.TransitionStrategy; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
...@@ -82,7 +75,8 @@ public class CsvMovement extends AbstractMovementModel { ...@@ -82,7 +75,8 @@ public class CsvMovement extends AbstractMovementModel {
@XMLConfigurableConstructor({ "movementPointsFile" , "minMovementSpeed", "maxMovementSpeed" }) @XMLConfigurableConstructor({ "movementPointsFile" , "minMovementSpeed", "maxMovementSpeed" })
public CsvMovement(String movementPointsFile, double minMovementSpeed, double maxMovementSpeed) { public CsvMovement(String movementPointsFile, double minMovementSpeed, double maxMovementSpeed) {
super(); super();
this.worldDimensions = Topology.getWorldDimension(); this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
this.file = movementPointsFile; this.file = movementPointsFile;
this.readPathInfos = new LinkedList<LinkedList<CsvPathInfo>>(); this.readPathInfos = new LinkedList<LinkedList<CsvPathInfo>>();
this.stateInfo = new LinkedHashMap<MovementSupported, CsvMovementInfo>(); this.stateInfo = new LinkedHashMap<MovementSupported, CsvMovementInfo>();
...@@ -144,7 +138,7 @@ public class CsvMovement extends AbstractMovementModel { ...@@ -144,7 +138,7 @@ public class CsvMovement extends AbstractMovementModel {
double distancePerMoveOperation = pathInfo.getSpeed() double distancePerMoveOperation = pathInfo.getSpeed()
* getTimeBetweenMoveOperations() / Time.SECOND; * getTimeBetweenMoveOperations() / Time.SECOND;
double distance = actPos.getDistance(targetPos); double distance = actPos.distanceTo(targetPos);
steps = (int) Math.round(distance / distancePerMoveOperation); steps = (int) Math.round(distance / distancePerMoveOperation);
......
/* /*
* 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.movement; package de.tud.kom.p2psim.impl.topology.movement;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Vector; import java.util.Vector;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import javax.swing.JComponent; import javax.swing.JComponent;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
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.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.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;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/** /**
* The SLAW Movement Model is based on the implementation in * The SLAW Movement Model is based on the implementation in
* BonnMotion Copyright (C) 2002-2010 University of Bonn * BonnMotion Copyright (C) 2002-2010 University of Bonn
* by Zia-Ul-Huda, Gufron Atokhojaev and Florian Schmitt * by Zia-Ul-Huda, Gufron Atokhojaev and Florian Schmitt
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 09.04.2012 * @version 1.0, 09.04.2012
*/ */
public class SLAWMovementModel extends AbstractWaypointMovementModel { public class SLAWMovementModel extends AbstractWaypointMovementModel {
private static final int powerlaw_step = 1; private static final int powerlaw_step = 1;
private static int levy_scale_factor = 1; private static int levy_scale_factor = 1;
private static int powerlaw_mode = 1; private static int powerlaw_mode = 1;
protected Random rand = Randoms protected Random rand = Randoms
.getRandom(SLAWMovementModel.class); .getRandom(SLAWMovementModel.class);
protected Random xorShiftRandom = new XorShiftRandom(rand.nextLong()); protected Random xorShiftRandom = new XorShiftRandom(rand.nextLong());
protected double beta = 1; protected double beta = 1;
protected long minpause = 10; protected long minpause = 10;
protected long maxpause = 50; protected long maxpause = 50;
protected double dist_alpha = 3; protected double dist_alpha = 3;
protected double cluster_range; protected double cluster_range;
protected int cluster_ratio = 3; protected int cluster_ratio = 3;
protected int waypoint_ratio = 3; protected int waypoint_ratio = 3;
protected Cluster[] clusters; protected Cluster[] clusters;
protected WeakHashMap<MovementSupported, SLAWMovementInformation> movementInformation; protected WeakHashMap<MovementSupported, SLAWMovementInformation> movementInformation;
// TODO: minpause and maxpause are currently in microseconds... should be // TODO: minpause and maxpause are currently in microseconds... should be
// changed to minutes // changed to minutes
@XMLConfigurableConstructor({"worldX", "worldY", "minpause", "maxpause", "beta", "distAlpha", "clusterRange", "clusterRatio", "waypointRatio" }) @XMLConfigurableConstructor({"worldX", "worldY", "minpause", "maxpause", "beta", "distAlpha", "clusterRange", "clusterRatio", "waypointRatio" })
public SLAWMovementModel(double worldX, double worldY, long minpause, long maxpause, double beta, double distAlpha, double clusterRange, int clusterRatio, int waypointRatio) { public SLAWMovementModel(double worldX, double worldY, long minpause, long maxpause, double beta, double distAlpha, double clusterRange, int clusterRatio, int waypointRatio) {
super(worldX, worldY); super(worldX, worldY);
this.minpause = minpause; this.minpause = minpause;
this.maxpause = maxpause; this.maxpause = maxpause;
this.dist_alpha = distAlpha; this.dist_alpha = distAlpha;
this.cluster_range = clusterRange; this.cluster_range = clusterRange;
this.cluster_ratio = clusterRatio; this.cluster_ratio = clusterRatio;
this.waypoint_ratio = waypointRatio; this.waypoint_ratio = waypointRatio;
movementInformation = new WeakHashMap<MovementSupported, SLAWMovementModel.SLAWMovementInformation>(); movementInformation = new WeakHashMap<MovementSupported, SLAWMovementModel.SLAWMovementInformation>();
} }
@Override @Override
public void nextPosition(MovementSupported node) { public void nextPosition(MovementSupported node) {
// These variables have values same as in the matlab implementation of // These variables have values same as in the matlab implementation of
// SLAW model by Seongik Hong, NCSU, US (3/10/2009) // SLAW model by Seongik Hong, NCSU, US (3/10/2009)
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");
} }
SLAWMovementInformation mi = movementInformation.get(node); SLAWMovementInformation mi = movementInformation.get(node);
if (mi == null) { if (mi == null) {
//System.err.println("Creating new movement information for node " + node.toString()); //System.err.println("Creating new movement information for node " + node.toString());
mi = new SLAWMovementInformation(); mi = new SLAWMovementInformation();
movementInformation.put(node, mi); movementInformation.put(node, mi);
} }
// log.debug("Selecting new destination for node " + mi.nodeId); // log.debug("Selecting new destination for node " + mi.nodeId);
// get random clusters and waypoints // get random clusters and waypoints
if (mi.clts == null) if (mi.clts == null)
mi.clts = make_selection(clusters, null, false); mi.clts = make_selection(clusters, null, false);
// get random clusters and waypoints // get random clusters and waypoints
if (mi.wlist == null) if (mi.wlist == null)
mi.wlist = get_waypoint_list(mi.clts); mi.wlist = get_waypoint_list(mi.clts);
// random source node // random source node
if (mi.srcIndex == -1) { if (mi.srcIndex == -1) {
int old = mi.srcIndex; int old = mi.srcIndex;
mi.srcIndex = (int) Math mi.srcIndex = (int) Math
.floor(randomNextDouble() * mi.wlist.length); .floor(randomNextDouble() * mi.wlist.length);
//System.err.println("mi.srcIndex was " + old + " but is now " + mi.srcIndex); //System.err.println("mi.srcIndex was " + old + " but is now " + mi.srcIndex);
// Set the initial position to the selected waypoint // Set the initial position to the selected waypoint
nextDestination(node, mi.wlist[mi.srcIndex].pos, 0); nextDestination(node, mi.wlist[mi.srcIndex].pos, 0);
//System.err.println("Default case? 0"); //System.err.println("Default case? 0");
return; return;
} }
if (mi.dstIndex != -1) { if (mi.dstIndex != -1) {
mi.srcIndex = mi.dstIndex; mi.srcIndex = mi.dstIndex;
} }
int count = 0; int count = 0;
PositionVector source = new PositionVector(node.getRealPosition() PositionVector source = new PositionVector(node.getRealPosition()
.getX(), node.getRealPosition().getY()); .getX(), node.getRealPosition().getY());
mi.wlist[mi.srcIndex].is_visited = true; mi.wlist[mi.srcIndex].is_visited = true;
// get list of not visited locations // get list of not visited locations
for (int i = 0; i < mi.wlist.length; i++) { for (int i = 0; i < mi.wlist.length; i++) {
if (!mi.wlist[i].is_visited) { if (!mi.wlist[i].is_visited) {
count++; count++;
} }
} }
// if all waypoints are visited then select new clusters and // if all waypoints are visited then select new clusters and
// waypoints. Destructive mode of original SLAW matlab // waypoints. Destructive mode of original SLAW matlab
// implementation by Seongik Hong, NCSU, US (3/10/2009) // implementation by Seongik Hong, NCSU, US (3/10/2009)
while (count == 0) { while (count == 0) {
mi.clts = make_selection(clusters, mi.clts, true); mi.clts = make_selection(clusters, mi.clts, true);
mi.wlist = get_waypoint_list(mi.clts); mi.wlist = get_waypoint_list(mi.clts);
for (int i = 0; i < mi.wlist.length; i++) { for (int i = 0; i < mi.wlist.length; i++) {
if (!mi.wlist[i].is_visited) { if (!mi.wlist[i].is_visited) {
if (source.getDistance(mi.wlist[i].pos) != 0.0) { if (source.distanceTo(mi.wlist[i].pos) != 0.0) {
count++; count++;
} else { } else {
mi.wlist[i].is_visited = true; mi.wlist[i].is_visited = true;
} }
} }
} }
} }
ClusterMember[] not_visited = new ClusterMember[count]; ClusterMember[] not_visited = new ClusterMember[count];
count = 0; count = 0;
for (int i = 0; i < mi.wlist.length; i++) { for (int i = 0; i < mi.wlist.length; i++) {
if (!mi.wlist[i].is_visited) { if (!mi.wlist[i].is_visited) {
not_visited[count++] = mi.wlist[i]; not_visited[count++] = mi.wlist[i];
} }
} }
// get distance from source to all remaining waypoints // get distance from source to all remaining waypoints
double[] dist = new double[not_visited.length]; double[] dist = new double[not_visited.length];
for (int i = 0; i < not_visited.length; i++) { for (int i = 0; i < not_visited.length; i++) {
dist[i] = source.getDistance(not_visited[i].pos); dist[i] = source.distanceTo(not_visited[i].pos);
} }
double[] weights = new double[not_visited.length]; double[] weights = new double[not_visited.length];
// cumulative sum of distance weights // cumulative sum of distance weights
for (int i = 0; i < weights.length; i++) { for (int i = 0; i < weights.length; i++) {
weights[i] = 0; weights[i] = 0;
for (int j = 0; j <= i; j++) { for (int j = 0; j <= i; j++) {
weights[i] += 1 / Math.pow(dist[j], this.dist_alpha); weights[i] += 1 / Math.pow(dist[j], this.dist_alpha);
} }
} }
for (int i = 0; i < weights.length; i++) { for (int i = 0; i < weights.length; i++) {
weights[i] /= weights[weights.length - 1]; weights[i] /= weights[weights.length - 1];
} }
double r = randomNextDouble(); double r = randomNextDouble();
int index; int index;
for (index = 0; index < weights.length; index++) { for (index = 0; index < weights.length; index++) {
if (r < weights[index]) { if (r < weights[index]) {
break; break;
} }
} }
// select the next destination // select the next destination
for (int i = 0; i < mi.wlist.length; i++) { for (int i = 0; i < mi.wlist.length; i++) {
if (mi.wlist[i].pos.equals(not_visited[index].pos)) { if (mi.wlist[i].pos.equals(not_visited[index].pos)) {
mi.dstIndex = i; mi.dstIndex = i;
double pauseTime = random_powerlaw(powerlaw_step, double pauseTime = random_powerlaw(powerlaw_step,
levy_scale_factor, powerlaw_mode)[0]; levy_scale_factor, powerlaw_mode)[0];
//System.err.println("Next pause time is " + pauseTime); //System.err.println("Next pause time is " + pauseTime);
nextDestination( nextDestination(
node, node,
mi.wlist[mi.dstIndex].pos, (long) pauseTime mi.wlist[mi.dstIndex].pos, (long) pauseTime
); );
break; break;
} }
} }
// change destination to next source // change destination to next source
// mi.srcIndex = mi.dstIndex; // mi.srcIndex = mi.dstIndex;
} }
/** /**
* returns aggregated list of cluster members from all passed clusters * returns aggregated list of cluster members from all passed clusters
* *
* @param clusters * @param clusters
* clusters list * clusters list
* @return array of ClusterMember type * @return array of ClusterMember type
*/ */
protected ClusterMember[] get_waypoint_list(Cluster[] clusters) { protected ClusterMember[] get_waypoint_list(Cluster[] clusters) {
ArrayList<ClusterMember> result = new ArrayList<ClusterMember>(); ArrayList<ClusterMember> result = new ArrayList<ClusterMember>();
for (Cluster cluster : clusters) { for (Cluster cluster : clusters) {
for (ClusterMember clustermember : cluster.members) { for (ClusterMember clustermember : cluster.members) {
result.add(clustermember); result.add(clustermember);
} }
} }
return result.toArray(new ClusterMember[0]); return result.toArray(new ClusterMember[0]);
} }
/** /**
* makes the selection of new clusters and waypoints from passed clusters * makes the selection of new clusters and waypoints from passed clusters
* *
* @param clusters * @param clusters
* array of clusters to make selection from * array of clusters to make selection from
* @param change_one * @param change_one
* changes only one of the clusters randomly and then selects new * changes only one of the clusters randomly and then selects new
* waypoints from all clusters * waypoints from all clusters
* @return array of selected clusters * @return array of selected clusters
*/ */
protected Cluster[] make_selection(Cluster[] clusters, Cluster[] cur_list, protected Cluster[] make_selection(Cluster[] clusters, Cluster[] cur_list,
boolean change_one) { boolean change_one) {
ArrayList<Integer> cluster_selection; ArrayList<Integer> cluster_selection;
if (!change_one) { if (!change_one) {
// Number of clusters to select // Number of clusters to select
int num_clusters = (int) Math.ceil((double) clusters.length int num_clusters = (int) Math.ceil((double) clusters.length
/ (double) cluster_ratio); / (double) cluster_ratio);
cluster_selection = new ArrayList<Integer>(num_clusters); cluster_selection = new ArrayList<Integer>(num_clusters);
for (int i = 0; i < num_clusters; i++) { for (int i = 0; i < num_clusters; i++) {
cluster_selection.add(i, -1); cluster_selection.add(i, -1);
} }
int[] total_list = new int[waypointModel.getNumberOfWaypoints(StrongWaypoint.class)]; int[] total_list = new int[waypointModel.getNumberOfWaypoints(StrongWaypoint.class)];
int counter = 0; int counter = 0;
// probability array // probability array
for (int i = 0; i < clusters.length; i++) { for (int i = 0; i < clusters.length; i++) {
for (int j = 0; j < clusters[i].members.length; j++) { for (int j = 0; j < clusters[i].members.length; j++) {
total_list[counter++] = clusters[i].index; total_list[counter++] = clusters[i].index;
} }
} }
// select clusters randomly with weights // select clusters randomly with weights
int t = total_list[(int) Math.floor(this.randomNextDouble() int t = total_list[(int) Math.floor(this.randomNextDouble()
* waypointModel.getNumberOfWaypoints(StrongWaypoint.class))]; * waypointModel.getNumberOfWaypoints(StrongWaypoint.class))];
for (int i = 0; i < cluster_selection.size(); i++) { for (int i = 0; i < cluster_selection.size(); i++) {
while (cluster_selection.contains(t)) { while (cluster_selection.contains(t)) {
t = total_list[(int) Math.floor(this.randomNextDouble() t = total_list[(int) Math.floor(this.randomNextDouble()
* waypointModel.getNumberOfWaypoints(StrongWaypoint.class))]; * waypointModel.getNumberOfWaypoints(StrongWaypoint.class))];
} }
cluster_selection.set(i, t); cluster_selection.set(i, t);
} }
} else {// just need to change one randomly } else {// just need to change one randomly
cluster_selection = new ArrayList<Integer>(cur_list.length); cluster_selection = new ArrayList<Integer>(cur_list.length);
for (Cluster cluster : cur_list) { for (Cluster cluster : cur_list) {
cluster_selection.add(cluster.index); cluster_selection.add(cluster.index);
} }
} }
// change one cluster without weight consideration // change one cluster without weight consideration
cluster_selection = change_one_random(cluster_selection, cluster_selection = change_one_random(cluster_selection,
clusters.length); clusters.length);
// select waypoints from selected clusters. // select waypoints from selected clusters.
Cluster[] result = new Cluster[cluster_selection.size()]; Cluster[] result = new Cluster[cluster_selection.size()];
double numberOfWaypoints; double numberOfWaypoints;
Cluster cluster_iterator = null; Cluster cluster_iterator = null;
for (int i = 0; i < cluster_selection.size(); i++) { for (int i = 0; i < cluster_selection.size(); i++) {
// find Cluster object in clusters array // find Cluster object in clusters array
for (int j = 0; j < clusters.length; j++) { for (int j = 0; j < clusters.length; j++) {
if (cluster_selection.get(i) == clusters[j].index) { if (cluster_selection.get(i) == clusters[j].index) {
cluster_iterator = clusters[j]; cluster_iterator = clusters[j];
break; break;
} }
} }
result[i] = new Cluster(cluster_iterator.index); result[i] = new Cluster(cluster_iterator.index);
numberOfWaypoints = (double) cluster_iterator.members.length numberOfWaypoints = (double) cluster_iterator.members.length
/ (double) this.waypoint_ratio; / (double) this.waypoint_ratio;
int[] waypoint_selection; int[] waypoint_selection;
if (numberOfWaypoints < 1) { if (numberOfWaypoints < 1) {
waypoint_selection = select_uniformly( waypoint_selection = select_uniformly(
cluster_iterator.members.length, 1); cluster_iterator.members.length, 1);
} else { } else {
if (this.randomNextDouble() < numberOfWaypoints % 1) { if (this.randomNextDouble() < numberOfWaypoints % 1) {
waypoint_selection = select_uniformly( waypoint_selection = select_uniformly(
cluster_iterator.members.length, cluster_iterator.members.length,
(int) (Math.floor(numberOfWaypoints) + 1)); (int) (Math.floor(numberOfWaypoints) + 1));
} else { } else {
waypoint_selection = select_uniformly( waypoint_selection = select_uniformly(
cluster_iterator.members.length, cluster_iterator.members.length,
(int) Math.floor(numberOfWaypoints)); (int) Math.floor(numberOfWaypoints));
} }
} }
result[i].members = new ClusterMember[waypoint_selection.length]; result[i].members = new ClusterMember[waypoint_selection.length];
for (int j = 0; j < waypoint_selection.length; j++) { for (int j = 0; j < waypoint_selection.length; j++) {
result[i].members[j] = cluster_iterator.members[waypoint_selection[j]] result[i].members[j] = cluster_iterator.members[waypoint_selection[j]]
.clone(); .clone();
} }
} }
return result; return result;
} }
/** /**
* changes one of the numbers randomly from the passed array. The new * changes one of the numbers randomly from the passed array. The new
* changed number is in range [1,n] * changed number is in range [1,n]
* *
* @param list * @param list
* array of integers * array of integers
* @param n * @param n
* range of numbers * range of numbers
* @return array of integers with one element changed randomly * @return array of integers with one element changed randomly
*/ */
protected ArrayList<Integer> change_one_random(ArrayList<Integer> list, protected ArrayList<Integer> change_one_random(ArrayList<Integer> list,
int n) { int n) {
int index = (int) Math.floor(this.randomNextDouble() * list.size()); int index = (int) Math.floor(this.randomNextDouble() * list.size());
int value = (int) Math.floor(this.randomNextDouble() * n) + 1; int value = (int) Math.floor(this.randomNextDouble() * n) + 1;
while (list.contains(value)) { while (list.contains(value)) {
value = (int) Math.floor(this.randomNextDouble() * n) + 1; value = (int) Math.floor(this.randomNextDouble() * n) + 1;
} }
list.set(index, value); list.set(index, value);
return list; return list;
} }
/** /**
* selects k numbers out of n uniformly * selects k numbers out of n uniformly
* *
* @param n * @param n
* @param k * @param k
* @return array of k integers * @return array of k integers
*/ */
protected int[] select_uniformly(int n, int k) { protected int[] select_uniformly(int n, int k) {
if (k > n) if (k > n)
throw new RuntimeException( throw new RuntimeException(
"SLAW.select_uniformaly(): value of k must not be larger than n."); "SLAW.select_uniformaly(): value of k must not be larger than n.");
int t; int t;
int[] list = new int[k]; int[] list = new int[k];
for (int i = 0; i < k; i++) { for (int i = 0; i < k; i++) {
list[i] = -1; list[i] = -1;
} }
boolean is_in; boolean is_in;
int count = 0; int count = 0;
while (count < k) { while (count < k) {
is_in = false; is_in = false;
t = (int) Math.floor(this.randomNextDouble() * n); t = (int) Math.floor(this.randomNextDouble() * n);
for (int i = 0; i < list.length; i++) { for (int i = 0; i < list.length; i++) {
if (list[i] == t) { if (list[i] == t) {
is_in = true; is_in = true;
break; break;
} }
} }
if (!is_in) { if (!is_in) {
list[count++] = t; list[count++] = t;
} }
} }
return list; return list;
} }
/** /**
* Generates random values from power-law distribution. * Generates random values from power-law distribution.
* *
* @param powerlaw_step * @param powerlaw_step
* the total numbers to generate. Returns an array of this size. * the total numbers to generate. Returns an array of this size.
* @param levy_scale_factor * @param levy_scale_factor
* levy scaling factor of distribution * levy scaling factor of distribution
* @param powerlaw_mode * @param powerlaw_mode
* 1: stabrnd 2: reverse computation * 1: stabrnd 2: reverse computation
* @return double array of powerlaw_step length * @return double array of powerlaw_step length
**/ **/
protected double[] random_powerlaw(int powerlaw_step, protected double[] random_powerlaw(int powerlaw_step,
int levy_scale_factor, int powerlaw_mode) { int levy_scale_factor, int powerlaw_mode) {
double[] result = new double[powerlaw_step]; double[] result = new double[powerlaw_step];
for (int xi = 0; xi < powerlaw_step;) { for (int xi = 0; xi < powerlaw_step;) {
if (powerlaw_mode == 1) { // stabrnd if (powerlaw_mode == 1) { // stabrnd
double[] stabrnd_result = stabrnd(0, levy_scale_factor, 0, double[] stabrnd_result = stabrnd(0, levy_scale_factor, 0,
powerlaw_step); powerlaw_step);
ArrayList<Double> temp = new ArrayList<Double>(); ArrayList<Double> temp = new ArrayList<Double>();
for (int i = 0; i < stabrnd_result.length; i++) { for (int i = 0; i < stabrnd_result.length; i++) {
if (stabrnd_result[i] > this.minpause if (stabrnd_result[i] > this.minpause
&& stabrnd_result[i] < this.maxpause) { && stabrnd_result[i] < this.maxpause) {
temp.add(new Double(stabrnd_result[i])); temp.add(new Double(stabrnd_result[i]));
} }
} }
if (temp.size() > 0) { if (temp.size() > 0) {
for (Double d : temp) { for (Double d : temp) {
result[xi++] = d; result[xi++] = d;
if (xi > powerlaw_step) if (xi > powerlaw_step)
break; break;
} }
} }
} else if (powerlaw_mode == 2) { // reverse computation } else if (powerlaw_mode == 2) { // reverse computation
double temp = Math.pow(randomNextDouble(), double temp = Math.pow(randomNextDouble(),
1 / (1 - (this.beta + 1))) * this.minpause; 1 / (1 - (this.beta + 1))) * this.minpause;
if (temp < this.maxpause) { if (temp < this.maxpause) {
result[xi++] = temp; result[xi++] = temp;
} }
} }
} }
return result; return result;
} }
/** /**
* Returns array of randomly generated n numbers based on the method of J.M. * Returns array of randomly generated n numbers based on the method of J.M.
* Chambers, C.L. Mallows and B.W. Stuck, * Chambers, C.L. Mallows and B.W. Stuck,
* "A Method for Simulating Stable Random Variables," JASA 71 (1976): 340-4. * "A Method for Simulating Stable Random Variables," JASA 71 (1976): 340-4.
* *
* @param b * @param b
* beta factor * beta factor
* @param levy_scale_factor * @param levy_scale_factor
* @param delta * @param delta
* @param n * @param n
* count of random numbers to generate * count of random numbers to generate
* @return double array of n length * @return double array of n length
*/ */
private double[] stabrnd(double b, int levy_scale_factor, double delta, private double[] stabrnd(double b, int levy_scale_factor, double delta,
int n) { int n) {
if (this.beta < .1 || this.beta > 2) { if (this.beta < .1 || this.beta > 2) {
throw new RuntimeException( throw new RuntimeException(
"SLAW.stabrnd(): Beta value must be in [.1,2]"); "SLAW.stabrnd(): Beta value must be in [.1,2]");
} }
if (Math.abs(b) > 1) { if (Math.abs(b) > 1) {
throw new RuntimeException( throw new RuntimeException(
"SLAW.stabrnd(): local beta value must be in [-1,1]"); "SLAW.stabrnd(): local beta value must be in [-1,1]");
} }
// Generate exponential w and uniform phi // Generate exponential w and uniform phi
double[] w = new double[n]; double[] w = new double[n];
double[] x = new double[n]; double[] x = new double[n];
double[] phi = new double[n]; double[] phi = new double[n];
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
w[i] = -Math.log(randomNextDouble()); w[i] = -Math.log(randomNextDouble());
phi[i] = (randomNextDouble() - 0.5) * Math.PI; phi[i] = (randomNextDouble() - 0.5) * Math.PI;
} }
// Gaussian case (Box-Muller) // Gaussian case (Box-Muller)
if (this.beta == 2) { if (this.beta == 2) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = 2 * Math.sqrt(w[i]) * Math.sin(phi[i]); x[i] = 2 * Math.sqrt(w[i]) * Math.sin(phi[i]);
x[i] = delta + levy_scale_factor * x[i]; x[i] = delta + levy_scale_factor * x[i];
} }
} else if (b == 0) { // Symmetrical cases } else if (b == 0) { // Symmetrical cases
if (this.beta == 1) { // Cauchy case if (this.beta == 1) { // Cauchy case
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = Math.tan(phi[i]); x[i] = Math.tan(phi[i]);
} }
} else { } else {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = Math.pow(Math.cos((1 - this.beta) * phi[i]) / w[i], x[i] = Math.pow(Math.cos((1 - this.beta) * phi[i]) / w[i],
1 / this.beta - 1) 1 / this.beta - 1)
* Math.sin(this.beta * phi[i]) * Math.sin(this.beta * phi[i])
/ Math.pow(Math.cos(phi[i]), 1 / this.beta); / Math.pow(Math.cos(phi[i]), 1 / this.beta);
} }
} }
} else { // General cases } else { // General cases
double cosphi, zeta, aphi, a1phi, bphi; double cosphi, zeta, aphi, a1phi, bphi;
if (Math.abs(this.beta - 1) > 0.00000001) { if (Math.abs(this.beta - 1) > 0.00000001) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
cosphi = Math.cos(phi[i]); cosphi = Math.cos(phi[i]);
zeta = b * Math.tan(Math.PI * this.beta / 2); zeta = b * Math.tan(Math.PI * this.beta / 2);
aphi = this.beta * phi[i]; aphi = this.beta * phi[i];
a1phi = (1 - this.beta) * phi[i]; a1phi = (1 - this.beta) * phi[i];
x[i] = (Math.sin(aphi) + zeta * Math.cos(aphi)) x[i] = (Math.sin(aphi) + zeta * Math.cos(aphi))
/ cosphi / cosphi
* Math.pow( * Math.pow(
(Math.cos(a1phi) + zeta * Math.sin(a1phi)) (Math.cos(a1phi) + zeta * Math.sin(a1phi))
/ (w[i] * cosphi), (1 - this.beta) / (w[i] * cosphi), (1 - this.beta)
/ this.beta); / this.beta);
} }
} else { } else {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
cosphi = Math.cos(phi[i]); cosphi = Math.cos(phi[i]);
bphi = Math.PI / 2 + b * phi[i]; bphi = Math.PI / 2 + b * phi[i];
x[i] = 2 x[i] = 2
/ Math.PI / Math.PI
* (bphi * Math.tan(phi[i]) - b * (bphi * Math.tan(phi[i]) - b
* Math.log((Math.PI / 2) * w[i] * cosphi * Math.log((Math.PI / 2) * w[i] * cosphi
/ bphi)); / bphi));
} }
if (this.beta != 1) { if (this.beta != 1) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] += b * Math.tan(Math.PI * this.beta / 2); x[i] += b * Math.tan(Math.PI * this.beta / 2);
} }
} }
} }
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
x[i] = delta + levy_scale_factor * x[i]; x[i] = delta + levy_scale_factor * x[i];
} }
} }
return x; return x;
} }
protected double randomNextDouble(final double value) { protected double randomNextDouble(final double value) {
return (randomNextDouble() * value); return (randomNextDouble() * value);
} }
protected double randomNextDouble() { protected double randomNextDouble() {
return xorShiftRandom.nextDouble(); return xorShiftRandom.nextDouble();
//return rand.nextDouble(); //return rand.nextDouble();
} }
private static final class Cluster { private static final class Cluster {
public ClusterMember[] members; public ClusterMember[] members;
public int index = -1; public int index = -1;
public Cluster(int _index) { public Cluster(int _index) {
index = _index; index = _index;
} }
public Cluster(int _index, ClusterMember[] _members) { public Cluster(int _index, ClusterMember[] _members) {
index = _index; index = _index;
members = _members; members = _members;
} }
public String toString() { public String toString() {
return "Cluster[index: " + index + "]"; return "Cluster[index: " + index + "]";
} }
} }
private static final class ClusterMember { private static final class ClusterMember {
public int cluster_index = -1; public int cluster_index = -1;
public PositionVector pos; public PositionVector pos;
public boolean is_visited = false; public boolean is_visited = false;
public ClusterMember(int _cluster_index, PositionVector _pos, public ClusterMember(int _cluster_index, PositionVector _pos,
boolean _is_visited) { boolean _is_visited) {
this.cluster_index = _cluster_index; this.cluster_index = _cluster_index;
this.is_visited = _is_visited; this.is_visited = _is_visited;
this.pos = _pos; this.pos = _pos;
} }
public ClusterMember clone() { public ClusterMember clone() {
return new ClusterMember(this.cluster_index, this.pos, return new ClusterMember(this.cluster_index, this.pos,
this.is_visited); this.is_visited);
} }
} }
private static class SLAWMovementInformation { private static class SLAWMovementInformation {
public SLAWMovementInformation() { public SLAWMovementInformation() {
// //
} }
public int srcIndex = -1; public int srcIndex = -1;
public int dstIndex = -1; public int dstIndex = -1;
public Cluster[] clts = null; public Cluster[] clts = null;
public ClusterMember[] wlist = null; public ClusterMember[] wlist = null;
} }
@Configure() @Configure()
@After(required={WaypointModel.class}) @After(required={WaypointModel.class})
public void _verifyConfig() { public void _verifyConfig() {
/* /*
* FIXME: get rid of this method! * FIXME: get rid of this method!
*/ */
Collection<Waypoint> strongWaypoints = waypointModel.getWaypoints(StrongWaypoint.class); Collection<Waypoint> strongWaypoints = waypointModel.getWaypoints(StrongWaypoint.class);
if (strongWaypoints == null) if (strongWaypoints == null)
throw new ConfigurationException("The configured waypoint model hasn't generated any strong waypoints that are required by the SLAWMovementModel."); throw new ConfigurationException("The configured waypoint model hasn't generated any strong waypoints that are required by the SLAWMovementModel.");
clusters = generate_clusters(waypointModel); clusters = generate_clusters(waypointModel);
if (clusters.length <= 2) { if (clusters.length <= 2) {
throw new ConfigurationException("The SLAW movement model could only generate 1 cluster, please adjust the cluster range parameter"); throw new ConfigurationException("The SLAW movement model could only generate 1 cluster, please adjust the cluster range parameter");
} }
VisualizationInjector.injectComponent("Clusters", -1, new SLAWClusterOverlay(clusters, waypointModel), false); VisualizationInjector.injectComponent("Clusters", -1, new SLAWClusterOverlay(clusters, waypointModel), false);
VisualizationInjector.addDisplayString(new DisplayString() { VisualizationInjector.addDisplayString(new DisplayString() {
@Override @Override
public String getDisplayString() { public String getDisplayString() {
int clusterWps = 0; int clusterWps = 0;
for (Cluster c : clusters) { for (Cluster c : clusters) {
clusterWps += c.members.length; clusterWps += c.members.length;
} }
return "SLAW[Clusters: " + clusters.length + ", WPs in clusters: " + clusterWps + ", Avg per cluster: " + (clusterWps / clusters.length) + "]"; return "SLAW[Clusters: " + clusters.length + ", WPs in clusters: " + clusterWps + ", Avg per cluster: " + (clusterWps / clusters.length) + "]";
} }
}); });
} }
@Override @Override
public void setWaypointModel(WaypointModel waypointModel) { public void setWaypointModel(WaypointModel waypointModel) {
super.setWaypointModel(waypointModel); super.setWaypointModel(waypointModel);
} }
/** /**
* generates clusters * generates clusters
* *
* @param waypoints * @param waypoints
* list of waypoint s * list of waypoint s
* @return array of clusters * @return array of clusters
*/ */
protected Cluster[] generate_clusters(WaypointModel model) { protected Cluster[] generate_clusters(WaypointModel model) {
Vector<PositionVector> all_points = new Vector<PositionVector>(); Vector<PositionVector> all_points = new Vector<PositionVector>();
Vector<PositionVector> new_points = new Vector<PositionVector>(); Vector<PositionVector> new_points = new Vector<PositionVector>();
Vector<PositionVector> members = new Vector<PositionVector>(); Vector<PositionVector> members = new Vector<PositionVector>();
Vector<Cluster> clusters = new Vector<Cluster>(); Vector<Cluster> clusters = new Vector<Cluster>();
Vector<ClusterMember> cluster_members = new Vector<ClusterMember>(); Vector<ClusterMember> cluster_members = new Vector<ClusterMember>();
Waypoint[] waypoints = new Waypoint[]{}; Waypoint[] waypoints = new Waypoint[]{};
Collection<Waypoint> waypointList = model.getWaypoints(StrongWaypoint.class); Collection<Waypoint> waypointList = model.getWaypoints(StrongWaypoint.class);
if (waypointList == null) if (waypointList == null)
throw new ConfigurationException("The configured waypoint model didn't generate any strong waypoints"); throw new ConfigurationException("The configured waypoint model didn't generate any strong waypoints");
waypoints = waypointList.toArray(waypoints); waypoints = waypointList.toArray(waypoints);
for (int i = 0; i < waypoints.length; i++) { for (int i = 0; i < waypoints.length; i++) {
all_points.add(waypoints[i].getPosition()); all_points.add(waypoints[i].getPosition());
} }
PositionVector init_pos = null; PositionVector init_pos = null;
int cluster_count = 0; int cluster_count = 0;
while (!all_points.isEmpty()) { while (!all_points.isEmpty()) {
if (init_pos == null) { if (init_pos == null) {
init_pos = all_points.firstElement(); init_pos = all_points.firstElement();
all_points.remove(0); all_points.remove(0);
members.add(init_pos); members.add(init_pos);
} }
for (int i = 0; i < all_points.size(); i++) { for (int i = 0; i < all_points.size(); i++) {
PositionVector new_pos = all_points.elementAt(i); PositionVector new_pos = all_points.elementAt(i);
if (init_pos.getDistance(new_pos) <= this.cluster_range) { if (init_pos.distanceTo(new_pos) <= this.cluster_range) {
new_points.add(new_pos); new_points.add(new_pos);
members.add(new_pos); members.add(new_pos);
all_points.remove(i--); all_points.remove(i--);
} }
}// for all_points }// for all_points
if (!new_points.isEmpty() && !all_points.isEmpty()) { if (!new_points.isEmpty() && !all_points.isEmpty()) {
init_pos = new_points.firstElement(); init_pos = new_points.firstElement();
new_points.remove(0); new_points.remove(0);
} }
else { else {
for (int i = 0; i < members.size(); i++) { for (int i = 0; i < members.size(); i++) {
cluster_members.add(new ClusterMember(cluster_count, members.elementAt(i), false)); cluster_members.add(new ClusterMember(cluster_count, members.elementAt(i), false));
} }
clusters.add(new Cluster(++cluster_count, cluster_members.toArray(new ClusterMember[0]))); clusters.add(new Cluster(++cluster_count, cluster_members.toArray(new ClusterMember[0])));
cluster_members.clear(); cluster_members.clear();
new_points.clear(); new_points.clear();
members.clear(); members.clear();
init_pos = null; init_pos = null;
} }
}// while all_points }// while all_points
return clusters.toArray(new Cluster[0]); return clusters.toArray(new Cluster[0]);
} }
private class SLAWClusterOverlay extends JComponent { private class SLAWClusterOverlay extends JComponent {
private Map<Cluster, Color> clusterColors = Maps.newHashMap(); private Map<Cluster, Color> clusterColors = Maps.newHashMap();
private Cluster[] clusters; private Cluster[] clusters;
private Random rnd = new Random(System.nanoTime()); private Random rnd = new Random(System.nanoTime());
private WaypointModel model; private WaypointModel model;
public SLAWClusterOverlay(Cluster[] clusters, WaypointModel model) { public SLAWClusterOverlay(Cluster[] clusters, WaypointModel model) {
super(); super();
this.clusters = clusters; this.clusters = clusters;
this.model = model; this.model = model;
PositionVector dimension = model.getMap().getDimensions(); PositionVector dimension = model.getMap().getDimensions();
setBounds(0, 0, (int) dimension.getX(), (int) dimension.getY()); setBounds(0, 0, (int) dimension.getX(), (int) dimension.getY());
setOpaque(false); setOpaque(false);
setVisible(true); setVisible(true);
} }
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
g2.setFont(new Font("SansSerif", Font.PLAIN, 9)); g2.setFont(new Font("SansSerif", Font.PLAIN, 9));
for (Cluster c : clusters) { for (Cluster c : clusters) {
PositionVector lastPos = null; PositionVector lastPos = null;
Color randomColor = clusterColors.get(c); Color randomColor = clusterColors.get(c);
if (randomColor == null) { if (randomColor == null) {
final float hue = rnd.nextFloat(); final float hue = rnd.nextFloat();
// Saturation between 0.1 and 0.3 // Saturation between 0.1 and 0.3
final float saturation = (rnd.nextInt(2000) + 1000) / 10000f; final float saturation = (rnd.nextInt(2000) + 1000) / 10000f;
final float luminance = 0.9f; final float luminance = 0.9f;
randomColor = Color.getHSBColor(hue, saturation, luminance); randomColor = Color.getHSBColor(hue, saturation, luminance);
randomColor = new Color(rnd.nextFloat(), rnd.nextFloat(), rnd.nextFloat()); randomColor = new Color(rnd.nextFloat(), rnd.nextFloat(), rnd.nextFloat());
clusterColors.put(c, randomColor); clusterColors.put(c, randomColor);
} }
g2.setColor(randomColor); g2.setColor(randomColor);
for (ClusterMember m : c.members) { for (ClusterMember m : c.members) {
if (lastPos == null) lastPos = m.pos; if (lastPos == null) lastPos = m.pos;
g2.drawLine((int)lastPos.getX(), (int)lastPos.getY(), (int)m.pos.getX(), (int)m.pos.getY()); g2.drawLine((int)lastPos.getX(), (int)lastPos.getY(), (int)m.pos.getX(), (int)m.pos.getY());
lastPos = m.pos; lastPos = m.pos;
} }
} }
} }
} }
} }
...@@ -59,7 +59,7 @@ public class TargetMovement extends AbstractMovementModel { ...@@ -59,7 +59,7 @@ public class TargetMovement extends AbstractMovementModel {
PositionVector rVec = new PositionVector(x, y); PositionVector rVec = new PositionVector(x, y);
rVec = rVec.minus(pos); rVec = rVec.minus(pos);
double length = rVec.getDistance(new PositionVector(0, 0)); double length = rVec.distanceTo(new PositionVector(0, 0));
PositionVector vec; PositionVector vec;
if (length > distance) { if (length > distance) {
......
/* /*
* 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.movement.local; package de.tud.kom.p2psim.impl.topology.movement.local;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.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;
/** /**
* This movement strategy moves directly towards a given destination without * This movement strategy moves directly towards a given destination without
* regard for obstacles or way points. * regard for obstacles or way points.
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 09.04.2012 * @version 1.0, 09.04.2012
*/ */
public class LinearMovement extends AbstractLocalMovementStrategy { public class LinearMovement extends AbstractLocalMovementStrategy {
public Either<PositionVector, Boolean> nextPosition(MovementSupported comp, public Either<PositionVector, Boolean> nextPosition(MovementSupported comp,
PositionVector destination) { PositionVector destination) {
PositionVector newPosition; PositionVector newPosition;
if (destination.getDistance(comp.getRealPosition()) < getMovementSpeed(comp)) { if (destination
newPosition = destination.clone(); .distanceTo(comp.getRealPosition()) < getMovementSpeed(comp)) {
} else { newPosition = destination.clone();
newPosition = comp.getRealPosition().moveStep(destination, getMovementSpeed(comp)); } else {
} newPosition = comp.getRealPosition().moveStep(destination, getMovementSpeed(comp));
return new Left<PositionVector, Boolean>(newPosition); }
} return new Left<PositionVector, Boolean>(newPosition);
} }
}
...@@ -25,6 +25,7 @@ import java.io.InputStream; ...@@ -25,6 +25,7 @@ import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
...@@ -34,12 +35,13 @@ import com.graphhopper.util.PointList; ...@@ -34,12 +35,13 @@ import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint; import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D; import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
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.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;
/** /**
* This movement strategy uses the data from MapQuest * This movement strategy uses the data from MapQuest
...@@ -63,7 +65,8 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy { ...@@ -63,7 +65,8 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
//if the distance is smaller than the given one, the node will choose the next point in the list //if the distance is smaller than the given one, the node will choose the next point in the list
public OnlineMapQuestMovement() { public OnlineMapQuestMovement() {
this.worldDimensions = Topology.getWorldDimension(); this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
latLeft = GPSCalculation.getLatLower(); latLeft = GPSCalculation.getLatLower();
latRight = GPSCalculation.getLatUpper(); latRight = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft(); lonLeft = GPSCalculation.getLonLeft();
...@@ -74,7 +77,8 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy { ...@@ -74,7 +77,8 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
PositionVector destination) { PositionVector destination) {
PositionVector newPosition = null; PositionVector newPosition = null;
if (destination.getDistance(comp.getRealPosition()) < getMovementSpeed(comp)) { if (destination
.distanceTo(comp.getRealPosition()) < getMovementSpeed(comp)) {
newPosition = destination.clone(); newPosition = destination.clone();
} else { } else {
//if not set already for this node or new destination is different than last one //if not set already for this node or new destination is different than last one
......
...@@ -31,12 +31,13 @@ import com.graphhopper.util.PointList; ...@@ -31,12 +31,13 @@ import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint; import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D; import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.Topology;
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.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;
/** /**
* 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
...@@ -68,7 +69,8 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -68,7 +69,8 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
private double tolerance = 1; private double tolerance = 1;
public RealWorldStreetsMovement() { public RealWorldStreetsMovement() {
this.worldDimensions = Topology.getWorldDimension(); this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
latLeft = GPSCalculation.getLatLower(); latLeft = GPSCalculation.getLatLower();
latRight = GPSCalculation.getLatUpper(); latRight = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft(); lonLeft = GPSCalculation.getLonLeft();
...@@ -90,7 +92,8 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -90,7 +92,8 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
if(!init) init(); if(!init) init();
PositionVector newPosition = null; PositionVector newPosition = null;
if (destination.getDistance(comp.getRealPosition()) < getMovementSpeed(comp)) { if (destination
.distanceTo(comp.getRealPosition()) < getMovementSpeed(comp)) {
newPosition = destination.clone(); newPosition = destination.clone();
} else { } else {
//if not set already for this node or new destination is different than last one //if not set already for this node or new destination is different than last one
......
/* /*
* 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.movement.local; package de.tud.kom.p2psim.impl.topology.movement.local;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path;
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;
import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Left;
import de.tud.kom.p2psim.impl.util.Right; import de.tud.kom.p2psim.impl.util.Right;
/** /**
* This movement strategy uses the getShortestPath method implemented by the * This movement strategy uses the getShortestPath method implemented by the
* waypoint model and moves along path given by this method. * waypoint model and moves along path given by this method.
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 10.04.2012 * @version 1.0, 10.04.2012
*/ */
public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy { public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy {
// Contains the shortest path and the currently used path // Contains the shortest path and the currently used path
protected final WeakHashMap<MovementSupported, Integer> currentPath = new WeakHashMap<MovementSupported, Integer>(); protected final WeakHashMap<MovementSupported, Integer> currentPath = new WeakHashMap<MovementSupported, Integer>();
protected final WeakHashMap<MovementSupported, List<Waypoint>> dstPaths = new WeakHashMap<MovementSupported, List<Waypoint>>(); protected final WeakHashMap<MovementSupported, List<Waypoint>> dstPaths = new WeakHashMap<MovementSupported, List<Waypoint>>();
// Used to check if the destination was altered by the waypoint movement // Used to check if the destination was altered by the waypoint movement
// model // model
protected WeakHashMap<MovementSupported, PositionVector> currentDestination = new WeakHashMap<MovementSupported, PositionVector>(); protected WeakHashMap<MovementSupported, PositionVector> currentDestination = new WeakHashMap<MovementSupported, PositionVector>();
/** /**
* Calculates the next position of the given movement supported component by * Calculates the next position of the given movement supported component by
* using the shortest path to the waypoint closest to the destination. * using the shortest path to the waypoint closest to the destination.
*/ */
@Override @Override
public Either<PositionVector, Boolean> nextPosition(MovementSupported comp, public Either<PositionVector, Boolean> nextPosition(MovementSupported comp,
PositionVector destination) { PositionVector destination) {
if (currentDestination.get(comp) == null if (currentDestination.get(comp) == null
|| !currentDestination.get(comp).equals(destination)) { || !currentDestination.get(comp).equals(destination)) {
currentDestination.put(comp, destination); currentDestination.put(comp, destination);
calculateNextMovementPath(comp, destination); calculateNextMovementPath(comp, destination);
// If the list of the shortest path is empty the destination is the // If the list of the shortest path is empty the destination is the
// same // same
// as the current position. Thus tell the abstract waypoint model // as the current position. Thus tell the abstract waypoint model
// that we // that we
// reached the destination. // reached the destination.
if (dstPaths.get(comp).size() == 0) { if (dstPaths.get(comp).size() == 0) {
return new Right<PositionVector, Boolean>(true); return new Right<PositionVector, Boolean>(true);
} }
} }
int currentPathIdx = currentPath.get(comp); int currentPathIdx = currentPath.get(comp);
Waypoint currentWaypoint = dstPaths.get(comp).get(currentPathIdx); Waypoint currentWaypoint = dstPaths.get(comp).get(currentPathIdx);
double speed = getMovementSpeed(comp); double speed = getMovementSpeed(comp);
PositionVector newPosition = comp.getRealPosition().moveStep( PositionVector newPosition = comp.getRealPosition().moveStep(
currentWaypoint.getPosition(), speed); currentWaypoint.getPosition(), speed);
if (destinationWaypointReached(currentWaypoint, newPosition, speed)) { if (destinationWaypointReached(currentWaypoint, newPosition, speed)) {
// We reached the next waypoint on the path to the destination // We reached the next waypoint on the path to the destination
// move to the next waypoint // move to the next waypoint
currentPath.put(comp, ++currentPathIdx); currentPath.put(comp, ++currentPathIdx);
// The destination waypoint has been reached, tell the abstract // The destination waypoint has been reached, tell the abstract
// waypoint model // waypoint model
if (dstPaths.get(comp).size() <= currentPathIdx) { if (dstPaths.get(comp).size() <= currentPathIdx) {
currentPath.put(comp, --currentPathIdx); currentPath.put(comp, --currentPathIdx);
return new Right<PositionVector, Boolean>(true); return new Right<PositionVector, Boolean>(true);
} }
} }
return new Left<PositionVector, Boolean>(newPosition); return new Left<PositionVector, Boolean>(newPosition);
} }
/** /**
* Finds the closest waypoints to the current position of the movement * Finds the closest waypoints to the current position of the movement
* supported component as well as the final destination and searches for a * supported component as well as the final destination and searches for a
* path between the two waypoints using the underlying network of * path between the two waypoints using the underlying network of
* WeakWaypoints. * WeakWaypoints.
* *
* @param comp * @param comp
* @param finalDestination * @param finalDestination
*/ */
protected void calculateNextMovementPath(MovementSupported comp, protected void calculateNextMovementPath(MovementSupported comp,
PositionVector finalDestination) { PositionVector finalDestination) {
// Required for shortest path calculation // Required for shortest path calculation
Waypoint closestWaypointToCurrentPosition = waypointModel Waypoint closestWaypointToCurrentPosition = waypointModel
.getClosestWaypoint(comp.getRealPosition(), WeakWaypoint.class); .getClosestWaypoint(comp.getRealPosition(), WeakWaypoint.class);
Waypoint closestWaypointToDestination = waypointModel Waypoint closestWaypointToDestination = waypointModel
.getClosestWaypoint(finalDestination, WeakWaypoint.class); .getClosestWaypoint(finalDestination, WeakWaypoint.class);
List<Path> shortestPath = waypointModel.getShortestPath( List<Path> shortestPath = waypointModel.getShortestPath(
closestWaypointToCurrentPosition, closestWaypointToDestination); closestWaypointToCurrentPosition, closestWaypointToDestination);
List<Waypoint> waypointList = buildWaypointList( List<Waypoint> waypointList = buildWaypointList(
closestWaypointToCurrentPosition, shortestPath); closestWaypointToCurrentPosition, shortestPath);
dstPaths.put(comp, waypointList); dstPaths.put(comp, waypointList);
currentPath.put(comp, Integer.valueOf(0)); currentPath.put(comp, Integer.valueOf(0));
} }
/** /**
* Build a list of waypoints that starts a the given starting waypoint based * Build a list of waypoints that starts a the given starting waypoint based
* on the given list of paths. * on the given list of paths.
* *
* @param start * @param start
* @param shortestPath * @param shortestPath
* @return * @return
*/ */
protected List<Waypoint> buildWaypointList(Waypoint start, protected List<Waypoint> buildWaypointList(Waypoint start,
List<Path> shortestPath) { List<Path> 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 (Path p : shortestPath) {
lastWaypoint = p.getOtherEnd(lastWaypoint); lastWaypoint = p.getOtherEnd(lastWaypoint);
waypointList.add(lastWaypoint); waypointList.add(lastWaypoint);
} }
return waypointList; return waypointList;
} }
/** /**
* Checks if the current destination waypoint has been reached by testing * Checks if the current destination waypoint has been reached by testing
* the distance between the current position an the current destination * the distance between the current position an the current destination
* waypoint for distance < speedLimit * 2. * waypoint for distance < speedLimit * 2.
* *
* FIXME BR: why *2? * FIXME BR: why *2?
* *
* @param currentWaypoint * @param currentWaypoint
* @param newPosition * @param newPosition
* @return * @return
*/ */
protected boolean destinationWaypointReached(Waypoint currentWaypoint, protected boolean destinationWaypointReached(Waypoint currentWaypoint,
PositionVector newPosition, double speed) { PositionVector newPosition, double speed) {
double distance = newPosition double distance = newPosition.distanceTo(currentWaypoint.getPosition());
.getDistance(currentWaypoint.getPosition());
return (distance < speed * 2);
return (distance < speed * 2); }
} }
}
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