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

Movement Models for abstract UAVs, multicoper UAVs and UAV Location actuators....

Movement Models for abstract UAVs, multicoper UAVs and UAV Location actuators. Multiple files refactored for better readability.
parent c5a8f78e
......@@ -42,9 +42,8 @@ public interface TopologyComponent extends SimHostComponent,
* Binder-class.
*
* @return
* @deprecated use Binder.getComponent(Topology.class) instead!
* use Binder.getComponent(Topology.class) instead!
*/
@Deprecated
public Topology getTopology();
}
/*
* 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.api.topology.movement;
public interface UAVLocationActuator extends SimLocationActuator {
public UAVMovementModel getUAVMovement();
}
/*
* 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.api.topology.movement;
public interface UAVMovementModel {
public void setPreferredCruiseSpeed(double v_pref);
public double getMaxCruiseSpeed();
public double getMinCruiseSpeed();
public double getCurrentSpeed();
public void move(long timeBetweenMovementOperations);
}
/*
* 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;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
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.placement.PlacementModel;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
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.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest;
import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSComponent;
import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSDataCallback;
import de.tudarmstadt.maki.simonstrator.api.component.sis.exception.InformationNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSTypes;
import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSInformationProvider.SiSProviderHandle;
import de.tudarmstadt.maki.simonstrator.api.component.sis.SiSInfoProperties;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sis.util.SiSTopologyProvider;
import de.tudarmstadt.maki.simonstrator.api.component.topology.TopologyID;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent.NetInterfaceName;
public abstract class AbstractTopologyComponent implements TopologyComponent {
protected SimHost host;
protected final PositionVector position;
protected Topology topology;
protected MovementModel movementModel;
protected PlacementModel placementModel;
private final boolean registerAsInformationProviderInSiS;
private Map<LocationListener, LocationRequestImpl> openRequests = new LinkedHashMap<LocationListener, LocationRequestImpl>();
private List<LocationListener> listeners = new LinkedList<>();
public AbstractTopologyComponent(SimHost host, Topology topology, MovementModel movementModel, PlacementModel placementModel, boolean registerAsInformationProviderInSiS) {
this.topology = topology;
this.host = host;
this.position = new PositionVector(0, 0);
this.movementModel = movementModel;
if (this.movementModel != null) {
this.movementModel.addComponent(this);
}
this.placementModel = placementModel;
if (this.placementModel != null) {
this.placementModel.addComponent(this);
}
this.registerAsInformationProviderInSiS = registerAsInformationProviderInSiS;
}
@Override
public void initialize() {
topology.addComponent(this);
movementModel.placeComponent(this);
if (placementModel != null) {
/*
* Legacy support for placement models.
*/
position.set(placementModel.place(this));
}
if (registerAsInformationProviderInSiS) {
try {
final SiSComponent sis = host.getComponent(SiSComponent.class);
sis.provide().nodeState(SiSTypes.PHY_LOCATION,
new SiSDataCallback<Location>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Location getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
throws InformationNotAvailableException {
if (nodeID.equals(getHost().getId())) {
return getLastLocation();
} else {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties();
}
});
sis.provide().nodeState(SiSTypes.SPEED,
new SiSDataCallback<Double>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Double getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
throws InformationNotAvailableException {
if (nodeID.equals(getHost().getId())) {
return getMovementSpeed();
} else {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties();
}
});
// Provide Underlay topology
Event.scheduleImmediately(new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
if (getHost().getLinkLayer().hasPhy(PhyType.WIFI)) {
new SiSTopologyProvider(sis,
SiSTypes.NEIGHBORS_WIFI,
AbstractTopologyComponent.this,
getTopologyID(NetInterfaceName.WIFI, true),
AbstractTopologyComponent.class);
}
}
}, null, 0);
} catch (ComponentNotAvailableException e) {
// OK
}
}
}
@Override
public void shutdown() {
topology = null;
host = null;
movementModel = null;
}
@Override
public SimHost getHost() {
return host;
}
@Override
public Topology getTopology() {
return topology;
}
/**
* Access to the movement model
* @return
*/
public MovementModel getMovementModel() {
return movementModel;
}
@Override
public Location getLastLocation() {
/*
* As we want to mimic real world behavior, the current position
* snapshot is cloned to prevent information propagation due to Java.
*/
return position.clone();
}
@Override
public PositionVector getRealPosition() {
return position.clone();
}
@Override
public void updateCurrentLocation(Location location) {
position.set(location);
for (LocationListener locationListener : listeners) {
locationListener.onLocationChanged(getHost(), getLastLocation());
}
}
@Override
public void requestLocationUpdates(LocationRequest request,
LocationListener listener) {
if (openRequests.containsKey(listener)) {
throw new AssertionError(
"This LocationListener is already in use.");
}
if (request == null) {
/*
* This listener wants to be triggered on EVERY position update, but
* it does not want to request position updates.
*/
if (!listeners.contains(listener)) {
listeners.add(listener);
}
} else {
/*
* Listener has its own request timing.
*/
LocationRequestImpl req = (LocationRequestImpl) request;
openRequests.put(listener, req);
req.immunizeAndStart(listener);
}
}
@Override
public void removeLocationUpdates(LocationListener listener) {
listeners.remove(listener);
LocationRequestImpl impl = openRequests.remove(listener);
if (impl != null) {
impl.cancel(listener);
}
}
@Override
public LocationRequest getLocationRequest() {
return new LocationRequestImpl(getHost(), this);
}
/*
* Methods for the Graph Interface
*/
/**
* Graph views: static, as we use global knowledge and maintain one shared
* graph (potentially with partitions!)
*/
private final static LinkedHashMap<TopologyID, LocalGraphView> graphViews = new LinkedHashMap<>();
@Override
public TopologyID getTopologyID(NetInterfaceName netName,
boolean onlyOnline) {
TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all"),
DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id, new LocalGraphView(netName, onlyOnline, topology));
}
return id;
}
@Override
public TopologyID getTopologyID(NetInterfaceName netName,
boolean onlyOnline, double range) {
TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all")
+ String.valueOf(range),
DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id,
new LocalGraphView(netName, onlyOnline, range, topology));
}
return id;
}
@Override
public INode getNode(TopologyID identifier) {
assert graphViews.containsKey(identifier);
return graphViews.get(identifier).getOwnNode(host);
}
@Override
public Set<IEdge> getNeighbors(TopologyID topologyIdentifier) {
assert graphViews.containsKey(topologyIdentifier);
return graphViews.get(topologyIdentifier).getNeighbors(host);
}
@Override
public Graph getLocalView(TopologyID topologyIdentifier) {
assert graphViews.containsKey(topologyIdentifier);
return graphViews.get(topologyIdentifier).getLocalView();
}
@Override
public Iterable<TopologyID> getTopologyIdentifiers() {
return graphViews.keySet();
}
@Override
public String toString() {
return "TopoComp: " + getHost().getId() + " at " + position.toString();
}
}
......@@ -94,6 +94,11 @@ public class DefaultTopology implements Topology {
listener.changedWaypointModel(model);
}
}
@Override
public WaypointModel getWaypointModel() {
return waypointModel;
}
@Override
public void setObstacleModel(ObstacleModel model) {
......@@ -102,6 +107,11 @@ public class DefaultTopology implements Topology {
listener.changedObstacleModel(model);
}
}
@Override
public ObstacleModel getObstacleModel() {
return obstacleModel;
}
@Override
public void addTopologyListener(TopologyListener listener) {
......@@ -175,13 +185,5 @@ public class DefaultTopology implements Topology {
}
}
@Override
public WaypointModel getWaypointModel() {
return waypointModel;
}
@Override
public ObstacleModel getObstacleModel() {
return obstacleModel;
}
}
......@@ -68,30 +68,15 @@ import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityList
/**
* Default implementation of a {@link TopologyComponent}.
*
* @author Bjoern Richerzhagen
* @version 1.0, 29.02.2012
* @author Bjoern Richerzhagen, Julian Zobel
* @version 2.0, 05.09.2018
*/
public class DefaultTopologyComponent implements TopologyComponent {
public class DefaultTopologyComponent extends AbstractTopologyComponent {
protected static Random rnd = Randoms.getRandom(AttractionPoint.class);
private SimHost host;
private final PositionVector position;
private Topology topology;
protected static Random rnd = Randoms.getRandom(DefaultTopologyComponent.class);
private double currentMovementSpeed = -1;
private Map<LocationListener, LocationRequestImpl> openRequests = new LinkedHashMap<LocationListener, LocationRequestImpl>();
private List<LocationListener> listeners = new LinkedList<>();
private MovementModel movementModel;
private PlacementModel placementModel;
private final boolean registerAsInformationProviderInSiS;
/**
* Create a TopologyComponent for the current host.
......@@ -102,146 +87,12 @@ public class DefaultTopologyComponent implements TopologyComponent {
*/
public DefaultTopologyComponent(SimHost host, Topology topology,
MovementModel movementModel, PlacementModel placementModel, boolean registerAsInformationProviderInSiS) {
this.topology = topology;
this.host = host;
this.position = new PositionVector(0, 0);
this.movementModel = movementModel;
if (this.movementModel != null) {
this.movementModel.addComponent(this);
}
this.placementModel = placementModel;
if (this.placementModel != null) {
this.placementModel.addComponent(this);
}
this.registerAsInformationProviderInSiS = registerAsInformationProviderInSiS;
super(host, topology, movementModel, placementModel, registerAsInformationProviderInSiS);
}
@Override
public void initialize() {
/*
* Set the component's initial position and notify listeners of the
* Topology that this component is initialized.
*/
topology.addComponent(this);
movementModel.placeComponent(this);
if (placementModel != null) {
/*
* Legacy support for placement models.
*/
position.set(placementModel.place(this));
}
if (registerAsInformationProviderInSiS) {
try {
final SiSComponent sis = host.getComponent(SiSComponent.class);
sis.provide().nodeState(SiSTypes.PHY_LOCATION,
new SiSDataCallback<Location>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Location getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
throws InformationNotAvailableException {
if (nodeID.equals(getHost().getId())) {
return getLastLocation();
} else {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties();
}
});
sis.provide().nodeState(SiSTypes.SPEED,
new SiSDataCallback<Double>() {
Set<INodeID> localID = INodeID
.getSingleIDSet(getHost().getId());
@Override
public Double getValue(INodeID nodeID,
SiSProviderHandle providerHandle)
throws InformationNotAvailableException {
if (nodeID.equals(getHost().getId())) {
return getMovementSpeed();
} else {
throw new InformationNotAvailableException();
}
}
@Override
public Set<INodeID> getObservedNodes() {
return localID;
}
@Override
public SiSInfoProperties getInfoProperties() {
return new SiSInfoProperties();
}
});
// Provide Underlay topology
Event.scheduleImmediately(new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
if (getHost().getLinkLayer().hasPhy(PhyType.WIFI)) {
new SiSTopologyProvider(sis,
SiSTypes.NEIGHBORS_WIFI,
DefaultTopologyComponent.this,
getTopologyID(NetInterfaceName.WIFI, true),
DefaultTopologyComponent.class);
}
}
}, null, 0);
} catch (ComponentNotAvailableException e) {
// OK
}
}
}
@Override
public void shutdown() {
topology = null;
host = null;
movementModel = null;
}
@Override
public SimHost getHost() {
return host;
}
@Override
public PositionVector getRealPosition() {
return position;
}
@Override
public Topology getTopology() {
return topology;
}
/**
* Access to the movement model
* @return
*/
public MovementModel getMovementModel() {
return movementModel;
super.initialize();
}
@Override
......@@ -279,36 +130,7 @@ public class DefaultTopologyComponent implements TopologyComponent {
this.currentMovementSpeed = speed;
}
@Override
public Location getLastLocation() {
/*
* As we want to mimic real world behavior, the current position
* snapshot is cloned to prevent information propagation due to Java.
*/
return position.clone();
}
@Override
public void updateCurrentLocation(Location location) {
position.set(location);
/*
* FIXME utilization of the NodeDebugMonitor leads to huge performance drop.
*/
// NodeDebugMonitor.update(this.getClass(), getHost().getId(), "Current Location", location);
// try {
// NodeDebugMonitor.update(this.getClass(), getHost().getId(),
// "Distance to target",
// location.distanceTo(movementModel.getTargetLocation(this)));
// } catch (UnsupportedOperationException e) {
// // This is not supported by the movement model (which may happen see
// // MovementModel.java - thus catch and ignore)
// }
// notify "non-request" listeners
for (LocationListener locationListener : listeners) {
locationListener.onLocationChanged(getHost(), getLastLocation());
}
}
@Override
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
......@@ -324,407 +146,6 @@ public class DefaultTopologyComponent implements TopologyComponent {
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return movementModel.getAllAttractionPoints();
}
@Override
public void requestLocationUpdates(LocationRequest request,
LocationListener listener) {
if (openRequests.containsKey(listener)) {
throw new AssertionError(
"This LocationListener is already in use.");
}
if (request == null) {
/*
* This listener wants to be triggered on EVERY position update, but
* it does not want to request position updates.
*/
if (!listeners.contains(listener)) {
listeners.add(listener);
}
} else {
/*
* Listener has its own request timing.
*/
LocationRequestImpl req = (LocationRequestImpl) request;
openRequests.put(listener, req);
req.immunizeAndStart(listener);
}
}
@Override
public void removeLocationUpdates(LocationListener listener) {
listeners.remove(listener);
LocationRequestImpl impl = openRequests.remove(listener);
if (impl != null) {
impl.cancel(listener);
}
}
@Override
public LocationRequest getLocationRequest() {
return new LocationRequestImpl();
}
/**
* Update 15.03.16 added support for multiple listeners (however, frequency
* etc. is immune after the first request is registered.)
*
* @author Bjoern Richerzhagen
* @version 1.0, Mar 15, 2016
*/
private class LocationRequestImpl implements LocationRequest, EventHandler {
private boolean immune = false;
private long interval = 1 * Simulator.MINUTE_UNIT;
private int priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0;
public LocationRequestImpl() {
// nothing to do
}
protected void cancel(LocationListener listener) {
boolean removed = listeners.remove(listener);
if (listeners.isEmpty()) {
// upcoming event is no longer valid!
eventTypeSeq++;
}
assert removed;
}
protected void immunizeAndStart(LocationListener listener) {
immune = true;
assert interval > 0;
if (listeners.isEmpty()) {
// Only start once!
lastLocation = null;
Event.scheduleImmediately(this, null, eventTypeSeq);
} else {
// Fire each new listener at least once
listener.onLocationChanged(getHost(), getLastLocation());
}
listeners.add(listener);
}
@Override
public void setInterval(long interval) {
if (!immune) {
this.interval = interval;
}
}
@Override
public void setPriority(int priority) {
if (!immune) {
this.priority = priority;
}
}
@Override
public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) {
/*
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* themselves.
*/
return;
}
if (!listeners.isEmpty()) {
// Only reschedule, if at least one listener is ... listening
Location newLoc = getLastLocation();
listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(getHost(), newLoc));
lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
}
}
}
/*
* Methods for the Graph Interface
*/
/**
* Graph views: static, as we use global knowledge and maintain one shared
* graph (potentially with partitions!)
*/
private final static LinkedHashMap<TopologyID, LocalGraphView> graphViews = new LinkedHashMap<>();
@Override
public TopologyID getTopologyID(NetInterfaceName netName,
boolean onlyOnline) {
TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all"),
DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id, new LocalGraphView(netName, onlyOnline));
}
return id;
}
@Override
public TopologyID getTopologyID(NetInterfaceName netName,
boolean onlyOnline, double range) {
TopologyID id = TopologyID.getIdentifier(
netName.toString() + (onlyOnline ? "-online" : "-all")
+ String.valueOf(range),
DefaultTopologyComponent.class);
if (!this.graphViews.containsKey(id)) {
this.graphViews.put(id,
new LocalGraphView(netName, onlyOnline, range));
}
return id;
}
@Override
public INode getNode(TopologyID identifier) {
assert graphViews.containsKey(identifier);
return graphViews.get(identifier).getOwnNode(host);
}
@Override
public Set<IEdge> getNeighbors(TopologyID topologyIdentifier) {
assert graphViews.containsKey(topologyIdentifier);
return graphViews.get(topologyIdentifier).getNeighbors(host);
}
@Override
public Graph getLocalView(TopologyID topologyIdentifier) {
assert graphViews.containsKey(topologyIdentifier);
return graphViews.get(topologyIdentifier).getLocalView();
}
@Override
public Iterable<TopologyID> getTopologyIdentifiers() {
return graphViews.keySet();
}
/**
* This is calculated based on global knowledge. It only registers as
* {@link LocationListener}, if a range is specified by the Provider.
*
* @author Bjoern Richerzhagen
* @version 1.0, May 13, 2015
*/
private class LocalGraphView
implements LocationListener, ConnectivityListener {
/**
* Marker: has there been any movement since the graph view was last
* requested? If so: recalculate! Otherwise, we ignore this object to
* not perform calculations if no one is interested...
*/
private final double distance;
private final boolean isDistanceBased;
private final NetInterfaceName medium;
private final TopologyView topoView;
private final boolean onlyOnline;
private Graph currentView;
private boolean isInvalid = true;
private final PhyType phy;
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline) {
this(medium, onlyOnline, -1);
}
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline,
double distance) {
this.medium = medium;
PhyType localPhy = null;
for (PhyType currPhy : PhyType.values()) {
if (currPhy.getNetInterfaceName() == medium
&& getTopology().getTopologyView(currPhy) != null) {
localPhy = currPhy;
break;
}
}
phy = localPhy;
assert localPhy != null;
this.topoView = getTopology().getTopologyView(localPhy);
this.distance = distance;
this.onlyOnline = onlyOnline;
this.isDistanceBased = (distance > 0);
assert !isDistanceBased || phy.isBroadcastMedium();
if (phy.isBroadcastMedium() || onlyOnline) {
for (Host host : Oracle.getAllHosts()) {
if (phy.isBroadcastMedium()) {
try {
DefaultTopologyComponent dcomp = host.getComponent(
DefaultTopologyComponent.class);
dcomp.requestLocationUpdates(null,
LocalGraphView.this);
} catch (ComponentNotAvailableException e) {
continue;
}
}
if (onlyOnline) {
if (host.getNetworkComponent()
.getByName(medium) != null) {
host.getNetworkComponent().getByName(medium)
.addConnectivityListener(
LocalGraphView.this);
}
}
}
}
}
private void recalculateLocalView() {
if (!isInvalid) {
/*
* Graphs are invalidated (i) based on movement, IFF a range was
* specified, (ii) based on online/offline events, IFF only
* online hosts are to be considered.
*/
return;
}
/*
* Calculate a complete global connectivity graph
*/
// Create new, empty graph
currentView = Graphs.createGraph();
// Add all (online?) nodes
for (MacLayer mac : topoView.getAllMacs()) {
if (!onlyOnline || mac.isOnline()) {
INode node = currentView.createNode(mac.getHost().getId());
node.setProperty(SiSTypes.PHY_LOCATION,
topoView.getPosition(mac.getMacAddress()).clone());
currentView.addElement(node);
}
}
if (isDistanceBased) {
// Build neighbors solely based on an assumed range
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Consider all nodes as potential neighbors
for (MacLayer neighborMac : topoView.getAllMacs()) {
// create, but do NOT add the node object
INode neighbor = currentView
.createNode(neighborMac.getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
// Distance?
if (topoView.getDistance(mac.getMacAddress(),
neighborMac.getMacAddress()) <= distance) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
neighborMac.getHost().getId());
currentView.addElement(edge);
}
}
}
}
} else {
// Build neighborhoods based on underlay neighbors (1-hop)
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Rely on underlay for neighbors
List<MacAddress> neighbors = topoView
.getNeighbors(mac.getMacAddress());
for (MacAddress neighborMac : neighbors) {
// create, but do NOT add the node object
INode neighbor = currentView.createNode(
topoView.getMac(neighborMac).getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
topoView.getMac(neighborMac).getHost()
.getId());
currentView.addElement(edge);
edge.setProperty(SiSTypes.PHY_DISTANCE,
topoView.getDistance(mac.getMacAddress(),
neighborMac));
}
}
}
}
isInvalid = false;
}
public INode getOwnNode(SimHost ownHost) {
MacLayer mac = ownHost.getLinkLayer().getMac(phy);
if (!onlyOnline || mac.isOnline()) {
return currentView.createNode(ownHost.getId());
}
return null;
}
public Set<IEdge> getNeighbors(SimHost ownHost) {
recalculateLocalView();
INode ownNode = getOwnNode(ownHost);
return currentView.getOutgoingEdges(ownNode.getId());
}
/**
* This is the global view, therefore we do not distinguish between
* hosts.
*
* @return
*/
public Graph getLocalView() {
recalculateLocalView();
return currentView.clone();
}
@Override
public void onLocationChanged(Host host, Location location) {
this.isInvalid = true;
}
@Override
public void wentOnline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
@Override
public void wentOffline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
}
@Override
public String toString() {
return "TopoComp: " + getHost().getId() + " at " + position.toString();
}
}
}
/*
* 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;
import java.util.List;
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.linklayer.mac.MacAddress;
import de.tud.kom.p2psim.api.linklayer.mac.MacLayer;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
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.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSTypes;
import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener;
/**
* This is calculated based on global knowledge. It only registers as
* {@link LocationListener}, if a range is specified by the Provider.
*
* @author Bjoern Richerzhagen
* @version 1.0, May 13, 2015
*/
public class LocalGraphView implements LocationListener, ConnectivityListener {
/**
* Marker: has there been any movement since the graph view was last
* requested? If so: recalculate! Otherwise, we ignore this object to
* not perform calculations if no one is interested...
*/
private final double distance;
private final boolean isDistanceBased;
private final NetInterfaceName medium;
private final TopologyView topoView;
private final boolean onlyOnline;
private Graph currentView;
private boolean isInvalid = true;
private final PhyType phy;
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline, Topology topology) {
this(medium, onlyOnline, -1, topology);
}
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline,
double distance, Topology topology) {
this.medium = medium;
PhyType localPhy = null;
for (PhyType currPhy : PhyType.values()) {
if (currPhy.getNetInterfaceName() == medium
&& topology.getTopologyView(currPhy) != null) {
localPhy = currPhy;
break;
}
}
phy = localPhy;
assert localPhy != null;
this.topoView = topology.getTopologyView(localPhy);
this.distance = distance;
this.onlyOnline = onlyOnline;
this.isDistanceBased = (distance > 0);
assert !isDistanceBased || phy.isBroadcastMedium();
if (phy.isBroadcastMedium() || onlyOnline) {
for (Host host : Oracle.getAllHosts()) {
if (phy.isBroadcastMedium()) {
try {
DefaultTopologyComponent dcomp = host.getComponent(
DefaultTopologyComponent.class);
dcomp.requestLocationUpdates(null,
LocalGraphView.this);
} catch (ComponentNotAvailableException e) {
continue;
}
}
if (onlyOnline) {
if (host.getNetworkComponent()
.getByName(medium) != null) {
host.getNetworkComponent().getByName(medium)
.addConnectivityListener(
LocalGraphView.this);
}
}
}
}
}
private void recalculateLocalView() {
if (!isInvalid) {
/*
* Graphs are invalidated (i) based on movement, IFF a range was
* specified, (ii) based on online/offline events, IFF only
* online hosts are to be considered.
*/
return;
}
/*
* Calculate a complete global connectivity graph
*/
// Create new, empty graph
currentView = Graphs.createGraph();
// Add all (online?) nodes
for (MacLayer mac : topoView.getAllMacs()) {
if (!onlyOnline || mac.isOnline()) {
INode node = currentView.createNode(mac.getHost().getId());
node.setProperty(SiSTypes.PHY_LOCATION,
topoView.getPosition(mac.getMacAddress()).clone());
currentView.addElement(node);
}
}
if (isDistanceBased) {
// Build neighbors solely based on an assumed range
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Consider all nodes as potential neighbors
for (MacLayer neighborMac : topoView.getAllMacs()) {
// create, but do NOT add the node object
INode neighbor = currentView
.createNode(neighborMac.getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
// Distance?
if (topoView.getDistance(mac.getMacAddress(),
neighborMac.getMacAddress()) <= distance) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
neighborMac.getHost().getId());
currentView.addElement(edge);
}
}
}
}
} else {
// Build neighborhoods based on underlay neighbors (1-hop)
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Rely on underlay for neighbors
List<MacAddress> neighbors = topoView
.getNeighbors(mac.getMacAddress());
for (MacAddress neighborMac : neighbors) {
// create, but do NOT add the node object
INode neighbor = currentView.createNode(
topoView.getMac(neighborMac).getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
topoView.getMac(neighborMac).getHost()
.getId());
currentView.addElement(edge);
edge.setProperty(SiSTypes.PHY_DISTANCE,
topoView.getDistance(mac.getMacAddress(),
neighborMac));
}
}
}
}
isInvalid = false;
}
public INode getOwnNode(SimHost ownHost) {
MacLayer mac = ownHost.getLinkLayer().getMac(phy);
if (!onlyOnline || mac.isOnline()) {
return currentView.createNode(ownHost.getId());
}
return null;
}
public Set<IEdge> getNeighbors(SimHost ownHost) {
recalculateLocalView();
INode ownNode = getOwnNode(ownHost);
return currentView.getOutgoingEdges(ownNode.getId());
}
/**
* This is the global view, therefore we do not distinguish between
* hosts.
*
* @return
*/
public Graph getLocalView() {
recalculateLocalView();
return currentView.clone();
}
@Override
public void onLocationChanged(Host host, Location location) {
this.isInvalid = true;
}
@Override
public void wentOnline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
@Override
public void wentOffline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
}
/*
* 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;
import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
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;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationSensor;
/**
* Update 15.03.16 added support for multiple listeners (however, frequency
* etc. is immune after the first request is registered.)
*
* @author Bjoern Richerzhagen
* @version 1.0, Mar 15, 2016
*/
public class LocationRequestImpl implements LocationRequest, EventHandler {
private boolean immune = false;
private long interval = 1 * Simulator.MINUTE_UNIT;
private int priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0;
private SimHost host;
private LocationSensor locationSensor;
public LocationRequestImpl(SimHost host, LocationSensor locationSensor) {
this.host = host;
this.locationSensor = locationSensor;
}
protected void cancel(LocationListener listener) {
boolean removed = listeners.remove(listener);
if (listeners.isEmpty()) {
// upcoming event is no longer valid!
eventTypeSeq++;
}
assert removed;
}
protected void immunizeAndStart(LocationListener listener) {
immune = true;
assert interval > 0;
if (listeners.isEmpty()) {
// Only start once!
lastLocation = null;
Event.scheduleImmediately(this, null, eventTypeSeq);
} else {
// Fire each new listener at least once
listener.onLocationChanged(host, locationSensor.getLastLocation());
}
listeners.add(listener);
}
@Override
public void setInterval(long interval) {
if (!immune) {
this.interval = interval;
}
}
@Override
public void setPriority(int priority) {
if (!immune) {
this.priority = priority;
}
}
@Override
public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) {
/*
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* themselves.
*/
return;
}
if (!listeners.isEmpty()) {
// Only reschedule, if at least one listener is ... listening
Location newLoc = locationSensor.getLastLocation();
listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(host, newLoc));
lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
}
}
}
......@@ -231,7 +231,7 @@ public class TopologyFactory implements HostComponentFactory {
}
/**
* Option to disable the default behavior of nodes registering as
* Option to enable the behavior of nodes registering as
* topology providers.
*
* @param registerAsLocationProviderInSiS
......
/*
* 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;
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
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.UAVLocationActuator;
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.movement.aerial.MutlicopterMovement;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
public class UAVTopologyComponent extends AbstractTopologyComponent implements UAVLocationActuator {
UAVMovementModel movement;
/**
* Create a TopologyComponent for the current host.
*
* @param host
* @param topology
* @param movementModel
*/
public UAVTopologyComponent(SimHost host, Topology topology,
MovementModel movementModel, PlacementModel placementModel, boolean registerAsInformationProviderInSiS) {
super(host, topology, movementModel, placementModel, registerAsInformationProviderInSiS);
}
@Override
public double getMinMovementSpeed() {
// TODO Auto-generated method stub
return 0;
}
@Override
public double getMaxMovementSpeed() {
// TODO Auto-generated method stub
return 0;
}
@Override
public double getMovementSpeed() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setMovementSpeed(double speed) {
// TODO Auto-generated method stub
}
@Override
public void setTargetAttractionPoint(AttractionPoint targetAttractionPoint)
throws UnsupportedOperationException {
// TODO Auto-generated method stub
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
// TODO Auto-generated method stub
return null;
}
@Override
public AttractionPoint getCurrentTargetAttractionPoint() {
// TODO Auto-generated method stub
return null;
}
@Override
public UAVMovementModel getUAVMovement() {
return movement;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.aerial;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel;
import de.tud.kom.p2psim.impl.topology.UAVTopologyComponent;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
public class MutlicopterMovement implements UAVMovementModel {
UAVTopologyComponent topologyComponent;
private final double maxCruiseSpeed;
private final double minCruiseSpeed;
private double preferredCruiseSpeed;
private double currentSpeed;
private List<Location> waypoints = new LinkedList<>();
private Map<Location, ?> locationCallbacks = new HashMap<>(); // TODO callback interface
public MutlicopterMovement(double maxCruiseSpeed, double minCruiseSpeed) {
this.maxCruiseSpeed = maxCruiseSpeed;
this.minCruiseSpeed = minCruiseSpeed;
}
@Override
public void setPreferredCruiseSpeed(double v_pref) {
this.preferredCruiseSpeed = v_pref;
}
@Override
public double getMaxCruiseSpeed() {
return maxCruiseSpeed;
}
@Override
public double getMinCruiseSpeed() {
return minCruiseSpeed;
}
@Override
public double getCurrentSpeed() {
return currentSpeed;
}
@Override
public void move(long timeBetweenMovementOperations) {
// TODO Auto-generated method stub
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.movement.aerial;
import java.util.LinkedList;
import java.util.List;
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.UAVLocationActuator;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
public class UAVMovement implements MovementModel, EventHandler {
private List<UAVLocationActuator> actuators = new LinkedList<>();
protected long timeBetweenMoveOperation = Time.SECOND;
@Override
public void addComponent(SimLocationActuator actuator) {
if(!actuators.contains(actuator) && actuator instanceof UAVLocationActuator)
actuators.add((UAVLocationActuator) actuator);
}
@Override
public void placeComponent(SimLocationActuator actuator) {
throw new UnsupportedOperationException();
}
@Override
public void setTimeBetweenMoveOperations(long time) {
this.timeBetweenMoveOperation = time;
}
@Override
public void eventOccurred(Object content, int type) {
this.triggerComponentMovement();
}
private void triggerComponentMovement() {
for (UAVLocationActuator actuator : actuators) {
actuator.getUAVMovement().move(timeBetweenMoveOperation);
}
}
}
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