Commit 84fd4c1b authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

Added Segment Retrieval (as config option)

- Visualization
- Refactored Route-Sensor
parent 982c7aff
...@@ -23,8 +23,6 @@ package de.tud.kom.p2psim.impl.topology; ...@@ -23,8 +23,6 @@ package de.tud.kom.p2psim.impl.topology;
import java.awt.Point; import java.awt.Point;
import java.util.Arrays; import java.util.Arrays;
import org.aopalliance.aop.AspectException;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
......
...@@ -26,6 +26,7 @@ import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel; ...@@ -26,6 +26,7 @@ import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
public abstract class AbstractLocalMovementStrategy implements public abstract class AbstractLocalMovementStrategy implements
LocalMovementStrategy { LocalMovementStrategy {
...@@ -34,6 +35,8 @@ public abstract class AbstractLocalMovementStrategy implements ...@@ -34,6 +35,8 @@ public abstract class AbstractLocalMovementStrategy implements
protected ObstacleModel obstacleModel; protected ObstacleModel obstacleModel;
private static boolean calculateRouteSegments = false;
private double scaleFactor = 1; private double scaleFactor = 1;
public double getMovementSpeed(SimLocationActuator ms) { public double getMovementSpeed(SimLocationActuator ms) {
...@@ -57,6 +60,29 @@ public abstract class AbstractLocalMovementStrategy implements ...@@ -57,6 +60,29 @@ public abstract class AbstractLocalMovementStrategy implements
this.obstacleModel = model; this.obstacleModel = model;
} }
protected boolean isCalculateRouteSegments() {
return calculateRouteSegments;
}
/**
* For the visualization: programmatically enable route segment
* calculations.
*/
public static void setCalculationOfRouteSegments(boolean setting) {
calculateRouteSegments = setting;
}
/**
* If you intend to use the {@link RouteSensor} and operate on a per-segment
* basis, set this to true. If you DO NOT use the respective segment data,
* set it to false, as this option consumes significant resources.
*
* @param calculateRouteSegments
*/
public void setCalculateRouteSegments(boolean calculateRouteSegments) {
this.calculateRouteSegments = calculateRouteSegments;
}
@Override @Override
public abstract Either<PositionVector, Boolean> nextPosition( public abstract Either<PositionVector, Boolean> nextPosition(
SimLocationActuator comp, PositionVector destination); SimLocationActuator comp, PositionVector destination);
......
...@@ -53,7 +53,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy { ...@@ -53,7 +53,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
private PositionVector worldDimensions; private PositionVector worldDimensions;
private static HashMap<SimLocationActuator, RealWorldMovementPoints> movementPoints = new HashMap<>(); private static HashMap<SimLocationActuator, RouteImpl> movementPoints = new HashMap<>();
private String movementType; // {Fastest, Shortest, Pedestrian, Bicycle} private String movementType; // {Fastest, Shortest, Pedestrian, Bicycle}
private String mapQuestKey; private String mapQuestKey;
...@@ -82,7 +82,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy { ...@@ -82,7 +82,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
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
RealWorldMovementPoints trajectory = movementPoints.get(comp); RouteImpl trajectory = movementPoints.get(comp);
if(trajectory == null || destination.distanceTo(trajectory.getDestination()) > 1.0) { if(trajectory == null || destination.distanceTo(trajectory.getDestination()) > 1.0) {
double[] startPosition = transformOwnWorldWindowToGPS(comp.getRealPosition().getX(), comp.getRealPosition().getY()); double[] startPosition = transformOwnWorldWindowToGPS(comp.getRealPosition().getX(), comp.getRealPosition().getY());
double[] destinationPosition = transformOwnWorldWindowToGPS(destination.getX(), destination.getY()); double[] destinationPosition = transformOwnWorldWindowToGPS(destination.getX(), destination.getY());
...@@ -123,7 +123,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy { ...@@ -123,7 +123,7 @@ public class OnlineMapQuestMovement extends AbstractLocalMovementStrategy {
} }
} }
} }
trajectory = new RealWorldMovementPoints(comp.getRealPosition(), destination, pointList); trajectory = new RouteImpl(comp.getRealPosition(), destination, pointList);
movementPoints.put(comp, trajectory); movementPoints.put(comp, trajectory);
} }
......
...@@ -20,6 +20,14 @@ ...@@ -20,6 +20,14 @@
package de.tud.kom.p2psim.impl.topology.movement.local; package de.tud.kom.p2psim.impl.topology.movement.local;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import com.graphhopper.GHRequest; import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse; import com.graphhopper.GHResponse;
import com.graphhopper.GraphHopper; import com.graphhopper.GraphHopper;
...@@ -31,19 +39,18 @@ import com.graphhopper.util.DistanceCalc2D; ...@@ -31,19 +39,18 @@ import com.graphhopper.util.DistanceCalc2D;
import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.PointList; import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint; import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation; import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView; import de.tud.kom.p2psim.impl.topology.movement.modularosm.RouteSensorComponent;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Left;
import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import java.util.*;
/** /**
* 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
...@@ -61,8 +68,10 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -61,8 +68,10 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
private LocationIndex index; private LocationIndex index;
private boolean init = false; private boolean init = false;
private static HashMap<SimLocationActuator, RealWorldMovementPoints> movementPoints = new HashMap<>(); private static HashMap<SimLocationActuator, RouteImpl> currentRoutes = new HashMap<>();
private Map<SimLocationActuator, RouteSensorComponent> routeSensorComponents = new LinkedHashMap<>();
private String osmFileLocation; //use pbf-format, because osm-format causes problems (xml-problems) private String osmFileLocation; //use pbf-format, because osm-format causes problems (xml-problems)
private String graphFolderFiles; private String graphFolderFiles;
private String movementType; //car, bike or foot private String movementType; //car, bike or foot
...@@ -87,6 +96,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -87,6 +96,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
latUpper = GPSCalculation.getLatUpper(); latUpper = GPSCalculation.getLatUpper();
lonLeft = GPSCalculation.getLonLeft(); lonLeft = GPSCalculation.getLonLeft();
lonRight = GPSCalculation.getLonRight(); lonRight = GPSCalculation.getLonRight();
} }
private void init() { private void init() {
...@@ -111,23 +121,42 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -111,23 +121,42 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
init = true; init = true;
} }
public Either<PositionVector, Boolean> nextPosition(SimLocationActuator comp, PositionVector destination) @Override
{ public Either<PositionVector, Boolean> nextPosition(
SimLocationActuator comp, PositionVector destination) {
return nextPosition(comp, destination, defaultMovement); return nextPosition(comp, destination, defaultMovement);
} }
public Either<PositionVector, Boolean> nextPosition(SimLocationActuator comp, public Either<PositionVector, Boolean> nextPosition(SimLocationActuator comp,
PositionVector destination, String movementType) { PositionVector destination, String movementType) {
if(movementType == null || movementType.equals("") || !this.movementType.contains(movementType)) if (movementType == null || movementType.equals("")
|| !this.movementType.contains(movementType)) {
throw new AssertionError("Invalid movement type: " + movementType); throw new AssertionError("Invalid movement type: " + movementType);
}
if (!init) {
init();
}
RouteSensorComponent routeSensor = routeSensorComponents.get(comp);
if (routeSensor == null) {
try {
routeSensorComponents.put(comp, comp.getHost()
.getComponent(RouteSensorComponent.class));
routeSensor = routeSensorComponents.get(comp);
} catch (ComponentNotAvailableException e) {
throw new AssertionError(
"The movement model needs to provide RouteSensorComponents.");
}
}
if(!init) init();
PositionVector newPosition = null; PositionVector newPosition = null;
if (destination.distanceTo(comp.getRealPosition()) > getMovementSpeed(comp)) if (destination
{ .distanceTo(comp.getRealPosition()) > getMovementSpeed(comp)) {
//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
RealWorldMovementPoints trajectory = movementPoints.get(comp); RouteImpl trajectory = currentRoutes.get(comp);
if(trajectory == null || destination.distanceTo(trajectory.getDestination()) > 1.0) { if(trajectory == null || destination.distanceTo(trajectory.getDestination()) > 1.0) {
double[] startPosition = transformOwnWorldWindowToGPS(comp.getRealPosition().getX(), comp.getRealPosition().getY()); double[] startPosition = transformOwnWorldWindowToGPS(comp.getRealPosition().getX(), comp.getRealPosition().getY());
double[] destinationPosition = transformOwnWorldWindowToGPS(destination.getX(), destination.getY()); double[] destinationPosition = transformOwnWorldWindowToGPS(destination.getX(), destination.getY());
...@@ -144,27 +173,27 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -144,27 +173,27 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
PointList pointList = new PointList(); PointList pointList = new PointList();
pointList.add(new GHPoint(destinationPosition[0], destinationPosition[1])); pointList.add(new GHPoint(destinationPosition[0], destinationPosition[1]));
trajectory = new RealWorldMovementPoints(comp.getRealPosition(), destination, pointList); trajectory = new RouteImpl(comp.getRealPosition(), destination, pointList);
movementPoints.put(comp, trajectory); currentRoutes.put(comp, trajectory);
} else { } else {
PointList pointList = rsp.getBest().getPoints(); PointList pointList = rsp.getBest().getPoints();
trajectory = new RealWorldMovementPoints(comp.getRealPosition(), destination, pointList);
/* if (isCalculateRouteSegments()) {
* TODO obtain route IDs along the path. /*
*/ * Obtain segment IDs along the route.
// for (GHPoint point : pointList) { */
// QueryResult qr = index.findClosest(point.getLat(), point.getLon(), EdgeFilter.ALL_EDGES); trajectory = new RouteImpl(comp.getRealPosition(),
// EdgeIteratorState nearEdge = qr.getClosestEdge(); destination, pointList,
// nearEdge. routeSensor.getSegmentListeners(),
// int channelId = -1; calculateSegments(pointList));
// if (nearEdge != null) { } else {
// channelId = nearEdge.getEdge(); trajectory = new RouteImpl(comp.getRealPosition(),
// } destination, pointList);
// currentRoute.add(new PointIdTuple(point, channelId)); }
// } currentRoutes.put(comp, trajectory);
movementPoints.put(comp, trajectory);
} }
routeSensor.setNewRoute(trajectory);
} }
newPosition = trajectory.updateCurrentLocation(comp, getMovementSpeed(comp), tolerance); newPosition = trajectory.updateCurrentLocation(comp, getMovementSpeed(comp), tolerance);
} }
...@@ -172,7 +201,45 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -172,7 +201,45 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
} }
/** /**
* Projects the world coordinates in the given gps window to the gps-coordinates * Calculate the route segments along the given point list.
*
* @return
*/
private List<RouteSegmentImpl> calculateSegments(PointList pointList) {
int ptIdx = 0;
int prevEdgeId = -1;
List<RouteSegmentImpl> segments = new LinkedList<>();
RouteSegmentImpl lastSegment = null;
for (GHPoint point : pointList) {
QueryResult qr = index.findClosest(point.getLat(), point.getLon(),
EdgeFilter.ALL_EDGES);
EdgeIteratorState nearEdge = qr.getClosestEdge();
if (nearEdge != null) {
int edgeId = nearEdge.getEdge();
if (edgeId != prevEdgeId) {
if (lastSegment != null) {
lastSegment.addRouteLocation(
transformGPSWindowToOwnWorld(point.getLat(),
point.getLon()));
}
lastSegment = new RouteSegmentImpl(Integer.toString(edgeId),
ptIdx, transformGPSWindowToOwnWorld(point.getLat(),
point.getLon()));
segments.add(lastSegment);
} else {
lastSegment.addRouteLocation(transformGPSWindowToOwnWorld(
point.getLat(), point.getLon()));
}
}
ptIdx++;
}
return segments;
}
/**
* Projects the world coordinates in the given gps window to the
* gps-coordinates
*
* @param x * @param x
* @param y * @param y
* @return The projected position in gps-coordinates (lat, long) * @return The projected position in gps-coordinates (lat, long)
...@@ -209,7 +276,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -209,7 +276,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
public List<PositionVector> getMovementPoints(SimLocationActuator ms) public List<PositionVector> getMovementPoints(SimLocationActuator ms)
{ {
List<PositionVector> positions = new LinkedList<>(); List<PositionVector> positions = new LinkedList<>();
PointList pointList = movementPoints.get(ms).getPointList(); PointList pointList = currentRoutes.get(ms).getPointList();
pointList.forEach(p -> positions.add(new PositionVector(transformGPSWindowToOwnWorld(p.getLat(), p.getLon())))); pointList.forEach(p -> positions.add(new PositionVector(transformGPSWindowToOwnWorld(p.getLat(), p.getLon()))));
...@@ -250,7 +317,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy { ...@@ -250,7 +317,7 @@ public class RealWorldStreetsMovement extends AbstractLocalMovementStrategy {
*/ */
public double getCurrentRouteLength(SimLocationActuator ms) public double getCurrentRouteLength(SimLocationActuator ms)
{ {
return movementPoints.get(ms).getPointList().calcDistance(new DistanceCalc2D()); return currentRoutes.get(ms).getPointList().calcDistance(new DistanceCalc2D());
} }
public void setOsmFileLocation(String osmFileLocation) { public void setOsmFileLocation(String osmFileLocation) {
......
...@@ -20,14 +20,19 @@ ...@@ -20,14 +20,19 @@
package de.tud.kom.p2psim.impl.topology.movement.local; package de.tud.kom.p2psim.impl.topology.movement.local;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
import com.graphhopper.util.PointList; import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint3D; import com.graphhopper.util.shapes.GHPoint3D;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor.RouteSegmentListener;
/** /**
* This class contains one trajectory from a start to a destination. It saves * This class contains one trajectory from a start to a destination. It saves
...@@ -35,36 +40,76 @@ import de.tud.kom.p2psim.impl.topology.PositionVector; ...@@ -35,36 +40,76 @@ import de.tud.kom.p2psim.impl.topology.PositionVector;
* speed and also (if enabled) the assigned IDs of the roads and walkways that * speed and also (if enabled) the assigned IDs of the roads and walkways that
* are traversed. * are traversed.
* *
* TODO add segment handling
*
* Segment handling is only done if there is a segment listener registered for
* the respective client.
*
* @author Bjoern Richerzhagen * @author Bjoern Richerzhagen
* @version 1.0, Aug 9, 2017 * @version 1.0, Aug 9, 2017
*/ */
public class RealWorldMovementPoints { public class RouteImpl implements Route {
private PositionVector start; private PositionVector start;
private PositionVector destination; private PositionVector destination;
private PointList pointList; private PointList pointList;
private final List<PositionVector> positionsList; private final List<PositionVector> positionsList;
private final List<RouteSegmentImpl> routeSegments;
private final Set<RouteSegmentListener> segmentListeners;
private int currentIndex; private int currentIndex;
private int currentSegmentIndex;
private int routeLength; private int routeLength;
public RealWorldMovementPoints(PositionVector start, private int routeSegmentsLength;
PositionVector destination, PointList pointList) {
/**
*
* @param start
* @param destination
* @param pointList
* @param segmentListeners
* @param routeSegments
*/
public RouteImpl(PositionVector start,
PositionVector destination, PointList pointList,
Set<RouteSegmentListener> segmentListeners,
List<RouteSegmentImpl> routeSegments) {
this.start = start; this.start = start;
this.destination = destination; this.destination = destination;
this.pointList = pointList; this.pointList = pointList;
this.positionsList = new LinkedList<>(); this.positionsList = new LinkedList<>();
// Create Position vectors ONCE // Create Position vectors ONCE
for (GHPoint3D temp : pointList) { for (GHPoint3D temp : pointList) {
positionsList.add(RealWorldStreetsMovement.transformGPSWindowToOwnWorld(temp.getLat(), temp.getLon())); positionsList
.add(RealWorldStreetsMovement.transformGPSWindowToOwnWorld(
temp.getLat(), temp.getLon()));
} }
routeLength = positionsList.size(); routeLength = positionsList.size();
this.segmentListeners = segmentListeners;
this.routeSegments = routeSegments;
this.routeSegmentsLength = routeSegments.size();
} }
/**
*
* @param start
* @param destination
* @param pointList
*/
public RouteImpl(PositionVector start,
PositionVector destination, PointList pointList) {
this(start, destination, pointList, Collections.emptySet(),
Collections.emptyList());
}
public PositionVector getStart() { public PositionVector getStart() {
return start; return start;
} }
...@@ -72,7 +117,46 @@ public class RealWorldMovementPoints { ...@@ -72,7 +117,46 @@ public class RealWorldMovementPoints {
public PositionVector getDestination() { public PositionVector getDestination() {
return destination; return destination;
} }
@Override
public Location getTargetLocation() {
return destination;
}
@Override
public boolean hasSegmentInformation() {
return routeSegmentsLength != 0;
}
@Override
public RouteSegment getCurrentSegment() {
if (!hasSegmentInformation()) {
throw new UnsupportedOperationException(
"To access segments within a Route, you need to enable the respective functionality in the local movement strategy (usually: calculateRouteSegments=true)");
}
return routeSegments.get(currentSegmentIndex);
}
@Override
public List<RouteSegment> getSegmentsAhead() {
if (!hasSegmentInformation()) {
throw new UnsupportedOperationException(
"To access segments within a Route, you need to enable the respective functionality in the local movement strategy (usually: calculateRouteSegments=true)");
}
return Collections.unmodifiableList(routeSegments
.subList(currentSegmentIndex, routeSegmentsLength));
}
@Override
public List<RouteSegment> getSegmentsBehind() {
if (!hasSegmentInformation()) {
throw new UnsupportedOperationException(
"To access segments within a Route, you need to enable the respective functionality in the local movement strategy (usually: calculateRouteSegments=true)");
}
return Collections.unmodifiableList(routeSegments
.subList(0, currentSegmentIndex));
}
/** /**
* Update the internal location with the given movement speed * Update the internal location with the given movement speed
* *
...@@ -80,24 +164,31 @@ public class RealWorldMovementPoints { ...@@ -80,24 +164,31 @@ public class RealWorldMovementPoints {
* @param realPosition * @param realPosition
* @return * @return
*/ */
public PositionVector updateCurrentLocation(SimLocationActuator comp, double speed, double tolerance) { public PositionVector updateCurrentLocation(SimLocationActuator comp,
List<PositionVector> sublist = positionsList.subList(currentIndex, routeLength); double speed, double tolerance) {
List<PositionVector> sublist = positionsList.subList(currentIndex,
routeLength);
PositionVector newPosition = null; PositionVector newPosition = null;
for (PositionVector candidate : sublist) { for (PositionVector candidate : sublist) {
newPosition = comp.getRealPosition().moveStep(candidate, speed); newPosition = comp.getRealPosition().moveStep(candidate, speed);
if (candidate if (candidate.distanceTo(comp.getRealPosition()) < tolerance) {
.distanceTo(comp.getRealPosition()) < tolerance) {
currentIndex++; currentIndex++;
} else { } else {
break; break;
} }
} }
/*
* TODO Segment handling (also inform listeners!)
*/
return newPosition; return newPosition;
} }
@Override @Override
public String toString() { public String toString() {
return "\n\tfrom "+start.toString()+" to "+destination.toString()+ "\n\tstep: "+currentIndex + " length: "+routeLength; return "\n\tfrom " + start.toString() + " to " + destination.toString()
+ "\n\tstep: " + currentIndex + " length: " + routeLength;
} }
public PointList getPointList() { public PointList getPointList() {
...@@ -107,4 +198,5 @@ public class RealWorldMovementPoints { ...@@ -107,4 +198,5 @@ public class RealWorldMovementPoints {
public int getCurrentIndex() { public int getCurrentIndex() {
return this.currentIndex; return this.currentIndex;
} }
} }
/*
* 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.local;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route.RouteSegment;
/**
* Implementation of a {@link RouteSegment}
*
* @author Bjoern Richerzhagen
* @version 1.0, Aug 10, 2017
*/
public class RouteSegmentImpl implements RouteSegment {
private final String id;
private final int fromRouteIndex;
private final List<Location> routeLocations;
/**
* The segment and associated points (via their index)
*
* @param id
* @param fromRouteIndex
*/
public RouteSegmentImpl(String id, int fromRouteIndex,
Location startLocation) {
this.id = id;
this.fromRouteIndex = fromRouteIndex;
this.routeLocations = new LinkedList<>();
this.routeLocations.add(startLocation);
}
public void addRouteLocation(Location location) {
this.routeLocations.add(location);
}
@Override
public String getSegmentId() {
return id;
}
@Override
public List<Location> getSegmentLocations() {
return Collections.unmodifiableList(routeLocations);
}
public int getFromRouteIndex() {
return fromRouteIndex;
}
}
...@@ -24,13 +24,10 @@ import java.util.LinkedHashMap; ...@@ -24,13 +24,10 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Vector; import java.util.Vector;
import javax.swing.JComponent;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.MovementModel; import de.tud.kom.p2psim.api.topology.movement.MovementModel;
...@@ -52,7 +49,6 @@ import de.tudarmstadt.maki.simonstrator.api.EventHandler; ...@@ -52,7 +49,6 @@ import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time; 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.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationActuator;
/** /**
* Modular Movement Model uses different models/strategies to create a movement * Modular Movement Model uses different models/strategies to create a movement
...@@ -117,6 +113,8 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -117,6 +113,8 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
private Map<SimLocationActuator, PositionVector> currentTarget = new LinkedHashMap<>(); private Map<SimLocationActuator, PositionVector> currentTarget = new LinkedHashMap<>();
private Map<SimLocationActuator, RouteSensorComponent> routeSensorComponents = new LinkedHashMap<>();
private boolean initialized = false; private boolean initialized = false;
private long timeBetweenMoveOperation = Simulator.SECOND_UNIT; private long timeBetweenMoveOperation = Simulator.SECOND_UNIT;
...@@ -128,9 +126,6 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -128,9 +126,6 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
.getWorldDimensions(); .getWorldDimensions();
this.rand = Randoms.getRandom(ModularMovementModel.class); this.rand = Randoms.getRandom(ModularMovementModel.class);
// Setting this model as default to prevent older code from braking. See Changelog.
modelVisualisation = new ModularMovementModelViz(this);
// scheduling initalization! // scheduling initalization!
Event.scheduleImmediately(this, null, EVENT_INIT); Event.scheduleImmediately(this, null, EVENT_INIT);
} }
...@@ -142,6 +137,9 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -142,6 +137,9 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
public void initialize() { public void initialize() {
if (!initialized) { if (!initialized) {
if (modelVisualisation == null) {
modelVisualisation = new ModularMovementModelViz(this);
}
VisualizationInjector.injectComponent(modelVisualisation); VisualizationInjector.injectComponent(modelVisualisation);
if (mapVisualization != null) { if (mapVisualization != null) {
VisualizationInjector.injectComponent(mapVisualization); VisualizationInjector.injectComponent(mapVisualization);
...@@ -224,8 +222,11 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac ...@@ -224,8 +222,11 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
@Override @Override
public void addComponent(SimLocationActuator comp) { public void addComponent(SimLocationActuator comp) {
moveableHosts.add(comp); moveableHosts.add(comp);
if (!routeSensorComponents.containsKey(comp)) {
routeSensorComponents.put(comp, new RouteSensorComponent(comp));
}
} }
public Set<SimLocationActuator> getAllLocationActuators() { public Set<SimLocationActuator> getAllLocationActuators() {
return moveableHosts; return moveableHosts;
} }
......
...@@ -27,6 +27,8 @@ import java.awt.Graphics2D; ...@@ -27,6 +27,8 @@ import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.JCheckBoxMenuItem; import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent; import javax.swing.JComponent;
...@@ -36,10 +38,20 @@ import javax.swing.event.ChangeListener; ...@@ -36,10 +38,20 @@ import javax.swing.event.ChangeListener;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.local.AbstractLocalMovementStrategy;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView; 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.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent; import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent;
import de.tud.kom.p2psim.impl.topology.views.visualization.world.NodeVisInteractionListener;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; 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.route.Route;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route.RouteSegment;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
/** /**
* Visualization Component of the Attraction Points in the Modular Movement * Visualization Component of the Attraction Points in the Modular Movement
...@@ -50,7 +62,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction ...@@ -50,7 +62,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
* @version 1.0, 02.07.2015 * @version 1.0, 02.07.2015
*/ */
public class ModularMovementModelViz extends JComponent public class ModularMovementModelViz extends JComponent
implements VisualizationComponent { implements VisualizationComponent, NodeVisInteractionListener {
protected ModularMovementModel movementModel; protected ModularMovementModel movementModel;
...@@ -58,29 +70,33 @@ public class ModularMovementModelViz extends JComponent ...@@ -58,29 +70,33 @@ public class ModularMovementModelViz extends JComponent
protected boolean showNodePositions = true; protected boolean showNodePositions = true;
protected boolean showTrajectories = false;
private JMenu menu; private JMenu menu;
private Map<Long, TrajectoryVis> trajectoryVisualizations = new LinkedHashMap<>();
private final static int NODE_PAD = 2; private final static int NODE_PAD = 2;
private final static int ATTR_PAD = 5; private final static int ATTR_PAD = 5;
private static Color COLOR_ATTR_POINT = Color.decode("#4A7B9D"); private static Color COLOR_ATTR_POINT = Color.decode("#4A7B9D");
public ModularMovementModelViz() public ModularMovementModelViz() {
{
init(); init();
} }
protected void init() protected void init() {
{
setBounds(0, 0, VisualizationInjector.getWorldX(), setBounds(0, 0, VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY()); VisualizationInjector.getWorldY());
VisualizationInjector.addInteractionListener(this);
setOpaque(true); setOpaque(true);
setVisible(true); setVisible(true);
menu = new JMenu("Mobility Model"); menu = new JMenu("Mobility Model");
menu.add(createCheckboxAp()); menu.add(createCheckboxAp());
menu.add(createCheckboxNodePositions()); menu.add(createCheckboxNodePositions());
menu.add(createCheckboxTrajectories());
} }
public ModularMovementModelViz(ModularMovementModel model) { public ModularMovementModelViz(ModularMovementModel model) {
...@@ -114,6 +130,23 @@ public class ModularMovementModelViz extends JComponent ...@@ -114,6 +130,23 @@ public class ModularMovementModelViz extends JComponent
return checkBox; return checkBox;
} }
private JCheckBoxMenuItem createCheckboxTrajectories() {
final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(
"show node trajectories", showTrajectories);
checkBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
showTrajectories = checkBox.isSelected();
AbstractLocalMovementStrategy
.setCalculationOfRouteSegments(showTrajectories);
VisualizationInjector.invalidate();
}
});
AbstractLocalMovementStrategy
.setCalculationOfRouteSegments(showTrajectories);
return checkBox;
}
@Override @Override
public void paint(Graphics g) { public void paint(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
...@@ -131,6 +164,69 @@ public class ModularMovementModelViz extends JComponent ...@@ -131,6 +164,69 @@ public class ModularMovementModelViz extends JComponent
drawNodePosition(g2, comp); drawNodePosition(g2, comp);
} }
} }
if (showTrajectories) {
for (TrajectoryVis tVis : trajectoryVisualizations.values()) {
tVis.drawTrajectory(g2);
}
}
}
@Override
public void onHostClick(long hostID, boolean isActive) {
if (isActive) {
Host h = Oracle.getHostByID(INodeID.get(hostID));
try {
RouteSensor routeSensor = h.getComponent(RouteSensor.class);
trajectoryVisualizations.put(hostID,
new TrajectoryVis(routeSensor));
} catch (ComponentNotAvailableException e) {
// ignore.
}
} else {
trajectoryVisualizations.remove(hostID);
}
}
/**
* Visualizes the movement trajectory of a given node.
*
* @author Bjoern Richerzhagen
* @version 1.0, Aug 10, 2017
*/
private class TrajectoryVis {
private final RouteSensor routeSensor;
public TrajectoryVis(RouteSensor routeSensor) {
this.routeSensor = routeSensor;
}
public void drawTrajectory(Graphics2D g2) {
Route rt = routeSensor.getRoute();
for (RouteSegment segment : rt.getSegmentsAhead()) {
Location lastLoc = null;
for (Location loc : segment.getSegmentLocations()) {
if (lastLoc == null) {
lastLoc = loc;
continue;
}
g2.setColor(Color.MAGENTA);
g2.drawLine(
VisualizationInjector
.scaleValue(lastLoc.getLongitude()),
VisualizationInjector
.scaleValue(lastLoc.getLatitude()),
VisualizationInjector
.scaleValue(loc.getLongitude()),
VisualizationInjector
.scaleValue(loc.getLatitude()));
lastLoc = loc;
}
}
}
} }
/** /**
......
...@@ -3,7 +3,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm; ...@@ -3,7 +3,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm;
import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldMovementPoints; import de.tud.kom.p2psim.impl.topology.movement.local.RouteImpl;
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement; import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy; import de.tud.kom.p2psim.impl.topology.movement.modularosm.transition.ITransitionStrategy;
import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Either;
......
/*
* 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.modularosm;
import java.util.LinkedHashSet;
import java.util.Set;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
/**
* The OSM-based models provide an implementation of the {@link RouteSensor},
* which is added as a new host component. It is created by supporting mobility
* models, registers itself with the host container and can then be retrieved
* via the host container from w.g., a local movement strategy.
*
* @author Bjoern Richerzhagen
* @version 1.0, Aug 10, 2017
*/
public class RouteSensorComponent implements RouteSensor {
private final SimLocationActuator actuator;
private Route currentRoute;
private final Set<RouteListener> listeners;
private final Set<RouteSegmentListener> segmentListeners;
public RouteSensorComponent(SimLocationActuator actuator) {
this.actuator = actuator;
this.listeners = new LinkedHashSet<>();
this.segmentListeners = new LinkedHashSet<>();
actuator.getHost().registerComponent(RouteSensorComponent.this);
}
@Override
public void initialize() {
//
}
@Override
public void shutdown() {
//
}
public SimLocationActuator getActuator() {
return actuator;
}
@Override
public Host getHost() {
return actuator.getHost();
}
@Override
public Route getRoute() {
return currentRoute;
}
@Override
public void addRouteListener(RouteListener listener) {
listeners.add(listener);
}
@Override
public void removeRouteListener(RouteListener listener) {
listeners.remove(listener);
}
@Override
public void addRouteSegmentListener(RouteSegmentListener listener) {
segmentListeners.add(listener);
}
@Override
public void removeRouteSegmentListener(RouteSegmentListener listener) {
segmentListeners.remove(listener);
}
/*
* The following methods are used by the mobility models.
*/
public void setNewRoute(Route newRoute) {
// notifies listeners
listeners.forEach(l -> l.onChangedRoute(this, currentRoute, newRoute));
currentRoute = newRoute;
}
public void reachedDestination() {
// notifies listeners
listeners.forEach(l -> l.onReachedDestination(this, currentRoute));
}
public Set<RouteSegmentListener> getSegmentListeners() {
return segmentListeners;
}
}
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
package de.tud.kom.p2psim.impl.topology.views; package de.tud.kom.p2psim.impl.topology.views;
import java.util.Arrays;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
...@@ -43,7 +44,6 @@ import de.tudarmstadt.maki.simonstrator.api.Time; ...@@ -43,7 +44,6 @@ import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.handover.HandoverSensor; import de.tudarmstadt.maki.simonstrator.api.component.sensor.handover.HandoverSensor;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
import edu.emory.mathcs.backport.java.util.Arrays;
/** /**
* This topology view offers a topology for mobile apps - mobile clients * This topology view offers a topology for mobile apps - mobile clients
......
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