package system; import java.util.ArrayList; import util.LimitedQueue; import util.Log; import android.content.Context; import android.location.Location; import android.location.LocationListener; public class ConcreteSimpleLocationManager extends SimpleLocationManager { /** * <1 accuracy less important * * >1 accuracy more important */ private static final float ACCURACY_WEIGHTING = 1f; private static final int MAX_NUMBR_OF_LOCATIONS = 15; private static final double SQRT2PII = Math.sqrt(2 * Math.PI); private static final String LOG_TAG = "ConcreteSimpleLocationManager"; private Location currentPosition; private LimitedQueue<Location> lastPositions; private final float mimProb = 0.5f; // TODO private Location lastStepPos; public ConcreteSimpleLocationManager(Context context) { super(context); } public LimitedQueue<Location> getLastPositions() { return lastPositions; } @Override public Location getCurrentBUfferedLocation() { return currentPosition; } @Override public void onLocationEventFromGPS(Location location, ArrayList<LocationListener> listenersToInform) { if (currentPosition == null) { currentPosition = new Location("AveragePosition"); } calcFromLastPositions(currentPosition, location); for (int i = 0; i < listenersToInform.size(); i++) { listenersToInform.get(i).onLocationChanged(currentPosition); } } @Override public void onLocationEventFromSteps(Location location, ArrayList<LocationListener> listenersToInform) { lastStepPos = location; onLocationEventFromGPS(location, listenersToInform); } public Location getLastStepPos() { return lastStepPos; } private boolean calcFromLastPositions(Location target, Location newLocation) { addToLastLocationsList(newLocation); float accuracySum = 0; float inverseAccuracySum = 0; double meanLat = 0; double meanAlti = 0; double meanLong = 0; /* * weights via accuracy * * example: a and b weights (e.g. 1/10m and 1/20m), x and y are latitude * values from the 2 measurements: * * 1/(a+b)*(a*x+b*y) * * TODO could also add a simple time control parameter via gaus * anzI=i*(i+1)/2 */ int numberOfLocations = lastPositions.size(); Log.d(LOG_TAG, "Calculating average of " + numberOfLocations + " locations"); for (int i = 0; i < numberOfLocations; i++) { Location l = lastPositions.get(i); float acc = ACCURACY_WEIGHTING / l.getAccuracy(); accuracySum += l.getAccuracy(); inverseAccuracySum += acc; meanLat += acc * l.getLatitude(); meanLong += acc * l.getLongitude(); meanAlti += l.getAltitude(); } target.setAccuracy(accuracySum / numberOfLocations); target.setAltitude(meanAlti / numberOfLocations); target.setLatitude(meanLat / inverseAccuracySum); target.setLongitude(meanLong / inverseAccuracySum); Log.d(LOG_TAG, "Average is: " + target); /* * check with gausian distr if value is ok to add (>a certaion * probability) TODO then add to list of location measurements */ // double variance=0; // variance/=numberOfLocations-1; // // double nLat = 1 // / (meanLat / inverseAccuracySum * SQRT2PII) // * Math.exp(-1 // / 2 // * ((t.getLatitude() - meanLat / inverseAccuracySum) / variance) // * ((t.getLatitude() - meanLat / inverseAccuracySum) / variance)); // System.out.println("nLat=" + nLat); return true; } @Override public void setMaxNrOfBufferedLocations(int maxNrOfBufferedLocations) { if (lastPositions == null) { lastPositions = new LimitedQueue<Location>(maxNrOfBufferedLocations); } else { lastPositions.setLimit(maxNrOfBufferedLocations); } } private void addToLastLocationsList(Location location) { if (lastPositions == null) { lastPositions = new LimitedQueue<Location>(MAX_NUMBR_OF_LOCATIONS); } lastPositions.add(location); } }