diff --git a/src/de/tud/kom/p2psim/api/energy/Battery.java b/src/de/tud/kom/p2psim/api/energy/Battery.java index f7ba7150902eb9f840348e157f0293f980f5d469..69573cce0e5da24631b9884a9c117227b62c5f26 100644 --- a/src/de/tud/kom/p2psim/api/energy/Battery.java +++ b/src/de/tud/kom/p2psim/api/energy/Battery.java @@ -31,6 +31,8 @@ package de.tud.kom.p2psim.api.energy; */ public interface Battery extends Cloneable { + public static double uJconverison = 1000000; + /** * Returns the maximum energy level in uJ. * diff --git a/src/de/tud/kom/p2psim/api/topology/component/ControllableLocationActuator.java b/src/de/tud/kom/p2psim/api/topology/component/ControllableLocationActuator.java index c7ab01d4f1234da04ffb0793ecfde333dcea991f..17c133758614b67e60ca2e92b2c588e3b357ccaa 100644 --- a/src/de/tud/kom/p2psim/api/topology/component/ControllableLocationActuator.java +++ b/src/de/tud/kom/p2psim/api/topology/component/ControllableLocationActuator.java @@ -48,9 +48,19 @@ public interface ControllableLocationActuator extends Actuator { public boolean deactivate(); public PositionVector getCurrentLocation(); + + public PositionVector getCurrentDirection(); + + public PositionVector getBaseLocation(); + + public void updateCurrentDirection(PositionVector direction); public double getCurrentBatteryLevel(); - + + public double getCurrentBatteryEnergy(); + + public double getMaximumBatteryCapacity(); + public LinkedList getTargetLocations(); public void setTargetLocation(PositionVector targetLocation, ReachedLocationCallback cb); @@ -76,4 +86,6 @@ public interface ControllableLocationActuator extends Actuator { public double getMaxMovementSpeed(); public double getMovementSpeed(); + + public double estimatePowerConsumption(double velocity); } diff --git a/src/de/tud/kom/p2psim/api/topology/movement/SimUAVLocationActuator.java b/src/de/tud/kom/p2psim/api/topology/movement/SimUAVLocationActuator.java index a96c95193043b87da859361b0328c5710fcf04ec..9d77e7f5e76d606ebba504fba05932e16aee4dcd 100644 --- a/src/de/tud/kom/p2psim/api/topology/movement/SimUAVLocationActuator.java +++ b/src/de/tud/kom/p2psim/api/topology/movement/SimUAVLocationActuator.java @@ -21,12 +21,13 @@ package de.tud.kom.p2psim.api.topology.movement; import de.tud.kom.p2psim.api.topology.component.ControllableLocationActuator; -import de.tud.kom.p2psim.impl.energy.components.ActuatorEnergyComponent; +import de.tud.kom.p2psim.impl.energy.components.StateActuatorEnergyComponent; +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; public interface SimUAVLocationActuator extends SimLocationActuator, ControllableLocationActuator { public UAVMovementModel getUAVMovement(); public void setUAVMovement(UAVMovementModel uavMovement); - public ActuatorEnergyComponent getActuatorEnergyComponent(); + } diff --git a/src/de/tud/kom/p2psim/api/topology/movement/UAVMovementModel.java b/src/de/tud/kom/p2psim/api/topology/movement/UAVMovementModel.java index 35e1968855fb8f6dffb48951d15a3975958a9692..77d710db29fd14b5d4d24a779e9c0a5ae7e4f1db 100644 --- a/src/de/tud/kom/p2psim/api/topology/movement/UAVMovementModel.java +++ b/src/de/tud/kom/p2psim/api/topology/movement/UAVMovementModel.java @@ -21,16 +21,23 @@ package de.tud.kom.p2psim.api.topology.movement; import java.util.LinkedList; + +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback; public interface UAVMovementModel { - public void setPreferredCruiseSpeed(double v_pref); + public void setMotorControl(StatelessMotorComponent motor); + + public void setPreferredSpeed(double v_pref); - public double getMaxCruiseSpeed(); - public double getMinCruiseSpeed(); + public double verticalAscentMaxVelocity(); + public double horizontalMaxVelocity(); public double getCurrentSpeed(); + public double minimumVelocity(); + + public double estimatePowerConsumption(double velocity); public void move(long timeBetweenMovementOperations); diff --git a/src/de/tud/kom/p2psim/impl/churn/MaxPeerCountChurnGenerator.java b/src/de/tud/kom/p2psim/impl/churn/MaxPeerCountChurnGenerator.java index ee8c4fe92bf4f92276194611ea1abefb7cece3d9..4a9125d9544778e1c4f5fa051d8f2028eebabfc2 100644 --- a/src/de/tud/kom/p2psim/impl/churn/MaxPeerCountChurnGenerator.java +++ b/src/de/tud/kom/p2psim/impl/churn/MaxPeerCountChurnGenerator.java @@ -114,8 +114,17 @@ public class MaxPeerCountChurnGenerator @XMLConfigurableConstructor({ "file", "maxNumberOfNodes" }) public MaxPeerCountChurnGenerator(String file, int maxNumberOfNodes) { this.maxNumberOfNodes = maxNumberOfNodes; - parseTrace(file); + parseTrace(file); } + + @XMLConfigurableConstructor({ "churnStart", "maxNumberOfNodes", "burstLength" }) + public MaxPeerCountChurnGenerator(long churnStart, int maxNumberOfNodes, long burstLength) { + this.maxNumberOfNodes = maxNumberOfNodes; + churnInfos.add(new ChurnInfo(churnStart, burstLength, maxNumberOfNodes)); + this.setChurnStart(churnStart); + } + + /** * A class that implements the {@link LifecycleComponent}-interface and can diff --git a/src/de/tud/kom/p2psim/impl/energy/components/MotorCharacteristic.java b/src/de/tud/kom/p2psim/impl/energy/components/MotorCharacteristic.java new file mode 100644 index 0000000000000000000000000000000000000000..6f55cf35277a95e38e4f85f570d4eb18e58c2db4 --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/energy/components/MotorCharacteristic.java @@ -0,0 +1,48 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.energy.components; + +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; + +public class MotorCharacteristic { + + private final double thrust; + private final double current; + + @XMLConfigurableConstructor({ "thrust", "current" }) + public MotorCharacteristic(double thrust, double current) { + this.thrust = thrust; + this.current = current; + } + + public double getCurrent() { + return current; + } + + public double getThrust() { + return thrust; + } + + @Override + public String toString() { + return "["+ thrust + "N @ " + current + "A]"; + } +} diff --git a/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/StateActuatorEnergyComponent.java similarity index 95% rename from src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java rename to src/de/tud/kom/p2psim/impl/energy/components/StateActuatorEnergyComponent.java index e74f9a87754cea89a7b0bc9da99d2dd4785f393e..99318b1acfdf5e3f8eb5a7e0aa6358ac97bff910 100644 --- a/src/de/tud/kom/p2psim/impl/energy/components/ActuatorEnergyComponent.java +++ b/src/de/tud/kom/p2psim/impl/energy/components/StateActuatorEnergyComponent.java @@ -36,7 +36,7 @@ import de.tudarmstadt.maki.simonstrator.api.Time; * @author Julian Zobel * @version 1.0, 11.09.2018 */ -public class ActuatorEnergyComponent implements EnergyComponent { +public class StateActuatorEnergyComponent implements EnergyComponent { /** * States supported by this energy component @@ -53,7 +53,7 @@ public class ActuatorEnergyComponent implements EnergyComponent { private double actuatorLoad; - public ActuatorEnergyComponent(int numberOfActuators, double volt, double hoverAmp, double maxAmp) { + public StateActuatorEnergyComponent(int numberOfActuators, double volt, double hoverAmp, double maxAmp) { OFF = new DefaultEnergyState("OFF", 0); FLY = new DefaultEnergyState("FLY", numberOfActuators * (hoverAmp * volt) * 1000000); MAX = new DefaultEnergyState("MAX", numberOfActuators * (maxAmp * volt) * 1000000); diff --git a/src/de/tud/kom/p2psim/impl/energy/components/StatelessMotorComponent.java b/src/de/tud/kom/p2psim/impl/energy/components/StatelessMotorComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..e5db40fea938b1950c97a5b5fc7de029f4932d0a --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/energy/components/StatelessMotorComponent.java @@ -0,0 +1,303 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.energy.components; + + +import java.util.Comparator; +import java.util.LinkedList; +import de.tud.kom.p2psim.api.energy.ComponentType; +import de.tud.kom.p2psim.api.energy.EnergyComponent; +import de.tud.kom.p2psim.api.energy.EnergyEventListener; +import de.tud.kom.p2psim.api.energy.EnergyState; +import de.tud.kom.p2psim.impl.energy.DefaultEnergyState; +import de.tudarmstadt.maki.simonstrator.api.Time; + + +/** + * Component for devices that provide thrust, such as electrical motors for UAV propulsion. + * Is configured by {@link MotorCharacteristic}s with a given thrust (N) and a given current (A). + * Values in between given characteristics are calculated by linear interpolation. + * + * + * @author Julian Zobel + * @version 1.0, 05.03.2019 + */ +public class StatelessMotorComponent implements EnergyComponent { + + public enum componentState {OFF, ON} + + private componentState state; + + private EnergyEventListener energyModel; + + private long lastEnergyConsumationTime; + + private double volts; + private final double uJconversionFactor = 1000000; + private final int numberOfActuators; + + private double thrust; + private double amps; + private EnergyState energyState; + private LinkedList characteristics = new LinkedList<>(); + + + public StatelessMotorComponent(int numberOfActuators, double volt) { + this.volts = volt; + this.numberOfActuators = numberOfActuators; + this.state = componentState.OFF; + this.lastEnergyConsumationTime = Time.getCurrentTime(); + + thrust = 0; + amps = 0; + energyState = new DefaultEnergyState("OFF", 0); + } + + /** + * Get the maximum thrust provided by this component. + * @return + */ + public double getMaxThrust() { + return characteristics.getLast().getThrust() * numberOfActuators; + } + + /** + * Set the new energy state and calculate the energy consumption from the last state + */ + private void setEnergyState() { + + // set the new energy state + EnergyState newState; + + if(state == componentState.ON) { + newState = new DefaultEnergyState("Actuator", numberOfActuators * (amps * volts) * uJconversionFactor); + } + else { + newState = new DefaultEnergyState("OFF", 0); + } + + // calculate energy consumption for the previous state + long timeSpentInState = Time.getCurrentTime() - lastEnergyConsumationTime; + + double cons = calculateEnergyConsumation(energyState, timeSpentInState); + + energyModel.componentConsumedEnergy(this, cons); + + // set new state + energyState = newState; + lastEnergyConsumationTime = Time.getCurrentTime(); + } + + /** + * Request a given amount of thrust to be provided from this component. If the amount is less than the minimum + * or more than the maximum, the minimum or maximum thrust values, respectively, are enforced. + * + * @param targetThrust + * @return The amount of thrust this component now generates. + */ + public double requestThrust(double targetThrust) { + + if(targetThrust == 0 || targetThrust <= numberOfActuators * characteristics.getFirst().getThrust()) { + setLoad(characteristics.getFirst()); + } + else if(targetThrust >= numberOfActuators * characteristics.getLast().getThrust()) { + setLoad(characteristics.getLast()); + } + else { + calculateAndSetThrustRelatedAmpereDraw(targetThrust); + } + + return this.thrust; + } + + /** + * + * @param targetThrust + * @return The power consumption for the target thrust in uW (micro watt) + */ + public double estimatePowerConsumptionWatt(double targetThrust) { + if(targetThrust == 0 || targetThrust <= numberOfActuators * characteristics.getFirst().getThrust()) { + // not allowed + return Double.NaN; + } + else if(targetThrust > numberOfActuators * characteristics.getLast().getThrust()) { + // not allowed + return Double.NaN; + } + else { + double amps = approximateAmpereDraw(targetThrust); + + return numberOfActuators * amps * volts; + } + } + + + /** + * Given an amount of thrust between the minimum and maximum values, the required current + * to provide this amount of thrust is calculated by linear interpolation by the nearest lower + * and upper {@link MotorCharacteristic}s. + * + * @param targetThrust + * @return the approximated ampere draw + */ + private double approximateAmpereDraw(double targetThrust) { + + MotorCharacteristic lower = null, upper = null; + + // find the lower and upper bounding characteristics + for (MotorCharacteristic ch : characteristics) { + // + if(ch.getThrust() * numberOfActuators == targetThrust) { + return ch.getCurrent(); + } + else { + // list is sorted, lower bound is the biggest that is lower + if(ch.getThrust() * numberOfActuators < targetThrust) { + lower = ch; + } + // the first that is greater is used as upper bound + else if(ch.getThrust() * numberOfActuators > targetThrust) { + upper = ch; + break; + } + } + } + + if(upper == null || lower == null) { + throw new UnsupportedOperationException("Lower or upper bounds cannot be null"); + } + + if(upper.getThrust() * numberOfActuators < targetThrust || lower.getThrust() * numberOfActuators > targetThrust) { + throw new UnsupportedOperationException("Lower or upper bound do not match"); + } + + /* + * Calculate the approximated current with the upper and lower bounds: + * Amp_approx = Amp_lower + (T_target - T_lower)/(T_upper - T_lower) * (Amp_upper - Amp_lower) + */ + double delta = (targetThrust - (lower.getThrust() * numberOfActuators))/(numberOfActuators * (upper.getThrust() - lower.getThrust())); + return lower.getCurrent() + delta * (upper.getCurrent() - lower.getCurrent()); + } + + /** + * Approximates the ampere draw required forthe requested thrust + * + * Target thrust should be strictly within the possible thrust limits + * + */ + private void calculateAndSetThrustRelatedAmpereDraw(double targetThrust) { + double calculatedAmps = approximateAmpereDraw(targetThrust); + setLoad(targetThrust, calculatedAmps); + } + + private void setLoad(double thrust, double amps) { + this.thrust = thrust; + this.amps = amps; + setEnergyState(); + } + + private void setLoad(MotorCharacteristic ch) { + this.thrust = ch.getThrust(); + this.amps = ch.getCurrent(); + setEnergyState(); + } + + /** + * Add a {@link MotorCharacteristic} for this motor. + * + * @param c + */ + public void addChar(MotorCharacteristic c) { + + characteristics.add(c); + + // sort the characteristics starting from low to high thrust + characteristics.sort(new Comparator() { + @Override + public int compare(MotorCharacteristic o1, + MotorCharacteristic o2) { + return (int) (o1.getThrust() - o2.getThrust()); + } + }); + + } + + + @Override + public void eventOccurred(Object content, int type) { + // TODO Auto-generated method stub + + } + + @Override + public ComponentType getType() { + return ComponentType.ACTUATOR; + } + + @Override + public boolean turnOff() { + this.thrust = 0; + this.amps = 0; + this.state = componentState.OFF; + setEnergyState(); + + return true; + } + + @Override + public boolean turnOn() { + if (isAvailable()) { + if(this.state != componentState.ON) { + this.state = componentState.ON; + requestThrust(0); + } + return true; + } + return false; + } + + public boolean isAvailable() { + if (energyModel.componentCanBeActivated(this)) { + return true; + } + return false; + } + + @Override + public boolean isOn() { + if(this.state != componentState.OFF && isAvailable()) { + return true; + } + return false; + } + + @Override + public void setEnergyEventListener(EnergyEventListener listener) { + energyModel = listener; + } + + public EnergyState getCurrentState() { + return energyState; + } + + + +} diff --git a/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorConfiguration.java b/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..9ac9a9edc1c4b31abfe3d743dce25a3c695a2dd9 --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorConfiguration.java @@ -0,0 +1,80 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.energy.configs; + +import java.util.LinkedList; +import de.tud.kom.p2psim.api.common.SimHost; +import de.tud.kom.p2psim.api.energy.EnergyConfiguration; +import de.tud.kom.p2psim.impl.energy.components.MotorCharacteristic; +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; + + +/** + * + * + * @author Julian Zobel + * @version 1.0, 05.03.2019 + */ +public class ActuatorConfiguration implements EnergyConfiguration { + + private int numberOfActuators; + private double volt; + + private LinkedList characteristics = new LinkedList<>(); + + @Override + public StatelessMotorComponent getConfiguredEnergyComponent(SimHost host) { + StatelessMotorComponent comp = new StatelessMotorComponent(numberOfActuators, volt); + + for (MotorCharacteristic c : characteristics) { + comp.addChar(c); + } + + return comp; + } + + @Override + public String getHelp() { + return "Fix actuator energy consumption config"; + } + + @Override + public boolean isWellConfigured() { + if(numberOfActuators >= 1 && volt > 0 && characteristics.size() >= 2) { + return true; + } + + return false; + } + + public void setNumberOfActuators(int num) { + numberOfActuators = num; + } + + public void setVolt(double voltage) { + this.volt = voltage; + } + + public void setMotorCharacteristic(MotorCharacteristic c) { + characteristics.add(c); + } + +} diff --git a/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorEnergyConsumptionConfig.java b/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorEnergyConsumptionConfig.java index 354586b55989fb9506e6ceb5eb4ef5bdf2eecb06..553567768dac30989ff0f87dd98768c9a4f0be0c 100644 --- a/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorEnergyConsumptionConfig.java +++ b/src/de/tud/kom/p2psim/impl/energy/configs/ActuatorEnergyConsumptionConfig.java @@ -22,15 +22,15 @@ package de.tud.kom.p2psim.impl.energy.configs; import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.energy.EnergyConfiguration; -import de.tud.kom.p2psim.impl.energy.components.ActuatorEnergyComponent; +import de.tud.kom.p2psim.impl.energy.components.StateActuatorEnergyComponent; /** - * Energy Configuration for {@link ActuatorEnergyComponent}s. + * Energy Configuration for {@link StateActuatorEnergyComponent}s. * * @author Julian Zobel * @version 1.0, 11.09.2018 */ -public class ActuatorEnergyConsumptionConfig implements EnergyConfiguration { +public class ActuatorEnergyConsumptionConfig implements EnergyConfiguration { private int numberOfActuators; private double volt; @@ -38,8 +38,8 @@ public class ActuatorEnergyConsumptionConfig implements EnergyConfiguration. + * + */ + +package de.tud.kom.p2psim.impl.topology.component; + +import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.Analyzer; + +public interface UAVStatisticAnalyzer extends Analyzer { + + public void uavSwitchedStates(UAVTopologyComponent uav, UAVTopologyComponent.UAVstate newState); + + +} diff --git a/src/de/tud/kom/p2psim/impl/topology/component/UAVTopologyComponent.java b/src/de/tud/kom/p2psim/impl/topology/component/UAVTopologyComponent.java index 47f2536491fb6a73c360c73923b40c642e61ebb3..c636197354a4a92196c2a0cefee12d96b66d5840 100644 --- a/src/de/tud/kom/p2psim/impl/topology/component/UAVTopologyComponent.java +++ b/src/de/tud/kom/p2psim/impl/topology/component/UAVTopologyComponent.java @@ -22,9 +22,6 @@ package de.tud.kom.p2psim.impl.topology.component; import java.util.LinkedList; import java.util.Set; - -import org.apache.batik.bridge.AbstractSVGGradientElementBridge.Stop; - import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.energy.ComponentType; import de.tud.kom.p2psim.api.energy.EnergyModel; @@ -35,15 +32,15 @@ import de.tud.kom.p2psim.api.topology.movement.SimUAVLocationActuator; import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel; import de.tud.kom.p2psim.api.topology.placement.PlacementModel; import de.tud.kom.p2psim.impl.energy.RechargeableBattery; -import de.tud.kom.p2psim.impl.energy.components.ActuatorEnergyComponent; +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; import de.tud.kom.p2psim.impl.energy.models.AbstractEnergyModel; import de.tud.kom.p2psim.impl.topology.placement.UAVBasePlacement; import de.tud.kom.p2psim.impl.topology.util.PositionVector; +import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException; import de.tudarmstadt.maki.simonstrator.api.component.overlay.OverlayComponent; 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.uavsupport.callbacks.BaseConnectedCallback; import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.BaseDisconnectedCallback; import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.BatteryReplacementCallback; @@ -64,7 +61,9 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S private OverlayComponent uavOverlayComponent; - private ActuatorEnergyComponent actuator; + protected PositionVector direction; + + private StatelessMotorComponent actuator; private RechargeableBattery battery; private UAVstate state = UAVstate.OFFLINE; @@ -82,6 +81,7 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S public UAVTopologyComponent(SimHost host, Topology topology, MovementModel movementModel, PlacementModel placementModel, boolean registerAsInformationProviderInSiS) { super(host, topology, movementModel, placementModel, registerAsInformationProviderInSiS); + direction = new PositionVector(0,-1,0); } @Override @@ -90,7 +90,8 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S try { actuator = getHost().getComponent(EnergyModel.class) - .getComponent(ComponentType.ACTUATOR, ActuatorEnergyComponent.class); + .getComponent(ComponentType.ACTUATOR, StatelessMotorComponent.class); + movement.setMotorControl(actuator); } catch (ComponentNotAvailableException e) { System.err.println("No Acutator Energy Component was found!"); } @@ -108,6 +109,11 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S public void setState(UAVstate newState) { this.state = newState; + + // TODO analyzer + if(Monitor.hasAnalyzer(UAVStatisticAnalyzer.class)) { + Monitor.getOrNull(UAVStatisticAnalyzer.class).uavSwitchedStates(this, newState); + } } public void setUAVComponent(OverlayComponent uavOverlayComponent) { @@ -120,12 +126,12 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S @Override public double getMinMovementSpeed() { - return movement.getMinCruiseSpeed(); + return movement.minimumVelocity(); } @Override public double getMaxMovementSpeed() { - return movement.getMaxCruiseSpeed(); + return movement.horizontalMaxVelocity(); } @Override @@ -135,14 +141,14 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S @Override public void setMovementSpeed(double speed) { - movement.setPreferredCruiseSpeed(speed); + movement.setPreferredSpeed(speed); } @Override public boolean isActive() { - if(actuator.isOn()) + if(actuator.isOn()) { return true; - else { + } else { if(state == UAVstate.ACTION || state == UAVstate.RETURN) { this.deactivate(); } @@ -153,7 +159,7 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S @Override public boolean activate() { if(actuator.turnOn()) { - state = UAVstate.ACTION; + this.setState(UAVstate.ACTION); return true; } else { @@ -165,18 +171,15 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S public boolean deactivate() { actuator.turnOff(); - if(this.position.getAltitude() != 0) { - state = UAVstate.CRASHED; - System.err.println("UAV was destroyed due to actuator deactivation during flight"); - + if(this.position.getAltitude() != 0) { + this.setState(UAVstate.CRASHED); + uavOverlayComponent.shutdown(); shutdownCommunication(); - } - else { - state = UAVstate.OFFLINE; - } - - + + } else { + this.setState(UAVstate.OFFLINE); + } return true; } @@ -190,6 +193,11 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S public double getCurrentBatteryLevel() { return battery.getCurrentPercentage(); } + + @Override + public double getCurrentBatteryEnergy() { + return battery.getCurrentEnergyLevel(); + } public RechargeableBattery getBattery() { return battery; @@ -205,11 +213,6 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S this.movement = uavMovement; } - @Override - public ActuatorEnergyComponent getActuatorEnergyComponent() { - return actuator; - } - @Override public Set getAllAttractionPoints() { throw new UnsupportedOperationException(); @@ -262,8 +265,8 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S } @Override - public void returnToBase(ReachedLocationCallback cb) { - this.state = UAVstate.RETURN; + public void returnToBase(ReachedLocationCallback cb) { + this.setState(UAVstate.RETURN); ReachedLocationCallback returnCallback = new ReachedLocationCallback() { @@ -274,13 +277,15 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S } }; + movement.setPreferredSpeed(movement.horizontalMaxVelocity()); movement.setTargetLocation(baseLocation, returnCallback); } public void batteryReplacement(BatteryReplacementCallback cb) { - if(state != UAVstate.BASE_CONNECTION) + if(state != UAVstate.BASE_CONNECTION) { throw new UnsupportedOperationException("Cannot recharge if not connected to base!"); + } BaseTopologyComponent base = UAVBasePlacement.base; base.getCharger().charge(this, cb); @@ -298,8 +303,7 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S if(cb != null) cb.successfulConnection(); - this.state = UAVstate.BASE_CONNECTION; - + this.setState(UAVstate.BASE_CONNECTION); shutdownCommunication(); } @@ -313,7 +317,6 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S if(cb != null) cb.successfulDisconnection(); - this.state = UAVstate.OFFLINE; } private void shutdownCommunication() { @@ -326,4 +329,31 @@ public class UAVTopologyComponent extends AbstractTopologyComponent implements S net.goOnline(); } + @Override + public PositionVector getCurrentDirection() { + return direction; + } + + @Override + public void updateCurrentDirection(PositionVector direction) { + this.direction.set(direction); + } + + @Override + public double getMaximumBatteryCapacity() { + return battery.getMaximumEnergyLevel(); + } + + @Override + public double estimatePowerConsumption(double velocity) { + return movement.estimatePowerConsumption(velocity); + } + + @Override + public PositionVector getBaseLocation() { + return baseLocation.clone(); + } + + + } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/aerial/MulticopterMovement.java b/src/de/tud/kom/p2psim/impl/topology/movement/aerial/MulticopterMovement.java new file mode 100644 index 0000000000000000000000000000000000000000..be9f1d0d9f4ecb86280a4315f89feff63cbf5443 --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/topology/movement/aerial/MulticopterMovement.java @@ -0,0 +1,322 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.topology.movement.aerial; + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; + +import org.apache.commons.math3.geometry.Vector; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; + +import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel; +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; +import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent; +import de.tud.kom.p2psim.impl.topology.util.PositionVector; +import de.tudarmstadt.maki.simonstrator.api.Time; +import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback; + +public class MulticopterMovement implements UAVMovementModel { + + + private UAVTopologyComponent topologyComponent; + + private PositionVector direction; + private double currentAngleOfAttack; + private double currentSpeed; + + private double preferredSpeed; + + + private LinkedList route = new LinkedList<>(); + private Map locationCallbacks = new LinkedHashMap<>(); // TODO callback interface + + private StatelessMotorComponent motor; + + + private double mass = 1.465; // kg + private final double airdensity = 1.2255; // kg/m^3 + private final double gravity = 9.807; // m/s^2 + private double A_top = 0.245; // m^2 + private double A_front = 0.04; // m^2 + private double dragCoefficient = 0.5; + private double maxPitchAngle = Math.toRadians(45); // 45° max angle + private double descentVelocityMax = 5; // m/s + private double maxTurnAngle = Math.toRadians(90); // 90° per second turn angle + + + public MulticopterMovement(UAVTopologyComponent topologyComponent) { + this.topologyComponent = topologyComponent; + this.direction = new PositionVector(0,0); + + } + + + /* + * + */ + + public double verticalDescentMaxThrust() { + // m * g - 0.5 * p * C * A * v^2 + return hoverThrustRequired() - 0.5 * bodyDrag(0, new PositionVector(0,0,1)) * descentVelocityMax * descentVelocityMax; + } + + public double verticalAscentMaxAcceleration() { + return (motor.getMaxThrust() - hoverThrustRequired()) / mass; + } + + public double verticalAscentMaxVelocity() { + double maxThrust = motor.getMaxThrust(); + return Math.sqrt(2.0 * (maxThrust - hoverThrustRequired()) / bodyDrag(0, new PositionVector(0,0,1))); + } + + + public double hoverThrustRequired() { + return mass * gravity; + } + + + public double horizontalMaxVelocity() { + + double horizontalThrust = horizontalMaxThrust(); + + double maxVelocity = Math.sqrt( (2.0 * horizontalThrust) / bodyDrag(maxPitchAngle, new PositionVector(1,0,0))); + + return maxVelocity; + } + + public double horizontalMaxThrust() { + + // hoverthrust / cos => amount of thrust in horizonal direction with °angle + double stableAltitudeMaximumTotalThrust = hoverThrustRequired() / Math.cos(maxPitchAngle); + + // fraction of total thrust in horizonal (forward) direction with °angle + double maximumHorizontalThrustStableAltitude = stableAltitudeMaximumTotalThrust * Math.sin(maxPitchAngle); + + return maximumHorizontalThrustStableAltitude; + } + + public double bodyDrag(double angleRadians, PositionVector direction) { + return airdensity * dragCoefficient * areaExposedToDrag(angleRadians, direction); + } + + public double areaExposedToDrag(double angleRadians, PositionVector direction) { + + Vector2D v = new Vector2D(Math.abs(direction.getX()) + Math.abs(direction.getY()), Math.abs(direction.getZ())); + v = v.normalize(); + + double areaExposedFront = v.getX() * (Math.sin(angleRadians) * A_top + Math.cos(angleRadians) * A_front); + double areaExposedTop = v.getY() * (Math.cos(angleRadians) * A_top + Math.sin(angleRadians) * A_front); + + return areaExposedFront + areaExposedTop; + } + + /* + * F_drag [N] = 0.5 * p * C_drag * A * v^2 + */ + public double currentDrag() { + return 0.5 * bodyDrag(currentAngleOfAttack, direction) * currentSpeed * currentSpeed; + } + + + + /* + * + */ + + @Override + public void setMotorControl(StatelessMotorComponent motor) { + this.motor = motor; + } + + @Override + public void move(long timeBetweenMovementOperations) { + + if(motor.isOn() && !route.isEmpty()) { + PositionVector position = new PositionVector(topologyComponent.getRealPosition()); + + double thrust = 0; + direction = new PositionVector(0,0,1); + + double distz = 100 - position.getZ(); + + if(distz < 100) { + + double time = ((double) timeBetweenMovementOperations) / ((double) Time.SECOND); + + // ASCENSION TO SAFETY HEIGHT + thrust = motor.requestThrust(motor.getMaxThrust()); + + double acc = ((thrust - hoverThrustRequired()) / mass ) - currentDrag(); + double speed = 0; + + if(acc < 0.1) { + // normal flight + speed = verticalAscentMaxVelocity(); + } + else { + // acceleration + speed = currentSpeed + acc * time; + } + + + System.out.println("ACCELERATION : " + acc); + System.out.println("SPEED : " + speed); + + //double dist = 0.5 * acc * (timeBetweenMovementOperations / Time.SECOND) * (timeBetweenMovementOperations / Time.SECOND); + double dist = currentSpeed * time; + + //double safetydistance = speed + + //System.out.println(); + + position.add(new PositionVector(0,0,dist)); + + System.out.println("NEW POSITION : " + position); + + topologyComponent.updateCurrentLocation(position); + } + else { + thrust = motor.requestThrust(hoverThrustRequired()); + topologyComponent.updateCurrentLocation(position); + } + + + + +// PositionVector directionToTarget = new PositionVector(route.getFirst()); +// directionToTarget.subtract(position); +// +// double distanceToTargetPosition = directionToTarget.getLength(); + + +// // If target point is reached within a 1 meter margin, we remove that point from the list +// if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < currentSpeed) +// { +// route.removeFirst(); +// +// topologyComponent.updateCurrentLocation(position); +// currentSpeed = 0; +// +// locationReached(position); +// return; +// } +// +// double timefactor = timeBetweenMovementOperations / Time.SECOND; +// +// currentSpeed = Math.min(distanceToTargetPosition, preferredSpeed); +// +// direction.normalize(); +// direction.multiplyScalar(currentSpeed * timefactor); +// +// PositionVector newPosition = new PositionVector(position); +// newPosition.add(direction); +// +// topologyComponent.updateCurrentLocation(newPosition); + + } + + //System.out.println(Simulator.getFormattedTime(Simulator.getCurrentTime()) + " | " + topologyComponent); + } + + + @Override + public void setPreferredSpeed(double v_pref) { + this.preferredSpeed = v_pref; + } + + @Override + public double getCurrentSpeed() { + return currentSpeed; + } + + /** + * Trigger the callback function, if there is a valid callback + * + * @param position + */ + private void locationReached(PositionVector position) { + if(locationCallbacks.containsKey(position)) { + locationCallbacks.get(position).reachedLocation(); + } + } + + @Override + public void setTargetLocation(PositionVector target, + ReachedLocationCallback reachedLocationCallback) { + route.clear(); + route.add(target); + if(reachedLocationCallback != null) + locationCallbacks.put(target, reachedLocationCallback); + + } + + @Override + public void setTargetLocationRoute(LinkedList route, + ReachedLocationCallback reachedLocationCallback) { + this.route.clear(); + this.route.addAll(route); + if(reachedLocationCallback != null) + locationCallbacks.put(route.getLast(), reachedLocationCallback); + } + + @Override + public void addTargetLocation(PositionVector target, + ReachedLocationCallback reachedLocationCallback) { + route.add(target); + if(reachedLocationCallback != null) + locationCallbacks.put(target, reachedLocationCallback); + } + + @Override + public LinkedList getTargetLocations() { + + LinkedList copy = new LinkedList<>(); + for (PositionVector pv : route) { + copy.add(pv.clone()); + } + + return copy; + } + + @Override + public void removeTargetLocations() { + route.clear(); + locationCallbacks.clear(); + } + + + @Override + public double minimumVelocity() { + return 0; + } + + + @Override + public double estimatePowerConsumption(double velocity) { + // TODO Auto-generated method stub + return 0; + } + + + +} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMulticopterMovement.java b/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMulticopterMovement.java new file mode 100644 index 0000000000000000000000000000000000000000..b2135cb72ab1ebecf9fb2c89d28bca2bcedadacd --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMulticopterMovement.java @@ -0,0 +1,463 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.topology.movement.aerial; + + +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; + +import de.tud.kom.p2psim.api.energy.Battery; +import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel; +import de.tud.kom.p2psim.impl.energy.components.StatelessMotorComponent; +import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent; +import de.tud.kom.p2psim.impl.topology.util.PositionVector; +import de.tudarmstadt.maki.simonstrator.api.Time; +import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback; + +/** + * Local movement logic specifically designs the movement for multicopter UAVs. + * This simple movement logic uses straight forward movement with the maximum speed available. + * + * @author Julian Zobel + * @version 1.0, 11.09.2018 + */ +public class SimpleMulticopterMovement implements UAVMovementModel { + + private UAVTopologyComponent topologyComponent; + + private double currentAngleOfAttack; + private double currentSpeed; + + private double targetSpeed; + + private LinkedList route = new LinkedList<>(); + private Map locationCallbacks = new LinkedHashMap<>(); // TODO callback interface + + private StatelessMotorComponent motor; + + private double mass = 1.465; // kg + private final double airdensity = 1.2045; // kg/m^3 + private final double gravity = 9.807; // m/s^2 + private double A_top = 0.245; // m^2 + private double A_front = 0.1; // m^2 + private double dragCoefficient = 0.7; + private double maxPitchAngle = Math.toRadians(60); // 45° max angle + private double descentVelocityMax = 5; // m/s + private double maxTurnAngle = Math.toRadians(90); // 90° per second turn angle + + + public SimpleMulticopterMovement(UAVTopologyComponent topologyComponent) { + this.topologyComponent = topologyComponent; + + + } + + boolean first = true; + + @Override + public void move(long timeBetweenMovementOperations) { + + if(motor.isOn() && !route.isEmpty()) { + PositionVector position = new PositionVector(topologyComponent.getRealPosition()); + + PositionVector target = route.getFirst(); + + double distanceToTargetPosition = position.distanceTo(target); + + + // If target point is reached within a 1 meter margin, we remove that point from the list + if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < currentSpeed) + { + target = route.removeFirst(); + + if(route.isEmpty()) { + + // go to hover mode + topologyComponent.updateCurrentLocation(target.clone()); + + currentSpeed = 0; + motor.requestThrust(hoverThrustRequired()); + + PositionVector direction = topologyComponent.getCurrentDirection().clone(); + direction.setEntry(2, 0); + topologyComponent.updateCurrentDirection(direction); + + locationReached(topologyComponent.getCurrentLocation()); + return; + } + else { + + // get to speed + if(targetSpeed > 0 && targetSpeed < horizontalMaxVelocity()) { + motor.requestThrust(estimateRequiredThrust(targetSpeed)); + currentSpeed = targetSpeed; + } + else { + motor.requestThrust(horizontalMaxVelocityRequiredTotalThrust()); + currentSpeed = horizontalMaxVelocity(); + } + + long timeUntilReachedLocation = (long) (distanceToTargetPosition / currentSpeed) * Time.SECOND; + + target = route.getFirst(); + PositionVector directionToTarget = new PositionVector(target); + directionToTarget.subtract(position); + + double timefactor = timeUntilReachedLocation / Time.SECOND; + + directionToTarget.normalize(); + topologyComponent.updateCurrentDirection(directionToTarget.clone()); + directionToTarget.multiplyScalar(currentSpeed * timefactor); + + PositionVector newPosition = new PositionVector(position); + newPosition.add(directionToTarget); + + topologyComponent.updateCurrentLocation(newPosition); + + if(timeUntilReachedLocation < timeBetweenMovementOperations) { + this.move(timeBetweenMovementOperations - timeUntilReachedLocation); + } + + } + + } + else { + double timefactor = timeBetweenMovementOperations / Time.SECOND; + + // get to speed + if(targetSpeed > 0 && targetSpeed < horizontalMaxVelocity()) { + motor.requestThrust(estimateRequiredThrust(targetSpeed)); + currentSpeed = targetSpeed; + } + else { + motor.requestThrust(horizontalMaxVelocityRequiredTotalThrust()); + currentSpeed = horizontalMaxVelocity(); + } + + PositionVector directionToTarget = new PositionVector(target); + directionToTarget.subtract(position); + + directionToTarget.normalize(); + + if(directionToTarget.getX() != 0 || directionToTarget.getY() != 0) { + topologyComponent.updateCurrentDirection(directionToTarget.clone()); + } + + directionToTarget.multiplyScalar(currentSpeed * timefactor); + + PositionVector newPosition = new PositionVector(position); + newPosition.add(directionToTarget); + + topologyComponent.updateCurrentLocation(newPosition); + } + + } + else if(motor.isOn()) { + + if(currentSpeed != 0) { + throw new UnsupportedOperationException("no route but speed not 0?"); + } + + PositionVector position = new PositionVector(topologyComponent.getRealPosition()); + + if(position.getAltitude() == 0) { + motor.requestThrust(0); + } + else { + motor.requestThrust(hoverThrustRequired()); + } + } + } + + /* + * + */ + + public double verticalDescentMaxThrust() { + // m * g - 0.5 * p * C * A * v^2 + return hoverThrustRequired() - 0.5 * bodyDrag(0, new PositionVector(0,0,1)) * descentVelocityMax * descentVelocityMax; + } + + public double verticalAscentMaxAcceleration() { + return (motor.getMaxThrust() - hoverThrustRequired()) / mass; + } + + public double verticalAscentMaxVelocity() { + double maxThrust = motor.getMaxThrust(); + return Math.sqrt(2.0 * (maxThrust - hoverThrustRequired()) / bodyDrag(0, new PositionVector(0,0,1))); + } + + + public double hoverThrustRequired() { + return mass * gravity; + } + + + public double horizontalMaxVelocity() { + + double horizontalThrust = horizontalComponentMaxThrust(); + + double maxVelocity = Math.sqrt( (2.0 * horizontalThrust) / bodyDrag(maxPitchAngle, new PositionVector(1,0,0))); + + return maxVelocity; + } + + public double horizontalComponentMaxThrust() { + + // hoverthrust / cos => amount of thrust in horizonal direction with °angle + double stableAltitudeMaximumTotalThrust = horizontalMaxVelocityRequiredTotalThrust(); + + // fraction of total thrust in horizonal (forward) direction with °angle + double maximumHorizontalThrustStableAltitude = stableAltitudeMaximumTotalThrust * Math.sin(maxPitchAngle); + + return maximumHorizontalThrustStableAltitude; + } + + public double horizontalMaxVelocityRequiredTotalThrust() { + return hoverThrustRequired() / Math.cos(maxPitchAngle); + } + + public double bodyDrag(double angleRadians, PositionVector direction) { + return airdensity * dragCoefficient * areaExposedToDrag(angleRadians, direction); + } + + public double areaExposedToDrag(double angleRadians, PositionVector direction) { + + Vector2D v = new Vector2D(Math.abs(direction.getX()) + Math.abs(direction.getY()), Math.abs(direction.getZ())); + v = v.normalize(); + + double areaExposedFront = v.getX() * (Math.sin(angleRadians) * A_top + Math.cos(angleRadians) * A_front ); + double areaExposedTop = v.getY() * (Math.cos(angleRadians) * A_top + Math.sin(angleRadians) * A_front); + + return areaExposedFront + areaExposedTop; + } + + /* + * F_drag [N] = 0.5 * p * C_drag * A * v^2 + */ + public double currentDrag() { + return 0.5 * bodyDrag(currentAngleOfAttack, topologyComponent.getCurrentDirection()) * currentSpeed * currentSpeed; + } + + /** + * Calculate the drag induced on the UAV with a given velocity and an angle of attack (in radians) moving forward horizontally. + * + * @param velocity + * @param angleInRadians + * @return + */ + private double forwardDrag(double velocity, double angleInRadians) { + return 0.5 * bodyDrag(angleInRadians, new PositionVector(1,0,0)) * velocity * velocity; + } + + + /* + * + */ + + @Override + public void setMotorControl(StatelessMotorComponent motor) { + this.motor = motor; + } + + + + + @Override + public void setPreferredSpeed(double v_pref) { + this.targetSpeed = v_pref; + } + + @Override + public double getCurrentSpeed() { + return currentSpeed; + } + + /** + * Trigger the callback function, if there is a valid callback + * + * @param position + */ + private void locationReached(PositionVector position) { + if(locationCallbacks.containsKey(position)) { + locationCallbacks.get(position).reachedLocation(); + } + } + + @Override + public void setTargetLocation(PositionVector target, + ReachedLocationCallback reachedLocationCallback) { + route.clear(); + route.add(target); + if(reachedLocationCallback != null) + locationCallbacks.put(target, reachedLocationCallback); + + } + + @Override + public void setTargetLocationRoute(LinkedList route, + ReachedLocationCallback reachedLocationCallback) { + this.route.clear(); + this.route.addAll(route); + if(reachedLocationCallback != null) + locationCallbacks.put(route.getLast(), reachedLocationCallback); + } + + @Override + public void addTargetLocation(PositionVector target, + ReachedLocationCallback reachedLocationCallback) { + route.add(target); + if(reachedLocationCallback != null) + locationCallbacks.put(target, reachedLocationCallback); + } + + @Override + public LinkedList getTargetLocations() { + + LinkedList copy = new LinkedList<>(); + for (PositionVector pv : route) { + copy.add(pv.clone()); + } + + return copy; + } + + @Override + public void removeTargetLocations() { + route.clear(); + locationCallbacks.clear(); + } + + + @Override + public double minimumVelocity() { + return minimumHorizontalVelocity(); + } + + + public double minimumHorizontalVelocity() { + return Math.sqrt(2 * hoverThrustRequired() * Math.tan(Math.toRadians(0.25)) / bodyDrag(Math.toRadians(0.25), new PositionVector(1,0,0))); + } + + @Override + public double estimatePowerConsumption(double velocity) { + + if(velocity == 0) { + return motor.estimatePowerConsumptionWatt(hoverThrustRequired()); + } + else if(velocity > horizontalMaxVelocity()) { + return -1; + } + else if(velocity < minimumHorizontalVelocity()) { + return -1; + } + else { + double estimateAngle = estimatePitchAngleForVelocity(velocity); + double estimatedDrag = forwardDrag(velocity, estimateAngle); + + double requiredThrust = Math.sqrt(hoverThrustRequired() * hoverThrustRequired() + estimatedDrag * estimatedDrag); + double wattage = motor.estimatePowerConsumptionWatt(requiredThrust); + + return wattage; + } + + + } + + public double estimateRequiredThrust(double velocity) { + if(velocity == 0) { + return motor.estimatePowerConsumptionWatt(hoverThrustRequired()); + } + else if(velocity > horizontalMaxVelocity()) { + return -1; + } + else if(velocity < minimumHorizontalVelocity()) { + return -1; + } + else { + double estimateAngle = estimatePitchAngleForVelocity(velocity); + double estimatedDrag = forwardDrag(velocity, estimateAngle); + double requiredThrust = Math.sqrt(hoverThrustRequired() * hoverThrustRequired() + estimatedDrag * estimatedDrag); + return requiredThrust; + } + } + + /** + * Estimate the pitch angle (angle of attack) required to get the target velocity. + * Angle precision is 1/4 degree. + * + * @param velocity + * @return + */ + private double estimatePitchAngleForVelocity(double velocity) { + + int low = 0; + int high = Integer.MAX_VALUE; + + double vsquared = (velocity * velocity); + + for(int i = 0; i <= ((int) Math.toDegrees(maxPitchAngle)); i++) { + + double v2 = 2 * hoverThrustRequired() * Math.tan(Math.toRadians(i)) / bodyDrag(Math.toRadians(i), new PositionVector(1,0,0)); + + if(v2 > vsquared && i < high) { + high = i; + } + else if(v2 < vsquared && i >= low) { + low = i; + } + else if(v2 == vsquared ) { + return Math.toRadians(i); + } + + } + + if(high < Integer.MAX_VALUE) { + double lo = low; + double hi = high; + + double nearest = -1; + double nearestDiff = Double.MAX_VALUE; + + double step = (hi - lo) / 4; + + for(int i = 0; i < 4; i++) { + + double d = lo + i * step; + + double v2 = 2 * hoverThrustRequired() * Math.tan(Math.toRadians(d)) / bodyDrag(Math.toRadians(d), new PositionVector(1,0,0)); + + double diff = Math.abs(((velocity * velocity) - v2)); + + if(diff < nearestDiff || (lo == 0 && i == 1)) { + nearestDiff = diff; + nearest = d; + } + } + + return Math.toRadians(nearest); + } + + return maxPitchAngle; + } +} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMutlicopterMovement.java b/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMutlicopterMovement.java deleted file mode 100644 index 870a9f9c1bd49b597e760f376e0b437da99e1908..0000000000000000000000000000000000000000 --- a/src/de/tud/kom/p2psim/impl/topology/movement/aerial/SimpleMutlicopterMovement.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * 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 . - * - */ - -package de.tud.kom.p2psim.impl.topology.movement.aerial; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; - -import org.joda.time.tz.ZoneInfoProvider; - -import de.tud.kom.p2psim.api.topology.movement.UAVMovementModel; -import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent; -import de.tud.kom.p2psim.impl.topology.util.PositionVector; -import de.tudarmstadt.maki.simonstrator.api.Time; -import de.tudarmstadt.maki.simonstrator.api.uavsupport.callbacks.ReachedLocationCallback; - -/** - * Local movement logic specifically designs the movement for multicopter UAVs. - * This simple movement logic uses straight forward movement with the maximum speed available. - * - * @author Julian Zobel - * @version 1.0, 11.09.2018 - */ -public class SimpleMutlicopterMovement implements UAVMovementModel { - - private UAVTopologyComponent topologyComponent; - - private final double maxCruiseSpeed; - private final double minCruiseSpeed; - private double preferredCruiseSpeed; - private double currentSpeed; - - private LinkedList route = new LinkedList<>(); - private Map locationCallbacks = new LinkedHashMap<>(); // TODO callback interface - - - public SimpleMutlicopterMovement(UAVTopologyComponent topologyComponent, double maxCruiseSpeed, double minCruiseSpeed) { - this.topologyComponent = topologyComponent; - this.maxCruiseSpeed = maxCruiseSpeed; - this.minCruiseSpeed = minCruiseSpeed; - this.preferredCruiseSpeed = this.maxCruiseSpeed; - - } - - @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) { - - if(topologyComponent.isActive() && !route.isEmpty()) { - PositionVector currentPosition= topologyComponent.getRealPosition(); - - PositionVector targetPosition = route.getFirst(); - Double distanceToTargetPosition = targetPosition.distanceTo(currentPosition); - - // If target point is reached within a 1 meter margin, we remove that point from the list - if(distanceToTargetPosition < 0.1 || distanceToTargetPosition < currentSpeed) - { - route.removeFirst(); - topologyComponent.getActuatorEnergyComponent().useActuator(0.5); - topologyComponent.updateCurrentLocation(targetPosition); // triggers energy consumption for last distance - currentSpeed = 0; - topologyComponent.getActuatorEnergyComponent().useActuator(0); // now hover - locationReached(targetPosition); - return; - } - - double timefactor = timeBetweenMovementOperations / Time.SECOND; - - currentSpeed = Math.min(distanceToTargetPosition, preferredCruiseSpeed); - - PositionVector direction = new PositionVector(targetPosition); - direction.subtract(currentPosition); - direction.normalize(); - direction.multiplyScalar(currentSpeed * timefactor); - - PositionVector newPosition = new PositionVector(currentPosition); - newPosition.add(direction); - - topologyComponent.getActuatorEnergyComponent().useActuator(1); - topologyComponent.updateCurrentLocation(newPosition); - - } - - //System.out.println(Simulator.getFormattedTime(Simulator.getCurrentTime()) + " | " + topologyComponent); - } - - /** - * Trigger the callback function, if there is a valid callback - * - * @param position - */ - private void locationReached(PositionVector position) { - if(locationCallbacks.containsKey(position)) { - locationCallbacks.get(position).reachedLocation(); - } - } - - @Override - public void setTargetLocation(PositionVector target, - ReachedLocationCallback reachedLocationCallback) { - route.clear(); - route.add(target); - if(reachedLocationCallback != null) - locationCallbacks.put(target, reachedLocationCallback); - - } - - @Override - public void setTargetLocationRoute(LinkedList route, - ReachedLocationCallback reachedLocationCallback) { - this.route.clear(); - this.route.addAll(route); - if(reachedLocationCallback != null) - locationCallbacks.put(route.getLast(), reachedLocationCallback); - } - - @Override - public void addTargetLocation(PositionVector target, - ReachedLocationCallback reachedLocationCallback) { - route.add(target); - if(reachedLocationCallback != null) - locationCallbacks.put(target, reachedLocationCallback); - } - - @Override - public LinkedList getTargetLocations() { - - LinkedList copy = new LinkedList<>(); - for (PositionVector pv : route) { - copy.add(pv.clone()); - } - - return copy; - } - - @Override - public void removeTargetLocations() { - route.clear(); - locationCallbacks.clear(); - } - - - - -} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMovementModel.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMovementModel.java index 3cc4a7b37f9f7e6b6c97553ec87ef5d24c7b45ec..3ffe1e2ed47aa748bf1e4f16915f13a369307fb0 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMovementModel.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMovementModel.java @@ -158,10 +158,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac */ localMovementStrategy .setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND); - - List attractionPoints = attractionGenerator - .getAttractionPoints(); - transition.setAttractionPoints(attractionPoints); + transition.addAttractionAssignmentListener(this); // This adds the mobile hosts (smartphones/users) to the transition @@ -197,13 +194,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac public AttractionPoint getTargetLocation(SimLocationActuator actuator) { return transition.getAssignment(actuator); } - - @Override - public Set getAllAttractionPoints() - throws UnsupportedOperationException { - return transition.getAllAttractionPoints(); - } - + private void checkConfiguration() { if (localMovementStrategy == null) { throw new ConfigurationException( @@ -362,6 +353,6 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac * @return */ public List getAttractionPoints() { - return new Vector(transition.getAllAttractionPoints()); + return new Vector(IAttractionGenerator.attractionPoints); } } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMultiTypeMovementModel.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMultiTypeMovementModel.java index b06b91cef55e9600668354e3dabff0212ad70302..1d04ec10c63fbc9491f05a96701ae7577b545537 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMultiTypeMovementModel.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/ModularMultiTypeMovementModel.java @@ -78,8 +78,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel suppressListenerNotify = true; for(ITransitionStrategy strategy : supportedTransitions.values()) - { - strategy.setAttractionPoints(transition.getAllAttractionPoints()); + { strategy.addAttractionAssignmentListener(this); for (SimLocationActuator ms : moveableHosts) { strategy.addComponent(ms); diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/BasicAttractionPoint.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/BasicAttractionPoint.java index 1cf750269f74384b4764a36cb682b5c99483fb9e..99d62c5b00cdf8be83a7699eae8709af33289e50 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/BasicAttractionPoint.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/BasicAttractionPoint.java @@ -2,6 +2,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; /** * A basic attraction point, as simple as it can get. Really just a named location @@ -18,7 +19,11 @@ public class BasicAttractionPoint extends PositionVector implements AttractionPo this.name = name; } - + @XMLConfigurableConstructor({ "name", "x", "y" }) + public BasicAttractionPoint(String name, double x, double y) { + this(name, new PositionVector(x, y)); + } + @Override public String getName() { return name; diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigAttractionGenerator.java index caf53936827090d171ffcf039a34377ee8c99a15..ebba120796198f0f05fee6e39d582163fd833368 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigAttractionGenerator.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigAttractionGenerator.java @@ -19,10 +19,7 @@ */ package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction; - -import java.util.LinkedList; import java.util.List; - import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; /** @@ -33,15 +30,14 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction */ public class ConfigAttractionGenerator implements IAttractionGenerator { - private final List points = new LinkedList<>(); @Override public List getAttractionPoints() { - return points; + return attractionPoints; } public void setAttractionPoint(AttractionPoint point) { - this.points.add(point); + attractionPoints.add(point); } } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigDynamicAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigDynamicAttractionGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..ba1292edabe0162d24d4ed12900a7afa79ff0059 --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/ConfigDynamicAttractionGenerator.java @@ -0,0 +1,82 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction; + +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import de.tud.kom.p2psim.api.scenario.ConfigurationException; +import de.tud.kom.p2psim.api.topology.Topology; +import de.tud.kom.p2psim.impl.topology.util.PositionVector; +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.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; + +/** + * Implementation of the interface {@link AttractionGenerator}. + * + + * @author Julian Zobel + * @version 1.0, April 2019 + */ +public class ConfigDynamicAttractionGenerator implements IAttractionGenerator { + + private LinkedList allAPs = new LinkedList<>(); + + @Override + public List getAttractionPoints() { + return attractionPoints; + } + + + + public void setAttractionPoint(TemporalAttractionPoint ap) { + allAPs.add(ap); + + Event.scheduleWithDelay(ap.getPlacementTime(), new EventHandler() { + @Override + public void eventOccurred(Object content, int type) { + placeAP(ap); + } + }, null, 0); + } + + private void placeAP(TemporalAttractionPoint ap) { + attractionPoints.add(ap); + + + Event.scheduleWithDelay(ap.getRemovalTime(), new EventHandler() { + @Override + public void eventOccurred(Object content, int type) { + removeAP(ap); + } + }, null, 0); + } + + private void removeAP(TemporalAttractionPoint ap) { + attractionPoints.remove(ap); + } + + +} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/CsvAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/CsvAttractionGenerator.java index fa6b6ffeb2c84be53868ce0c95a7bfbf8064eba6..d223a3bc54820cf351fee79ddf24cdd04dac061b 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/CsvAttractionGenerator.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/CsvAttractionGenerator.java @@ -47,7 +47,7 @@ public class CsvAttractionGenerator implements IAttractionGenerator { private final String SEP = ";"; - private List attractionPoints; + private double radius = 0; /** * @@ -58,12 +58,17 @@ public class CsvAttractionGenerator implements IAttractionGenerator { this.worldDimensions = Binder.getComponentOrNull(Topology.class) .getWorldDimensions(); this.file = placementFile; + + readData(); } + public void setRadius(double radius) { + this.radius = radius; + } + @Override public List getAttractionPoints() { - if (attractionPoints == null) { - attractionPoints = new LinkedList<>(); + if (attractionPoints == null) { readData(); } return attractionPoints; @@ -93,8 +98,37 @@ public class CsvAttractionGenerator implements IAttractionGenerator { + y); continue; } - attractionPoints.add(new AttractionPointImpl("AP"+i, new PositionVector(x, - y))); + AttractionPoint ap = new AttractionPointImpl("AP"+i, new PositionVector(x, y)); + ap.setRadius(radius); + attractionPoints.add(ap); + + i++; + entrySuccessfullyRead = true; + } catch (NumberFormatException e) { + // Ignore leading comments + if (entrySuccessfullyRead) { + // System.err.println("CSV ParseError " + line); + } + } + } + else if(parts.length == 3) { + try { + Double x = Double.parseDouble(parts[0]); + Double y = Double.parseDouble(parts[1]); + Double r = Double.parseDouble(parts[2]); + + if (x > worldDimensions.getX() + || y > worldDimensions.getY() || x < 0 + || y < 0) { + System.err.println("Skipped entry " + x + ";" + + y); + continue; + } + + AttractionPoint ap = new AttractionPointImpl("AP"+i, new PositionVector(x, y)); + ap.setRadius(r); + attractionPoints.add(ap); + i++; entrySuccessfullyRead = true; } catch (NumberFormatException e) { @@ -104,6 +138,7 @@ public class CsvAttractionGenerator implements IAttractionGenerator { } } } + } else { throw new AssertionError("To many columns in CSV."); } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/EquidistantSquareAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/EquidistantSquareAttractionGenerator.java index 43aa3e883ed589831cd1a1f770c66433255f46dd..064813b6f2bf99515d47c47b15072a23be0c36cc 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/EquidistantSquareAttractionGenerator.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/EquidistantSquareAttractionGenerator.java @@ -25,6 +25,7 @@ import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; /** * Implementation of the interface {@link AttractionGenerator}. @@ -38,12 +39,15 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction public class EquidistantSquareAttractionGenerator implements IAttractionGenerator { private PositionVector worldDimension; + private double squareSize; - public EquidistantSquareAttractionGenerator() { + @XMLConfigurableConstructor({ "squareSize" }) + public EquidistantSquareAttractionGenerator(double squareSize) { this.worldDimension = Binder.getComponentOrNull(Topology.class) .getWorldDimensions(); + this.squareSize = squareSize; createAttractionPoints(); } @@ -56,23 +60,23 @@ public class EquidistantSquareAttractionGenerator implements IAttractionGenerato } private void createAttractionPoints() { + + double x = worldDimension.getX() / 2; + double y = worldDimension.getY() / 2; - double x = worldDimension.getX(); - double y = worldDimension.getY(); - - PositionVector p1 = new PositionVector(x/4, y/4); + PositionVector p1 = new PositionVector(x - squareSize, y - squareSize); AttractionPoint ap1 = new AttractionPointImpl("AP1", p1); attractionPoints.add(ap1); - PositionVector p2 = new PositionVector(x/4 + x/2, y/4); + PositionVector p2 = new PositionVector(x - squareSize, y + squareSize); AttractionPoint ap2 = new AttractionPointImpl("AP2", p2); attractionPoints.add(ap2); - PositionVector p3 = new PositionVector(x/4 + x/2, y/4 + y/2); + PositionVector p3 = new PositionVector(x + squareSize, y - squareSize); AttractionPoint ap3 = new AttractionPointImpl("AP3", p3); attractionPoints.add(ap3); - PositionVector p4 = new PositionVector(x/4, y/4 + y/2); + PositionVector p4 = new PositionVector(x + squareSize, y + squareSize); AttractionPoint ap4 = new AttractionPointImpl("AP4", p4); attractionPoints.add(ap4); } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomAttractionGenerator.java index a36bd93b262d83db8c0083edb9c524fdb3225516..cce04dfe7dd31f42a50375b5fce48e16eaf572ad 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomAttractionGenerator.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomAttractionGenerator.java @@ -103,13 +103,19 @@ public class RandomAttractionGenerator implements IAttractionGenerator { if(c < 20) { + // if not within the world dimensions, directly go back to calculation + if(posVec.getX() + radius > worldDimension.getX() || posVec.getY() + radius > worldDimension.getY() + || posVec.getX() - radius < 0 || posVec.getY() - radius < 0) { + i--; + c++; + continue create; + } + for (AttractionPoint ap : result) { // if this point is closer than the given minimum distance to another point, or the radii of the points would overlap, // or if the radius would exceed the simulation area // then discard this attraction point and create a new one - if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0 - || posVec.getX() + radius > worldDimension.getX() || posVec.getY() + radius > worldDimension.getY() - || posVec.getX() - radius < 0 || posVec.getY() - radius < 0) { + if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0 ) { i--; c++; continue create; @@ -118,7 +124,7 @@ public class RandomAttractionGenerator implements IAttractionGenerator { } else { - radius = 10; + radius = minimumRadius; } AttractionPoint aPoint = new AttractionPointImpl("AP-"+i, posVec); diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomDynamicAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomDynamicAttractionGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..8027526a7abb512ec9e4a587d773484a4a12687d --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/RandomDynamicAttractionGenerator.java @@ -0,0 +1,208 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction; + +import java.util.List; +import java.util.Random; +import de.tud.kom.p2psim.api.scenario.ConfigurationException; +import de.tud.kom.p2psim.api.topology.Topology; +import de.tud.kom.p2psim.impl.topology.util.PositionVector; +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.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; + +/** + * Implementation of the interface {@link AttractionGenerator}. + * + * Generates a random number (out of a given interval) of attraction points. The radius is chosen randomly from a given interval. + * Generated attraction points will most likely not overlay and be completely within the world dimensions. + * With a certain lifetime chosen from a given lifetime interval, attraction points are removed after time and the number of + * attraction points that will be in the area are recalculated. If necessary, attraction points are either removed + * or added. + * + * @author Julian Zobel + * @version 1.0, March 2019 + */ +public class RandomDynamicAttractionGenerator implements IAttractionGenerator { + + private Random rand; + + private PositionVector worldDimension; + + private int minNumberOfAttractionPoints; + private int maxNumberOfAttractionPoints; + + private long minDynamicIntervall; + private long maxDynamicIntervall; + + private double minimumDistance = 100; + + private double maximumRadius = 100; + private double minimumRadius = 10; + + @XMLConfigurableConstructor({"minNumberOfAttractionPoints", "maxNumberOfAttractionPoints", "minimumRadius", + "maximumRadius", "minDynamicIntervall", "maxDynamicIntervall", "minimumDistance" }) + public RandomDynamicAttractionGenerator(int minNumberOfAttractionPoints, int maxNumberOfAttractionPoints, + double minimumRadius, double maximumRadius, long minDynamicIntervall, long maxDynamicIntervall, + double minimumDistance) { + + this.rand = Randoms.getRandom(RandomDynamicAttractionGenerator.class); + this.worldDimension = Binder.getComponentOrNull(Topology.class) + .getWorldDimensions(); + + if (minNumberOfAttractionPoints <= 0) { + throw new ConfigurationException( + "NumberOfAttractionPoints should be at least 1!"); + } + if(minNumberOfAttractionPoints > maxNumberOfAttractionPoints) { + throw new ConfigurationException( + "Minimum and maximum numbers of attraction points not correctly set!"); + } + + this.minNumberOfAttractionPoints = minNumberOfAttractionPoints; + this.maxNumberOfAttractionPoints = maxNumberOfAttractionPoints; + + this.minimumRadius = minimumRadius; + this.maximumRadius = maximumRadius; + this.minimumDistance = minimumDistance; + + this.minDynamicIntervall = minDynamicIntervall; + this.maxDynamicIntervall = maxDynamicIntervall; + + attractionPoints.clear(); + updateAttractionPoints(); + } + + @Override + public List getAttractionPoints() { + return attractionPoints; + } + + private int randomNumberOfAttractionPoints() { + return minNumberOfAttractionPoints + rand.nextInt((maxNumberOfAttractionPoints - minNumberOfAttractionPoints) + 1); + } + + + private void scheduleDynamicEvent(AttractionPoint attractionPoint) { + + long r = (long) (rand.nextDouble() * (maxDynamicIntervall - minDynamicIntervall)) + minDynamicIntervall; + + Event.scheduleWithDelay(r, new EventHandler() { + @Override + public void eventOccurred(Object content, int type) { + // maybe was already removed... + if(attractionPoints.contains(attractionPoint)) { + attractionPoints.remove(attractionPoint); + updateAttractionPoints(); + } + } + }, null, 0); + } + + protected void updateAttractionPoints() { + int numberOfAttractionPoints = randomNumberOfAttractionPoints(); + + // do nothing if this is the required amount of attraction points + if(numberOfAttractionPoints == attractionPoints.size()) { + return; + } + + // remove until this number fits + else if(numberOfAttractionPoints < attractionPoints.size()) { + int deltaAP = attractionPoints.size() - numberOfAttractionPoints; + + for(int i = 0; i < deltaAP; i++) { + int random = rand.nextInt(attractionPoints.size()); + attractionPoints.remove(random); + } + return; + } + + // add more attraction points until it fits + else { + int deltaAP = numberOfAttractionPoints - attractionPoints.size(); + + for(int i = 0; i < deltaAP; i++) { + AttractionPoint newAP = createAttractionPoint(); + scheduleDynamicEvent(newAP); + attractionPoints.add(newAP); + } + } + } + + /** + * Create an attraction point that is conform to all other currently saved attraction points. + * + * @return + */ + private AttractionPoint createAttractionPoint() { + // make a break counter to prevent more than 10 iterations and an infinity loop in general. + int c = 20; + + create: for(int i = 0; i < c; i++) { + PositionVector posVec = createPosVec(); + + // set the radius of this attraction point + // minimum radius is 10 meters + double radius = Math.max(minimumRadius, rand.nextDouble() * maximumRadius); + + if(i < c) { + // check if the attraction points would be completely within world dimensions (including radius!) + if((posVec.getX() + radius) >= worldDimension.getX() || (posVec.getY() + radius) >= worldDimension.getY() + || (posVec.getX() - radius) <= 0 || (posVec.getY() - radius) <= 0) { + continue create; + } + + // if within world dimensions, continue checking against other attraction points + for (AttractionPoint ap : attractionPoints) { + // if this point is closer than the given minimum distance to another point, or the radii of the points would overlap, + // or if the radius would exceed the simulation area + // then discard this attraction point and create a new one + if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0) { + continue create; + } + } + + } + else { + radius = 0; + } + + AttractionPoint aPoint = new AttractionPointImpl("AP-" + rand.nextInt(), posVec); + aPoint.setRadius(radius); + return aPoint; + } + + return null; + } + + + + private PositionVector createPosVec() { + double x = rand.nextDouble() * worldDimension.getX(); + double y = rand.nextDouble() * worldDimension.getY(); + return new PositionVector(x, y); + } + +} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TemporalAttractionPoint.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TemporalAttractionPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..1dd32902c8e772e6ea759edd21d540850559ad81 --- /dev/null +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TemporalAttractionPoint.java @@ -0,0 +1,53 @@ +/* + * 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 . + * + */ + +package de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction; + +import de.tud.kom.p2psim.impl.topology.util.PositionVector; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; + +public class TemporalAttractionPoint extends BasicAttractionPoint { + + private long placementTime; + private long removalTime; + + @XMLConfigurableConstructor({"name", "x", "y", "radius", "weight", "placementTime", "removalTime" }) + public TemporalAttractionPoint(String name, double x, double y, double radius, double weight, long placementTime, long removalTime) { + this(name, new PositionVector(x,y), radius, weight, placementTime, removalTime); + } + + public TemporalAttractionPoint(String name, PositionVector pos, double radius, double weight, long placementTime, long removalTime) { + super(name, pos); + setWeight(weight); + setRadius(radius); + + this.placementTime = placementTime; + this.removalTime = removalTime; + } + + public long getPlacementTime() { + return placementTime; + } + + public long getRemovalTime() { + return removalTime; + } + +} diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TwoPointFixedAttractionGenerator.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TwoPointFixedAttractionGenerator.java index 7f0e76a519466a7f7698e1b65409351e4a61469c..62a0f0cc3d3265f0c4dd3798469d2f5066ff938c 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TwoPointFixedAttractionGenerator.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/attraction/TwoPointFixedAttractionGenerator.java @@ -25,6 +25,7 @@ import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; +import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor; /** * Implementation of the interface {@link AttractionGenerator}. @@ -39,11 +40,19 @@ public class TwoPointFixedAttractionGenerator implements IAttractionGenerator { private PositionVector worldDimension; - public TwoPointFixedAttractionGenerator() { + private double x1, x2, y1, y2; + + @XMLConfigurableConstructor({ "x1", "y1", "x2", "y2"}) + public TwoPointFixedAttractionGenerator(double x1, double y1, double x2, double y2) { this.worldDimension = Binder.getComponentOrNull(Topology.class) .getWorldDimensions(); - + + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + createAttractionPoints(); } @@ -56,16 +65,16 @@ public class TwoPointFixedAttractionGenerator implements IAttractionGenerator { } private void createAttractionPoints() { - - double x = worldDimension.getX(); - double y = worldDimension.getY(); - - PositionVector p1 = new PositionVector(0 + 0.1 * x, y/2); + + PositionVector p1 = new PositionVector(x1, y1); AttractionPoint ap1 = new AttractionPointImpl("AP1", p1); + ap1.setRadius(100); attractionPoints.add(ap1); - PositionVector p2 = new PositionVector(0.9 * x, y/2); + + PositionVector p2 = new PositionVector(x2, y2); AttractionPoint ap2 = new AttractionPointImpl("AP2", p2); + ap2.setRadius(100); attractionPoints.add(ap2); } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/AbstractAttractionBasedTransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/AbstractAttractionBasedTransitionStrategy.java index 0f0aaa270fa7f82cfa29003a39a941671536c35a..3aea89f9633a46b48081ec47b4e02e8bef6958ad 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/AbstractAttractionBasedTransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/AbstractAttractionBasedTransitionStrategy.java @@ -44,9 +44,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction public abstract class AbstractAttractionBasedTransitionStrategy implements ITransitionStrategy { protected Random rnd = Randoms.getRandom(AbstractAttractionBasedTransitionStrategy.class); - - protected Set attractionPoints = new LinkedHashSet<>(); - + protected Map assignments = new LinkedHashMap<>(); protected Map lastAssignments = new LinkedHashMap<>(); @@ -76,18 +74,6 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran listeners.remove(listener); } - @Override - public void setAttractionPoints( - Collection attractionPoints) { - this.attractionPoints.clear(); - this.attractionPoints.addAll(attractionPoints); - } - - @Override - public Set getAllAttractionPoints() { - return Collections.unmodifiableSet(attractionPoints); - } - /** * Notify all listeners of an updated attraction point assignment for the given component * diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/FixedAssignmentStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/FixedAssignmentStrategy.java index a23e7ecc9324f96d9b92246e1ffa0c9e51e4f75b..a82ae611fe5951261b49aae06ed3947e95504f99 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/FixedAssignmentStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/FixedAssignmentStrategy.java @@ -28,6 +28,7 @@ import de.tud.kom.p2psim.api.common.SimHost; import de.tud.kom.p2psim.api.common.SimHostComponent; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; +import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; /** @@ -57,14 +58,14 @@ public class FixedAssignmentStrategy extends AbstractAttractionBasedTransitionSt // No assignments been done before. if (assignments.isEmpty()) { - AttractionPoint aPoint = attractionPoints.iterator().next(); + AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next(); assignments.put(ms, aPoint); mappingGroupId(ms, aPoint); } // GroupId is not mapped. else if (!mappingGroupIdAP.containsKey(mappingMSHost.get(ms) .getProperties().getGroupID())) { - for (AttractionPoint actAP : attractionPoints) { + for (AttractionPoint actAP : IAttractionGenerator.attractionPoints) { if (!mappingAPGroupId.containsKey(actAP)) { assignments.put(ms, actAP); mappingGroupId(ms, actAP); diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ITransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ITransitionStrategy.java index c20c97c4563ceba7200401c4a7d11368d7cbf6f8..dbadc7b2cec84a70b2b5871fd6161419fb05bb55 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ITransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ITransitionStrategy.java @@ -46,21 +46,6 @@ public interface ITransitionStrategy { public void removeAttractionAssignmentListener(AttractionAssignmentListener listener); - /** - * Should be called first, to add the Attraction Points for the assignment! - * - * @param attractionPoints - */ - public void setAttractionPoints( - Collection attractionPoints); - - /** - * Return a set of all attraction points - * - * @return - */ - public Set getAllAttractionPoints(); - /** * Add the object and assign the MS to an {@link AttractionPoint}. * diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/InAreaRoamingTransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/InAreaRoamingTransitionStrategy.java index faedd495e0b8133ffc640a6a3d5aa52aa03d8fc4..c796c462e10436945d3d7198748c3b3a4865d2c6 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/InAreaRoamingTransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/InAreaRoamingTransitionStrategy.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel; +import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.Time; @@ -94,13 +95,26 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran @Override public void eventOccurred(Object content, int type) { - if(type == EVENT_PAUSE_ENDED) { - SimLocationActuator comp = (SimLocationActuator) content; - this.addComponent(comp); + if(type == EVENT_PAUSE_ENDED) { + SimLocationActuator comp = (SimLocationActuator) content; + + // if the transit was triggered beforehand (e.g., attraction point moved), then do nothing. + if(roamingStates.get(comp) != roamingTransitionState.TRANSITION) { + this.addComponent(comp); + } } else if(type == EVENT_ROAMING_PAUSE_ENDED) { + SimLocationActuator comp = (SimLocationActuator) content; - this.roamAroundAttractionPoint(comp); + AttractionPoint currentAttractionPoint = this.assignments.get(comp); + + // if the attraction point was removed in the meantime, go directly to transit state + if(!IAttractionGenerator.attractionPoints.contains(currentAttractionPoint)) { + this.addComponent(comp); + } + else { + this.roamAroundAttractionPoint(comp); + } } } @@ -108,7 +122,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran private AttractionPoint getNewAttractionPoint(SimLocationActuator component) { double score = rnd.nextDouble(); List candidates = new LinkedList<>(); - for (AttractionPoint ap : attractionPoints) { + for (AttractionPoint ap : IAttractionGenerator.attractionPoints) { if (ap.getWeight() >= score) { if(lastAssignments.get(component) == null || !ap.equals(lastAssignments.get(component))) { candidates.add(ap); @@ -116,7 +130,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran } } if (candidates.isEmpty()) { - candidates.addAll(attractionPoints); + candidates.addAll(IAttractionGenerator.attractionPoints); } AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size())); return assignment; diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ManualAssignmentStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ManualAssignmentStrategy.java index e2b1dbfdc481bc37b0e919bfbf3eef2dc775e941..145325cfe7f59e6e7730e015abb4d9172ab2ed49 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ManualAssignmentStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/ManualAssignmentStrategy.java @@ -40,12 +40,10 @@ public class ManualAssignmentStrategy implements ITransitionStrategy listeners.remove(listener); } - @Override public void setAttractionPoints(Collection attractionPoints) { aPoints.addAll(attractionPoints); } - @Override public Set getAllAttractionPoints() { return aPoints; } diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/RandomInAreaTransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/RandomInAreaTransitionStrategy.java index f0d96a48fb4a0de2124fe28e8c042cc1edca8e61..ff3f0cbed0d9cdbd9e0bc1effdec6f03d813c61c 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/RandomInAreaTransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/RandomInAreaTransitionStrategy.java @@ -5,6 +5,7 @@ import java.util.Map; import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint; +import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Monitor; @@ -48,7 +49,7 @@ public class RandomInAreaTransitionStrategy extends AbstractAttractionBasedTrans if(!assignments.containsKey(ms)) { - AttractionPoint aPoint = attractionPoints.iterator().next(); + AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next(); assignments.put(ms, aPoint); currentTarget.put(ms, nextRandomPosition(aPoint, defaultRadius)); currentSearchRadius.put(ms, defaultRadius); diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/SocialTransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/SocialTransitionStrategy.java index ca94480ef8cb81243015fb8254656bf976817746..58145ef1dd856f3eb3cf2170b50b70705bab8df0 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/SocialTransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/SocialTransitionStrategy.java @@ -38,6 +38,7 @@ import de.tud.kom.p2psim.api.topology.Topology; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; import de.tud.kom.p2psim.api.topology.social.SocialView; import de.tud.kom.p2psim.impl.simengine.Simulator; +import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tud.kom.p2psim.impl.topology.util.PositionVector; import de.tudarmstadt.maki.simonstrator.api.Binder; import de.tudarmstadt.maki.simonstrator.api.Event; @@ -131,12 +132,6 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS public void setSocialId(String socialId) { this.socialId = socialId; } - - @Override - public void setAttractionPoints(Collection attractionPoints) { - init(); - super.setAttractionPoints(attractionPoints); - } @Override public void addComponent(SimLocationActuator ms) { @@ -146,8 +141,8 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS // position. // TODO: needed? We do Transition as next, and this will delete the // assignment.. - AttractionPoint nearest = attractionPoints.iterator().next(); - for (AttractionPoint aPoint : attractionPoints) { + AttractionPoint nearest = IAttractionGenerator.attractionPoints.iterator().next(); + for (AttractionPoint aPoint : IAttractionGenerator.attractionPoints) { if (nearest.distanceTo(ms.getRealPosition()) > aPoint .distanceTo(ms.getRealPosition())) { nearest = aPoint; @@ -181,7 +176,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS List apFriends = getFriendsPlaces(ms); List apClusters = getClusterPlaces(ms); List apRandom = getRandomPlaces(ms, - (int) Math.max(attractionPoints.size() * 0.2, 5)); + (int) Math.max(IAttractionGenerator.attractionPoints.size() * 0.2, 5)); AttractionPoint ap = null; if (rnd.nextDouble() < socialFactor) { @@ -299,7 +294,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS private List getRandomPlaces(SimLocationActuator ms, int number) { - List result = new Vector(attractionPoints); + List result = new Vector(IAttractionGenerator.attractionPoints); Collections.shuffle(result, rnd); return result.subList(0, Math.min(result.size(), number)); } @@ -339,7 +334,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS private void assignFavoritePlaces(SimLocationActuator ms) { Set msFavoritePlaces = new LinkedHashSet(); LinkedList temp = new LinkedList( - attractionPoints); + IAttractionGenerator.attractionPoints); Collections.shuffle(temp, rnd); for (int i = 0; i < numberOfFavoritePlaces; i++) { if (!temp.isEmpty()) { diff --git a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/WeightedTransitionStrategy.java b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/WeightedTransitionStrategy.java index 62ce631abc32a09b2468a7a67b7f18800bc6be87..e3f6e20c16034895d85ee2b68893cf244c37b4c2 100644 --- a/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/WeightedTransitionStrategy.java +++ b/src/de/tud/kom/p2psim/impl/topology/movement/modularosm/transition/WeightedTransitionStrategy.java @@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition; import java.util.LinkedList; import java.util.List; import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator; +import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator; import de.tudarmstadt.maki.simonstrator.api.Event; import de.tudarmstadt.maki.simonstrator.api.EventHandler; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint; @@ -50,13 +51,13 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedTransitio private AttractionPoint getNewAssignment(SimLocationActuator component) { double score = rnd.nextDouble(); List candidates = new LinkedList<>(); - for (AttractionPoint ap : attractionPoints) { + for (AttractionPoint ap : IAttractionGenerator.attractionPoints) { if (ap.getWeight() >= score) { candidates.add(ap); } } if (candidates.isEmpty()) { - candidates.addAll(attractionPoints); + candidates.addAll(IAttractionGenerator.attractionPoints); } AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size())); notifyListenersOfAssignmentUpdate(component, assignment); diff --git a/src/de/tud/kom/p2psim/impl/topology/util/PositionVector.java b/src/de/tud/kom/p2psim/impl/topology/util/PositionVector.java index 212711d9790502b4c9fa88268931739f8213284e..991905390cb98228229f011c7d92f0109bc4455c 100644 --- a/src/de/tud/kom/p2psim/impl/topology/util/PositionVector.java +++ b/src/de/tud/kom/p2psim/impl/topology/util/PositionVector.java @@ -54,9 +54,9 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; * assertions. Replace does now fully replace the position vector entries. PVs are now * always at least 3D (with 0 altitude) * - * - 14.03.2019 Louis Neumann: added timestamp when creating a PositionVector and adjusted ageOfLocation() + * - 14.03.2019 Louis Neumann: Added timestamp when creating a PositionVector and adjusted ageOfLocation() * - * - 18.04.2019 Louis Neumann: added setAgeofLocation() + * - 04.06.2019 Julian Zobel: Clone function also clones the timestamp from the cloned position. * * @author Bjoern Richerzhagen, Julian Zobel, Louis Neumann * @version 1.2, 10.09.2018 @@ -107,6 +107,7 @@ public class PositionVector implements Location { for (int i = 0; i < vec.getDimensions(); i++) { setEntry(i, vec.getEntry(i)); } + this.created = Time.getCurrentTime(); } @@ -161,7 +162,9 @@ public class PositionVector implements Location { /* * If you extend Position Vector, make sure to overwrite this method! */ - return new PositionVector(this); // use clone constructor + PositionVector clone = new PositionVector(this); // use clone constructor + clone.setTimestamp(this.created); + return clone; } @@ -554,15 +557,11 @@ public class PositionVector implements Location { @Override public long getAgeOfLocation() { - return Time.getCurrentTime() - created; - + return Time.getCurrentTime() - created; } - /** - * - * @param ageOfLocation the ageOfLocation to set - */ - public void setAgeofLocation(long ageOfLocation) { - this.created = ageOfLocation; + + private void setTimestamp(long locationTimestamp) { + this.created = locationTimestamp; } @Override