Back to project page TrafficTracker.
The source code is released under:
MIT License
If you think the Android project TrafficTracker listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/** * //from w w w . java 2 s. c o m */ package com.dev.nuwan.roadtrafficmonitor; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.Log; import android.view.View; import android.widget.TextView; /** * Primary processor for Accelerator sensor data. Calculate velocity, position * data from the accelerator data. * * @author nthusitha * @date 08-Nov-2014 * */ public class LinearAccelaratorSensorListener implements SensorEventListener, VelocityAware { private static int BUFFER_CAPACITY = 5; private static ConcurrentLinkedQueue<LinearAccelaratorSensorListener.Movement> MOVEMENTS = new ConcurrentLinkedQueue<LinearAccelaratorSensorListener.Movement>(); private static ConcurrentLinkedQueue<LinearAccelaratorSensorListener.Movement> VELOCITY_DEVIATION_LIST = new ConcurrentLinkedQueue<LinearAccelaratorSensorListener.Movement>(); private static volatile boolean MOVEMENT_FLAG = false; public static volatile boolean CALIBRATION_FLAG = true; // true at start. // false - when // calibration is // done // private float[] meanAccerationVals = new float[] {}; private static double POSITIVE_LIMIT = 0.5; private static double NEGATIVE_LIMIT = -0.5; // 3000 micro secs delay between samples // Use this value wisely not to generate millions of velocity values private static float SAMPLE_WIDTH = 3 / 1000; private static float MOVEMENT_COUNT = 6680; // ususually this value is // derived from (1/(3000micros // seconds) * sample time // (secs)) // number of accelerometer data count to calculate one single velocity value private static short ACCELRATION_SAMPLE_COUNT = 64; // private float[] meanAccerationVals = new float[] {}; // number of data points required for calibration private static short CALIBRATION_SAMPLE_COUNT = 50; private static float CALIBRATE_X; private static float CALIBRATE_Y; private static float CALIBRATE_Z; private static float ACCELERATION_X_1; private static float ACCELERATION_Y_1; private static float ACCELERATION_Z_1; // previous acceleration private static float ACCELERATION_X_0; private static float ACCELERATION_Y_0; private static float ACCELERATION_Z_0; private static float VELOCITY_X_1; private static float VELOCITY_Y_1; private static float VELOCITY_Z_1; // previous velocity private static float VELOCITY_X_0; private static float VELOCITY_Y_0; private static float VELOCITY_Z_0; // for testing private static TextView TXT_VIEW; private final ScheduledExecutorService movementMonitorSchedular = Executors .newScheduledThreadPool(1); /** * Check continuously about movement end check. This method allows movement * end detection. If a certain number of acceleration samples are equal to * zero we can assume movement has stopped. Accumulated Error generated in * the velocity calculations is eliminated by resetting the velocity * variables. This stops position increment and greatly eliminates position * error. */ private void doMovementEndCheck(SensorEvent sEvent) { // TODO: Implement this. } /** * RESET DATA COUNT */ private void reset() { // TODO: RESET DATA COUNT } /** * Monitor the MOVEMENT queue. */ private void monitor() { /* * while(START_MOVMENT_MONITOR_FLAG){ * * * } */ Runnable mMonitor = new Runnable() { @Override public void run() { // if run this every 1 second there will be 333.33 velocity // readings // to process. // TODO: Add smart algorithm if necessary to calculate movement // changes. double avgVelocity = 0, velocitySum = -1; for (int i = 0; i < MOVEMENT_COUNT; i++) { if (MOVEMENTS.isEmpty()) { break; } else { if (MOVEMENTS.peek() != null) { velocitySum = velocitySum + MOVEMENTS.poll().getVelocity(); } else { // no elements in the queue break; } } } if (velocitySum >= 0) { avgVelocity = velocitySum / MOVEMENT_COUNT; Movement m = new Movement(System.currentTimeMillis()); m.setVelocity(avgVelocity); VELOCITY_DEVIATION_LIST.add(m); } } }; final ScheduledFuture<?> movementMonitorSch = movementMonitorSchedular .scheduleAtFixedRate(mMonitor, 0, 20, TimeUnit.SECONDS); } private void inspect() { Runnable inspector = new Runnable() { @Override public void run() { // check last 5 movements and trigger gps and get co-ordinates // and update traffic API's // as required. // use standard deviation to calculation motion. notify_(); } }; final ScheduledFuture<?> movementMonitorSch = movementMonitorSchedular .scheduleAtFixedRate(inspector, 100, 100, TimeUnit.SECONDS); } /** * Check velocity */ private void velocity(SensorEvent sEvent) { // calculate velocity /* * while (ACCELRATION_SAMPLE_THRESHOLD > 0) { * * ACCELRATION_SAMPLE_COUNT--; } */ for (int i = 0; i < ACCELRATION_SAMPLE_COUNT; i++) { ACCELERATION_X_1 = ACCELERATION_X_1 + sEvent.values[0]; ACCELERATION_Y_1 = ACCELERATION_Y_1 + sEvent.values[1]; ACCELERATION_Z_1 = ACCELERATION_Z_1 + sEvent.values[2]; } // low pass filter to reduce noise // if (ACCELRATION_SAMPLE_THRESHOLD == 0) { // set the threshold value back in each cycle // ACCELRATION_SAMPLE_COUNT = ACCELRATION_SAMPLE_COUNT; ACCELERATION_X_1 = ACCELERATION_X_1 / ACCELRATION_SAMPLE_COUNT; ACCELERATION_Y_1 = ACCELERATION_Y_1 / ACCELRATION_SAMPLE_COUNT; ACCELERATION_Z_1 = ACCELERATION_Z_1 / ACCELRATION_SAMPLE_COUNT; // remove zero reference data (acquired from the calibration stage) ACCELERATION_X_1 = ACCELERATION_X_1 - CALIBRATE_X; ACCELERATION_Y_1 = ACCELERATION_Y_1 - CALIBRATE_Y; ACCELERATION_Z_1 = ACCELERATION_Z_1 - CALIBRATE_Z; // begin debug log Log.i("SENSOR VELOCITY MODE", "accX" + ACCELERATION_X_1); Log.i("SENSOR VELOCITY MODE", "accY" + ACCELERATION_Y_1); Log.i("SENSOR VELOCITY MODE", "accZ" + ACCELERATION_Z_1); // end debug log // adding a discrimination window x axis if ((ACCELERATION_X_1 <= POSITIVE_LIMIT) && (ACCELERATION_X_1 >= NEGATIVE_LIMIT)) { ACCELERATION_X_1 = 0; } if ((ACCELERATION_Y_1 <= POSITIVE_LIMIT) && (ACCELERATION_Y_1 >= NEGATIVE_LIMIT)) { ACCELERATION_Y_1 = 0; } // adding a discrimination window to Z axis if ((ACCELERATION_Z_1 <= POSITIVE_LIMIT) && (ACCELERATION_Z_1 >= NEGATIVE_LIMIT)) { ACCELERATION_Z_1 = 0; } Log.i("APPLIED DISCRIMINIATION WINDOW", "accX" + ACCELERATION_X_1); Log.i("APPLIED DISCRIMINIATION WINDOW", "accY" + ACCELERATION_Y_1); Log.i("APPLIED DISCRIMINIATION WINDOW", "accZ" + ACCELERATION_Z_1); // X integration (according to mathematical integration), the time // need to be 1 unit (1 milli) VELOCITY_X_1 = VELOCITY_X_1 + ACCELERATION_X_1 + ((ACCELERATION_X_1 - ACCELERATION_X_0) / 2) * SAMPLE_WIDTH; VELOCITY_Y_1 = VELOCITY_Y_1 + ACCELERATION_Y_1 + ((ACCELERATION_Y_1 - ACCELERATION_Y_0) / 2) * SAMPLE_WIDTH; VELOCITY_Z_1 = VELOCITY_Z_1 + ACCELERATION_Z_1 + ((ACCELERATION_Z_1 - ACCELERATION_Z_0) / 2) * SAMPLE_WIDTH; // replace old acceleration values with new ones ACCELERATION_X_0 = ACCELERATION_X_1; ACCELERATION_Y_0 = ACCELERATION_Y_1; ACCELERATION_Z_0 = ACCELERATION_Z_1; // replace old velocity values with new ones VELOCITY_X_0 = VELOCITY_X_1; VELOCITY_Y_0 = VELOCITY_Y_1; VELOCITY_Z_0 = VELOCITY_Z_1; Movement movement = new Movement(System.currentTimeMillis()); movement.setVelocity(resultantVelocity(VELOCITY_X_0, VELOCITY_Y_0, VELOCITY_Z_0)); MOVEMENTS.add(movement); // } } /** * Only return the magnitude of the velocity to determine the movement of * the object. We only calculate flat plane velocity in this case (x, z * planes) * * @param x * @param y * @param z * @return - resultant velocity from the 3-vector velocity. * */ private double resultantVelocity(float x, float y, float z) { // return Math.abs(Math.pow((Math.pow(x, 2) + Math.pow(z, 2)), 0.5)); } /* * (non-Javadoc) * * @see * android.hardware.SensorEventListener#onAccuracyChanged(android.hardware * .Sensor, int) */ @Override public void onAccuracyChanged(Sensor arg0, int arg1) { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see * android.hardware.SensorEventListener#onSensorChanged(android.hardware * .SensorEvent) */ @Override public void onSensorChanged(SensorEvent event) { if (!MOVEMENT_FLAG) { MOVEMENT_FLAG = true; velocity(event); monitor(); inspect(); } else { velocity(event); } } /** * Class for handling calibrate event of the Accelerometer. Add Calibration * Listener first to calibrate the accelerometer sensor first before reading * data from the accelerometer. * * @author nthusitha * @date 08-Nov-2014 * */ public static class CalibratorListener implements SensorEventListener { @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { /* * while (CALIBRATION_SAMPLE_THRESHOLD > 0) { * CALIBRATION_SAMPLE_THRESHOLD--; } */ for (int i = 0; i < CALIBRATION_SAMPLE_COUNT; i++) { CALIBRATE_X = CALIBRATE_X + event.values[0]; CALIBRATE_Y = CALIBRATE_Y + event.values[1]; CALIBRATE_Z = CALIBRATE_Z + event.values[2]; } // if (CALIBRATION_SAMPLE_THRESHOLD == 0) { CALIBRATE_X = CALIBRATE_X / CALIBRATION_SAMPLE_COUNT; CALIBRATE_Y = CALIBRATE_Y / CALIBRATION_SAMPLE_COUNT; CALIBRATE_Z = CALIBRATE_Z / CALIBRATION_SAMPLE_COUNT; CALIBRATION_FLAG = false; // } } } /** * Represents vechicle's average movement at a given time. * * @author nthusitha * */ public static class Movement { private long timestamp; private double velocity; public Movement(long timestamp) { this.timestamp = timestamp; } public double getVelocity() { return velocity; } public void setVelocity(double velocity) { this.velocity = velocity; } public long getTimestamp() { return timestamp; } } // for testing (to put values in the screen) @Override public void notify_() { if (TXT_VIEW != null) { String vals = ">>"; for (byte i = 0; i < 5; i++) { if (VELOCITY_DEVIATION_LIST.peek() != null) { vals = vals + VELOCITY_DEVIATION_LIST.poll().getVelocity() + ", "; Log.i("NOTIFY MODE", "RESULTANT VELOCITIES - " + vals); } } TXT_VIEW.setText(vals); } } // for testing (to put values in the screen) @Override public void addUI(TextView v) { if (v != null) { TXT_VIEW = v; } } }