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

Refactoring due to Location/Attraction API changes

- removed obsolete and duplicate modular movement classes (check your
config-files, you might need to replace "modular" with "modularosm" in
some cases
parent 0d0f5448
......@@ -20,7 +20,10 @@
package de.tud.kom.p2psim.api.topology.movement;
import java.util.Set;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
* A movement model for a group of {@link TopologyComponent}s. The movement
......@@ -55,11 +58,38 @@ public interface MovementModel {
* view)
*
* @param actuator
* @param longitude
* @param latitude
* @param targetAttractionPoint
*/
default public void changeTargetLocation(SimLocationActuator actuator,
AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* OPTIONAL: returns the movement target of the actuator.
*
* OBVIOUSLY, this is not supported by all models (from a semantic point of
* view)
*
* @param actuator
* @return target AttractionPoint
*/
default public AttractionPoint getTargetLocation(
SimLocationActuator actuator) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* OPTIONAL returns a list of all attraction points
*
* @return
* @throws UnsupportedOperationException
*/
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude);
default public Set<AttractionPoint> getAllAttractionPoints()
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
/**
* If you want to trigger the movement periodically, set this to a time
......
......@@ -38,7 +38,6 @@ import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
......@@ -53,6 +52,7 @@ import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent.NetInterfaceName;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest;
......@@ -256,17 +256,28 @@ public class DefaultTopologyComponent implements TopologyComponent {
}
@Override
public void updateCurrentLocation(double longitude, double latitude) {
position.setEntries(longitude, latitude);
public void updateCurrentLocation(Location location) {
position.set(location);
// notify "non-request" listeners
for (LocationListener locationListener : listeners) {
locationListener.onLocationChanged(getHost(), getLastLocation());
}
}
@Override
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
movementModel.changeTargetLocation(this, targetAttractionPoint);
}
@Override
public AttractionPoint getCurrentTargetAttractionPoint() {
return movementModel.getTargetLocation(this);
}
@Override
public void setNewTargetLocation(double longitude, double latitude) {
movementModel.changeTargetLocation(this, longitude, latitude);
public Set<AttractionPoint> getAllAttractionPoints() {
return movementModel.getAllAttractionPoints();
}
@Override
......
......@@ -23,6 +23,8 @@ package de.tud.kom.p2psim.impl.topology;
import java.awt.Point;
import java.util.Arrays;
import org.aopalliance.aop.AspectException;
import com.vividsolutions.jts.geom.Coordinate;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
......@@ -58,6 +60,8 @@ public class PositionVector implements Location {
* transforms can be performed in the getter-methods.
*/
private double[] values;
private double accuracy = -1;
/**
* Create a new Position Vector
......@@ -96,6 +100,38 @@ public class PositionVector implements Location {
setEntry(i, values[i]);
}
}
@Override
public void setLatitude(double latitude)
throws UnsupportedOperationException {
this.setEntry(1, latitude);
}
@Override
public void setLongitude(double longitude)
throws UnsupportedOperationException {
this.setEntry(0, longitude);
}
@Override
public void setAccuracy(double accuracy)
throws UnsupportedOperationException {
if (accuracy < 0) {
throw new AssertionError();
}
this.accuracy = accuracy;
}
@Override
public double getAccuracy() {
assert hasAccuracy() : "should check for hasAccuracy first!";
return accuracy;
}
@Override
public boolean hasAccuracy() {
return accuracy != -1;
}
/**
* Number of Dimensions
......
......@@ -36,10 +36,8 @@ import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.network.modular.DBHostListManager;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.topology.movement.AbstractMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.AbstractWaypointMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.NoMovement;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.placement.GNPPlacement;
import de.tud.kom.p2psim.impl.topology.views.latency.GNPLatency;
import de.tudarmstadt.maki.simonstrator.api.Binder;
......@@ -47,7 +45,6 @@ import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.HostComponentFactory;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......
......@@ -20,6 +20,7 @@
package de.tud.kom.p2psim.impl.topology.movement;
import java.nio.channels.UnsupportedAddressTypeException;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
......@@ -40,6 +41,7 @@ import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
......@@ -69,13 +71,6 @@ public abstract class AbstractMovementModel implements MovementModel {
public void placeComponent(SimLocationActuator actuator) {
// not supported
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) throws UnsupportedOperationException {
// not supported by default. Extend this method, if needed.
throw new UnsupportedOperationException();
}
/**
* Gets called periodically (after timeBetweenMoveOperations) or by an
......@@ -178,19 +173,7 @@ public abstract class AbstractMovementModel implements MovementModel {
*/
protected void updatePosition(SimLocationActuator actuator,
PositionVector newPosition) {
this.updatePosition(actuator, newPosition.getLongitude(),
newPosition.getLatitude());
}
/**
* Call this method to finally update the location of the given component.
*
* @param actuator
* @param newPosition
*/
protected void updatePosition(SimLocationActuator actuator,
double longitude, double latitude) {
actuator.updateCurrentLocation(longitude, latitude);
actuator.updateCurrentLocation(newPosition);
}
/**
......
......@@ -41,6 +41,7 @@ import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
......@@ -78,7 +79,7 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
private double unscaledSpeedLimit = speedLimit;
private Random rnd = Randoms.getRandom(AbstractWaypointMovementModel.class);
public AbstractWaypointMovementModel(double worldX, double worldY) {
worldDimensions = new PositionVector(worldX, worldY);
destinations = new WeakHashMap<SimLocationActuator, PositionVector>();
......@@ -97,9 +98,7 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
}
if (this.waypointModel == null) {
Monitor.log(
AbstractWaypointMovementModel.class,
Level.INFO,
Monitor.log(AbstractWaypointMovementModel.class, Level.INFO,
"No waypoint model has been configured. Thus the movement speed won't be adjusted for the scale of the waypoint model.");
}
//
......@@ -110,7 +109,7 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
return true;
}
/**
* This default implementation relies on {@link PlacementModel}s to be
* configured in the {@link TopologyFactory}
......@@ -119,13 +118,6 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
public void placeComponent(SimLocationActuator actuator) {
// not supported
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) throws UnsupportedOperationException {
// not supported by default. Extend this method, if needed.
throw new UnsupportedOperationException();
}
/**
* Gets called periodically (after timeBetweenMoveOperations) or by an
......@@ -191,7 +183,7 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
}
}
}
/**
* Call this method to finally update the location of the given component.
*
......@@ -200,18 +192,7 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
*/
protected void updatePosition(SimLocationActuator actuator,
PositionVector newPosition) {
this.updatePosition(actuator, newPosition.getLongitude(), newPosition.getLatitude());
}
/**
* Call this method to finally update the location of the given component.
*
* @param actuator
* @param newPosition
*/
protected void updatePosition(SimLocationActuator actuator,
double longitude, double latitude) {
actuator.updateCurrentLocation(longitude, latitude);
actuator.updateCurrentLocation(newPosition);
}
/**
......@@ -243,7 +224,8 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
* @param dst
* @return Returns true if the destination was reached
*/
private boolean reachedPosition(SimLocationActuator comp, PositionVector dst) {
private boolean reachedPosition(SimLocationActuator comp,
PositionVector dst) {
PositionVector pos = comp.getRealPosition();
double distance = pos.distanceTo(dst);
......@@ -263,10 +245,10 @@ public abstract class AbstractWaypointMovementModel implements MovementModel {
private PositionVector getDestination(SimLocationActuator comp) {
PositionVector dst = destinations.get(comp);
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Pos: "
+ comp.getRealPosition());
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG, "Dst: "
+ dst);
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Pos: " + comp.getRealPosition());
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
"Dst: " + dst);
if (dst == null) {
Monitor.log(AbstractWaypointMovementModel.class, Level.DEBUG,
......
......@@ -33,15 +33,14 @@ import de.tud.kom.p2psim.api.common.SimHost;
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.MovementSupported;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
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.transition.FixedAssignmentStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.FixedAssignmentStrategy;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......
......@@ -24,47 +24,25 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import javax.swing.JComponent;
import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldMovementPoints;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModelViz;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.TransitionStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
*
......@@ -155,7 +133,7 @@ public class StreetMovement implements MovementModel, EventHandler {
PositionVector startingPosition = this.returnRandomPositionBetweenPoints(a,b);
ms.updateCurrentLocation(startingPosition.getLongitude(), startingPosition.getLatitude());
ms.updateCurrentLocation(startingPosition);
positions.put(ms, ms.getRealPosition());
......@@ -173,13 +151,13 @@ public class StreetMovement implements MovementModel, EventHandler {
double longMin, longMax, latMin, latMax, longNew, latNew;
// Points have different longitude, so only search for random value for longitude
if(a.getRealPosition().getLongitude() != b.getRealPosition().getLongitude()) {
if(a.getRealPosition().getLongitude() < b.getRealPosition().getLongitude()) {
longMin = a.getRealPosition().getLongitude();
longMax = b.getRealPosition().getLongitude();
if(a.getLongitude() != b.getLongitude()) {
if(a.getLongitude() < b.getLongitude()) {
longMin = a.getLongitude();
longMax = b.getLongitude();
} else {
longMin = b.getRealPosition().getLongitude();
longMax = a.getRealPosition().getLongitude();
longMin = b.getLongitude();
longMax = a.getLongitude();
}
do {
......@@ -187,17 +165,17 @@ public class StreetMovement implements MovementModel, EventHandler {
} while(longNew < longMin);
assert longNew > longMin && longNew <= longMax;
return new PositionVector(longNew, a.getRealPosition().getLatitude());
return new PositionVector(longNew, a.getLatitude());
}
// Points have different latitude, so only search for random value for latitude
if(a.getRealPosition().getLatitude() != b.getRealPosition().getLatitude()) {
if(a.getRealPosition().getLatitude() < b.getRealPosition().getLatitude()) {
latMin = a.getRealPosition().getLatitude();
latMax = b.getRealPosition().getLatitude();
if(a.getLatitude() != b.getLatitude()) {
if(a.getLatitude() < b.getLatitude()) {
latMin = a.getLatitude();
latMax = b.getLatitude();
} else {
latMin = b.getRealPosition().getLatitude();
latMax = a.getRealPosition().getLatitude();
latMin = b.getLatitude();
latMax = a.getLatitude();
}
do{
......@@ -205,7 +183,7 @@ public class StreetMovement implements MovementModel, EventHandler {
} while(latNew < latMin);
assert latNew > latMin && latNew <= latMax;
return new PositionVector(a.getRealPosition().getLongitude(), latNew);
return new PositionVector(a.getLongitude(), latNew);
}
return null;
......@@ -221,12 +199,11 @@ public class StreetMovement implements MovementModel, EventHandler {
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) {
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
/*
* Set a new target AP for the current actuator
*/
attractionOfClients.put(actuator, new AttractionPoint((int) longitude, (int) latitude, ""));
attractionOfClients.put(actuator, ap);
}
......@@ -253,13 +230,12 @@ public class StreetMovement implements MovementModel, EventHandler {
for (Entry<SimLocationActuator, AttractionPoint> entry : attractionOfClients.entrySet()) {
SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector attractionCenter = (PositionVector) entry.getValue();
PositionVector destination = new PositionVector(attractionCenter);
if (destination.distanceTo(ms.getRealPosition()) > ms.getMovementSpeed()) {
PositionVector newPosition = ms.getRealPosition().moveStep(destination, ms.getMovementSpeed());
ms.updateCurrentLocation(newPosition.getLongitude(), newPosition.getLatitude());
ms.updateCurrentLocation(newPosition);
positions.put(ms, newPosition);
} else {
assignNewAttractionPoint(ms);
......@@ -333,7 +309,7 @@ public class StreetMovement implements MovementModel, EventHandler {
}
}
protected List<AttractionPoint> getAttractionPoints() {
public List<AttractionPoint> getAttractionPoints() {
return attractionPoints;
}
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.AbstractWaypointMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.CsvMovement;
import de.tud.kom.p2psim.impl.topology.movement.NoMovement;
import de.tud.kom.p2psim.impl.topology.movement.RandomPathMovement;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionGenerator;
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.TransitionStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
* Modular Movement Model uses different models/strategies to create a movement
* model. In this implementation, it has 4 different models/strategies.
* <p>
* M0: AttractionGenerator -> Generates the {@link AttractionPoint}s and place
* them on the map. The {@link AttractionPoint}s can be moved!
* <p>
* M1: A general {@link MovementModel}, like {@link RandomPathMovement} or
* {@link NoMovement}. It takes the {@link AttractionPoint}s and move them
* around the world.
* <p>
* M2: The {@link TransitionStrategy}! It takes the Hosts, which should be moved
* around, but calculates only the assignment to the {@link AttractionPoint}s.
* It doesn't move the Hosts! It will be only assignment a new AttractionPoint!
*
* <p>
* M3: The {@link LocalMovementStrategy} is responsible for the movement of the
* Hosts. It moves the hosts to the assigned AttractionPoint, and if the
* AttractionPoint has moved, then will be followed. The
* {@link LocalMovementStrategy} will be called from the
* {@link ModularMovementModel} to do a Movement!
* <p>
* This class contains all four components and manage the data exchange.
* Additionally it contains an periodic operation, which handle the movement of
* all hosts. This mean, that it will be call the {@link LocalMovementStrategy}
* with the destination. Please take care, that the handling of the movement of
* the AttractionPoints will be handled by the movement model in M1! <br>
* Further it contains an offset for every Host, which will be added to the
* destination point (AttractionPoint), so that not all hosts, which are
* assigned to one {@link AttractionPoint}, lies on the same point.<br>
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class ModularMovementModel implements MovementModel, EventHandler {
private final int EVENT_MOVE = 1;
private final int EVENT_INIT = 2;
protected PositionVector worldDimensions;
protected MovementModel movementModel = new NoMovement();
protected TransitionStrategy transition;
protected AttractionGenerator attractionGenerator;
protected LocalMovementStrategy localMovementStrategy;
private Set<SimLocationActuator> movementListeners = new LinkedHashSet<SimLocationActuator>();
private Set<SimLocationActuator> moveableHosts = new LinkedHashSet<SimLocationActuator>();
private Map<SimLocationActuator, PositionVector> offsetPosition = new LinkedHashMap<SimLocationActuator, PositionVector>();
private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
private Random rand;
public ModularMovementModel() {
this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
this.rand = Randoms.getRandom(ModularMovementModel.class);
// scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT);
}
/**
* This Method will be not called from the Components. So we call this
* manually!
*/
public void initialize() {
if (!initialized) {
VisualizationInjector.injectComponent("AttractionPoints", -1,
new ModularMovementModelViz(this), false);
checkConfiguration();
// FIXME NR: Special implementation for crater to give movement model
// the mapping of APs to Hosts to enable offline/online going of the
// respective nodes when necessary
if (movementModel.getClass() == CsvMovement.class && transition.getClass() == FixedAssignmentStrategy.class) {
CsvMovement csvMovement = (CsvMovement) movementModel;
FixedAssignmentStrategy transitionStrategy = (FixedAssignmentStrategy) transition;
csvMovement.addTransitionStrategy(transitionStrategy);
}
// setWayPointModel
localMovementStrategy.setObstacleModel(Binder
.getComponentOrNull(Topology.class).getObstacleModel());
localMovementStrategy.setWaypointModel(Binder
.getComponentOrNull(Topology.class).getWaypointModel());
if (movementModel instanceof AbstractWaypointMovementModel) {
AbstractWaypointMovementModel awmm = (AbstractWaypointMovementModel) movementModel;
awmm.setWaypointModel(Binder.getComponentOrNull(Topology.class)
.getWaypointModel());
}
List<AttractionPoint> attractionPoints = attractionGenerator
.getAttractionPoints();
for (AttractionPoint att : attractionPoints) {
movementModel.addComponent(att);
}
transition.setAttractionPoints(attractionPoints);
for (SimLocationActuator ms : moveableHosts) {
transition.addComponent(ms);
}
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
// initial move
move();
initialized = true;
}
}
private void checkConfiguration() {
if (localMovementStrategy == null) {
throw new ConfigurationException(
"LocalMovementStrategy is missing in ModularMovementModel!");
}
if (movementModel == null) {
throw new ConfigurationException(
"MovementModel is missing in ModularMovementModel!");
}
if (transition == null) {
throw new ConfigurationException(
"TransitionStrategy is missing in ModularMovementModel!");
}
if (attractionGenerator == null) {
throw new ConfigurationException(
"AttractionGenerator is missing in ModularMovementModel!");
}
if (movementModel instanceof AbstractWaypointMovementModel
&& Binder.getComponentOrNull(Topology.class)
.getWaypointModel() == null) {
throw new ConfigurationException(
"Missing WaypointModel for the ModuloarMovementModel.movementModel");
}
}
/**
* This default implementation relies on {@link PlacementModel}s to be
* configured in the {@link TopologyFactory}
*/
@Override
public void placeComponent(SimLocationActuator actuator) {
// not supported
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public void addComponent(SimLocationActuator comp) {
moveableHosts.add(comp);
offsetPosition.put(comp, randomOffsetVector());
}
@Override
public void setTimeBetweenMoveOperations(long time) {
if (time > 0) {
this.timeBetweenMoveOperation = time;
} else {
throw new ConfigurationException(
"time is negative for the Move Operations");
}
}
private PositionVector randomOffsetVector() {
double x = rand.nextGaussian() * 6;
double y = rand.nextGaussian() * 6;
return new PositionVector(x, y);
}
protected void move() {
Map<SimLocationActuator, AttractionPoint> assigns = transition
.getAssignments();
for (Entry<SimLocationActuator, AttractionPoint> entry : assigns
.entrySet()) {
SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector destination = new PositionVector(attractionCenter);
destination.add(offsetPosition.get(ms));
doLocalMovement(ms, destination);
}
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null,
EVENT_MOVE);
}
/**
*
* Ask the local movement strategy for the next position. It may return the
* next position or a boolean with true to notify the movement model that it
* can't get any closer to the current way point.
*
* @param ms
* @param destination
*/
private void doLocalMovement(SimLocationActuator ms,
PositionVector destination) {
Either<PositionVector, Boolean> either = localMovementStrategy
.nextPosition(ms, destination);
if (either.hasLeft()) {
ms.updateCurrentLocation(either.getLeft().getLongitude(), either.getLeft().getLatitude());
}
}
public void setMovementModel(MovementModel mm) {
this.movementModel = mm;
}
public void setAttractionGenerator(AttractionGenerator attractionGenerator) {
this.attractionGenerator = attractionGenerator;
}
public void setLocalMovementStrategy(
LocalMovementStrategy localMovementStrategy) {
this.localMovementStrategy = localMovementStrategy;
}
public void setTransitionStrategy(TransitionStrategy transition) {
this.transition = transition;
}
@Override
public void eventOccurred(Object content, int type) {
if (type == EVENT_INIT) {
initialize();
} else if (type == EVENT_MOVE) {
move();
}
}
/**
* Only for visualization!
*
* @return
*/
protected List<AttractionPoint> getAttractionPoints() {
return new Vector<AttractionPoint>(transition.getAssignments().values());
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
/**
* Visualization Component of the Attraction Points in the Modular Movement
* Model.
*
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class ModularMovementModelViz extends JComponent {
private ModularMovementModel movementModel;
public ModularMovementModelViz(ModularMovementModel model) {
setBounds(0, 0, VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
setOpaque(true);
setVisible(true);
this.movementModel = model;
}
@Override
public void paint(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (AttractionPoint aPoint : movementModel.getAttractionPoints()) {
Point point = aPoint.getRealPosition().asPoint();
// draw border
g2.setColor(Color.BLACK);
g2.setStroke(new BasicStroke(1f));
g2.drawOval(VisualizationInjector.scaleValue(point.x) - 15,
VisualizationInjector.scaleValue(point.y) - 15, 30, 30);
g2.setColor(new Color(0.2f, 0.8f, 0.2f, 0.6f));
g2.fillOval(VisualizationInjector.scaleValue(point.x) - 15,
VisualizationInjector.scaleValue(point.y) - 15, 30, 30);
}
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.attraction;
import java.util.List;
/**
* This is the interface for the generator of the {@link AttractionPoint}s. It
* gets the set number of AttractionPoints back. This mean, it will be generate
* them and set the Position of them.
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public interface AttractionGenerator {
public void setNumberOfAttractionPoints(int numberOfAttractionPoints);
public List<AttractionPoint> getAttractionPoints();
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.attraction;
import java.util.Random;
import de.tud.kom.p2psim.api.topology.movement.MovementListener;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationActuator;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest;
/**
* This is the implementation of a AttractionPoint, which implements the
* {@link LocationActuator} interface. So a {@link AttractionPoint} has the
* ability to be moved.
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class AttractionPoint implements SimLocationActuator {
protected static Random rnd = Randoms.getRandom(AttractionPoint.class);
private PositionVector posVec;
private double minSpeed;
private double maxSpeed;
private double currentSpeed = -1;
public AttractionPoint(PositionVector posVec, double minSpeed,
double maxSpeed) {
this.posVec = posVec;
this.minSpeed = minSpeed;
this.maxSpeed = maxSpeed;
}
@Override
public double getMinMovementSpeed() {
return minSpeed;
}
@Override
public double getMaxMovementSpeed() {
return maxSpeed;
}
@Override
public void setMovementSpeed(double speed) {
this.currentSpeed = speed;
}
@Override
public double getMovementSpeed() {
if (currentSpeed == -1) {
double min_speed = getMinMovementSpeed();
double max_speed = getMaxMovementSpeed();
double value = rnd.nextDouble();
this.currentSpeed = (value * (max_speed - min_speed)) + min_speed;
}
return currentSpeed;
}
@Override
public Location getLastLocation() {
return posVec;
}
@Override
public void requestLocationUpdates(LocationRequest request,
LocationListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void removeLocationUpdates(LocationListener listener) {
throw new UnsupportedOperationException();
}
@Override
public LocationRequest getLocationRequest() {
throw new UnsupportedOperationException();
}
@Override
public void initialize() {
throw new UnsupportedOperationException();
}
@Override
public void shutdown() {
throw new UnsupportedOperationException();
}
@Override
public Host getHost() {
throw new UnsupportedOperationException();
}
@Override
public void updateCurrentLocation(double longitude, double latitude) {
posVec.setEntries(longitude, latitude);
}
@Override
public void setNewTargetLocation(double longitude, double latitude)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
@Override
public PositionVector getRealPosition() {
return posVec;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.transition;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* A {@link TransitionStrategy} for a case in which nodes are affiliated to an
* {@link AttractionPoint} only in the beginning. No further transition will
* take place.
*
* @author Nils Richerzhagen
* @version 1.0, 04.08.2014
*/
public class FixedAssignmentStrategy implements TransitionStrategy {
private Random rnd;
private List<SimLocationActuator> comps = new LinkedList<SimLocationActuator>();
private List<AttractionPoint> aPoints = new LinkedList<AttractionPoint>();
private Map<SimLocationActuator, AttractionPoint> assignments = new LinkedHashMap<SimLocationActuator, AttractionPoint>();
private Map<SimLocationActuator, SimHost> mappingMSHost = new LinkedHashMap<SimLocationActuator, SimHost>();
private Map<SimHost, SimLocationActuator> mappingHostMS = new LinkedHashMap<SimHost, SimLocationActuator>();
private Map<String, AttractionPoint> mappingGroupIdAP = new LinkedHashMap<String, AttractionPoint>();
private Map<AttractionPoint, String> mappingAPGroupId = new LinkedHashMap<AttractionPoint, String>();
public FixedAssignmentStrategy() {
rnd = Randoms.getRandom(FixedAssignmentStrategy.class);
}
@Override
public Map<SimLocationActuator, AttractionPoint> getAssignments() {
return new HashMap<SimLocationActuator, AttractionPoint>(assignments);
}
@Override
public void setAttractionPoints(List<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public void addComponent(SimLocationActuator ms) {
comps.add(ms);
mappingHost(ms);
// No assignments been done before.
if (assignments.isEmpty()) {
AttractionPoint aPoint = aPoints.iterator().next();
assignments.put(ms, aPoint);
mappingGroupId(ms, aPoint);
setStartPosition(ms, aPoint.getRealPosition());
}
// GroupId is not mapped.
else if (!mappingGroupIdAP.containsKey(
mappingMSHost.get(ms).getProperties().getGroupID())) {
for (AttractionPoint actAP : aPoints) {
if (!mappingAPGroupId.containsKey(actAP)) {
assignments.put(ms, actAP);
mappingGroupId(ms, actAP);
setStartPosition(ms, actAP.getRealPosition());
break;
}
}
}
// GroupId is already mapped.
else if (mappingGroupIdAP.containsKey(
mappingMSHost.get(ms).getProperties().getGroupID())) {
AttractionPoint aPoint = mappingGroupIdAP
.get(mappingMSHost.get(ms).getProperties().getGroupID());
assignments.put(ms, aPoint);
setStartPosition(ms, aPoint.getRealPosition());
} else {
throw new Error("Should not happen.");
}
}
private void mappingHost(SimLocationActuator ms) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mappingHostMS.put(host, ms);
mappingMSHost.put(ms, host);
}
private void mappingGroupId(SimLocationActuator ms, AttractionPoint AP) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mappingAPGroupId.put(AP,
mappingMSHost.get(ms).getProperties().getGroupID());
mappingGroupIdAP.put(mappingMSHost.get(ms).getProperties().getGroupID(),
AP);
}
private void setStartPosition(SimLocationActuator ms,
PositionVector aPointReferencePosition) {
double minJitter = 50.0;
double maxJitter = 100.0;
double xJitter = (rnd.nextDouble() * (maxJitter - minJitter))
+ minJitter;
double yJitter = (rnd.nextDouble() * (maxJitter - minJitter))
+ minJitter;
PositionVector jitterVector = new PositionVector(xJitter, yJitter);
PositionVector newPos = aPointReferencePosition.plus(jitterVector);
ms.updateCurrentLocation(newPos.getLongitude(), newPos.getLatitude());
}
/**
* Used by the MobilityModel (M1) of the {@link ModularMovementModel} to get
* the groupId of the affiliated nodes to that {@link AttractionPoint}. Once
* the groupId is known nodes can be set <b>offline</b> or <b>online</b>.
*
* @param attractionPoint
* @return
*/
public String getGroupIdOfAttractionPoint(AttractionPoint attractionPoint) {
return mappingAPGroupId.get(attractionPoint);
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.transition;
import java.util.*;
import java.util.Map.Entry;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* This is a {@link TransitionStrategy} for the Social Case. It will be try to
* build groups based on the {@link SocialView} information. For this, it tries
* to assignment the given {@link SimLocationActuator} objects to the given
* {@link AttractionPoint}s. For the {@link SocialView}, it is required a
* {@link #socialId}, to find the right {@link SocialView}.
*
* <br>
*
* The Strategy has the parameter of {@link #socialFactor},
* {@link #minPauseTime} and {@link #maxPauseTime}. The socialFactor should be a
* value between 0 and 1. It gives the probability for a social based transition
* or the transition to a random {@link AttractionPoint}. If the social based
* transition is selected, then will be used a scoring to find the right
* {@link AttractionPoint}. For that, it will be used only the AttractionPoints,
* of the hosts, which are in the same SocialCluster or are SocialNeighbors. For
* this AttractionPoints it will be find the highest scoring, which is to found
* in {@link #score(SimLocationActuator, AttractionPoint, List, List, List, List)}
* .
*
* <br>
*
* After the finding of the next {@link AttractionPoint}, it will be scheduled
* an Event, with a delay between min- and maxPauseTime. After this delay, it
* will be tried to assign a new {@link AttractionPoint} like the described
* above.
*
*
* @author Christoph Muenker
* @version 1.0, 02.07.2013
*/
public class SocialTransitionStrategy implements TransitionStrategy,
EventHandler {
private String socialId = null;
private SocialView socialView;
private List<SimLocationActuator> comps = new Vector<SimLocationActuator>();
private List<AttractionPoint> aPoints = new Vector<AttractionPoint>();
private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<SimLocationActuator, AttractionPoint>();
private Map<SimLocationActuator, Set<AttractionPoint>> favoritePlaces = new HashMap<SimLocationActuator, Set<AttractionPoint>>();
private Map<SimLocationActuator, SimHost> mapMsHost = new HashMap<SimLocationActuator, SimHost>();
private Map<SimHost, SimLocationActuator> mapHostMs = new HashMap<SimHost, SimLocationActuator>();
private double minPauseTime = Simulator.MINUTE_UNIT * 0.5;
private double maxPauseTime = Simulator.MINUTE_UNIT * 100;
private double socialFactor = 0.8;
private long numberOfFavoritePlaces = 4;
private Random rand;
private PositionVector worldDimension;
private boolean init = false;
public SocialTransitionStrategy() {
this.rand = Randoms.getRandom(SocialTransitionStrategy.class);
}
private void init() {
if (!init) {
if (socialId == null) {
throw new ConfigurationException(
"SocialId is not set, to find the needed SocialView!");
}
socialView = Binder.getComponentOrNull(Topology.class)
.getSocialView(socialId);
if (socialView == null) {
throw new ConfigurationException(
"Cannot find the right socialView. Is the socialId correct?");
}
if (minPauseTime > maxPauseTime) {
throw new ConfigurationException(
"MinPauseTime should be smaller then maxPauseTime.");
}
worldDimension = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
init = true;
}
}
public void setSocialId(String socialId) {
this.socialId = socialId;
}
@Override
public Map<SimLocationActuator, AttractionPoint> getAssignments() {
return new HashMap<SimLocationActuator, AttractionPoint>(assignments);
}
@Override
public void setAttractionPoints(List<AttractionPoint> attractionPoints) {
init();
aPoints.addAll(attractionPoints);
}
@Override
public void addComponent(SimLocationActuator ms) {
comps.add(ms);
mappingHost(ms);
// assign the ms to an attractionPoint, which is near to the ms
// position.
// TODO: needed? We do Transition as next, and this will delete the
// assignment..
AttractionPoint nearest = aPoints.iterator().next();
for (AttractionPoint aPoint : aPoints) {
if (nearest.getRealPosition()
.distanceTo(ms.getRealPosition()) > aPoint.getRealPosition()
.distanceTo(ms.getRealPosition())) {
nearest = aPoint;
}
}
assignments.put(ms, nearest);
assignFavoritePlaces(ms);
doTransition(ms);
}
public void doTransition(SimLocationActuator ms) {
List<AttractionPoint> apFavorites = getFavoritePlaces(ms);
List<AttractionPoint> apFriends = getFriendsPlaces(ms);
List<AttractionPoint> apClusters = getClusterPlaces(ms);
List<AttractionPoint> apRandom = getRandomPlaces(ms,
(int) Math.max(aPoints.size() * 0.2, 5));
AttractionPoint ap = null;
if (rand.nextDouble() < socialFactor) {
ap = findHighestScore(ms, apFavorites, apFriends, apClusters,
apRandom);
} else {
List<AttractionPoint> aps = new ArrayList<AttractionPoint>();
aps.addAll(apRandom);
aps.addAll(apFavorites);
ap = aps.get(rand.nextInt(apRandom.size()));
}
assignments.put(ms, ap);
Event.scheduleWithDelay(getPauseTime(), this, ms, 0);
}
private AttractionPoint findHighestScore(SimLocationActuator ms,
List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
Set<AttractionPoint> aps = new LinkedHashSet<AttractionPoint>();
aps.addAll(apFavorites);
aps.addAll(apFriends);
aps.addAll(apClusters);
aps.addAll(apRandom);
double maxScore = 0;
AttractionPoint maxAp = null;
for (AttractionPoint ap : aps) {
double score = score(ms, ap, apFavorites, apFriends, apClusters,
apRandom);
// System.out.println(score);
if (score > maxScore) {
maxScore = score;
maxAp = ap;
}
}
return maxAp;
}
/**
* Score the given AttractionPoint for the given {@link SimLocationActuator}. <br>
* (clusterScore/#NodesInAp + friendsScore + 1/#NodesInAp) * socialFactor +
* (distanceScore + penalty) + (1-socialFactor) <br>
*
* clusterScore = 1 if one is in the same cluster in this AP<br>
* friendsScore = 1 if one friend is in the same AP<br>
* penalty = -1 if AP the actually AP is <br>
* distance = 1 - (distance / maxDistance)
*
* @param ms
* @param ap
* @param apFavorites
* @param apFriends
* @param apClusters
* @param apRandom
* @return
*/
private double score(SimLocationActuator ms, AttractionPoint ap,
List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
double distance = ms.getRealPosition().distanceTo(ap.getRealPosition());
double distanceScore = 1 - (distance / worldDimension.getLength());
double clusterScore = 0;
double friendsScore = 0;
if (apClusters.contains(ap)) {
if (occurence(ap, apClusters) > 3) {
// occurence give the number of other peers in this AP
clusterScore = 1.0 / (occurence(ap, apClusters) - 1);
} else {
clusterScore = 1.0;
}
}
if (apFriends.contains(ap)) {
if (occurence(ap, apFriends) > 3) {
// occurence give the number of other peers in this AP
friendsScore = 1.0 / (occurence(ap, apFriends) - 1);
} else {
friendsScore = 1.0;
}
}
// penalty for distance
double penalty = 0;
if (ap.equals(assignments.get(ms))) {
penalty = -1;
}
return (clusterScore / assignedToAp(ap) + friendsScore + 1.0 / assignedToAp(ap))
* socialFactor
+ (distanceScore + penalty) * (1 - socialFactor);
}
// counts the number of the AttractionPoint in the list
private int occurence(AttractionPoint ap, List<AttractionPoint> aps) {
int i = 0;
for (AttractionPoint a : aps) {
if (a.equals(ap)) {
i++;
}
}
return i;
}
private int assignedToAp(AttractionPoint ap) {
int i = 1;
for (Entry<SimLocationActuator, AttractionPoint> entry : assignments
.entrySet()) {
if (entry.getValue().equals(ap)) {
i++;
}
}
return i;
}
private List<AttractionPoint> getRandomPlaces(SimLocationActuator ms,
int number) {
Collections.shuffle(aPoints, rand);
List<AttractionPoint> result = new Vector<AttractionPoint>();
Iterator<AttractionPoint> iAP = aPoints.iterator();
for (int i = 0; i < number && iAP.hasNext(); i++) {
result.add(iAP.next());
}
return result;
}
private List<AttractionPoint> getClusterPlaces(SimLocationActuator ms) {
List<AttractionPoint> result = new Vector<AttractionPoint>();
SimHost msHost = mapMsHost.get(ms);
for (SimHost host : socialView.getCluster(msHost)) {
SimLocationActuator temp = mapHostMs.get(host);
if (assignments.get(temp) != null) {
result.add(assignments.get(temp));
}
}
return result;
}
private List<AttractionPoint> getFriendsPlaces(SimLocationActuator ms) {
List<AttractionPoint> result = new Vector<AttractionPoint>();
SimHost msHost = mapMsHost.get(ms);
for (SimHost host : socialView.getNeighbors(msHost)) {
SimLocationActuator temp = mapHostMs.get(host);
if (assignments.get(temp) != null) {
result.add(assignments.get(temp));
}
}
return result;
}
private List<AttractionPoint> getFavoritePlaces(SimLocationActuator ms) {
return new Vector<AttractionPoint>(favoritePlaces.get(ms));
}
private AttractionPoint getRandomPlace(SimLocationActuator ms) {
Collections.shuffle(aPoints, rand);
return aPoints.iterator().next();
}
private AttractionPoint getNearestPlace(SimLocationActuator ms,
List<AttractionPoint> aps) {
if (aps.isEmpty()) {
return null;
}
AttractionPoint nearest = aps.iterator().next();
for (AttractionPoint aPoint : aps) {
if (nearest.getRealPosition()
.distanceTo(ms.getRealPosition()) > aPoint.getRealPosition()
.distanceTo(ms.getRealPosition())
&& !assignments.get(ms).equals(aPoint)) {
nearest = aPoint;
}
}
return nearest;
}
private AttractionPoint getNearestFavoritePlace(SimLocationActuator ms) {
Set<AttractionPoint> fps = favoritePlaces.get(ms);
AttractionPoint nearest = fps.iterator().next();
for (AttractionPoint aPoint : fps) {
if (nearest.getRealPosition()
.distanceTo(ms.getRealPosition()) > aPoint.getRealPosition()
.distanceTo(ms.getRealPosition())
&& !assignments.get(ms).equals(aPoint)) {
nearest = aPoint;
}
}
return nearest;
}
private void assignFavoritePlaces(SimLocationActuator ms) {
Set<AttractionPoint> msFavoritePlaces = new LinkedHashSet<AttractionPoint>();
LinkedList<AttractionPoint> temp = new LinkedList<AttractionPoint>(
aPoints);
Collections.shuffle(temp, rand);
for (int i = 0; i < numberOfFavoritePlaces; i++) {
if (!temp.isEmpty()) {
msFavoritePlaces.add(temp.removeFirst());
}
}
favoritePlaces.put(ms, msFavoritePlaces);
}
private void mappingHost(SimLocationActuator ms) {
SimHostComponent comp = (SimHostComponent) ms;
SimHost host = comp.getHost();
assert host != null;
mapHostMs.put(host, ms);
mapMsHost.put(ms, host);
}
protected long getPauseTime() {
return (long) ((rand.nextDouble() * (maxPauseTime - minPauseTime)) + minPauseTime);
}
public void setMinPauseTime(long minPauseTime) {
if (minPauseTime < 0) {
throw new ConfigurationException(
"MinPauseTime should be bigger then 0!");
}
this.minPauseTime = minPauseTime;
}
public void setMaxPauseTime(long maxPauseTime) {
if (maxPauseTime < 0) {
throw new ConfigurationException(
"MaxPauseTime should be bigger then 0!");
}
this.maxPauseTime = maxPauseTime;
}
@Override
public void eventOccurred(Object se, int type) {
doTransition((SimLocationActuator) se);
}
public void setSocialFactor(double socialFactor) {
if (socialFactor < 0 || socialFactor > 1) {
throw new ConfigurationException(
"socialFactor should be between 0 and 1!");
}
this.socialFactor = socialFactor;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.transition;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modular.attraction.AttractionPoint;
/**
* This is the interface for the Transition Strategy.<br>
* It derives automatically the assignments of the added
* {@link SimLocationActuator} to the {@link AttractionPoint}s. This mean, that
* the implementation must handle the new assignments after a certain time. The
* {@link ModularMovementModel}, will be only call the {@link #getAssignments()}
* in every MovementStep, to calculate the movement of the
* {@link SimLocationActuator} Objects, in respect to the Assignment.
*
* @author Christoph Muenker
* @version 1.0, 25.06.2013
*/
public interface TransitionStrategy {
/**
* Returns the assignments of the MovementSupported Objects to the
* AttractionPoints
*
* @return
*/
public Map<SimLocationActuator, AttractionPoint> getAssignments();
/**
* Should be called first, to add the Attraction Points for the assignment!
*
* @param attractionPoints
*/
public void setAttractionPoints(List<AttractionPoint> attractionPoints);
/**
* Add the {@link SimLocationActuator} object and assign the MS to an
* {@link AttractionPoint}.
*
* @param ms
*/
public void addComponent(SimLocationActuator ms);
}
......@@ -31,11 +31,8 @@ import java.util.Vector;
import javax.swing.JComponent;
import org.w3c.dom.Attr;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
......@@ -43,8 +40,6 @@ import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.TransitionStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
......@@ -54,7 +49,7 @@ import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationActuator;
/**
......@@ -90,7 +85,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationAc
*
*
*
* @author Martin Hellwig
* @author Martin Hellwig, Christoph Muenker
* @version 1.0, 07.07.2015
*/
public class ModularMovementModel implements MovementModel, EventHandler {
......@@ -134,12 +129,11 @@ public class ModularMovementModel implements MovementModel, EventHandler {
*/
public void initialize() {
if (!initialized) {
VisualizationInjector.injectComponent("AttractionPoints", -1,
new ModularMovementModelViz(this), true, false);
VisualizationInjector.injectComponent("Real Map", -2,
(JComponent) mapVisualization, true, false);
if (!initialized) {
VisualizationInjector.injectComponent(new ModularMovementModelViz(this));
if (mapVisualization != null) {
VisualizationInjector.injectComponent(mapVisualization);
}
checkConfiguration();
......@@ -178,22 +172,13 @@ public class ModularMovementModel implements MovementModel, EventHandler {
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) {
/*
* Set a new target AP for the current actuator (or assign to an AP close by)
*/
AttractionPoint apFound = null;
for (AttractionPoint ap : transition.getAllAttractionPoints()) {
if (ap.getRealPosition().distanceTo(new PositionVector(longitude, latitude)) < 1) {
apFound = ap;
break;
}
}
if (apFound == null) {
apFound = new AttractionPoint((int) longitude, (int) latitude, "");
}
transition.updateTargetAttractionPoint(actuator, apFound);
public void changeTargetLocation(SimLocationActuator actuator, AttractionPoint ap) {
transition.updateTargetAttractionPoint(actuator, ap);
}
@Override
public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
return transition.getAssignments().get(actuator);
}
private void checkConfiguration() {
......@@ -240,8 +225,7 @@ public class ModularMovementModel implements MovementModel, EventHandler {
for (Entry<SimLocationActuator, AttractionPoint> entry : assigns
.entrySet()) {
SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector attractionCenter = (PositionVector) entry.getValue();
PositionVector destination = new PositionVector(attractionCenter);
destination.add(offsetPosition.get(ms));
......@@ -268,8 +252,7 @@ public class ModularMovementModel implements MovementModel, EventHandler {
Either<PositionVector, Boolean> either = localMovementStrategy
.nextPosition(ms, destination);
if (either.hasLeft()) {
ms.updateCurrentLocation(either.getLeft().getLongitude(),
either.getLeft().getLatitude());
ms.updateCurrentLocation(either.getLeft());
/*
* Check for negative or out of bound coordinates!
*/
......@@ -321,13 +304,4 @@ public class ModularMovementModel implements MovementModel, EventHandler {
public List<AttractionPoint> getAttractionPoints() {
return new Vector<AttractionPoint>(transition.getAllAttractionPoints());
}
/**
* Only for visualization
* @param actuator
* @return
*/
public AttractionPoint getCurrentAttractionPoint(LocationActuator actuator) {
return transition.getAssignments().get(actuator);
}
}
......@@ -27,10 +27,13 @@ import java.awt.Point;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JMenu;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
* Visualization Component of the Attraction Points in the Modular Movement Model.
......@@ -39,7 +42,7 @@ import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.Visualiza
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*/
public class ModularMovementModelViz extends JComponent {
public class ModularMovementModelViz extends JComponent implements VisualizationComponent {
private ModularMovementModel movementModel;
......@@ -61,7 +64,7 @@ public class ModularMovementModelViz extends JComponent {
RenderingHints.VALUE_ANTIALIAS_ON);
for (AttractionPoint aPoint : movementModel.getAttractionPoints()) {
Point point = aPoint.getRealPosition().asPoint();
Point point = ((PositionVector) aPoint).asPoint();
// draw border
g2.setColor(Color.BLACK);
g2.setFont(VisualizationTopologyView.FONT_MEDIUM);
......@@ -74,4 +77,24 @@ public class ModularMovementModelViz extends JComponent {
}
}
@Override
public String getDisplayName() {
return "Mobility Model";
}
@Override
public JComponent getComponent() {
return this;
}
@Override
public JMenu getCustomMenu() {
return null;
}
@Override
public boolean isHidden() {
return false;
}
}
/*
* Copyright (c) 2005-2015 KOM – Multimedia Communications Lab
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
......@@ -24,38 +24,56 @@ import java.util.Random;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
* This is the implementation of a AttractionPoint. This type of
* {@link AttractionPoint} has not the ability to be moved. Its data come from
* osm-POIs, which are static locations
* In the current implementation, {@link AttractionPoint}s cannot move anymore.
*
* @author Martin Hellwig
* @version 1.0, 02.07.2015
*
* @author Christoph Muenker, Bjoern Richerzhagen
* @version 1.0, 02.07.2013
*/
public class AttractionPoint {
public class AttractionPointImpl extends PositionVector implements AttractionPoint {
protected static Random rnd = Randoms.getRandom(AttractionPoint.class);
private PositionVector posVec;
private String name;
@XMLConfigurableConstructor({ "x", "y", "name" })
public AttractionPoint(int x, int y, String name) {
this(new PositionVector(x, y), name);
}
public AttractionPoint(PositionVector posVec, String name) {
this.posVec = posVec;
public AttractionPointImpl(String name, PositionVector posVec) {
super(posVec);
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public AttractionPoint clone(String newName) {
return new AttractionPointImpl(name, this);
}
public PositionVector getRealPosition() {
return posVec;
@Override
public int hashCode() {
final int prime = 31;
int result = prime * ((name == null) ? 0 : name.hashCode());
return result;
}
public String getName() {
return name;
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
AttractionPointImpl other = (AttractionPointImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
......@@ -23,6 +23,8 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction;
import java.util.LinkedList;
import java.util.List;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
* For simple scenarios: add attraction points by specifying a coordinate.
*
......
......@@ -18,7 +18,7 @@
*
*/
package de.tud.kom.p2psim.impl.topology.movement.modular.attraction;
package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction;
import java.io.BufferedReader;
import java.io.FileReader;
......@@ -29,6 +29,7 @@ import java.util.List;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......@@ -38,19 +39,15 @@ import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
* @author Nils Richerzhagen
* @version 1.0, 16.07.2014
*/
public class CsvAttractionGenerator implements AttractionGenerator {
public class CsvAttractionGenerator implements IAttractionGenerator {
private PositionVector worldDimensions;
private String file;
private final String SEP = ";";
private List<PositionVector> attractionPointsPositions;
private double minSpeed = 2;
private double maxSpeed = 2;
private List<AttractionPoint> attractionPoints;
/**
*
......@@ -60,38 +57,27 @@ public class CsvAttractionGenerator implements AttractionGenerator {
public CsvAttractionGenerator(String placementFile) {
this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
attractionPointsPositions = new LinkedList<PositionVector>();
this.file = placementFile;
}
@Override
public void setNumberOfAttractionPoints(int numberOfAttractionPoints) {
// Number of AttractionPoints is set by the CSV file.
}
@Override
public List<AttractionPoint> getAttractionPoints() {
readData();
List<AttractionPoint> result = new LinkedList<AttractionPoint>();
for (PositionVector attractionPointPositionVector : attractionPointsPositions) {
AttractionPoint aPoint = new AttractionPoint(
attractionPointPositionVector, minSpeed, maxSpeed);
result.add(aPoint);
if (attractionPoints == null) {
attractionPoints = new LinkedList<>();
readData();
}
return result;
return attractionPoints;
}
private void readData() {
attractionPointsPositions.clear();
boolean entrySuccessfullyRead = false;
BufferedReader csv = null;
try {
csv = new BufferedReader(new FileReader(file));
int i = 0;
while (csv.ready()) {
String line = csv.readLine();
if (line.indexOf(SEP) > -1) {
String[] parts = line.split(SEP);
......@@ -107,9 +93,9 @@ public class CsvAttractionGenerator implements AttractionGenerator {
+ y);
continue;
}
attractionPointsPositions.add(new PositionVector(x,
y));
attractionPoints.add(new AttractionPointImpl("AP"+i, new PositionVector(x,
y)));
i++;
entrySuccessfullyRead = true;
} catch (NumberFormatException e) {
// Ignore leading comments
......@@ -122,7 +108,6 @@ public class CsvAttractionGenerator implements AttractionGenerator {
throw new AssertionError("To many columns in CSV.");
}
}
} catch (Exception e) {
System.err.println(e.toString());
} finally {
......
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