diff --git a/UML_structure.dia b/UML_structure.dia new file mode 100644 index 0000000..6b3925b Binary files /dev/null and b/UML_structure.dia differ diff --git a/runSim.sh b/runSim.sh old mode 100644 new mode 100755 diff --git a/scenarios/scenario1_active.xml b/scenarios/scenario1_active.xml index 77c4530..c921f7f 100644 --- a/scenarios/scenario1_active.xml +++ b/scenarios/scenario1_active.xml @@ -1,16 +1,16 @@ - + - - - - - - + + + - + diff --git a/src/epics/ai/AWASSLookAheadNode.java b/src/epics/ai/AWASSLookAheadNode.java new file mode 100644 index 0000000..2384f92 --- /dev/null +++ b/src/epics/ai/AWASSLookAheadNode.java @@ -0,0 +1,122 @@ +package epics.ai; + +import static java.lang.Math.cos; +import static java.lang.Math.sin; + +import java.util.HashMap; +import java.util.Map; + +import epics.camsim.core.TraceableObject; +import epics.common.AbstractAINode; +import epics.common.Coordinate2D; +import epics.common.IBanditSolver; +import epics.common.IRegistration; +import epics.common.ITrObjectRepresentation; +import epics.common.RandomNumberGenerator; +import epics.common.RandomUse.USE; + +public class AWASSLookAheadNode extends AbstractAINode { //ActiveAINodeMulti { + + /** The confidence for an object below which we advertise */ + public static final double CONF_THRESHOLD = 0.1; + private static final int LOOK_AHEAD = 2; + private static final double AUCT_PROB = 0.2; + + /** Keep track of confidence from last time step to find whether + * it has increased or decreased */ + private Map lastConfidence = new HashMap(); + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + */ + public AWASSLookAheadNode(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg){ + super(staticVG, vg, r, rg); + } + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + * @param bs the bandit solver to decide the best communication policy and auctioning schedule + */ + public AWASSLookAheadNode(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs){ + super(staticVG, vg, r, rg, bs); + } + + public AWASSLookAheadNode(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + } + + public AWASSLookAheadNode(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + } + + /** + * creates a passive ai instance from another existing instance + * @param ai the given existing AI instance + */ + public AWASSLookAheadNode(AbstractAINode ai){ + super(ai); + if (ai instanceof AWASSLookAheadNode) { + AWASSLookAheadNode pass = (AWASSLookAheadNode) ai; + lastConfidence = pass.lastConfidence; + } + } + + private Coordinate2D toCameraSpace(final Coordinate2D pointPos){ + final Coordinate2D camPos = camController.getPostion(); + final double camAngle = -camController.getHeading(); + final double dx = pointPos.getX()-camPos.getX(); + final double dy = pointPos.getY()-camPos.getY(); + final double x = dx * cos(camAngle) + dy * sin(camAngle); + final double y = -dx * sin(camAngle) + dy * cos(camAngle); + return new Coordinate2D(x, y); + } + + + @Override + public void advertiseTrackedObjects() { + for (ITrObjectRepresentation io : this.getAllTrackedObjects_bb().values()) { + double conf = this.getConfidence(io); + double lastConf = this.getLastConfidenceFor(io); + if (this.camController.objectIsVisible(io) == -1){ + if (conf < CONF_THRESHOLD && (conf == 0 || conf < lastConf)) { + final TraceableObject obj = io.getTraceableObject(); + //if(camController.isObjectInFOV(obj)){ + final Coordinate2D expectedNext = toCameraSpace(obj.esteemNext(LOOK_AHEAD)); + if((conf != 0 && !camController.isCoordinateInFOV(expectedNext)) || randomGen.nextDouble(USE.UNIV) < AUCT_PROB){ + /* + * Start an auction if: + * - the object is in FOV and it's expected to exit the FOV in near future + * - the object is not in FOV with probability AUCT_PROB + */ + callForHelp(io); + } + } + } + this.addLastConfidence(io, conf); + } + } + + protected void addLastConfidence(ITrObjectRepresentation io, double conf) { + this.lastConfidence.put(io, conf); + } + + protected double getLastConfidenceFor(ITrObjectRepresentation io) { + if (lastConfidence.containsKey(io)) { + return lastConfidence.get(io); + } else { + return 0.0; + } + } +} diff --git a/src/epics/ai/AWASSLookAheadNodeClustering.java b/src/epics/ai/AWASSLookAheadNodeClustering.java new file mode 100644 index 0000000..4af7e8e --- /dev/null +++ b/src/epics/ai/AWASSLookAheadNodeClustering.java @@ -0,0 +1,111 @@ +package epics.ai; + +import static java.lang.Math.cos; +import static java.lang.Math.sin; + +import java.util.HashMap; +import java.util.Map; + +import epics.camsim.core.TraceableObject; +import epics.common.AbstractAINode; +import epics.common.Coordinate2D; +import epics.common.IBanditSolver; +import epics.common.IRegistration; +import epics.common.ITrObjectRepresentation; +import epics.common.RandomNumberGenerator; +import epics.common.RandomUse.USE; + +public class AWASSLookAheadNodeClustering extends AbstractClusterFoVAINode { //ActiveAINodeMulti { + + /** The confidence for an object below which we advertise */ + public static final double CONF_THRESHOLD = 0.1; + private static final int LOOK_AHEAD = 2; + private static final double AUCT_PROB = 0.2; + + /** Keep track of confidence from last time step to find whether + * it has increased or decreased */ + private Map lastConfidence = new HashMap(); + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + */ + public AWASSLookAheadNodeClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg){ + super(staticVG, vg, r, rg); + } + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + * @param bs the bandit solver to decide the best communication policy and auctioning schedule + */ + public AWASSLookAheadNodeClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs){ + super(staticVG, vg, r, rg, bs); + } + + public AWASSLookAheadNodeClustering(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + } + + public AWASSLookAheadNodeClustering(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + } + + /** + * creates a passive ai instance from another existing instance + * @param ai the given existing AI instance + */ + public AWASSLookAheadNodeClustering(AbstractAINode ai){ + super(ai); + if (ai instanceof AWASSLookAheadNodeClustering) { + AWASSLookAheadNodeClustering pass = (AWASSLookAheadNodeClustering) ai; + lastConfidence = pass.lastConfidence; + } + } + + @Override + public void advertiseTrackedObjects() { + for (ITrObjectRepresentation io : this.getAllTrackedObjects_bb().values()) { + double conf = this.getConfidence(io); + double lastConf = this.getLastConfidenceFor(io); + if (this.camController.objectIsVisible(io) == -1){ + if (conf < CONF_THRESHOLD && (conf == 0 || conf < lastConf)) { + final TraceableObject obj = io.getTraceableObject(); + //if(camController.isObjectInFOV(obj)){ + final Coordinate2D expectedNext = toCameraSpace(obj.esteemNext(LOOK_AHEAD)); + if((conf != 0 && !camController.isCoordinateInFOV(expectedNext)) || randomGen.nextDouble(USE.UNIV) < AUCT_PROB){ + /* + * Start an auction if: + * - the object is in FOV and it's expected to exit the FOV in near future + * - the object is not in FOV with probability AUCT_PROB + */ + callForHelp(io); + } + } + } + this.addLastConfidence(io, conf); + } + } + + protected void addLastConfidence(ITrObjectRepresentation io, double conf) { + this.lastConfidence.put(io, conf); + } + + protected double getLastConfidenceFor(ITrObjectRepresentation io) { + if (lastConfidence.containsKey(io)) { + return lastConfidence.get(io); + } else { + return 0.0; + } + } +} diff --git a/src/epics/ai/AbstractClusterFoVAINode.java b/src/epics/ai/AbstractClusterFoVAINode.java new file mode 100644 index 0000000..44db192 --- /dev/null +++ b/src/epics/ai/AbstractClusterFoVAINode.java @@ -0,0 +1,261 @@ +package epics.ai; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import static java.lang.Math.PI; +import static java.lang.Math.cos; +import static java.lang.Math.sin; + +import epics.common.Coordinate2D; +import epics.common.RandomNumberGenerator; +import epics.common.AbstractAINode; +import epics.common.IRegistration; +import epics.common.IBanditSolver; +import epics.common.ITrObjectRepresentation; + +import epics.ai.kmeans.*; + +public abstract class AbstractClusterFoVAINode extends AbstractAINode { + SequentialKMeans kmeans; + +// protected Map visionGraph = new HashMap(); + + // the idea: we cluster the FoV based on the hand-over positions. + // therefor, + // we should get the visionGraph based on the current position of the object + // we should update the K-Means when a handover takes place + + // connnnstructor + public AbstractClusterFoVAINode(AbstractAINode old){ + super(old); + initKMeans(); + } + + /** + * Creates an AI Node WITHOUT bandit solver + * for switching to another node automatically. + * This constructor simply calls instantiateAINode(). Overriding classes + * should only call super and do real handling in instantiateAINode(). + * This is painful but is to enforce these arguments in the constructor. + * + * @param comm communication used + * @param staticVG if true, only static vision graph is used + * @param vg initial vision graph + * @param r global registration component + * @param rg random number generator for this node + */ + public AbstractClusterFoVAINode(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg){ + super(staticVG, vg, r, rg); + initKMeans(); + } + + /** + * Creates an AI Node WITHOUT bandit solver for switching to another node automatically + * @param comm the used communication policy + * @param staticVG if static vision graph or not + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param auctionDuration the duration of auctions + * @param rg the random number generator for this instance + */ + public AbstractClusterFoVAINode( + boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + initKMeans(); + } + + /** + * Standard constructor including bandit solver + * @param comm communication used + * @param staticVG if true, only static vision graph is used + * @param vg initial vision graph + * @param r global registration component + * @param rg random number generator for this node + * @param bs the bandit solver to find the best strategy + */ + public AbstractClusterFoVAINode( + boolean staticVG, Map vg, + IRegistration r, RandomNumberGenerator rg, IBanditSolver bs){ + super(staticVG, vg, r, rg, bs); + initKMeans(); + } + + + public AbstractClusterFoVAINode( + boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + initKMeans(); + } + + private void initKMeans() { + this.kmeans = new SequentialKMeans(2); // 2 features/dimension, -> the position of the object at handover + } + + /** + * copies the given AbstractClusterFoVAINode + * @param ai the given AiNode + */ + public void instantiateAINode(AbstractClusterFoVAINode ai){ + super.instantiateAINode(ai); + this.kmeans = ai.kmeans; + } + + + protected Coordinate2D toCameraSpace(final Coordinate2D pointPos){ + final Coordinate2D camPos = camController.getPostion(); + final double camAngle = -camController.getHeading(); + final double dx = pointPos.getX()-camPos.getX(); + final double dy = pointPos.getY()-camPos.getY(); + final double x = dx * cos(camAngle) + dy * sin(camAngle); + final double y = -dx * sin(camAngle) + dy * cos(camAngle); + return new Coordinate2D(x, y); + } + + + protected Map getVisionGraphForObject(ITrObjectRepresentation rto) { + Coordinate2D coords = toCameraSpace(rto.getTraceableObject().getCurrentPosition()); + double[] co = new double[2]; + co[0] = coords.getX(); + co[1] = coords.getY(); + + Cluster c = this.kmeans.getClosestCluster( new ClusterPoint(co) ); + //System.out.println("For obj at "+coords+", got "+c); + return c.visionGraph; + } + + + // this should be the moment of handover... + @Override + protected void removeTrackedObject(ITrObjectRepresentation rto) { + super.removeTrackedObject(rto); + //System.out.println("THIS IS Hand-overrrrrr"); + + Coordinate2D coords = toCameraSpace(rto.getTraceableObject().getCurrentPosition()); + double[] co = new double[2]; + co[0] = coords.getX(); + co[1] = coords.getY(); + + this.kmeans.add(new ClusterPoint(co)); + } + + + + /** + * updates the vision graph. reduces every link by the evaporationrate + */ + @Override + protected void updateVisionGraph() { + if(!staticVG){ + Iterator clusters = this.kmeans.getClusterIterator(); + while (clusters.hasNext()) { + Cluster cluster = clusters.next(); + + ArrayList toRemove = new ArrayList(); + for (Map.Entry e : vgEntrySet(cluster)) { + double val = e.getValue(); + e.setValue( e.getValue() * EVAPORATIONRATE); //0.995); + if (val < 0) { + toRemove.add(e.getKey()); + } + } + for (int i = 0; i < toRemove.size(); i++) { + vgRemove(toRemove.get(i), cluster); + } + } // for each cluster + } + } + + + + /** + * returns the vision graph + * the graph consists of cameras (key) and the corresponding strength (value) in a map + * @return the vision graph + */ + @Override + public Map getVisionGraph() { + return null; + } + public Map getVisionGraph(ITrObjectRepresentation itro) { + return this.getVisionGraphForObject(itro); + } + + /** Whether the key exists for this cam name (ignoring object here) */ + @Override + public boolean vgContainsKey(String camName, ITrObjectRepresentation itro) { + return getVisionGraph(itro).containsKey(camName); + } + + /** Get all values in the vision graph (ignoring object here) */ + @Override + public Collection vgGetValues(ITrObjectRepresentation itro) { + return getVisionGraph(itro).values(); + } + + /** Get all cameras with values in the vision graph */ + @Override + public Set vgGetCamSet() { + return null; + } + + public Set vgGetCamSet(ITrObjectRepresentation itro) { + return getVisionGraph(itro).keySet(); + } + + + /** Get the pheromone value for this camera name (ignoring object here) */ + @Override + public Double vgGet(String camName, ITrObjectRepresentation itro) { + return getVisionGraph(itro).get(camName); + } + + // TODO + + /** Put a value in the vision graph under this camera name (ignoring + * object here) */ + public Double vgPut(String camName, ITrObjectRepresentation itro, Double value) { + return getVisionGraph(itro).put(camName, value); + } + + /** Get all entries (key-value pairs) in the vision graph */ + public Set> vgEntrySet() { + return null; + } + public Set> vgEntrySet(ITrObjectRepresentation itro) { + return getVisionGraph(itro).entrySet(); + } + + public Set> vgEntrySet(Cluster cluster) { + return cluster.visionGraph.entrySet(); + } + + /** Remove from the vision graph the key-value pair for the given key */ + public Double vgRemove(String name) { + return null; + } + public Double vgRemove(String name, ITrObjectRepresentation itro) { + return getVisionGraph(itro).remove(name); + } + public Double vgRemove(String name, Cluster cluster) { + return cluster.visionGraph.remove(name); + } + + private void printVisionGraph() { + // for all vision graphs print +// String neighbours = ""; +// for (String neighbour : visionGraph.keySet()) { +// neighbours += "; " + neighbour; +// } +// System.out.println(this.camController.getName() + +// " has the following neighbours:" + neighbours); + } + + +} + diff --git a/src/epics/ai/ActiveAINodeMulti.java b/src/epics/ai/ActiveAINodeMulti.java index b6306f6..7f297d4 100644 --- a/src/epics/ai/ActiveAINodeMulti.java +++ b/src/epics/ai/ActiveAINodeMulti.java @@ -9,81 +9,114 @@ import epics.common.RandomNumberGenerator; /** - * Implementation of AbstractAINode. - * defines the behaviour of the camera node regarding communication policies and the auction invitation schedules. - * this class uses the active auction invitation schedule to send invitations to other cameras in every timestep. - * @author Marcin Bogdanski & Lukas Esterle, refactored by Horatio Cane + * Implementation of AbstractAINode. defines the behaviour of the camera node + * regarding communication policies and the auction invitation schedules. this + * class uses the active auction invitation schedule to send invitations to + * other cameras in every timestep. + * + * @author Marcin Bogdanski & Lukas Esterle, refactored by Horatio Cane */ public class ActiveAINodeMulti extends AbstractAINode { - - /** - * Creates an AI Node with active auction schedule from another, existing ai node - * @param ai the existing ai node - */ - public ActiveAINodeMulti(AbstractAINode ai){ - super(ai); - } - - /** - * Creates an AI Node with active auction schedule WITHOUT bandit solver for switching to another node automatically - * @param comm the used communication policy - * @param staticVG if static vision graph or not - * @param vg the initial vision graph - * @param r the global registration component - can be null - * @param auctionDuration the duration of auctions - * @param rg the random number generator for this instance - */ - public ActiveAINodeMulti(boolean staticVG, - Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { - super(staticVG, vg, r, auctionDuration, rg); - } - - /** - * Creates an AI Node with active auction schedule WITH a bandit solver for switching to another node automatically - * @param comm the used communication policy - * @param staticVG if static vision graph or not - * @param vg the initial vision graph - * @param r the global registration component - can be null - * @param auctionDuration the duration of auctions - * @param rg the random number generator for this instance - * @param bs the bandit solver - */ - public ActiveAINodeMulti(boolean staticVG, - Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { - super(staticVG, vg, r, auctionDuration, rg, bs); - } - - /** - * Creates an AI Node with active auction schedule WITHOUT bandit solver for switching to another node automatically - * @param comm the used communication policy - * @param staticVG if static vision graph or not - * @param vg the initial vision graph - * @param r the global registration component - can be null - * @param rg the random number generator for this instance - */ - public ActiveAINodeMulti(boolean staticVG, - Map vg, IRegistration r, RandomNumberGenerator rg) { - super(staticVG, vg, r, rg); - } - - /** - * Creates an AI Node with active auction schedule WITH a bandit solver for switching to another node automatically - * @param comm the used communication policy - * @param staticVG if static vision graph or not - * @param vg the initial vision graph - * @param r the global registration component - can be null - * @param rg the random number generator for this instance - * @param bs the bandit solver - */ - public ActiveAINodeMulti(boolean staticVG, - Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs) { - super(staticVG, vg, r, rg, bs); - } - - public void advertiseTrackedObjects() { - // Active strategy means all objects are advertised every time + + /** + * Creates an AI Node with active auction schedule from another, existing ai + * node + * + * @param ai + * the existing ai node + */ + public ActiveAINodeMulti(AbstractAINode ai) { + super(ai); + } + + /** + * Creates an AI Node with active auction schedule WITHOUT bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param auctionDuration + * the duration of auctions + * @param rg + * the random number generator for this instance + */ + public ActiveAINodeMulti(boolean staticVG, Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + } + + /** + * Creates an AI Node with active auction schedule WITH a bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param auctionDuration + * the duration of auctions + * @param rg + * the random number generator for this instance + * @param bs + * the bandit solver + */ + public ActiveAINodeMulti(boolean staticVG, Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + } + + /** + * Creates an AI Node with active auction schedule WITHOUT bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param rg + * the random number generator for this instance + */ + public ActiveAINodeMulti(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg) { + super(staticVG, vg, r, rg); + } + + /** + * Creates an AI Node with active auction schedule WITH a bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param rg + * the random number generator for this instance + * @param bs + * the bandit solver + */ + public ActiveAINodeMulti(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, rg, bs); + } + + public void advertiseTrackedObjects() { + // Active strategy means all objects are advertised every time for (ITrObjectRepresentation io : this.getAllTrackedObjects_bb().values()) { - callForHelp(io); + callForHelp(io); } } } diff --git a/src/epics/ai/ActiveAINodeMultiClustering.java b/src/epics/ai/ActiveAINodeMultiClustering.java new file mode 100644 index 0000000..e10bd40 --- /dev/null +++ b/src/epics/ai/ActiveAINodeMultiClustering.java @@ -0,0 +1,122 @@ +package epics.ai; + +import java.util.Map; + +import epics.common.AbstractAINode; +import epics.common.IBanditSolver; +import epics.common.IRegistration; +import epics.common.ITrObjectRepresentation; +import epics.common.RandomNumberGenerator; + +/** + * Implementation of AbstractAINode. defines the behaviour of the camera node + * regarding communication policies and the auction invitation schedules. this + * class uses the active auction invitation schedule to send invitations to + * other cameras in every timestep. + * + * @author Marcin Bogdanski & Lukas Esterle, refactored by Horatio Cane + */ +public class ActiveAINodeMultiClustering extends AbstractClusterFoVAINode { + + /** + * Creates an AI Node with active auction schedule from another, existing ai + * node + * + * @param ai + * the existing ai node + */ + public ActiveAINodeMultiClustering(AbstractAINode ai) { + super(ai); + } + + /** + * Creates an AI Node with active auction schedule WITHOUT bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param auctionDuration + * the duration of auctions + * @param rg + * the random number generator for this instance + */ + public ActiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + } + + /** + * Creates an AI Node with active auction schedule WITH a bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param auctionDuration + * the duration of auctions + * @param rg + * the random number generator for this instance + * @param bs + * the bandit solver + */ + public ActiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + } + + /** + * Creates an AI Node with active auction schedule WITHOUT bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param rg + * the random number generator for this instance + */ + public ActiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg) { + super(staticVG, vg, r, rg); + } + + /** + * Creates an AI Node with active auction schedule WITH a bandit solver for + * switching to another node automatically + * + * @param comm + * the used communication policy + * @param staticVG + * if static vision graph or not + * @param vg + * the initial vision graph + * @param r + * the global registration component - can be null + * @param rg + * the random number generator for this instance + * @param bs + * the bandit solver + */ + public ActiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, rg, bs); + } + + public void advertiseTrackedObjects() { + // Active strategy means all objects are advertised every time + for (ITrObjectRepresentation io : this.getAllTrackedObjects_bb().values()) { + callForHelp(io); + } + } +} diff --git a/src/epics/ai/PassiveAINodeMultiClustering.java b/src/epics/ai/PassiveAINodeMultiClustering.java new file mode 100644 index 0000000..25af236 --- /dev/null +++ b/src/epics/ai/PassiveAINodeMultiClustering.java @@ -0,0 +1,98 @@ +package epics.ai; + +import java.util.HashMap; +import java.util.Map; + +import epics.common.AbstractAINode; +import epics.common.IBanditSolver; +import epics.common.IRegistration; +import epics.common.ITrObjectRepresentation; +import epics.common.RandomNumberGenerator; + +public class PassiveAINodeMultiClustering extends AbstractClusterFoVAINode { //ActiveAINodeMulti { + + /** The confidence for an object below which we advertise */ + public static final double CONF_THRESHOLD = 0.1; + + /** Keep track of confidence from last time step to find whether + * it has increased or decreased */ + private Map lastConfidence = new HashMap(); + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + */ + public PassiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg){ + super(staticVG, vg, r, rg); + } + + /** + * constructor for this node. calls its super constructor and sets the DEFAULT_AUCTION_DURATION + * @param comm the communication policy + * @param staticVG if static or dynamic vision graph + * @param vg the initial vision graph + * @param r the global registration component - can be null + * @param rg the random number generator for this instance + * @param bs the bandit solver to decide the best communication policy and auctioning schedule + */ + public PassiveAINodeMultiClustering(boolean staticVG, Map vg, IRegistration r, RandomNumberGenerator rg, IBanditSolver bs){ + super(staticVG, vg, r, rg, bs); + } + + public PassiveAINodeMultiClustering(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg) { + super(staticVG, vg, r, auctionDuration, rg); + } + + public PassiveAINodeMultiClustering(boolean staticVG, + Map vg, IRegistration r, int auctionDuration, RandomNumberGenerator rg, IBanditSolver bs) { + super(staticVG, vg, r, auctionDuration, rg, bs); + } + + /** + * creates a passive ai instance from another existing instance + * @param ai the given existing AI instance + */ + public PassiveAINodeMultiClustering(AbstractAINode ai){ + super(ai); + if (ai instanceof PassiveAINodeMultiClustering) { + PassiveAINodeMultiClustering pass = (PassiveAINodeMultiClustering) ai; + lastConfidence = pass.lastConfidence; + } + } + + @Override + public void advertiseTrackedObjects() { + for (ITrObjectRepresentation io : this.getAllTrackedObjects_bb().values()) { + double conf = this.getConfidence(io); + double lastConf = this.getLastConfidenceFor(io); + + if (this.camController.realObjectsUsed()){ + if(this.camController.objectIsVisible(io) == 1){ + callForHelp(io); + } + } else if (this.camController.objectIsVisible(io) == -1){ + if (conf < CONF_THRESHOLD && (conf == 0 || conf < lastConf)) { + callForHelp(io); + } + } + this.addLastConfidence(io, conf); + } + } + + protected void addLastConfidence(ITrObjectRepresentation io, double conf) { + this.lastConfidence.put(io, conf); + } + + protected double getLastConfidenceFor(ITrObjectRepresentation io) { + if (lastConfidence.containsKey(io)) { + return lastConfidence.get(io); + } else { + return 0.0; + } + } +} diff --git a/src/epics/ai/kmeans/Cluster.java b/src/epics/ai/kmeans/Cluster.java new file mode 100644 index 0000000..ca8739c --- /dev/null +++ b/src/epics/ai/kmeans/Cluster.java @@ -0,0 +1,91 @@ +/* by Hedde Bosman */ + +package epics.ai.kmeans; + + +import java.util.Map; +import java.util.HashMap; + +// this class is not 'generic' anymore... due to the vision graph being added here... + +public class Cluster { + private ClusterPoint center; // the mean/center of the cluster + private double count; // the number of cluster points associated to this mean + private int relevance; + + // again, public = lazy... + public Map visionGraph; + + public Cluster(int numCoordinates) { + count = 0.0; + center = new ClusterPoint(numCoordinates); + visionGraph = new HashMap(); + this.resetRelevance(); + } + public Cluster(ClusterPoint x) { + count = 1.0; + center = x; + visionGraph = new HashMap(); + this.resetRelevance(); + } + + // initiate the cluster center by using random values between [-1,1] + public void initRandomCenter() { + for (int i = 0; i < center.coordinates.length; i++) { + center.coordinates[i] = Math.random()*2.0-1.0; // random() is 0-1 + } + } + + // get the distance from the cluster center to point x + public double distanceTo(ClusterPoint x) { + return center.distanceTo(x); + } + public double distanceTo(Cluster x) { + return center.distanceTo(x.center); + } + + // should get called every time a point has been added to THIS cluster + public void resetRelevance() { + this.relevance = SequentialKMeans.CLUSTER_LIFETIME; + } + // should get called every time a point has been added to ANY cluster + public boolean decrementRelevance() { + return (--relevance < 0); + } + + ///////////////////////////////////////////////////////// + // functions to add a point to this cluster + ///////////////////////////////////////////////////////// + + // if factor is fixed, we forget + public void addForgetfull(ClusterPoint x, double factor) { + // for each coordinate (x,y,...) + for (int i = 0; i < center.coordinates.length; i++) { + // add factor * diff(this,x)^2 + center.coordinates[i] += factor * (x.coordinates[i] - center.coordinates[i]); + } + this.resetRelevance(); + } + + // fixed forgetting factor + public void addForgetfull(ClusterPoint x) { + this.addForgetfull(x, 0.01); + } + + // changing forgetting factor (learning rate is slower when number of data points increases) + public void add(ClusterPoint x) { + count += 1.0; + double factor = 1.0 / count; + this.addForgetfull(x, factor); + } + + public String toString() { + String r = "Cluster, center=[ "; + for (int i = 0; i < this.center.coordinates.length; i++) { + r += this.center.coordinates[i] + " "; + } + r += "]; count="+this.count; + return r; + } +} + diff --git a/src/epics/ai/kmeans/ClusterPoint.java b/src/epics/ai/kmeans/ClusterPoint.java new file mode 100644 index 0000000..c3a98fe --- /dev/null +++ b/src/epics/ai/kmeans/ClusterPoint.java @@ -0,0 +1,44 @@ +/* by Hedde Bosman */ + +package epics.ai.kmeans; + +public class ClusterPoint { + public double[] coordinates; // public = being lazy + + // constructor by number of coordinates (no initalization) + public ClusterPoint(int numCoordinates) { + this.coordinates = new double[numCoordinates]; + } + + // constructor by array of doubles that represent coordinates + public ClusterPoint(double[] coords) { + this.coordinates = coords; + } + + // determine euclidian distance from this point to point y + // returns NaN when number of coordinates do not match (different spaces) + public double distanceTo(ClusterPoint y) { + if (y.coordinates.length != this.coordinates.length) { + return Double.NaN; + } + + double dist = 0.0; + + for (int i = 0; i < this.coordinates.length; i++) { + dist += Math.pow((this.coordinates[i]-y.coordinates[i]), 2); + } + dist = Math.sqrt(dist); + + return dist; + } + + public String toString() { + String r = "[ "; + for (int i = 0; i < this.coordinates.length; i++) { + r += this.coordinates[i]+" "; + } + r += "]"; + return r; + } +} + diff --git a/src/epics/ai/kmeans/SequentialKMeans.java b/src/epics/ai/kmeans/SequentialKMeans.java new file mode 100644 index 0000000..1bc3e47 --- /dev/null +++ b/src/epics/ai/kmeans/SequentialKMeans.java @@ -0,0 +1,138 @@ +/* by Hedde Bosman */ + +/* + implemented follwing the pseudo-code at: + http://www.cs.princeton.edu/courses/archive/fall08/cos436/Duda/C/sk_means.htm +*/ + +package epics.ai.kmeans; + +import java.util.Vector; +import java.util.Iterator; +import java.util.HashMap; + +// this class is not generic anymore... it clones the vision graph when adding a new cluster + +public class SequentialKMeans { + private int maxNumClusters; + private Vector clusters; // the clusters :P + + // if a cluster has not seen a new point associated with it for CLUSTER_LIFETIME datapoints, we remove it... + public final static int CLUSTER_LIFETIME = 100; + + public final static double MINIMUM_INTER_CLUSTER_DISTANCE = 0.05; + // CLUSTER_ADD_FACTOR = 0.5 => 0.5*(maxDistance between clusters), so maximum non-overlapping radius + // any larger values means that they all overlap + public final static double CLUSTER_ADD_FACTOR = 0.5; + + + public SequentialKMeans(int numCoordinates) { + clusters = new Vector(); + // only add one cluster, the adaptive 'add' should add new ones on demand + Cluster c = new Cluster(numCoordinates); + c.initRandomCenter(); + clusters.add(c); + + maxNumClusters = 10; + } + // constructor, requires #clusters and #coordinates + public SequentialKMeans(int numCoordinates, int numClusters) { + clusters = new Vector(); + + for (int i = 0; i < numClusters; i++) { + Cluster c = new Cluster(numCoordinates); + c.initRandomCenter(); + clusters.add(c); + } + + maxNumClusters = 10; + } + + public double getMaximumInterClusterDistance() { + double dist = MINIMUM_INTER_CLUSTER_DISTANCE; + for (int i = 0; i < clusters.size(); i++) { + for (int j = i+1; j < clusters.size(); j++) { + double tmpDist = clusters.get(i).distanceTo(clusters.get(j)); + if (dist < tmpDist) + dist = tmpDist; + } + } + return dist; + } + + public int getClosestClusterIndex(ClusterPoint x) { + double dist = Double.MAX_VALUE; + int idx = -1; + + // for each cluster + for (int i = 0; i < clusters.size(); i++) { + // determine if the center is closer than other clusters + double tmpDist = clusters.get(i).distanceTo(x); + if (dist > tmpDist) { + // if so, this is the closest clusters + dist = tmpDist; + idx = i; + } + } + return idx; + } + public Cluster getClosestCluster(ClusterPoint x) { + return clusters.get( getClosestClusterIndex(x) ); + } + + public Iterator getClusterIterator() { + return clusters.iterator(); + } + + // add a single point to the cluster it is closest to + public void add(ClusterPoint x) { + int idx = getClosestClusterIndex(x); + // yes, less efficient than inlining the getClosestClusterIndex + // but, saves some code duplication + double dist = clusters.get(idx).distanceTo(x); + + + if (dist < CLUSTER_ADD_FACTOR*this.getMaximumInterClusterDistance()) { + // add it to the closest cluster + clusters.get(idx).add(x); + } else { + // should add a new cluster, because it's outside of the radius of any other, i.e. an outlier + if (clusters.size() < maxNumClusters) { + // yes, we are not yet at our maximum number of clusters! + Cluster c = new Cluster(x); + c.visionGraph = (HashMap) ((HashMap)clusters.get(idx).visionGraph).clone(); // clone the vision graph of the closest cluster + clusters.add(c); +// System.out.println("CLUSTER ADD "+c); + } else { + // we're already at the max number of clusters, so add it to the closest cluster + // this is basically where we become a voronoi diagram + clusters.get(idx).add(x); + } + }//*/ + + // keep track of cluster 'relevance' and remove irrelevant clusters + if (clusters.size() > 1) { // at least have one cluster... :P + Iterator it = clusters.iterator(); + while (it.hasNext()) { + Cluster c = it.next(); + if (c.decrementRelevance()) { + //System.out.println("Removing cluster "+c); + it.remove(); +// System.out.println("CLUSTER REMOVE "+c); + // maybe merge it? + } + } + } + } + + public String toString() { + String r = ""; + + for (int i = 0; i < clusters.size(); i++) { + r += clusters.get(i).toString() + "\n"; + } + + return r; + } +}; + diff --git a/src/epics/camsim/core/CameraController.java b/src/epics/camsim/core/CameraController.java index a493d91..e67b6b2 100644 --- a/src/epics/camsim/core/CameraController.java +++ b/src/epics/camsim/core/CameraController.java @@ -412,6 +412,8 @@ public IMessage sendMessage(String to, MessageType msgType, Object content){ stats.addCommunication(1.0, this.getName()); } else if (msgType == MessageType.StartTracking) { stats.addHandover(1.0); + } else if(msgType == MessageType.Found){ + stats.addBid(); } } catch (Exception e) { e.printStackTrace(); @@ -645,4 +647,26 @@ public int objectIsVisible(ITrObjectRepresentation tor) { return 1; } } + + @Override + public boolean isObjectInFOV(TraceableObject tor){ + return visible_objects.containsKey(tor); + } + + @Override + public Coordinate2D getPostion() { + return new Coordinate2D(x, y); + } + + @Override + public boolean isCoordinateInFOV(Coordinate2D pos) { + final double dist = Math.hypot(pos.getX(), pos.getY()); + if(dist < range) { + final double angle = Math.atan2(pos.getY(), pos.getX()); + final double angleS = (Math.PI-viewing_angle)/2; + final double angleF = (Math.PI+viewing_angle) /2; + return angleS < angle && angle < angleF; + } + return false; + } } diff --git a/src/epics/camsim/core/SimCore.java b/src/epics/camsim/core/SimCore.java index af40e77..f0c6b96 100644 --- a/src/epics/camsim/core/SimCore.java +++ b/src/epics/camsim/core/SimCore.java @@ -31,1192 +31,1286 @@ import epics.commpolicy.Step; /** - * SimCore represents the main core of the simulation. each object and camera is controlled from here. - * the SimCore drives the simulation in discrete time steps. + * SimCore represents the main core of the simulation. each object and camera is + * controlled from here. the SimCore drives the simulation in discrete time + * steps. + * * @author Marcin Bogdanski */ public class SimCore { - int CAMERRORRATE = -1; //percent of camera error. -1 = no camera error - int RESETRATE = 50; //looses knowledge about everything - happens in x percentage of cameraerror (only when error occurs, knowledgeloss can happen) + int CAMERRORRATE = -1; // percent of camera error. -1 = no camera error + int RESETRATE = 50; // looses knowledge about everything - happens in x + // percentage of cameraerror (only when error occurs, + // knowledgeloss can happen) static final boolean BIDIRECTIONAL_VISION = true; boolean USEGLOBAL = false; String EPSILONGREEDY = "epics.learning.EpsilonGreedy"; private double epsilon = 0.1; double alpha = 0.5; - private int selectInterval = 0; //if < 1, a new strategy is selected every timestep + private int selectInterval = 0; // if < 1, a new strategy is selected every + // timestep private int currentSelectInt = 0; - + Statistics stats; RandomNumberGenerator randomGen; - + int interval = 1; - - static int camIDGenerator = 0; - public static int getNextID(){ return camIDGenerator++; } - - /* - * Simulation area - */ - private double min_x; - /** - * returns the minimum x value for the simulation environment - * @return minimum x of simulation environment - */ - public double get_min_x(){return min_x;} - private double max_x; - /** - * returns the maximum x value for the simulation environment - * @return maximum x of simulation environment - */ - public double get_max_x(){return max_x;} - private double min_y; - /** - * returns the minimum y value for the simulation environment - * @return minimum y of simulation environment - */ - public double get_min_y(){return min_y;} - private double max_y; - /** - * returns the maximum y value for the simulation environment - * @return maximum y of simulation environment - */ - public double get_max_y(){return max_y;} - private long sim_time; - /** - * returns the maximum simulation time - * @return maximum simulation time - */ - public long get_sim_time(){return sim_time;} - private String ai_alg; public boolean staticVG = false; - - private boolean firstUpdate; - private ArrayList events; - private boolean _runReal; - private int step; - - private IRegistration reg = null; - private SimSettings settings; - private String paramFile; - - - /** - * checks if the given coordinates are in range - * throws a IllegalArgumentException if they are not - * @param x - * @param y - */ - private void checkCoordInRange( double x, double y ){ - if ( x < min_x || x > max_x || y < min_y || y > max_y ){ - throw new IllegalArgumentException("x/y value out of simulation field."); - } - } - - private ArrayList cameras = new ArrayList(); - private ArrayList objects = new ArrayList(); + + static int camIDGenerator = 0; + + public static int getNextID() { + return camIDGenerator++; + } + + /* + * Simulation area + */ + private double min_x; + + /** + * returns the minimum x value for the simulation environment + * + * @return minimum x of simulation environment + */ + public double get_min_x() { + return min_x; + } + + private double max_x; + + /** + * returns the maximum x value for the simulation environment + * + * @return maximum x of simulation environment + */ + public double get_max_x() { + return max_x; + } + + private double min_y; + + /** + * returns the minimum y value for the simulation environment + * + * @return minimum y of simulation environment + */ + public double get_min_y() { + return min_y; + } + + private double max_y; + + /** + * returns the maximum y value for the simulation environment + * + * @return maximum y of simulation environment + */ + public double get_max_y() { + return max_y; + } + + private long sim_time; + + /** + * returns the maximum simulation time + * + * @return maximum simulation time + */ + public long get_sim_time() { + return sim_time; + } + + private String ai_alg; + public boolean staticVG = false; + + private boolean firstUpdate; + private ArrayList events; + private boolean _runReal; + private int step; + + private IRegistration reg = null; + private SimSettings settings; + private String paramFile; + + /** + * checks if the given coordinates are in range throws a + * IllegalArgumentException if they are not + * + * @param x + * @param y + */ + private void checkCoordInRange(double x, double y) { + if (x < min_x || x > max_x || y < min_y || y > max_y) { + throw new IllegalArgumentException("x/y value out of simulation field."); + } + } + + private ArrayList cameras = new ArrayList(); + private ArrayList objects = new ArrayList(); private AbstractCommunication _comm = null; private String outputFile; - /** * Constructor pure simulation - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param ss settings of simulations - generated from an scenariofile - * @param global global coordination used - * @param camError the probability of failing cameras - * @param camReset probability of a reset after a camera failed + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param ss + * settings of simulations - generated from an scenariofile + * @param global + * global coordination used + * @param camError + * the probability of failing cameras + * @param camReset + * probability of a reset after a camera failed */ - public SimCore( long seed, String output, SimSettings ss, boolean global){ + public SimCore(long seed, String output, SimSettings ss, boolean global) { initSimCore(seed, output, global, -1, 50, alpha, false, false, "", null); this.interpretFile(ss); } - /** - * Constructor pure simulation - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param ss settings of simulations - generated from an scenariofile - * @param global global coordination used - * @param banditParam the epsilon/temperature value for bandit solvers - * @param alpha the alpha value for the weighted reward function used in bandit solvers + * Constructor pure simulation + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param ss + * settings of simulations - generated from an scenariofile + * @param global + * global coordination used + * @param banditParam + * the epsilon/temperature value for bandit solvers + * @param alpha + * the alpha value for the weighted reward function used in + * bandit solvers */ - public SimCore( long seed, String output, SimSettings ss, boolean global, double banditParam, double alpha){ + public SimCore(long seed, String output, SimSettings ss, boolean global, double banditParam, double alpha) { initSimCore(seed, output, global, -1, 50, alpha, false, false, "", null); this.interpretFile(ss); } /** * Constructor - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param ss settings of simulations - generated from an scenariofile - * @param global global coordination used - * @param banditParam the epsilon/temperature value for bandit solvers - * @param alpha the alpha value for the weighted reward function used in bandit solvers - * @param realData indicates if real data has been used - * @param allStatistics indicates if statistics are also taken for each camera seperately + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param ss + * settings of simulations - generated from an scenariofile + * @param global + * global coordination used + * @param banditParam + * the epsilon/temperature value for bandit solvers + * @param alpha + * the alpha value for the weighted reward function used in + * bandit solvers + * @param realData + * indicates if real data has been used + * @param allStatistics + * indicates if statistics are also taken for each camera + * seperately */ - public SimCore( long seed, String output, SimSettings ss, boolean global, double epsilon, double alpha, boolean realData, boolean allStatistics){ + public SimCore(long seed, String output, SimSettings ss, boolean global, double epsilon, double alpha, boolean realData, boolean allStatistics) { initSimCore(seed, output, global, -1, 50, alpha, realData, allStatistics, "", null); this.epsilon = epsilon; - this.interpretFile(ss); + this.interpretFile(ss); } - + /** - * Constructor pure simulation - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param ss settings of simulations - generated from an scenariofile - * @param global global coordination used - * @param camError the probability of failing cameras - * @param camReset probability of a reset after a camera failed - * @param alpha the alpha value for the weighted reward function used in bandit solvers - * @param realData indicates if real data has been used - * @param allStatistics indicates if statistics are also taken for each camera seperately + * Constructor pure simulation + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param ss + * settings of simulations - generated from an scenariofile + * @param global + * global coordination used + * @param camError + * the probability of failing cameras + * @param camReset + * probability of a reset after a camera failed + * @param alpha + * the alpha value for the weighted reward function used in + * bandit solvers + * @param realData + * indicates if real data has been used + * @param allStatistics + * indicates if statistics are also taken for each camera + * seperately */ - public SimCore( long seed, String output, SimSettings ss, - boolean global, int camError, int camReset, double alpha, boolean realData, boolean allStatistics) { - initSimCore(seed, output, global, camError, camReset, - alpha, realData, allStatistics, "", null); + public SimCore(long seed, String output, SimSettings ss, boolean global, int camError, int camReset, double alpha, boolean realData, boolean allStatistics) { + initSimCore(seed, output, global, camError, camReset, alpha, realData, allStatistics, "", null); + this.interpretFile(ss); + } + + /** + * Constructor pure simulation + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param summaryFile + * File for a summarised statistics file + * @param paramFile + * parameterfile for simulations + * @param ss + * settings of simulations - generated from an scenariofile + * @param global + * global coordination used + * @param camError + * the probability of failing cameras + * @param camReset + * probability of a reset after a camera failed + * @param realData + * indicates if real data has been used + * @param allStatistics + * indicates if statistics are also taken for each camera + * seperately + */ + public SimCore(long seed, String output, String summaryFile, String paramFile, SimSettings ss, boolean global, int camError, int camReset, boolean realData, boolean allStatistics) { + initSimCore(seed, output, global, camError, camReset, alpha, realData, allStatistics, summaryFile, paramFile); this.interpretFile(ss); } - - /** - * Constructor pure simulation - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param summaryFile File for a summarised statistics file - * @param paramFile parameterfile for simulations - * @param ss settings of simulations - generated from an scenariofile - * @param global global coordination used - * @param camError the probability of failing cameras - * @param camReset probability of a reset after a camera failed - * @param realData indicates if real data has been used - * @param allStatistics indicates if statistics are also taken for each camera seperately - */ - public SimCore(long seed, String output, String summaryFile, String paramFile, SimSettings ss, - boolean global, int camError, int camReset, boolean realData, boolean allStatistics) { - initSimCore(seed, output, global, camError, camReset, - alpha, realData, allStatistics, summaryFile, paramFile); - this.interpretFile(ss); - } /** * Initiation method for the simcore. Sets all the parameters - * @param seed for the random number generators - * @param output outputfilename for statistics - * @param global global coordination used - * @param camError the probability of failing cameras - * @param camReset probability of a reset after a camera failed - * @param alpha the alpha value for the weighted reward function used in bandit solvers - * @param realData indicates if real data has been used - * @param allStatistics indicates if statistics are also taken for each camera seperately - * @param summaryFile File for a summarised statistics file - * @param paramFile parameterfile for simulations + * + * @param seed + * for the random number generators + * @param output + * outputfilename for statistics + * @param global + * global coordination used + * @param camError + * the probability of failing cameras + * @param camReset + * probability of a reset after a camera failed + * @param alpha + * the alpha value for the weighted reward function used in + * bandit solvers + * @param realData + * indicates if real data has been used + * @param allStatistics + * indicates if statistics are also taken for each camera + * seperately + * @param summaryFile + * File for a summarised statistics file + * @param paramFile + * parameterfile for simulations */ - private void initSimCore(long seed, String output, boolean global, - int camError, int camReset, double alpha, - boolean realData, boolean allStatistics, String summary, String paramFile) { + private void initSimCore(long seed, String output, boolean global, int camError, int camReset, double alpha, boolean realData, boolean allStatistics, String summary, String paramFile) { this.RESETRATE = camReset; - this.CAMERRORRATE = camError; - this.alpha = alpha; - + this.CAMERRORRATE = camError; + this.alpha = alpha; + USEGLOBAL = global; - + _runReal = realData; step = 0; firstUpdate = true; - - if(USEGLOBAL){ - reg = new GlobalRegistration(); - } - - randomGen = new RandomNumberGenerator(seed); - outputFile = output; - if(summary == ""){ - stats = new Statistics(output, "E://Results//sum_result/" + output.substring(output.indexOf('/')+1), allStatistics, randomGen.getSeed()); + + if (USEGLOBAL) { + reg = new GlobalRegistration(); } - else{ + + randomGen = new RandomNumberGenerator(seed); + outputFile = output; + if (summary == "") { + stats = new Statistics(output, "E://Results//sum_result/" + output.substring(output.indexOf('/') + 1), allStatistics, randomGen.getSeed()); + } else { stats = new Statistics(output, summary, allStatistics, randomGen.getSeed()); } - + } - - /** - * Interprets the SimSettings object and creates cameras, vision graphs - * and trackable objects with their corresponding behaviour as well as - * the simulation environment itself - * @param ss The object containing the settings for this simulation - */ - public void interpretFile(SimSettings ss){ - settings = ss; - - if(ss.min_x != null){ - this.min_x = ss.min_x; - } - else{ - this.min_x = -30; - } - if(ss.max_x != null){ - this.max_x = ss.max_x; - } - else{ - this.max_x = 30; - } - if(ss.min_y != null){ - this.min_y = ss.min_y; - } - else{ - this.min_y = -30; - } - if(ss.max_y != null){ - this.max_y = ss.max_y; - } - else{ - this.max_y = 30; - } - - if(ss.visionGraph != null){ - staticVG = ss.visionGraph.isStatic; - } - - - for (SimSettings.CameraSettings cs : ss.cameras){ - Map vg = null; - - if(ss.visionGraph != null){ - vg = new HashMap(); - if(ss.visionGraph.vg.containsKey(cs.name)){ - ArrayList neighs = ss.visionGraph.vg.get(cs.name); - for(String s : neighs){ - vg.put(s, 1.0); - } - } - - if(staticVG){ - for(Map.Entry> all : ss.visionGraph.vg.entrySet()){ - if(all.getValue().contains(cs.name)) - vg.put(all.getKey(), 1.0); - } - } - } - - this.add_camera( - cs.name, cs.x, cs.y, - cs.heading, cs.viewing_angle, - cs.range, cs.ai_algorithm, - cs.comm, cs.customComm, - cs.limit, vg, cs.bandit, - cs.predefConfidences, cs.predefVisibility); - } - - for (SimSettings.TrObjectSettings tro : ss.objects){ - this.add_object(tro.x, tro.y, tro.heading, tro.speed, tro.features); - } - - for (TrObjectWithWaypoints objWithWP : ss.objectsWithWaypoints) { - this.add_object(objWithWP.speed, objWithWP.waypoints, objWithWP.features); - } - - events = ss.events; - } - - /** Writes statistics and closes all statistics files */ - public void close_files(){ - try { + + /** + * Interprets the SimSettings object and creates cameras, vision graphs and + * trackable objects with their corresponding behaviour as well as the + * simulation environment itself + * + * @param ss + * The object containing the settings for this simulation + */ + public void interpretFile(SimSettings ss) { + settings = ss; + + if (ss.min_x != null) { + this.min_x = ss.min_x; + } else { + this.min_x = -30; + } + if (ss.max_x != null) { + this.max_x = ss.max_x; + } else { + this.max_x = 30; + } + if (ss.min_y != null) { + this.min_y = ss.min_y; + } else { + this.min_y = -30; + } + if (ss.max_y != null) { + this.max_y = ss.max_y; + } else { + this.max_y = 30; + } + + if (ss.visionGraph != null) { + staticVG = ss.visionGraph.isStatic; + } + + for (SimSettings.CameraSettings cs : ss.cameras) { + Map vg = null; + + if (ss.visionGraph != null) { + vg = new HashMap(); + if (ss.visionGraph.vg.containsKey(cs.name)) { + ArrayList neighs = ss.visionGraph.vg.get(cs.name); + for (String s : neighs) { + vg.put(s, 1.0); + } + } + + if (staticVG) { + for (Map.Entry> all : ss.visionGraph.vg.entrySet()) { + if (all.getValue().contains(cs.name)) + vg.put(all.getKey(), 1.0); + } + } + } + + this.add_camera(cs.name, cs.x, cs.y, cs.heading, cs.viewing_angle, cs.range, cs.ai_algorithm, cs.comm, cs.customComm, cs.limit, vg, cs.bandit, cs.predefConfidences, cs.predefVisibility); + } + + for (SimSettings.TrObjectSettings tro : ss.objects) { + this.add_object(tro.x, tro.y, tro.heading, tro.speed, tro.features); + } + + for (TrObjectWithWaypoints objWithWP : ss.objectsWithWaypoints) { + this.add_object(objWithWP.speed, objWithWP.waypoints, objWithWP.features); + } + + events = ss.events; + } + + /** Writes statistics and closes all statistics files */ + public void close_files() { + try { stats.close(); } catch (Exception e) { e.printStackTrace(); } - } - - /** Outputs all information from all bandit solvers into files */ - private void printAllBanditResults(){ - for(CameraController cc : this.cameras){ + } + + /** Outputs all information from all bandit solvers into files */ + private void printAllBanditResults() { + for (CameraController cc : this.cameras) { IBanditSolver bs = cc.getAINode().getBanditSolver(); - if(bs != null){ + if (bs != null) { ArrayList> results = bs.getResults(); printResults(results, outputFile + "_" + cc.getName() + ".csv"); } - + } - } - - /** - * Convenience method to print arrayLists within ArrayLists into - * specific files - * @param res results to be stored in file - * @param filename the filename to store results to - */ - private void printResults(ArrayList> res, String filename){ + } + + /** + * Convenience method to print arrayLists within ArrayLists into specific + * files + * + * @param res + * results to be stored in file + * @param filename + * the filename to store results to + */ + private void printResults(ArrayList> res, String filename) { File f = new File(filename); PrintWriter out; try { FileWriter fw = new FileWriter(f); out = new PrintWriter(fw); int size = res.get(0).size(); - for(int j = 0; j < size; j++){ - for(int i = 0; i < res.size()-1; i++){ + for (int j = 0; j < size; j++) { + for (int i = 0; i < res.size() - 1; i++) { out.print(res.get(i).get(j) + ";"); } - out.println(res.get(res.size()-1).get(j)); + out.println(res.get(res.size() - 1).get(j)); } out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } - + } - /** - * Creates a new camera and adds it to the list of cameras WITH an AINODE as parameter - * @param name defines the name of the camera - * @param x_pos defines the x position in the internal coordinates - * @param y_pos defines the y position in the internal coordinates - * @param heading_degrees defines the direction of the viewing point - * @param angle_degrees defines the width of the viewing angle - * @param range defines the range (distance) of the camera's view - * @param ai_algorithm defines the initial algorithm approach used - * @param comm defines the initial/predefined communication strategy - * @param limit sets limit for amount of objects being tracked (0 = unlimited) - * @param vg contains the predefined vision graph - * @param bandit defines the used bandit solver algorithm - * @param predefConfidences defines a list of objects represented by an ArrayList of - * their confidences where each element is for one frame/timestep - * @param predefVisibility defines a list of objects represented by an ArrayList of - * their visibility (0 = visible, 1 = not visible or at touching border) where each - * element is for one frame/timestep + /** + * Creates a new camera and adds it to the list of cameras WITH an AINODE as + * parameter + * + * @param name + * defines the name of the camera + * @param x_pos + * defines the x position in the internal coordinates + * @param y_pos + * defines the y position in the internal coordinates + * @param heading_degrees + * defines the direction of the viewing point + * @param angle_degrees + * defines the width of the viewing angle + * @param range + * defines the range (distance) of the camera's view + * @param ai_algorithm + * defines the initial algorithm approach used + * @param comm + * defines the initial/predefined communication strategy + * @param limit + * sets limit for amount of objects being tracked (0 = unlimited) + * @param vg + * contains the predefined vision graph + * @param bandit + * defines the used bandit solver algorithm + * @param predefConfidences + * defines a list of objects represented by an ArrayList of their + * confidences where each element is for one frame/timestep + * @param predefVisibility + * defines a list of objects represented by an ArrayList of their + * visibility (0 = visible, 1 = not visible or at touching + * border) where each element is for one frame/timestep */ - public void add_camera( - String name, - double x_pos, double y_pos, - double heading_degrees, - double angle_degrees, - double range, - String ai_algorithm, - int commValue, - String customComm, - int limit, - Map vg, - String bandit, - ArrayList> predefConfidences, - ArrayList> predefVisibility){ - - ai_alg = ai_algorithm; - add_camera( - name, x_pos, y_pos, heading_degrees, angle_degrees, - range, commValue, customComm, limit, vg, bandit, - predefConfidences, predefVisibility); - } - - /** - * Creates a new camera and adds it to the list of cameras all having the same predefined aiNode - * @param name defines the name of the camera - * @param x_pos defines the x position in the internal coordinates - * @param y_pos defines the y position in the internal coordinates - * @param heading_degrees defines the direction of the viewing point - * @param angle_degrees defines the width of the viewing angle - * @param range defines the range (distance) of the camera's view - * @param comm defines the initial/predefined communication strategy - * @param limit sets limit for amount of objects being tracked (0 = unlimited) - * @param vg contains the predefined vision graph - * @param bandit defines the used bandit solver algorithm - * @param predefConfidences defines a list of objects represented by an ArrayList of - * their confidences where each element is for one frame/timestep - * @param predefVisibility defines a list of objects represented by an ArrayList of - * their visibility (0 = visible, 1 = not visible or at touching border) where each - * element is for one frame/timestep - */ - public void add_camera( - String name, - double x_pos, double y_pos, - double heading_degrees, - double angle_degrees, - double range, - int commValue, - String customComm, - int limit, - Map vg, - String bandit, - ArrayList> predefConfidences, - ArrayList> predefVisibility){ - - checkCoordInRange(x_pos, y_pos); - - AbstractAINode aiNode = null; - try { - aiNode = newAINodeFromName(ai_alg, staticVG, vg, reg, bandit); - } catch (Exception e) { - System.out.println("Couldn't initialise AI Node from name given in scenario file: "+ai_alg); - System.out.println("Is it a fully qualified class name? e.g. 'epics.ai.ActiveAINodeMulti'"); - e.printStackTrace(); - System.exit(1); - } - - CameraController cc = new CameraController( - name, - x_pos, y_pos, - Math.toRadians(heading_degrees), - Math.toRadians(angle_degrees), - range, aiNode, limit, stats, randomGen, predefConfidences, predefVisibility); - - - try { - Class[] commConstructorTypes = {AbstractAINode.class, ICameraController.class}; - Class commClass = getCommClass(commValue, customComm); - Constructor cons = commClass.getConstructor(commConstructorTypes); - _comm = (AbstractCommunication) cons.newInstance(aiNode, cc); - aiNode.setComm(_comm); - } catch (Exception e) { - System.err.println("Failed to create a communication class"); + public void add_camera(String name, double x_pos, double y_pos, double heading_degrees, double angle_degrees, double range, String ai_algorithm, int commValue, String customComm, int limit, Map vg, String bandit, ArrayList> predefConfidences, ArrayList> predefVisibility) { + + ai_alg = ai_algorithm; + add_camera(name, x_pos, y_pos, heading_degrees, angle_degrees, range, commValue, customComm, limit, vg, bandit, predefConfidences, predefVisibility); + } + + /** + * Creates a new camera and adds it to the list of cameras all having the + * same predefined aiNode + * + * @param name + * defines the name of the camera + * @param x_pos + * defines the x position in the internal coordinates + * @param y_pos + * defines the y position in the internal coordinates + * @param heading_degrees + * defines the direction of the viewing point + * @param angle_degrees + * defines the width of the viewing angle + * @param range + * defines the range (distance) of the camera's view + * @param comm + * defines the initial/predefined communication strategy + * @param limit + * sets limit for amount of objects being tracked (0 = unlimited) + * @param vg + * contains the predefined vision graph + * @param bandit + * defines the used bandit solver algorithm + * @param predefConfidences + * defines a list of objects represented by an ArrayList of their + * confidences where each element is for one frame/timestep + * @param predefVisibility + * defines a list of objects represented by an ArrayList of their + * visibility (0 = visible, 1 = not visible or at touching + * border) where each element is for one frame/timestep + */ + public void add_camera(String name, double x_pos, double y_pos, double heading_degrees, double angle_degrees, double range, int commValue, String customComm, int limit, Map vg, String bandit, ArrayList> predefConfidences, ArrayList> predefVisibility) { + + checkCoordInRange(x_pos, y_pos); + + AbstractAINode aiNode = null; + try { + aiNode = newAINodeFromName(ai_alg, staticVG, vg, reg, bandit); + } catch (Exception e) { + System.out.println("Couldn't initialise AI Node from name given in scenario file: " + ai_alg); + System.out.println("Is it a fully qualified class name? e.g. 'epics.ai.ActiveAINodeMulti'"); + e.printStackTrace(); + System.exit(1); + } + + CameraController cc = new CameraController(name, x_pos, y_pos, Math.toRadians(heading_degrees), Math.toRadians(angle_degrees), range, aiNode, limit, stats, randomGen, predefConfidences, predefVisibility); + + try { + Class[] commConstructorTypes = { AbstractAINode.class, ICameraController.class }; + Class commClass = getCommClass(commValue, customComm); + Constructor cons = commClass.getConstructor(commConstructorTypes); + _comm = (AbstractCommunication) cons.newInstance(aiNode, cc); + aiNode.setComm(_comm); + } catch (Exception e) { + System.err.println("Failed to create a communication class"); e.printStackTrace(); System.exit(1); } - - try { - if (paramFile != null) { - this.applyParamsToAINode(aiNode, paramFile); - } - } catch (IOException e) { - System.out.println("Couldn't read ParamFile: " + paramFile); - e.printStackTrace(); - System.exit(1); - } - - if(USEGLOBAL){ - reg.addCamera(cc); - } - - this.getCameras().add(cc); - for (CameraController c1 : this.cameras){ - c1.addCamera(cc); - cc.addCamera(c1); - } + + try { + if (paramFile != null) { + this.applyParamsToAINode(aiNode, paramFile); + } + } catch (IOException e) { + System.out.println("Couldn't read ParamFile: " + paramFile); + e.printStackTrace(); + System.exit(1); + } + + if (USEGLOBAL) { + reg.addCamera(cc); + } + + this.getCameras().add(cc); + for (CameraController c1 : this.cameras) { + c1.addCamera(cc); + cc.addCamera(c1); + } } - - public Class getCommClass(int commValue, String customComm) throws ClassNotFoundException { - switch(commValue){ - case 0: return Broadcast.class; - case 1: return Smooth.class; - case 2: return Step.class; - case 4: - if (customComm == null || customComm.equals("")) { - throw new IllegalArgumentException("No CustomComm value provided"); - } - Class nodeType = Class.forName(customComm); - return (Class) nodeType; - default: - throw new IllegalArgumentException("Comm value provided is invalid: "+commValue); - + + public Class getCommClass(int commValue, String customComm) throws ClassNotFoundException { + switch (commValue) { + case 0: + return Broadcast.class; + case 1: + return Smooth.class; + case 2: + return Step.class; + case 4: + if (customComm == null || customComm.equals("")) { + throw new IllegalArgumentException("No CustomComm value provided"); + } + Class nodeType = Class.forName(customComm); + return (Class) nodeType; + default: + throw new IllegalArgumentException("Comm value provided is invalid: " + commValue); + } - } - - /** Given a node's class name, dynamically loads the class and - * instantiates a new node of that type using reflection - * @param fullyQualifiedClassName the class name - has to include package - * name if not in the same package. eg.: epics.ai.ActiveAINodeMulti - * @param comm the communication policy: 0 = Broadcast, 1 = Smooth, 2 = step - * @param staticVG defines if VG is static as predefined or can change dynamically - * @param vg a predefined VG - may or may not change over time - * @param r a global registration - * @param banditS the class name of a bandit solver - * @return AbstractAINode the created AINode - * @throws ClassNotFoundException if the class for the AINode or the BanditSolver wasn't found - */ - public AbstractAINode newAINodeFromName(String fullyQualifiedClassName, - boolean staticVG, Map vg, IRegistration r, String banditS) - throws ClassNotFoundException, SecurityException, NoSuchMethodException, - IllegalArgumentException, InstantiationException, IllegalAccessException, - InvocationTargetException { - IBanditSolver bs = null; - try { - if(banditS != null){ - if(!banditS.equals("")){ + } + + /** + * Given a node's class name, dynamically loads the class and instantiates a + * new node of that type using reflection + * + * @param fullyQualifiedClassName + * the class name - has to include package name if not in the + * same package. eg.: epics.ai.ActiveAINodeMulti + * @param comm + * the communication policy: 0 = Broadcast, 1 = Smooth, 2 = step + * @param staticVG + * defines if VG is static as predefined or can change + * dynamically + * @param vg + * a predefined VG - may or may not change over time + * @param r + * a global registration + * @param banditS + * the class name of a bandit solver + * @return AbstractAINode the created AINode + * @throws ClassNotFoundException + * if the class for the AINode or the BanditSolver wasn't found + */ + public AbstractAINode newAINodeFromName(String fullyQualifiedClassName, boolean staticVG, Map vg, IRegistration r, String banditS) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { + IBanditSolver bs = null; + try { + if (banditS != null) { + if (!banditS.equals("")) { Class banditType = Class.forName(banditS); - Class[] banditConstructorTypes = {int.class, double.class, double.class, int.class, RandomNumberGenerator.class}; + Class[] banditConstructorTypes = { int.class, double.class, double.class, int.class, RandomNumberGenerator.class }; Constructor banditCons = banditType.getConstructor(banditConstructorTypes); - bs = (IBanditSolver) banditCons.newInstance(6, epsilon, alpha, interval, randomGen); - } - } + bs = (IBanditSolver) banditCons.newInstance(6, epsilon, alpha, interval, randomGen); + } + } } catch (ClassNotFoundException e) { - if(!banditS.equals("")) - System.out.println("AAAHHH " + banditS + " not found..."); + if (!banditS.equals("")) + System.out.println("AAAHHH " + banditS + " not found..."); } - - Class nodeType = Class.forName(fullyQualifiedClassName); - Class[] constructorTypes = {boolean.class, Map.class, IRegistration.class, RandomNumberGenerator.class, IBanditSolver.class}; - Constructor cons = nodeType.getConstructor(constructorTypes); - AbstractAINode node = (AbstractAINode) cons.newInstance(staticVG, vg, r, randomGen, bs); - return node; - } - - /** - * Creates an AINode from an existing one using reflection. Clones the contents of the existing node into the new one. - * @param fullyQualifiedClassName the class name - has to include package name if not in the same package. eg.: epics.ai.ActiveAINodeMulti - * @param comm the communication policy: 0 = Broadcast, 1 = Smooth, 2 = step - * @param ai the pre-existing AINode - * @return a specific implementation of an abstract AINode - */ - public AbstractAINode newAINodeFromName(String fullyQualifiedClassName, - AbstractCommunication comm, AbstractAINode ai) - throws ClassNotFoundException, SecurityException, NoSuchMethodException, - IllegalArgumentException, InstantiationException, IllegalAccessException, - InvocationTargetException { - Class nodeType = Class.forName(fullyQualifiedClassName); - Class[] constructorTypes = {AbstractAINode.class}; - Constructor[] allCons = nodeType.getDeclaredConstructors(); - - Constructor cons = nodeType.getConstructor(constructorTypes); - AbstractAINode node = (AbstractAINode) cons.newInstance(ai); - node.setComm(comm); - return node; - } - - /** - * Given a file which contains parameters for our run, we run through - * the params and apply each one to the AI node. This is mainly to aid - * running of experiments, where the necessary parameters can be applied - * to the node for a particular run, then the params file is changed for - * the next run - * @param node to apply parameters to - * @param paramsFilepath contains the filepath for the parameterfile - * @throws IOException in case opening of file fails - */ - public void applyParamsToAINode(AbstractAINode node, String paramsFilepath) throws IOException { - RunParams.loadIfNotLoaded(paramsFilepath); - System.out.println("Setting params for " + node.getName() + "..."); - Set> props = RunParams.getAllProperties(); - for (Entry prop : props) { - String key = (String) prop.getKey(); - String value = (String) prop.getValue(); - if (! node.setParam(key, value)) { - throw new IllegalStateException("Param "+key+" could not be applied"); - } - } - } - - /** - * adds a camera with random position, oritentation, range and angle - */ - public void add_random_camera(){ - int absCom = randomGen.nextInt(3, RandomUse.USE.UNIV); // Random comm - - String algo = ""; - switch(randomGen.nextInt(2, RandomUse.USE.UNIV)){ - case 0: algo = "epics.ai.ActiveAINodeMulti"; break; - case 1: algo = "epics.ai.PassiveAINodeMulti"; break; - } - - this.add_camera( - "C"+getNextID(), - randomGen.nextDouble(RandomUse.USE.UNIV) * (max_x - min_x) + min_x, - randomGen.nextDouble(RandomUse.USE.UNIV) * (max_y - min_y) + min_y, - randomGen.nextDouble(RandomUse.USE.UNIV) * 360, - randomGen.nextDouble(RandomUse.USE.UNIV) * 90 + 15, - randomGen.nextDouble(RandomUse.USE.UNIV) * 20 + 10, - algo, - absCom, - null, // No custom comm - 0, null, "", null, null); - } - - /** - * removes a certain camera based on the index in the list - * - * !! removed cameras can not be recoverd !! - * @param remove_index list index - */ - public void remove_camera_index( int remove_index ){ - CameraController cc = null; - if ( remove_index < this.cameras.size() ){ - cc = this.cameras.remove(remove_index); - } - - if(USEGLOBAL){ - if(cc != null) - reg.removeCamera(cc); - } - } - - /** - * removes a camera with a certain name - * - * !! removed cameras can not be recoverd !! - * @param name name of the camera to remove - */ - public void remove_camera( String name ){ - int remove_index = -1; - for ( int i = 0; i < this.cameras.size(); i++ ){ - System.out.println(this.cameras.get(i).getName()); - if ( this.cameras.get(i).getName().equals(name) ){ - remove_index = i; - } - } - CameraController cc = null; - if ( remove_index != -1 ){ - cc = this.cameras.remove(remove_index); - } - if(USEGLOBAL){ - if(cc != null) - reg.removeCamera(cc); - } - } - - /** - * removes a random camera from the list of cameras. - * - * !! removed cameras can not be recoverd !! - */ - public void remove_random_camera(){ - if ( this.cameras.isEmpty()){ - return; - } - int rnd_int = randomGen.nextInt( this.cameras.size(), RandomUse.USE.UNIV ); - CameraController cam_to_remove = this.cameras.get(rnd_int); - for ( CameraController c : this.cameras ){ - c.removeCamera( cam_to_remove ); - } - this.cameras.remove(cam_to_remove); - if(USEGLOBAL){ - reg.removeCamera(cam_to_remove); - } - } - - /** - * Removes all cameras and creates the same amount of new random cameras - * - * !! removed cameras can not be recoverd !! - */ - public void recreate_cameras(){ - int num_camers = cameras.size(); - cameras.clear(); - for ( int i = 0; i < num_camers; i++ ){ - this.add_random_camera(); - } - for(TraceableObject to : this.getObjects()){ - if(USEGLOBAL){ - reg.advertiseGlobally(new TraceableObjectRepresentation(to, to.getFeatures())); - } - for(CameraController cc : this.getCameras()){ - if(!cc.isOffline()) - cc.getAINode().receiveMessage(new Message("", cc.getName(), MessageType.StartSearch, new TraceableObjectRepresentation(to, to.getFeatures()))); - } - } - } - - /** - * Adds object to the simulation with specified parameters. - * starting position has to be within the simulation environment. - * - * @param pos_x starting position - * @param pos_y starting position - * @param heading_degrees initial direction of movement - * @param speed speed of the object - * @param features unique identification of the object - */ - public void add_object( - double pos_x, double pos_y, - double heading_degrees, double speed, - double features ){ - TraceableObject to = new TraceableObject(features, this, pos_x, pos_y, Math.toRadians(heading_degrees), speed, randomGen); - add_object(to); - } - - /** - * Adds object to the simulation with specified parameters. - * starting position has to be within the simulation environment. - * - * creates random unique features for this object - * - * @param pos_x starting position - * @param pos_y starting position - * @param heading_degrees initial direction of movement - * @param speed speed of the object - */ - public void add_object(double pos_x, double pos_y, double heading_degrees, double speed){ - double features = 0.111 * getNextID(); - add_object(pos_x, pos_y, heading_degrees, speed, features); - } - - /** - * Adds object to the simulation with specified parameters and a predefined path. - * starting position and waypoints have to be within the simulation environment. - * - * @param speed speed of the object - * @param waypoints given waypoints. after last waypoint returns to first waypoint - * @param id unique id/features of object - */ - public void add_object(double speed, List waypoints, double features){ - TraceableObject to = new TraceableObject(features, this, speed, waypoints, randomGen); - add_object(to); - } - - /** - * Adds the given TraceableObject to the simulation. - * For convenience methods, see other add_object methods - */ - public void add_object(TraceableObject to) { - this.getObjects().add(to); - if(USEGLOBAL){ - reg.advertiseGlobally(new TraceableObjectRepresentation(to, to.getFeatures())); - } else { - for (CameraController cc : this.getCameras()) { - if (!cc.isOffline()) - cc.getAINode().receiveMessage( - new Message("", cc.getName(), MessageType.StartSearch, new TraceableObjectRepresentation(to, to.getFeatures()))); - } - } - } - - /** - * adds an object at random position with random direction and speed. - */ - public void add_random_object(){ - add_object( - randomGen.nextDouble(RandomUse.USE.UNIV) * (max_x - min_x) + min_x, - randomGen.nextDouble(RandomUse.USE.UNIV) * (max_y - min_y) + min_y, - randomGen.nextDouble(RandomUse.USE.UNIV) * 360, - randomGen.nextDouble(RandomUse.USE.UNIV) * 0.6 + 0.4); - } - - /** - * removes a random object from all objects - */ - public void remove_random_object(){ - if(this.objects.isEmpty()){ - return; - } - - int rnd = randomGen.nextInt(objects.size() , RandomUse.USE.UNIV); - TraceableObject obj_to_remove = this.objects.get(rnd); - - for (CameraController c : this.cameras){ - c.removeObject(obj_to_remove.getFeatures()); - } - this.objects.remove(rnd); - } - - - /** - * Updates the simulation by one step - decides if it uses pure simulation or works with real data - */ - public void update() throws Exception{ - if(_runReal){ - updateReal(); - } - else{ - updateSim(); - } - firstUpdate = false; - step ++; - } - - //TODO: FIX SEQUENCE!! - /** - * updates the simulation by one timestep. using real data this corresponds to one frame. - * - * 1. for all cameras - * a. all objects visibility and confidence is updated. - * b. banditsolver selects strategy if applicable. - * 2. for all cameras - * a. AINode is updated - * b. BanditSolver reward is updated if applicable - * 3. statistics are updated - */ - public void updateReal() throws Exception{ - if(firstUpdate) - setSearchFor(); - - // Update all traceable objects (move them around) --> not really, just get the confidence for all objects - for( CameraController c : this.cameras ){ + + Class nodeType = Class.forName(fullyQualifiedClassName); + Class[] constructorTypes = { boolean.class, Map.class, IRegistration.class, RandomNumberGenerator.class, IBanditSolver.class }; + Constructor cons = nodeType.getConstructor(constructorTypes); + AbstractAINode node = (AbstractAINode) cons.newInstance(staticVG, vg, r, randomGen, bs); + return node; + } + + /** + * Creates an AINode from an existing one using reflection. Clones the + * contents of the existing node into the new one. + * + * @param fullyQualifiedClassName + * the class name - has to include package name if not in the + * same package. eg.: epics.ai.ActiveAINodeMulti + * @param comm + * the communication policy: 0 = Broadcast, 1 = Smooth, 2 = step + * @param ai + * the pre-existing AINode + * @return a specific implementation of an abstract AINode + */ + public AbstractAINode newAINodeFromName(String fullyQualifiedClassName, AbstractCommunication comm, AbstractAINode ai) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { + Class nodeType = Class.forName(fullyQualifiedClassName); + Class[] constructorTypes = { AbstractAINode.class }; + Constructor[] allCons = nodeType.getDeclaredConstructors(); + + Constructor cons = nodeType.getConstructor(constructorTypes); + AbstractAINode node = (AbstractAINode) cons.newInstance(ai); + node.setComm(comm); + return node; + } + + /** + * Given a file which contains parameters for our run, we run through the + * params and apply each one to the AI node. This is mainly to aid running + * of experiments, where the necessary parameters can be applied to the node + * for a particular run, then the params file is changed for the next run + * + * @param node + * to apply parameters to + * @param paramsFilepath + * contains the filepath for the parameterfile + * @throws IOException + * in case opening of file fails + */ + public void applyParamsToAINode(AbstractAINode node, String paramsFilepath) throws IOException { + RunParams.loadIfNotLoaded(paramsFilepath); + System.out.println("Setting params for " + node.getName() + "..."); + Set> props = RunParams.getAllProperties(); + for (Entry prop : props) { + String key = (String) prop.getKey(); + String value = (String) prop.getValue(); + if (!node.setParam(key, value)) { + throw new IllegalStateException("Param " + key + " could not be applied"); + } + } + } + + /** + * adds a camera with random position, oritentation, range and angle + */ + public void add_random_camera() { + int absCom = randomGen.nextInt(3, RandomUse.USE.UNIV); // Random comm + + String algo = ""; + switch (randomGen.nextInt(2, RandomUse.USE.UNIV)) { + case 0: + algo = "epics.ai.ActiveAINodeMulti"; + break; + case 1: + algo = "epics.ai.PassiveAINodeMulti"; + break; + } + + this.add_camera("C" + getNextID(), randomGen.nextDouble(RandomUse.USE.UNIV) * (max_x - min_x) + min_x, randomGen.nextDouble(RandomUse.USE.UNIV) * (max_y - min_y) + min_y, randomGen.nextDouble(RandomUse.USE.UNIV) * 360, randomGen.nextDouble(RandomUse.USE.UNIV) * 90 + 15, randomGen.nextDouble(RandomUse.USE.UNIV) * 20 + 10, algo, absCom, null, // No + // custom + // comm + 0, null, "", null, null); + } + + /** + * removes a certain camera based on the index in the list + * + * !! removed cameras can not be recoverd !! + * + * @param remove_index + * list index + */ + public void remove_camera_index(int remove_index) { + CameraController cc = null; + if (remove_index < this.cameras.size()) { + cc = this.cameras.remove(remove_index); + } + + if (USEGLOBAL) { + if (cc != null) + reg.removeCamera(cc); + } + } + + /** + * removes a camera with a certain name + * + * !! removed cameras can not be recoverd !! + * + * @param name + * name of the camera to remove + */ + public void remove_camera(String name) { + int remove_index = -1; + for (int i = 0; i < this.cameras.size(); i++) { + System.out.println(this.cameras.get(i).getName()); + if (this.cameras.get(i).getName().equals(name)) { + remove_index = i; + } + } + CameraController cc = null; + if (remove_index != -1) { + cc = this.cameras.remove(remove_index); + } + if (USEGLOBAL) { + if (cc != null) + reg.removeCamera(cc); + } + } + + /** + * removes a random camera from the list of cameras. + * + * !! removed cameras can not be recoverd !! + */ + public void remove_random_camera() { + if (this.cameras.isEmpty()) { + return; + } + int rnd_int = randomGen.nextInt(this.cameras.size(), RandomUse.USE.UNIV); + CameraController cam_to_remove = this.cameras.get(rnd_int); + for (CameraController c : this.cameras) { + c.removeCamera(cam_to_remove); + } + this.cameras.remove(cam_to_remove); + if (USEGLOBAL) { + reg.removeCamera(cam_to_remove); + } + } + + /** + * Removes all cameras and creates the same amount of new random cameras + * + * !! removed cameras can not be recoverd !! + */ + public void recreate_cameras() { + int num_camers = cameras.size(); + cameras.clear(); + for (int i = 0; i < num_camers; i++) { + this.add_random_camera(); + } + for (TraceableObject to : this.getObjects()) { + if (USEGLOBAL) { + reg.advertiseGlobally(new TraceableObjectRepresentation(to, to.getFeatures())); + } + for (CameraController cc : this.getCameras()) { + if (!cc.isOffline()) + cc.getAINode().receiveMessage(new Message("", cc.getName(), MessageType.StartSearch, new TraceableObjectRepresentation(to, to.getFeatures()))); + } + } + } + + /** + * Adds object to the simulation with specified parameters. starting + * position has to be within the simulation environment. + * + * @param pos_x + * starting position + * @param pos_y + * starting position + * @param heading_degrees + * initial direction of movement + * @param speed + * speed of the object + * @param features + * unique identification of the object + */ + public void add_object(double pos_x, double pos_y, double heading_degrees, double speed, double features) { + TraceableObject to = new TraceableObject(features, this, pos_x, pos_y, Math.toRadians(heading_degrees), speed, randomGen); + add_object(to); + } + + /** + * Adds object to the simulation with specified parameters. starting + * position has to be within the simulation environment. + * + * creates random unique features for this object + * + * @param pos_x + * starting position + * @param pos_y + * starting position + * @param heading_degrees + * initial direction of movement + * @param speed + * speed of the object + */ + public void add_object(double pos_x, double pos_y, double heading_degrees, double speed) { + double features = 0.111 * getNextID(); + add_object(pos_x, pos_y, heading_degrees, speed, features); + } + + /** + * Adds object to the simulation with specified parameters and a predefined + * path. starting position and waypoints have to be within the simulation + * environment. + * + * @param speed + * speed of the object + * @param waypoints + * given waypoints. after last waypoint returns to first waypoint + * @param id + * unique id/features of object + */ + public void add_object(double speed, List waypoints, double features) { + TraceableObject to = new TraceableObject(features, this, speed, waypoints, randomGen); + add_object(to); + } + + /** + * Adds the given TraceableObject to the simulation. For convenience + * methods, see other add_object methods + */ + public void add_object(TraceableObject to) { + this.getObjects().add(to); + if (USEGLOBAL) { + reg.advertiseGlobally(new TraceableObjectRepresentation(to, to.getFeatures())); + } else { + for (CameraController cc : this.getCameras()) { + if (!cc.isOffline()) + cc.getAINode().receiveMessage(new Message("", cc.getName(), MessageType.StartSearch, new TraceableObjectRepresentation(to, to.getFeatures()))); + } + } + } + + /** + * adds an object at random position with random direction and speed. + */ + public void add_random_object() { + add_object(randomGen.nextDouble(RandomUse.USE.UNIV) * (max_x - min_x) + min_x, randomGen.nextDouble(RandomUse.USE.UNIV) * (max_y - min_y) + min_y, randomGen.nextDouble(RandomUse.USE.UNIV) * 360, randomGen.nextDouble(RandomUse.USE.UNIV) * 0.6 + 0.4); + } + + /** + * removes a random object from all objects + */ + public void remove_random_object() { + if (this.objects.isEmpty()) { + return; + } + + int rnd = randomGen.nextInt(objects.size(), RandomUse.USE.UNIV); + TraceableObject obj_to_remove = this.objects.get(rnd); + + for (CameraController c : this.cameras) { + c.removeObject(obj_to_remove.getFeatures()); + } + this.objects.remove(rnd); + } + + /** + * Updates the simulation by one step - decides if it uses pure simulation + * or works with real data + */ + public void update() throws Exception { + if (_runReal) { + updateReal(); + } else { + updateSim(); + } + firstUpdate = false; + step++; + } + + // TODO: FIX SEQUENCE!! + /** + * updates the simulation by one timestep. using real data this corresponds + * to one frame. + * + * 1. for all cameras a. all objects visibility and confidence is updated. + * b. banditsolver selects strategy if applicable. 2. for all cameras a. + * AINode is updated b. BanditSolver reward is updated if applicable 3. + * statistics are updated + */ + public void updateReal() throws Exception { + if (firstUpdate) + setSearchFor(); + + // Update all traceable objects (move them around) --> not really, just + // get the confidence for all objects + for (CameraController c : this.cameras) { c.nextStep(); - if(!c.isOffline()){ - for ( TraceableObject o : this.objects ){ - c.update_confidence_real(step, o ); - } - if(!c.getVisibleObjects_bb().isEmpty()){ - stats.addVisible(); - } + if (!c.isOffline()) { + for (TraceableObject o : this.objects) { + c.update_confidence_real(step, o); + } + if (!c.getVisibleObjects_bb().isEmpty()) { + stats.addVisible(); + } } - - - //run BanditSolver, select next method, set AI! hope it works ;) - AbstractAINode ai = c.getAINode(); - AbstractCommunication prevComm = ai.getComm(); - IBanditSolver bs = ai.getBanditSolver(); - int strategy = -1; - if(bs != null){ -// if(doSelection) - int prevStrat = getStratForAI(ai); - strategy = bs.selectAction(); - if(prevStrat != strategy) - stats.setStrat(strategy, c.getName()); - } - - switch (strategy) { - case 0: //ABC - AbstractAINode newAI1 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Broadcast(ai, c), ai); - c.setAINode(newAI1); - break; - case 1: //ASM - AbstractAINode newAI2 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Smooth(ai, c), ai); - c.setAINode(newAI2); - break; - case 2: //AST - AbstractAINode newAI3 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Step(ai, c),ai); - c.setAINode(newAI3); - break; - case 3: //PBC - AbstractAINode newAI4 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Broadcast(ai, c), ai); - c.setAINode(newAI4); - break; - case 4: //PSM - AbstractAINode newAI5 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Smooth(ai, c), ai); - c.setAINode(newAI5); - break; - case 5: //PST - AbstractAINode newAI6 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Step(ai, c), ai); - c.setAINode(newAI6); - break; - default: - //STICK TO OLD - } - } - - //do trading for all cameras - for( CameraController c : this.cameras ){ - c.updateAI(); - - //check if bandit solvers are used - IBanditSolver bs = c.getAINode().getBanditSolver(); - if(bs != null){ - int nrMessages = c.getAINode().getSentMessages(); - double commOverhead = 0.0; - if(nrMessages > 0){ - commOverhead = (nrMessages-c.getAINode().getNrOfBids()) / nrMessages; // - } - double utility = c.getAINode().getUtility()+c.getAINode().getReceivedUtility() - c.getAINode().getPaidUtility(); - stats.setReward(utility, commOverhead, c.getName()); - bs.setCurrentReward(utility, commOverhead); - } - } - - this.computeUtility(); - stats.nextTimeStep(); - } - - /** - * USED ONLY WITH REAL DATA - */ - private void setSearchFor() { - IMessage im = new Message("", "3.cvs", MessageType.StartSearch, new TraceableObjectRepresentation(this.objects.get(0), this.objects.get(0).getFeatures())); - CameraController cc = this.cameras.get(2); - AbstractAINode ai = cc.getAINode(); + + // run BanditSolver, select next method, set AI! hope it works ;) + AbstractAINode ai = c.getAINode(); + AbstractCommunication prevComm = ai.getComm(); + IBanditSolver bs = ai.getBanditSolver(); + int strategy = -1; + if (bs != null) { + // if(doSelection) + int prevStrat = getStratForAI(ai); + strategy = bs.selectAction(); + if (prevStrat != strategy) + stats.setStrat(strategy, c.getName()); + } + + switch (strategy) { + case 0: // ABC + AbstractAINode newAI1 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Broadcast(ai, c), ai); + c.setAINode(newAI1); + break; + case 1: // ASM + AbstractAINode newAI2 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Smooth(ai, c), ai); + c.setAINode(newAI2); + break; + case 2: // AST + AbstractAINode newAI3 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Step(ai, c), ai); + c.setAINode(newAI3); + break; + case 3: // PBC + AbstractAINode newAI4 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Broadcast(ai, c), ai); + c.setAINode(newAI4); + break; + case 4: // PSM + AbstractAINode newAI5 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Smooth(ai, c), ai); + c.setAINode(newAI5); + break; + case 5: // PST + AbstractAINode newAI6 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Step(ai, c), ai); + c.setAINode(newAI6); + break; + default: + // STICK TO OLD + } + } + + // do trading for all cameras + for (CameraController c : this.cameras) { + c.updateAI(); + + // check if bandit solvers are used + IBanditSolver bs = c.getAINode().getBanditSolver(); + if (bs != null) { + int nrMessages = c.getAINode().getSentMessages(); + double commOverhead = 0.0; + if (nrMessages > 0) { + commOverhead = (nrMessages - c.getAINode().getNrOfBids()) / nrMessages; // + } + double utility = c.getAINode().getUtility() + c.getAINode().getReceivedUtility() - c.getAINode().getPaidUtility(); + stats.setReward(utility, commOverhead, c.getName()); + bs.setCurrentReward(utility, commOverhead); + } + } + + this.computeUtility(); + stats.nextTimeStep(); + } + + /** + * USED ONLY WITH REAL DATA + */ + private void setSearchFor() { + IMessage im = new Message("", "3.cvs", MessageType.StartSearch, new TraceableObjectRepresentation(this.objects.get(0), this.objects.get(0).getFeatures())); + CameraController cc = this.cameras.get(2); + AbstractAINode ai = cc.getAINode(); ai.receiveMessage(im); } /** * Updates the pure simulation for one timestep. * - * 1. Checks and precesses Events - * 2. Moves all trackable objects - * 3. Fails random cameras based on the given failing probability - this rate can be 0 - * 4. For all Cameras: - * a. Updates the visibility and confidence for all objects - * b. BanditSolver selects strategy if applicable - * - * 5. All Cameras advertise objects - * 6. All Cameras - * a. Update their received messages - * b. process auctions - * c. check for searched objects - * d. send messages - * 7. all Cameras - * a. update their AI - * b. update rewards for bandit solver if applicable - * + * 1. Checks and precesses Events 2. Moves all trackable objects 3. Fails + * random cameras based on the given failing probability - this rate can be + * 0 4. For all Cameras: a. Updates the visibility and confidence for all + * objects b. BanditSolver selects strategy if applicable + * + * 5. All Cameras advertise objects 6. All Cameras a. Update their received + * messages b. process auctions c. check for searched objects d. send + * messages 7. all Cameras a. update their AI b. update rewards for bandit + * solver if applicable + * * @throws Exception */ - public void updateSim() throws Exception{ - - // Print messages on the screen, one per step - if( CmdLogger.hasSomething() ){ - CmdLogger.update(); - System.out.println("CMDLogger is not empty... this shouldn't be"); - return; - } - - boolean doSelection = false; - //update interval for selecting new strategy - if(selectInterval > 1){ - if(currentSelectInt >= selectInterval){ - doSelection = true; - currentSelectInt = 0; - } - else{ - currentSelectInt ++; - } - } - else{ - doSelection = true; - } - - //check events - process event - checkAndProcessEvent(stats.get_time_step()); - - if(USEGLOBAL){ - reg.update(); - } - - // Update all traceable objects (move them around) - for (TraceableObject o : this.objects){ - o.update(); - } - - // random camera select - random timespan to go offline... + public void updateSim() throws Exception { + + // Print messages on the screen, one per step + if (CmdLogger.hasSomething()) { + CmdLogger.update(); + System.out.println("CMDLogger is not empty... this shouldn't be"); + return; + } + + boolean doSelection = false; + // update interval for selecting new strategy + if (selectInterval > 1) { + if (currentSelectInt >= selectInterval) { + doSelection = true; + currentSelectInt = 0; + } else { + currentSelectInt++; + } + } else { + doSelection = true; + } + + // check events - process event + checkAndProcessEvent(stats.get_time_step()); + + if (USEGLOBAL) { + reg.update(); + } + + // Update all traceable objects (move them around) + for (TraceableObject o : this.objects) { + o.update(); + } + + // random camera select - random timespan to go offline... int random = randomGen.nextInt(100, RandomUse.USE.ERROR); - - if(random <= CAMERRORRATE){ - //select random camera and set it offline for a random number of timesteps + + if (random <= CAMERRORRATE) { + // select random camera and set it offline for a random number of + // timesteps int ranCam = randomGen.nextInt(this.cameras.size(), RandomUse.USE.ERROR); - int sleepFor = randomGen.nextInt(10, RandomUse.USE.ERROR); - - CameraController cc = cameras.get(ranCam); - cc.setOffline(sleepFor); - int ranReset = randomGen.nextInt(100, RandomUse.USE.ERROR); - if(ranReset > RESETRATE){ - cc.resetCamera(); - } - } - - //update all objects position in the world view - //select a new ai if bandit solvers are used - for(CameraController c : this.cameras){ - if(!c.isOffline()){ - for (TraceableObject o : this.objects){ - c.update_confidence(o); - } - if(!c.getVisibleObjects_bb().isEmpty()){ - stats.addVisible(); - } - } - - //run BanditSolver, select next method, set AI! hope it works ;) - AbstractAINode ai = c.getAINode(); - AbstractCommunication prevComm = ai.getComm(); - IBanditSolver bs = ai.getBanditSolver(); - int strategy = -1; - if(bs != null){ -// if(doSelection) - int prevStrat = getStratForAI(ai); - strategy = bs.selectAction(); - ///System.out.println(step + "-" + c.getName() + ": " + strategy); - if(prevStrat != strategy) - stats.setStrat(strategy, c.getName()); - } - -// System.out.println(c.getName() + " current: " + ai.getClass() + ai.getComm() + " - next: " + strategy); - switch (strategy) { - case 0: //ABC - AbstractAINode newAI1 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Broadcast(ai, c), ai); //staticVG, ai.getVisionGraph(), reg); + int sleepFor = randomGen.nextInt(10, RandomUse.USE.ERROR); + + CameraController cc = cameras.get(ranCam); + cc.setOffline(sleepFor); + int ranReset = randomGen.nextInt(100, RandomUse.USE.ERROR); + if (ranReset > RESETRATE) { + cc.resetCamera(); + } + } + + // update all objects position in the world view + // select a new ai if bandit solvers are used + for (CameraController c : this.cameras) { + if (!c.isOffline()) { + for (TraceableObject o : this.objects) { + c.update_confidence(o); + } + if (!c.getVisibleObjects_bb().isEmpty()) { + stats.addVisible(); + } + } + + // run BanditSolver, select next method, set AI! hope it works ;) + AbstractAINode ai = c.getAINode(); + AbstractCommunication prevComm = ai.getComm(); + IBanditSolver bs = ai.getBanditSolver(); + int strategy = -1; + if (bs != null) { + // if(doSelection) + int prevStrat = getStratForAI(ai); + strategy = bs.selectAction(); + // /System.out.println(step + "-" + c.getName() + ": " + + // strategy); + if (prevStrat != strategy) + stats.setStrat(strategy, c.getName()); + } + + // System.out.println(c.getName() + " current: " + ai.getClass() + + // ai.getComm() + " - next: " + strategy); + switch (strategy) { + case 0: // ABC + AbstractAINode newAI1 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Broadcast(ai, c), ai); // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI1); break; - case 1: //ASM - AbstractAINode newAI2 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Smooth(ai, c), ai); // newAINodeFromName("epics.ai.ActiveAINodeMulti", 1, staticVG, ai.getVisionGraph(), reg); + case 1: // ASM + AbstractAINode newAI2 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Smooth(ai, c), ai); // newAINodeFromName("epics.ai.ActiveAINodeMulti", + // 1, + // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI2); break; - case 2: //AST - AbstractAINode newAI3 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Step(ai, c), ai); // staticVG, ai.getVisionGraph(), reg); + case 2: // AST + AbstractAINode newAI3 = newAINodeFromName("epics.ai.ActiveAINodeMulti", new Step(ai, c), ai); // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI3); break; - case 3: //PBC - AbstractAINode newAI4 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Broadcast(ai, c), ai); //staticVG, ai.getVisionGraph(), reg); + case 3: // PBC + AbstractAINode newAI4 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Broadcast(ai, c), ai); // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI4); break; - case 4: //PSM - AbstractAINode newAI5 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Smooth(ai, c), ai); //staticVG, ai.getVisionGraph(), reg); + case 4: // PSM + AbstractAINode newAI5 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Smooth(ai, c), ai); // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI5); break; - case 5: //PST - AbstractAINode newAI6 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Step(ai, c), ai); //staticVG, ai.getVisionGraph(), reg); + case 5: // PST + AbstractAINode newAI6 = newAINodeFromName("epics.ai.PassiveAINodeMulti", new Step(ai, c), ai); // staticVG, + // ai.getVisionGraph(), + // reg); c.setAINode(newAI6); break; default: - //STICK TO OLD + // STICK TO OLD } - } - - // Advertise each camera's owned objects - for(CameraController c : this.cameras){ - c.getAINode().advertiseTrackedObjects(); - } - - // Place all bids before updateAI() is called in the next loop - for(CameraController c : this.cameras){ - c.getAINode().updateReceivedDelay(); - c.getAINode().updateAuctionDuration(); - c.getAINode().checkIfSearchedIsVisible(); - c.forwardMessages(); // Push messages to relevant nodes - } - - //do trading for all cameras - for( CameraController c : this.cameras ){ - c.updateAI(); - - int nrMessages = c.getAINode().getSentMessages(); + } + + // Advertise each camera's owned objects + for (CameraController c : this.cameras) { + c.getAINode().advertiseTrackedObjects(); + } + + // Place all bids before updateAI() is called in the next loop + for (CameraController c : this.cameras) { + c.getAINode().updateReceivedDelay(); + c.getAINode().updateAuctionDuration(); + c.getAINode().checkIfSearchedIsVisible(); + c.forwardMessages(); // Push messages to relevant nodes + } + + // do trading for all cameras + for (CameraController c : this.cameras) { + c.updateAI(); + + int nrMessages = c.getAINode().getSentMessages(); double commOverhead = 0.0; -// if(nrMessages > 0){ -// commOverhead = (nrMessages-c.getAINode().getNrOfBids()) / nrMessages; // -// } - + // if(nrMessages > 0){ + // commOverhead = (nrMessages-c.getAINode().getNrOfBids()) / + // nrMessages; // + // } + commOverhead = nrMessages; - + stats.setCommunicationOverhead(commOverhead, c.getName()); - - //check if bandit solvers are used + + // check if bandit solvers are used IBanditSolver bs = c.getAINode().getBanditSolver(); - if(bs != null){ - double utility = c.getAINode().getUtility()+c.getAINode().getReceivedUtility() - c.getAINode().getPaidUtility(); + if (bs != null) { + double utility = c.getAINode().getUtility() + c.getAINode().getReceivedUtility() - c.getAINode().getPaidUtility(); stats.setReward(utility, commOverhead, c.getName()); - bs.setCurrentReward(utility, commOverhead, ((double) c.getAINode().getTrackedObjects().size())); + bs.setCurrentReward(utility, commOverhead, ((double) c.getAINode().getTrackedObjects().size())); } - } - this.computeUtility(); - stats.nextTimeStep(); - } + } + this.computeUtility(); + stats.nextTimeStep(); + } /** * Returns an index for a given AI used by bandit solvers * - * 0 = active Broadcast, 1 = active Smooth, 2 = active Step - * 3 = passive Broadcast, 4 = passive smooth, 5 = passive step - * @param ai the ai to get the index for - * @return index for ai + * 0 = active Broadcast, 1 = active Smooth, 2 = active Step 3 = passive + * Broadcast, 4 = passive smooth, 5 = passive step + * + * @param ai + * the ai to get the index for + * @return index for ai */ private int getStratForAI(AbstractAINode ai) { - if(ai.getClass() == epics.ai.ActiveAINodeMulti.class){ - if(ai.getComm() instanceof Broadcast) - return 0; - else - if(ai.getComm() instanceof Step) - return 1; - else - if(ai.getComm() instanceof Smooth) - return 2; - } - else{ - if(ai.getClass() == epics.ai.PassiveAINodeMulti.class){ - if(ai.getComm() instanceof Broadcast) - return 3; - else - if(ai.getComm() instanceof Step) - return 4; - else - if(ai.getComm() instanceof Smooth) - return 5; + if (ai.getClass() == epics.ai.ActiveAINodeMulti.class) { + if (ai.getComm() instanceof Broadcast) + return 0; + else if (ai.getComm() instanceof Step) + return 1; + else if (ai.getComm() instanceof Smooth) + return 2; + } else { + if (ai.getClass() == epics.ai.PassiveAINodeMulti.class) { + if (ai.getComm() instanceof Broadcast) + return 3; + else if (ai.getComm() instanceof Step) + return 4; + else if (ai.getComm() instanceof Smooth) + return 5; } } return -1; } /** - * checks if one of the predefined events should occure in the given timestep. - * if so, this method also processes these events + * checks if one of the predefined events should occure in the given + * timestep. if so, this method also processes these events + * * @param currentTimeStep */ private void checkAndProcessEvent(int currentTimeStep) { - for(SimSettings.Event e : events){ - if(e.timestep == currentTimeStep){ - //process event - if(e.event.equals("add")){ - if(e.participant == 1){ // camera - this.add_camera(e.name, e.x, e.y, e.heading, e.angle, e.range, e.comm, null, - e.limit, null, e.bandit, null, null); - } - else{ //object - if(e.waypoints == null){ + for (SimSettings.Event e : events) { + if (e.timestep == currentTimeStep) { + // process event + if (e.event.equals("add")) { + if (e.participant == 1) { // camera + this.add_camera(e.name, e.x, e.y, e.heading, e.angle, e.range, e.comm, null, e.limit, null, e.bandit, null, null); + } else { // object + if (e.waypoints == null) { this.add_object(e.x, e.y, e.heading, e.speed, Double.parseDouble(e.name)); - } - else{ + } else { this.add_object(e.speed, e.waypoints, Double.parseDouble(e.name)); } } - } - else if(e.event.equals("error")){ - if(e.participant == 1){ // camera - if(e.duration == -1){ - if(USEGLOBAL){ + } else if (e.event.equals("error")) { + if (e.participant == 1) { // camera + if (e.duration == -1) { + if (USEGLOBAL) { reg.removeCamera(this.getCameraByName(e.name)); } - - if(!getCameraByName(e.name).isOffline()) + + if (!getCameraByName(e.name).isOffline()) this.getCameraByName(e.name).setOffline(-1); - } - else{ - if(!getCameraByName(e.name).isOffline()) + } else { + if (!getCameraByName(e.name).isOffline()) this.getCameraByName(e.name).setOffline(e.duration); } - - } - else if(e.participant == 2){ //object + + } else if (e.participant == 2) { // object int remove = -1; - + String[] fs = e.name.split(";"); List ownFeatures = new ArrayList(); - for(int j = 0; j < fs.length; j++){ + for (int j = 0; j < fs.length; j++) { ownFeatures.add(Double.parseDouble(fs[j])); } boolean found = false; - - //TraceableObject tor = new TraceableObject(ownFeatures.get(0), this, 0, 0, 0, 0); - + + // TraceableObject tor = new + // TraceableObject(ownFeatures.get(0), this, 0, 0, 0, + // 0); + for (CameraController cc : this.cameras) { cc.removeObject(ownFeatures); } - - for(int i = 0; i < getObjects().size(); i++){ + + for (int i = 0; i < getObjects().size(); i++) { List otherFeatures = getObjects().get(i).getFeatures(); found = true; - if(ownFeatures.size() == otherFeatures.size()){ - for(int k = 0; k < ownFeatures.size(); k++){ - if(!ownFeatures.get(k).equals(otherFeatures.get(k))){ + if (ownFeatures.size() == otherFeatures.size()) { + for (int k = 0; k < ownFeatures.size(); k++) { + if (!ownFeatures.get(k).equals(otherFeatures.get(k))) { found = false; } } - } - else{ + } else { found = false; } - - if(found == true){ + + if (found == true) { remove = i; break; } } - - if(found){ + + if (found) { this.objects.remove(remove); - //getObjects().remove(remove); + // getObjects().remove(remove); } - } - else if(e.participant == 3){ //GRC - if(reg != null){ + } else if (e.participant == 3) { // GRC + if (reg != null) { reg.setOffline(e.duration); } } - } - else if(e.event.equals("change")){ - if(e.participant == 1){ // camera - for ( int i = 0; i < this.cameras.size(); i++ ){ - CameraController cc = this.cameras.get(i); - if ( cc.getName().equals(e.name) ){ - cc.change(e.x, e.y, e.heading, e.angle, e.range); - } - } + } else if (e.event.equals("change")) { + if (e.participant == 1) { // camera + for (int i = 0; i < this.cameras.size(); i++) { + CameraController cc = this.cameras.get(i); + if (cc.getName().equals(e.name)) { + cc.change(e.x, e.y, e.heading, e.angle, e.range); + } + } } } } @@ -1225,55 +1319,55 @@ else if(e.event.equals("change")){ /** * Helper method to print the properties of all objects + * * @throws Exception */ private void printObjects() throws Exception { Map> tracked = new HashMap>(); - Map> searched = new HashMap>(); - for(CameraController c : this.cameras){ - for(epics.common.ITrObjectRepresentation to : c.getAINode().getTrackedObjects().values()){ - TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; - if(tracked.containsKey(tor.getTraceableObject())){ - tracked.get(tor.getTraceableObject()).add(c); - } - else{ - List list = new ArrayList(); - list.add(c); - tracked.put(tor.getTraceableObject(), list); - } - } - if(c.getAINode().getSearchedObjects() != null){ - for(epics.common.ITrObjectRepresentation to : c.getAINode().getSearchedObjects().keySet()){ - TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; - if(searched.containsKey(tor.getTraceableObject())){ - searched.get(tor.getTraceableObject()).add(c); - } - else{ - List list = new ArrayList(); - list.add(c); - searched.put(tor.getTraceableObject(), list); - } - } - } - } - + Map> searched = new HashMap>(); + for (CameraController c : this.cameras) { + for (epics.common.ITrObjectRepresentation to : c.getAINode().getTrackedObjects().values()) { + TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; + if (tracked.containsKey(tor.getTraceableObject())) { + tracked.get(tor.getTraceableObject()).add(c); + } else { + List list = new ArrayList(); + list.add(c); + tracked.put(tor.getTraceableObject(), list); + } + } + if (c.getAINode().getSearchedObjects() != null) { + for (epics.common.ITrObjectRepresentation to : c.getAINode().getSearchedObjects().keySet()) { + TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; + if (searched.containsKey(tor.getTraceableObject())) { + searched.get(tor.getTraceableObject()).add(c); + } else { + List list = new ArrayList(); + list.add(c); + searched.put(tor.getTraceableObject(), list); + } + } + } + } + System.out.println("############################ PRINT OBJECT INFO #########################################"); int sum = tracked.size() + searched.size(); System.out.println("searched size: " + searched.size() + " + tracked size: " + tracked.size() + " = " + sum + " should be: " + this.objects.size()); -// if((tracked.size() + searched.size()) != this.objects.size()) -// throw new Exception("INCONSISTENCY: " + tracked.size() + searched.size() + " is not " + this.objects.size()); + // if((tracked.size() + searched.size()) != this.objects.size()) + // throw new Exception("INCONSISTENCY: " + tracked.size() + + // searched.size() + " is not " + this.objects.size()); System.out.println(""); System.out.println("object + searched + tracked"); - for(TraceableObject to : this.objects){ + for (TraceableObject to : this.objects) { String output = "Object " + to.getFeatures() + " searched by "; - if(searched.containsKey(to)){ - for(CameraController c : searched.get(to)){ + if (searched.containsKey(to)) { + for (CameraController c : searched.get(to)) { output += c.getName() + ", "; } } output += " tracked by "; - if(tracked.containsKey(to)){ - for(CameraController c : tracked.get(to)){ + if (tracked.containsKey(to)) { + for (CameraController c : tracked.get(to)) { output += c.getName() + ", "; } } @@ -1284,116 +1378,121 @@ private void printObjects() throws Exception { /** * helper method to check inconsistencies between objects and cameras + * * @throws Exception */ - public void checkConsistency() throws Exception{ - - Map tracing = new HashMap(); - Map searching = new HashMap(); - - for(CameraController c : this.cameras){ - for(epics.common.ITrObjectRepresentation to : c.getAINode().getTrackedObjects().values()){ - TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; - tracing.put(tor.getTraceableObject(), true); - if(c.getVisibleObjects().containsKey(tor)){ - throw new Exception("wait what? inconsistent - if its not visible, it cant be tracked!!"); - } - } - if(c.getAINode().getSearchedObjects() != null){ - for(epics.common.ITrObjectRepresentation to : c.getAINode().getSearchedObjects().keySet()){ - TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; - searching.put(tor.getTraceableObject(), true); - } - } - - - } - - for(TraceableObject to : this.objects){ - if(!tracing.containsKey(to)){ - if(!searching.containsKey(to)){ - throw new Exception("INCONSISTENCY!!"); - } - } - } - } - - /** - * computes the utility of the entire network and - * adds this to the statistics - * @return the sum of all cameras utilities. - */ - public double computeUtility(){ - double utility_sum = 0; - for (CameraController c : this.cameras){ - if(!c.isOffline()){ - utility_sum += c.getAINode().getUtility(); - try { - stats.addUtility( c.getAINode().getUtility(), c.getName()); + public void checkConsistency() throws Exception { + + Map tracing = new HashMap(); + Map searching = new HashMap(); + + for (CameraController c : this.cameras) { + for (epics.common.ITrObjectRepresentation to : c.getAINode().getTrackedObjects().values()) { + TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; + tracing.put(tor.getTraceableObject(), true); + if (c.getVisibleObjects().containsKey(tor)) { + throw new Exception("wait what? inconsistent - if its not visible, it cant be tracked!!"); + } + } + if (c.getAINode().getSearchedObjects() != null) { + for (epics.common.ITrObjectRepresentation to : c.getAINode().getSearchedObjects().keySet()) { + TraceableObjectRepresentation tor = (TraceableObjectRepresentation) to; + searching.put(tor.getTraceableObject(), true); + } + } + + } + + for (TraceableObject to : this.objects) { + if (!tracing.containsKey(to)) { + if (!searching.containsKey(to)) { + throw new Exception("INCONSISTENCY!!"); + } + } + } + } + + /** + * computes the utility of the entire network and adds this to the + * statistics + * + * @return the sum of all cameras utilities. + */ + public double computeUtility() { + double utility_sum = 0; + for (CameraController c : this.cameras) { + if (!c.isOffline()) { + utility_sum += c.getAINode().getUtility(); + try { + stats.addUtility(c.getAINode().getUtility(), c.getName()); } catch (Exception e) { e.printStackTrace(); } - } - } - return utility_sum; - } - - /** - * returns all cameras - * @return all cameras - */ - public ArrayList getCameras() { - return cameras; - } - - /** - * returns the camera with a specific name - * @param name name of camera to return - * @return the camera - */ - public CameraController getCameraByName( String name ){ - for ( int i = 0; i < cameras.size(); i++ ){ - if ( cameras.get(i).getName().compareTo(name) == 0 ){ - return cameras.get(i); - } - } - return null; - } - - /** - * Returns a list of all objects - * @return List of all objects - */ - public ArrayList getObjects() { - return objects; - } - - /** - * Save the scenario currently active in the simulation to an XML file. - * This supports regular objects as well as objects with waypoints. - * Note that this does not represent angles 100% correctly. - * This should only be used to store randomised scenarios. - * - * @param absolutePath path of XML-File + } + } + return utility_sum; + } + + /** + * returns all cameras + * + * @return all cameras + */ + public ArrayList getCameras() { + return cameras; + } + + /** + * returns the camera with a specific name + * + * @param name + * name of camera to return + * @return the camera + */ + public CameraController getCameraByName(String name) { + for (int i = 0; i < cameras.size(); i++) { + if (cameras.get(i).getName().compareTo(name) == 0) { + return cameras.get(i); + } + } + return null; + } + + /** + * Returns a list of all objects + * + * @return List of all objects + */ + public ArrayList getObjects() { + return objects; + } + + /** + * Save the scenario currently active in the simulation to an XML file. This + * supports regular objects as well as objects with waypoints. Note that + * this does not represent angles 100% correctly. This should only be used + * to store randomised scenarios. + * + * @param absolutePath + * path of XML-File */ public void save_to_xml(String absolutePath) { File f = new File(absolutePath + ".xml"); - + FileWriter fw; try { fw = new FileWriter(f); - String s = ""+System.getProperty( "line.separator" )+""+System.getProperty( "line.separator" )+" " + - ""+ System.getProperty( "line.separator" )+ " "+ System.getProperty( "line.separator" ); + String s = "" + System.getProperty("line.separator") + "" + System.getProperty("line.separator") + " " + "" + System.getProperty("line.separator") + " " + System.getProperty("line.separator"); fw.write(s); - + for (CameraController cam : cameras) { - fw.write(" "+ cam.toString() + System.getProperty("line.separator")); + fw.write(" " + cam.toString() + System.getProperty("line.separator")); } - fw.write(" "+System.getProperty( "line.separator" )+" "+System.getProperty( "line.separator" )); - for(TraceableObject to : objects){ - fw.write(" "+ to.toXMLString(" ") + System.getProperty("line.separator")); + fw.write(" " + System.getProperty("line.separator") + " " + System.getProperty("line.separator")); + for (TraceableObject to : objects) { + fw.write(" " + to.toXMLString(" ") + System.getProperty("line.separator")); } - fw.write(" "+System.getProperty("line.separator")+" "+System.getProperty("line.separator")+""); + fw.write(" " + System.getProperty("line.separator") + " " + System.getProperty("line.separator") + ""); fw.close(); } catch (IOException e) { e.printStackTrace(); @@ -1401,37 +1500,41 @@ public void save_to_xml(String absolutePath) { } /** - * Resets the simulation environment to a minimum of -70 and maximum of 70 in x and y direction + * Resets the simulation environment to a minimum of -70 and maximum of 70 + * in x and y direction */ public void reset() { this.min_x = -70; this.max_x = 70; this.min_y = -70; - this.max_y = 70; + this.max_y = 70; } /** * returns the statistics summary as a string - * @param spaces if spaces should be added after delimiters + * + * @param spaces + * if spaces should be added after delimiters * @return the summary as string * @throws Exception */ - public String getStatSummary(boolean spaces) throws Exception{ - return stats.getSummary(spaces); + public String getStatSummary(boolean spaces) throws Exception { + return stats.getSummary(spaces); } - + /** * gets a summary description (header) - * @param spaces if spaces should be added after elimiters + * + * @param spaces + * if spaces should be added after elimiters * @return the description as string * @throws Exception */ - public String getStatSumDesc(boolean spaces) throws Exception{ - return stats.getSummaryDesc(spaces); + public String getStatSumDesc(boolean spaces) throws Exception { + return stats.getSummaryDesc(spaces); } - - public void setQuiet(boolean b) { - stats.setQuiet(b); - } + public void setQuiet(boolean b) { + stats.setQuiet(b); + } } diff --git a/src/epics/camsim/core/Statistics.java b/src/epics/camsim/core/Statistics.java index 5b00b0d..e1e7e6c 100644 --- a/src/epics/camsim/core/Statistics.java +++ b/src/epics/camsim/core/Statistics.java @@ -30,6 +30,7 @@ public int get_time_step() { private int visible_tmp = 0; private double util_cumulative = 0; private double comm_cumulative = 0; + private double bids_cumulative = 0; private double handover_cumulative = 0; private Map> tmp_camUtil = new HashMap>(); private Map perCam = new HashMap(); @@ -40,7 +41,6 @@ public int get_time_step() { private ArrayList visible = new ArrayList(); private ArrayList strategy = new ArrayList(); - private long threadId; private Integer strategy_tmp; private double tmp_totutil; private ArrayList totUtil = new ArrayList(); @@ -76,6 +76,7 @@ public void init(String outputFile, String summaryFile, boolean allStatistics, l handover_tmp = 0; util_cumulative = 0; comm_cumulative = 0; + bids_cumulative = 0; handover_cumulative = 0; comm_oh_cumulative = 0; comm_oh_tmp = 0; @@ -199,6 +200,7 @@ public String getSummary(boolean spaces) throws Exception{ + handover_tmp + comma + handover_cumulative + comma + comm_oh_cumulative + comma + + bids_cumulative + comma + visible_tmp; return summary; } @@ -218,6 +220,7 @@ public String getSummaryDesc(boolean spaces) throws Exception{ + "HANDOVER" + comma + "CUMULATIVE_HANDOVER" + comma + "CUMULATIVE_COMM_OH" + comma + + "CUMULATIVE BIDS" + comma + "VISIBLE"; return desc; } @@ -225,6 +228,11 @@ public String getSummaryDesc(boolean spaces) throws Exception{ public void addVisible() throws Exception{ } + public void addBid(){ + System.out.println("CALLED"); + bids_cumulative++; + } + public void addUtility(double utility, String camName) throws Exception{ // if(threadId != Thread.currentThread().getId()){ // throw new Exception("thread " + Thread.currentThread().getId() + " not equal to initiator thread ("+ threadId +")"); diff --git a/src/epics/camsim/core/TraceableObject.java b/src/epics/camsim/core/TraceableObject.java index 7e8f29e..17b4c57 100644 --- a/src/epics/camsim/core/TraceableObject.java +++ b/src/epics/camsim/core/TraceableObject.java @@ -1,5 +1,6 @@ package epics.camsim.core; +import epics.common.Coordinate2D; import epics.common.RandomNumberGenerator; import epics.common.RandomUse; @@ -112,6 +113,19 @@ public double getTurnaroundAngle() { return angle; } + public Coordinate2D esteemNext(int lookAhead) { + double resX = x, resY = y; + for(int i=0; i< lookAhead; i++){ + resX += Math.sin(this.heading) * speed; + resY += Math.cos(this.heading) * speed; + } + return new Coordinate2D(resX, resY); + } + + public Coordinate2D getCurrentPosition() { + return new Coordinate2D(x, y); + } + public double getX(){ return this.x; } diff --git a/src/epics/camwin/WorldView.java b/src/epics/camwin/WorldView.java index 3e9ad26..5546c2d 100644 --- a/src/epics/camwin/WorldView.java +++ b/src/epics/camwin/WorldView.java @@ -136,39 +136,41 @@ public void paintComponent(Graphics g) { */ Map vg = c.getDrawableVisionGraph(); - for (Map.Entry e : vg.entrySet()){ - - CameraController cc = sim_model.getCameraByName(e.getKey()); - if (cc == null){ - continue; - } - double ccX = this.cst.simToWindowX(cc.getX()); - double ccY = this.cst.simToWindowY(cc.getY()); - - double val = e.getValue(); - int col = (int)(val * 255); - if (col > 255) { col = 255; } - - int thickness = 0; - if(val > 0) { - thickness = MIN_THICKNESS; - } - if(val > 1) { - thickness = MIN_THICKNESS + 2; - } - if(thickness > 6 ) { thickness = 6; } - if( thickness < MIN_THICKNESS) { thickness = MIN_THICKNESS;} - - g2.setStroke(new BasicStroke(thickness)); - - // Fading red - g2.setColor(new Color(255, 255-col, 255-col )); - - Line2D.Double edge = new Line2D.Double( - this.cst.simToWindowX(c.getX()), this.cst.simToWindowY(c.getY()), - this.cst.simToWindowX(cc.getX()), this.cst.simToWindowY(cc.getY()) ); - g2.draw(edge); - } + if (vg != null && vg.entrySet() != null) { + for (Map.Entry e : vg.entrySet()){ + + CameraController cc = sim_model.getCameraByName(e.getKey()); + if (cc == null){ + continue; + } + double ccX = this.cst.simToWindowX(cc.getX()); + double ccY = this.cst.simToWindowY(cc.getY()); + + double val = e.getValue(); + int col = (int)(val * 255); + if (col > 255) { col = 255; } + + int thickness = 0; + if(val > 0) { + thickness = MIN_THICKNESS; + } + if(val > 1) { + thickness = MIN_THICKNESS + 2; + } + if(thickness > 6 ) { thickness = 6; } + if( thickness < MIN_THICKNESS) { thickness = MIN_THICKNESS;} + + g2.setStroke(new BasicStroke(thickness)); + + // Fading red + g2.setColor(new Color(255, 255-col, 255-col )); + + Line2D.Double edge = new Line2D.Double( + this.cst.simToWindowX(c.getX()), this.cst.simToWindowY(c.getY()), + this.cst.simToWindowX(cc.getX()), this.cst.simToWindowY(cc.getY()) ); + g2.draw(edge); + } + } // if vg != null g2.setStroke(new BasicStroke(MIN_THICKNESS)); @@ -338,4 +340,4 @@ private void drawString(Graphics g, String text, int x, int y) { public void update(Observable obs, Object obj) { repaint(); } -} \ No newline at end of file +} diff --git a/src/epics/common/AbstractAINode.java b/src/epics/common/AbstractAINode.java index 1341afa..c1ae501 100644 --- a/src/epics/common/AbstractAINode.java +++ b/src/epics/common/AbstractAINode.java @@ -46,7 +46,7 @@ protected Pair(ITrObjectRepresentation itro, double confidence) { public static final boolean VISION_RCVER_BOUND = false; //receiver builds up VG --> does not make much sense... public static final boolean BIDIRECTIONAL_VISION = false; - boolean staticVG = false; + protected boolean staticVG = false; // private int communication; protected Map visionGraph = new HashMap(); protected Map, ITrObjectRepresentation> trackedObjects = new HashMap, ITrObjectRepresentation>(); @@ -1034,6 +1034,7 @@ protected void checkBidsForObjects() { ICameraController giveTo = null; Map bids = this.getBiddingsFor(tor); // Bids from other cams + // TODO: here count bids if (bids != null) { for (Map.Entry e : bids.entrySet()) { // iterate over bids @@ -1065,14 +1066,14 @@ protected void checkBidsForObjects() { //_paidUtility += secondHighest; sendMessage(MessageType.StopSearch, tor); stepsTillBroadcast.remove(tor); - } else { + } else { // other camera won tor.setPrice(secondHighest); IMessage reply = this.camController.sendMessage(giveTo.getName(), MessageType.StartTracking, tor); _receivedUtility += secondHighest; //highest; if(DEBUG_CAM) CmdLogger.println(this.camController.getName() + " sent StartTracking msg to: " + giveTo.getName() + " for object " + tor.getFeatures()); - if(reply != null){ + if(reply != null){ // an error? if(reg != null){ reg.objectTrackedBy(tor, this.camController); } @@ -1080,7 +1081,7 @@ protected void checkBidsForObjects() { delete.remove(tor); // do not delete if other camera does not respond (or responds irrationally) this.getBiddingsFor(tor).remove(giveTo); } - else{ + else{ // the cam responded if(!VISION_ON_BID){ if(BIDIRECTIONAL_VISION || (!VISION_RCVER_BOUND)) strengthenVisionEdge(giveTo.getName(), tor); @@ -1097,7 +1098,7 @@ protected void checkBidsForObjects() { sendMessage(MessageType.StopSearch, tor); stepsTillBroadcast.remove(tor); } - } + }// other cam won auction } removeRunningAuction(tor); } diff --git a/src/epics/common/Coordinate2D.java b/src/epics/common/Coordinate2D.java new file mode 100644 index 0000000..6acd69d --- /dev/null +++ b/src/epics/common/Coordinate2D.java @@ -0,0 +1,46 @@ +/** + * + */ +package epics.common; + +import java.io.Serializable; + +/** + * @author Danilo Pianini + * + */ +public class Coordinate2D implements Serializable { + + private static final long serialVersionUID = -1574428171808612137L; + + private final double x, y; + private String stringCache; + + public Coordinate2D(double xc, double yc) { + x = xc; + y = yc; + } + + /** + * @return the x + */ + public double getX() { + return x; + } + + /** + * @return the y + */ + public double getY() { + return y; + } + + @Override + public String toString(){ + if(stringCache == null){ + stringCache = "["+x+","+y+"]"; + } + return stringCache; + } + +} diff --git a/src/epics/common/ICameraController.java b/src/epics/common/ICameraController.java index f4c2a50..a715d05 100644 --- a/src/epics/common/ICameraController.java +++ b/src/epics/common/ICameraController.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; +import epics.camsim.core.TraceableObject; import epics.camsim.core.TraceableObjectRepresentation; /** @@ -36,9 +37,19 @@ public interface ICameraController{ void removeObject(List features); public void change(double xCoord, double yCoord, double head, double angle, double range); // e.x, e.y, e.heading, e.angle, e.range, e.comm, e.limit + + public Coordinate2D getPostion(); + + /** + * @return an angle, in radians, representing the heading of this camera + */ + public double getHeading(); public void setAINode(AbstractAINode ai); public int objectIsVisible(ITrObjectRepresentation tor); public boolean realObjectsUsed(); + + boolean isObjectInFOV(TraceableObject tor); + boolean isCoordinateInFOV(Coordinate2D pos); } diff --git a/src/epics/common/ITrObjectRepresentation.java b/src/epics/common/ITrObjectRepresentation.java index 54212c3..e31a0ac 100644 --- a/src/epics/common/ITrObjectRepresentation.java +++ b/src/epics/common/ITrObjectRepresentation.java @@ -2,6 +2,8 @@ import java.util.List; +import epics.camsim.core.TraceableObject; + /** * * @author Marcin Bogdanski @@ -11,4 +13,5 @@ public interface ITrObjectRepresentation { public List getFeatures(); public void setPrice(double price); public double getPrice(); + public TraceableObject getTraceableObject(); } diff --git a/src/epics/commpolicy/Fix.java b/src/epics/commpolicy/Fix.java index c88101c..c089212 100644 --- a/src/epics/commpolicy/Fix.java +++ b/src/epics/commpolicy/Fix.java @@ -10,6 +10,8 @@ import epics.common.ITrObjectRepresentation; import epics.common.AbstractCommunication; +import epics.ai.AbstractClusterFoVAINode; + /** * Sends the given message to the neighbouring cameras in the vision graph. * This method does not make use of the strength of the links. @@ -27,9 +29,16 @@ public void multicast(MessageType mt, Object o) { Map> advertised = ai.getAdvertisedObjects(); List cams = new ArrayList(); - for (String name : ai.vgGetCamSet()) { - this.camController.sendMessage(name, mt, o); - cams.add(name); + if (ai.vgGetCamSet()!=null) { + for (String name : ai.vgGetCamSet()) { + this.camController.sendMessage(name, mt, o); + cams.add(name); + } + } else { // for some AI we need the object, so that we can change the vision graph based on it + for (String name : ((AbstractClusterFoVAINode)ai).vgGetCamSet((ITrObjectRepresentation) o)) { + this.camController.sendMessage(name, mt, o); + cams.add(name); + } } if(mt == MessageType.StartSearch){ diff --git a/src/simsim/epics/simSim/SimSim.java b/src/simsim/epics/simSim/SimSim.java index c7de1c0..5db34fd 100644 --- a/src/simsim/epics/simSim/SimSim.java +++ b/src/simsim/epics/simSim/SimSim.java @@ -28,12 +28,12 @@ */ public class SimSim { - public static String loadScenariosFrom = "..//..//..//..//scenarios//2Cams"; //can be overwriten using argument [0] - public static String writeResultsTo = "..//..//..//..//..//..//Results//"; //can be overwriten using argument [1] (automatically overwrites loadScenariosFrom) + public static String loadScenariosFrom = "scenarios//AWASS//"; //can be overwriten using argument [0] + public static String writeResultsTo = ".//"; //can be overwriten using argument [1] (automatically overwrites loadScenariosFrom) public static boolean allStatistics = false; - public static boolean runHomogeneous = false; + public static boolean runHomogeneous = true; public static boolean runByParameter = false; - public static boolean runAllPossibleVersions = true; + public static boolean runAllPossibleVersions = false; public static boolean runBandits = false; static int duration = 1000; //how many timesteps @@ -1149,6 +1149,10 @@ public static CommPolicy fromString(String text) { enum AuctionsSchedule { ACTIVE("epics.ai.ActiveAINodeMulti", "A") , PASSIVE("epics.ai.PassiveAINodeMulti", "P") + , ACTIVECLUSTERING("epics.ai.ActiveAINodeMultiClustering", "AC") + , PASSIVECLUSTERING("epics.ai.PassiveAINodeMultiClustering", "PC") + , LOOKAHEAD("epics.ai.AWASSLookAheadNode", "L") + , LOOKAHEADCLUSTERING("epics.ai.AWASSLookAheadNodeClustering", "LC") ; /** * @param text diff --git a/src/simsim/epics/simSim/SimSimReal.java b/src/simsim/epics/simSim/SimSimReal.java index 59354e4..7f30f42 100644 --- a/src/simsim/epics/simSim/SimSimReal.java +++ b/src/simsim/epics/simSim/SimSimReal.java @@ -65,7 +65,7 @@ public static void main(String[] args){ //get folder - File dir = new File("E:\\Scenarios\\RealDataT1.4_AR"); + File dir = new File(System.getProperty("")); RunAllRealDataScen(dir); }