Commit 4b963d5b authored by Julian Zobel's avatar Julian Zobel
Browse files

Simple movement model, let clients move on straight lines between points like a grid or similar

parent c1761134
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;
import javax.swing.JComponent;
import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.movement.MovementModel;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.local.LocalMovementStrategy;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldMovementPoints;
import de.tud.kom.p2psim.impl.topology.movement.modular.ModularMovementModelViz;
import de.tud.kom.p2psim.impl.topology.movement.modular.transition.TransitionStrategy;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.AttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.mapvisualization.IMapVisualization;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
* Modular Movement Model uses different models/strategies to create a movement
* model. In this implementation, it has 3 different models/strategies.
* <p>
* M0: AttractionGenerator -> Generates the {@link AttractionPoint}s and place
* them on the map. The {@link AttractionPoint}s can't be moved, because they
* are static POIs from real-world data!
* <p>
* M1: A general {@link MovementModel} is not used, because we use static
* attraction points.
* <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!
*
*/
public class StreetMovement implements MovementModel, EventHandler {
private final int EVENT_MOVE = 1;
private final int EVENT_INIT = 2;
protected PositionVector worldDimensions;
private Set<SimLocationActuator> moveableHosts = new LinkedHashSet<SimLocationActuator>();
private Map<SimLocationActuator, PositionVector> positions = new LinkedHashMap<SimLocationActuator, PositionVector>();
private Map<SimLocationActuator, AttractionPoint> attractionOfClients = new LinkedHashMap<SimLocationActuator, AttractionPoint>();
List<AttractionPoint> attractionPoints = new LinkedList<AttractionPoint>();
private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
private Random rand;
private double latLeft; //Values from -90 to 90; always smaller than latRight
private double latRight; //Values from -90 to 90
private double lonLeft; //Values from -180 to 180; Always smaller than lonRight
private double lonRight; //Values from -180 to 180
public StreetMovement() {
this.worldDimensions = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
this.rand = Randoms.getRandom(StreetMovement.class);
latLeft = GPSCalculation.getLatLower();
latRight = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft();
lonRight = GPSCalculation.getLonRight();
System.out.println("Scheduling first event for Init");
// scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT);
}
/**
* This Method will be not called from the Components. So we call this
* manually!
*/
public void initialize() {
if (!initialized) {
//AttractionPoint p1 = new AttractionPoint((int)(worldDimensions.getX())/2,(int)(worldDimensions.getY()/2), "center");
//attractionPoints.add(p1);
//System.out.println("Initialized Attraction Points with length " + attractionPoints.size());
setTimeBetweenMoveOperations(timeBetweenMoveOperation);
for (SimLocationActuator ms : moveableHosts) {
AttractionPoint a = attractionPoints.get(rand.nextInt(attractionPoints.size()));
attractionOfClients.put(ms, a);
ms.updateCurrentLocation(a.getRealPosition().getLongitude(), a.getRealPosition().getLatitude());
positions.put(ms, ms.getRealPosition());
}
// initial move
move();
initialized = true;
}
}
/**
* This default implementation relies on {@link PlacementModel}s to be
* configured in the {@link TopologyFactory}
*/
@Override
public void placeComponent(SimLocationActuator actuator) {
}
@Override
public void changeTargetLocation(SimLocationActuator actuator,
double longitude, double latitude) {
/*
* Set a new target AP for the current actuator
*/
attractionOfClients.put(actuator, new AttractionPoint((int) longitude, (int) latitude, ""));
}
@Override
public void addComponent(SimLocationActuator comp) {
moveableHosts.add(comp);
positions.put(comp, comp.getRealPosition());
}
@Override
public void setTimeBetweenMoveOperations(long time) {
if (time > 0) {
this.timeBetweenMoveOperation = time;
} else {
throw new ConfigurationException(
"time is negative for the Move Operations");
}
}
private PositionVector randomOffsetVector() {
double x = rand.nextGaussian() * 6;
double y = rand.nextGaussian() * 6;
return new PositionVector(x, y);
}
protected void move() {
for (Entry<SimLocationActuator, AttractionPoint> entry : attractionOfClients.entrySet()) {
SimLocationActuator ms = entry.getKey();
PositionVector attractionCenter = entry.getValue()
.getRealPosition();
PositionVector destination = new PositionVector(attractionCenter);
if (destination.distanceTo(ms.getRealPosition()) > ms.getMovementSpeed()) {
PositionVector newPosition = ms.getRealPosition().moveStep(destination, ms.getMovementSpeed());
ms.updateCurrentLocation(newPosition.getLongitude(), newPosition.getLatitude());
positions.put(ms, newPosition);
} else {
assignNewAttractionPoint(ms);
}
/*
* Check for negative or out of bound coordinates!
*/
assert ms.getRealPosition().getX() >= 0.0
&& ms.getRealPosition().getX() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getX();
assert ms.getRealPosition().getY() >= 0.0
&& ms.getRealPosition().getY() <= Binder
.getComponentOrNull(Topology.class)
.getWorldDimensions().getY();
}
Event.scheduleWithDelay(timeBetweenMoveOperation, this, null,
EVENT_MOVE);
}
private void assignNewAttractionPoint(SimLocationActuator ms) {
if(attractionOfClients.containsKey(ms)) {
boolean updownrand = rand.nextBoolean();
int index = attractionPoints.indexOf(attractionOfClients.get(ms));
if(updownrand) {
index = ((index + 1) % attractionPoints.size());
} else {
index = ((index - 1 + attractionPoints.size()) % attractionPoints.size());
}
attractionOfClients.put(ms, attractionPoints.get(index));
} else {
attractionOfClients.put(ms, attractionPoints.get(rand.nextInt(attractionPoints.size())));
}
}
@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 attractionPoints;
}
public void setAttractionPoint(AttractionPoint point) {
this.attractionPoints.add(point);
}
}
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