Android Open Source - TrafficTracker Linear Accelarator Sensor Listener






From Project

Back to project page TrafficTracker.

License

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.

Java Source Code

/**
 * //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;
    }

  }

}




Java Source Code List

com.dev.nuwan.roadtrafficmonitor.LinearAccelaratorSensorListener.java
com.dev.nuwan.roadtrafficmonitor.MainActivity.java
com.dev.nuwan.roadtrafficmonitor.VelocityAware.java