Code:
package ae.test.accelerometertester;
import java.util.LinkedList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.view.ViewTreeObserver;
public class MainActivity extends Activity implements OnItemSelectedListener{
private static final int FILTER_OFF = 0;
private static final int FILTER_LOW = 1;
private static final int FILTER_IIR = 2;
private static final int X_INDEX = 0;
private static final int Y_INDEX = 1;
private static final int Z_INDEX = 2;
// total nanoseconds in 1 second
private static final long NANOSECOND = 1000000000L;
// This value is the total time being displayed from across the width of the screen
private static final float MAX_TIME_PERIOD = 3.0f;
// This value is used to amplify the small jitters to make them more visible
private static final float MAGNITUDE = 100.0F;
// The top and bottom borders of the bitmap
private static final int BORDER_HEIGHT = 5;
// This controls how far from center the filter paths are drawn. A value of 0
// will draw the filtered paths directly on top of the raw paths.
private static final int FILTERED_PATH_OFFSET = 10;
private SensorManager sensorManager;
private SensorEventListener sensorListener;
private Sensor accelSensor;
private RadioButton offRadioButton;
private RadioButton lowPassRadioButton;
private RadioButton iirRadioButton;
private TextView lowPassAlphaTextView;
private EditText lowPassEditText;
private TextView iirAlphaTextView;
private EditText iirEditText;
private CheckBox avgCheckBox;
private Spinner avgSpinner;
private CheckBox fpsCheckBox;
private Spinner fpsSpinner;
private int fpsArray[];
private int fps;
private CheckBox deadzoneCheckBox;
private TextView deadzoneTextView;
private EditText deadzoneEditText;
private float deadzone;
private float lowAlpha;
private float iirAlpha;
private LinkedList<Data> sensorData;
private int avgMax;
private int avgArray[];
private int currentFilter;
private long lastEvent;
private ImageView img;
private Bitmap bitmap;
private Canvas canvas;
private Paint separatorPaint;
private Paint pathPaint;
private LinkedList<Data> rawDataList;
private LinkedList<Data> filteredDataList;
private int bitmapWidth;
private int bitmapHeight;
private float separatorInterval;
private float centerLineInterval;
/* class Data
* Description: This represents the accelerometer event. It contains the x, y, and z
* value of the event as well as the time stamp.
*/
class Data {
public float[] data;
public long timeStamp;
public Data(float xval, float yval, float zval, long time){
data = new float[3];
data[X_INDEX] = xval;
data[Y_INDEX] = yval;
data[Z_INDEX] = zval;
timeStamp = time;
}
public Data(Data in){
data = in.data;
timeStamp = in.timeStamp;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get an instance of the WindowManager
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
bitmapWidth = display.getWidth();
bitmapHeight = 450;
separatorPaint = new Paint();
separatorPaint.setStyle(Paint.Style.FILL_AND_STROKE);
separatorPaint.setStrokeWidth(4.0f);
separatorPaint.setColor(Color.LTGRAY);
separatorPaint.setTextSize(50.0f);
pathPaint = new Paint();
pathPaint.setStyle(Paint.Style.FILL_AND_STROKE);
pathPaint.setStrokeWidth(2.0f);
sensorData = new LinkedList<Data>();
rawDataList = new LinkedList<Data>();
filteredDataList = new LinkedList<Data>();
lastEvent = 0L;
// Get an instance of the SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorListener = new AccelListener();
findViewControls();
initViewControls();
createImageView();
}
/* Name: findViewControls()
* Description: Initializes all view controls associated with activity_main.xml
* Parameters: None
*/
private void findViewControls(){
offRadioButton = (RadioButton)findViewById(R.id.offRB);
lowPassRadioButton = (RadioButton)findViewById(R.id.lowRB);
iirRadioButton = (RadioButton)findViewById(R.id.IIRRB);
avgCheckBox = (CheckBox)findViewById(R.id.avgCB);
lowPassAlphaTextView = (TextView)findViewById(R.id.lowalphaTV);
lowPassEditText = (EditText)findViewById(R.id.LowPassET);
iirAlphaTextView = (TextView)findViewById(R.id.iirAlphaTV);
iirEditText = (EditText)findViewById(R.id.iirET);
avgSpinner = (Spinner)findViewById(R.id.avgSpinner);
fpsCheckBox = (CheckBox)findViewById(R.id.fpsCB);
fpsSpinner = (Spinner)findViewById(R.id.fpsSpinner);
deadzoneCheckBox = (CheckBox)findViewById(R.id.deadzoneCB);
deadzoneTextView = (TextView)findViewById(R.id.deadzoneTV);
deadzoneEditText = (EditText)findViewById(R.id.deadzoneET);
}
/* Name: initViewControls()
* Description: Set default values for view controls associated with activity_main.xml
* Parameters: None
*/
private void initViewControls(){
currentFilter = FILTER_OFF;
setRadioButton(currentFilter);
lowAlpha = 0.8f;
lowPassEditText.setText(Float.toString(lowAlpha));
lowPassAlphaTextView.setText(Float.toString(lowAlpha));
iirAlpha = 0.15f;
iirAlphaTextView.setText(Float.toString(iirAlpha));
iirEditText.setText(Float.toString(iirAlpha));
int spinnervalues[] = {3, 5, 10, 15, 20};
avgArray = spinnervalues;
avgMax = avgArray[1];
avgSpinner.setSelection(1);
avgSpinner.setOnItemSelectedListener(this);
int fpsValues[] = {1, 3, 5, 10, 20, 40};
fpsArray = fpsValues;
fps = fpsArray[2];
fpsSpinner.setSelection(2);
fpsSpinner.setOnItemSelectedListener(this);
deadzone = 0.1f;
deadzoneTextView.setText(Float.toString(deadzone));
deadzoneEditText.setText(Float.toString(deadzone));
}
/* Name: createImageView()
* Description: Creates and initializes the ImageView, Bitmap, and canvas that the
* accelerometer data is drawn inside. The bitmap height is devices
* dependent. The bitmap cannot be built until the layout has been
* inflated. A ViewTreeObserver is used to listen for this event.
* The bitmap is then created and drawn.
* Parameters: None
*/
private void createImageView() {
final LinearLayout layout = (LinearLayout)findViewById(R.id.Row1Layout);
img = new ImageView(this);
layout.addView(img);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
bitmapHeight = layout.getMeasuredHeight();
bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.BLACK);
canvas = new Canvas(bitmap);
img.setImageBitmap(bitmap);
separatorInterval = (float)(bitmapHeight - (BORDER_HEIGHT*2)) / MAX_TIME_PERIOD;
centerLineInterval = separatorInterval / 2.0f;
drawCenterLines(0);
drawAxisSeparators();
img.invalidate();
}
});
}
/* Name: onResume()
* Description: Overrides android.app.Activity#onResume(). The sensor listener is
* registered here. This allows the app to turn the listener on when
* the app is brought to the front.
* Parameters: None
*/
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(sensorListener, accelSensor, SensorManager.SENSOR_DELAY_UI);
}
/* Name: onPause()
* Description: Overrides android.app.Activity#onPause(). The sensor Listener is
* unregistered at this point. This prevents the app from being active
* when it gets moved to the background.
* Parameters: None
*/
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(sensorListener);
}
//@Override
//protected void onSaveInstanceState(Bundle outState){
// super.onSaveInstanceState(outState);
//}
/* Name: onItemSelected()
* Description: Overrides
* android.widget.AdapterView.OnItemSelectedListener#onItemSelected().
* Handles spinners selection for avgSpinner and fpsSpinner.
* Parameters: default (see android documentation)
*/
@Override
public void onItemSelected(AdapterView<?> parent, View v, int position,
long id) {
switch (parent.getId()) {
case R.id.avgSpinner:
avgMax = avgArray[avgSpinner.getSelectedItemPosition()];
break;
case R.id.fpsSpinner:
fps = fpsArray[fpsSpinner.getSelectedItemPosition()];
break;
}
}
/* Name: onNothingSelected()
* Description: Overrides
* android.widget.AdapterView.OnItemSelectedListener#onNothingSelected().
* This must be implemented, however it is not used.
*/
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
/* Name: setButtonClicked()
* Description: Converts an EditText value into a float and updates a TextView with
* this float value. The values are capped between 0.0f and 1.0f.
* Parameters: EditText et where float value is to be retrieved from
* TexView tv where et value is diplayed.
*/
private float setButtonClicked(EditText et, TextView tv) {
String sAlpha = et.getText().toString().trim();
float alpha = Float.valueOf(sAlpha).floatValue();
if (alpha < 0.0f) alpha = 0.0f;
if (alpha > 1.0f) alpha = 1.0f;
tv.setText(Float.toString(alpha));
return alpha;
}
/* Name: mainClickHandler()
* Description: Handles all button presses on activity_main.xml
* Parameters: View v the view that was clicked
*/
public void mainClickHandler(View v){
switch (v.getId()) {
case R.id.setlowbutton:
lowAlpha = setButtonClicked(lowPassEditText, lowPassAlphaTextView);
break;
case R.id.setiirbutton:
iirAlpha = setButtonClicked(iirEditText, iirAlphaTextView);
break;
case R.id.offRB:
setRadioButton(FILTER_OFF);
break;
case R.id.lowRB:
setRadioButton(FILTER_LOW);
break;
case R.id.IIRRB:
setRadioButton(FILTER_IIR);
break;
case R.id.deadzoneButton:
deadzone = setButtonClicked(deadzoneEditText, deadzoneTextView);
break;
}
}
/* Name setRadioButton()
* Description: Controls switching between the radio buttons. If one is clicked,
* it will be selected while the others will be unselected.
*/
private void setRadioButton(int filtertype){
if (filtertype == FILTER_OFF) {
offRadioButton.setChecked(true);
currentFilter = FILTER_OFF;
} else offRadioButton.setChecked(false);
if (filtertype == FILTER_LOW) {
lowPassRadioButton.setChecked(true);
currentFilter = FILTER_LOW;
} else lowPassRadioButton.setChecked(false);
if (filtertype == FILTER_IIR) {
iirRadioButton.setChecked(true);
currentFilter = FILTER_IIR;
} else iirRadioButton.setChecked(false);
}
/* Name: updateSensorData()
* Description: Adds new sensor data to sensorData while ensuring that sensorData
* does not grow too large.
* Parameters: Data data New data to be added to sensorData
*/
private void updateSensorData(Data data) {
sensorData.add(data);
while (sensorData.size() > avgMax) {
sensorData.remove();
}
}
/* Name: deadZone()
* Description: Processes incoming data using a dead zone filter. If the dead zone
* filter is being used, the delta value is found for each axis of
* inData. If the delta value greater than the dead zone threshold
* then the inData value is passed out, else the previous value is
* passed out. each axis is considered individually.
* Parameters: Data inData data element to be filtered.
*/
protected Data deadZone(Data inData){
Data ouput = new Data(inData);
if (deadzoneCheckBox.isChecked()){
Data prevData = sensorData.getLast();
float deltaX = Math.abs(ouput.data[X_INDEX] - prevData.data[X_INDEX]);
float deltaY = Math.abs(ouput.data[Y_INDEX] - prevData.data[Y_INDEX]);
float deltaZ = Math.abs(ouput.data[Z_INDEX] - prevData.data[Z_INDEX]);
if (deltaX < deadzone) ouput.data[X_INDEX] = prevData.data[X_INDEX];
if (deltaY < deadzone) ouput.data[Y_INDEX] = prevData.data[Y_INDEX];
if (deltaZ < deadzone) ouput.data[Z_INDEX] = prevData.data[Z_INDEX];
}
return ouput;
}
/* Name: lowPass()
* Description: This is a low pass filter. It works by only allowing a value to
* change by a percentage (alpha) of difference between the previous
* value and the new value.
* output = previous + alpha * (in - previous)
*
* Parameters: Data data this is the latest sensor value.
*/
private Data lowPass(Data data){
Data prev = sensorData.getLast();
Data output = new Data(0.0f, 0.0f, 0.0f, data.timeStamp);
output.data[X_INDEX] = prev.data[X_INDEX] + lowAlpha * (data.data[X_INDEX] - prev.data[X_INDEX]);
output.data[Y_INDEX] = prev.data[Y_INDEX] + lowAlpha * (data.data[Y_INDEX] - prev.data[Y_INDEX]);
output.data[Z_INDEX] = prev.data[Z_INDEX] + lowAlpha * (data.data[Z_INDEX] - prev.data[Z_INDEX]);
return output;
}
/* Name: iirFilter()
* Description: This is a infinite impulse response filter. It works by combining a
* percentage (alpha) of previous value with the opposite percentage of
* the new value.
* output = previous * alpha + (1 - alpha) * in
*
* Parameters: Data data this is the latest sensor value.
*/
private Data iirFilter(Data data){
Data prev = sensorData.getLast();
Data output = new Data(0.0f, 0.0f, 0.0f, data.timeStamp);
output.data[X_INDEX] = prev.data[X_INDEX] * iirAlpha + (1.0f - iirAlpha) * data.data[X_INDEX];
output.data[Y_INDEX] = prev.data[Y_INDEX] * iirAlpha + (1.0f - iirAlpha) * data.data[Y_INDEX];
output.data[Z_INDEX] = prev.data[Z_INDEX] * iirAlpha + (1.0f - iirAlpha) * data.data[Z_INDEX];
return output;
}
/* Name: avgFilter()
* Description: Rolling average filter. This outputs the average value for
* all sensorData elements. The size of sensorData is controlled
* by updataSensorData()
* Parameters: None
*/
protected Data avgFilter(){
Data output = new Data(0.0f, 0.0f, 0.0f, 0L);
int count = 0;
int max = sensorData.size();
while (count < max) {
Data next = sensorData.get(count);
output.data[X_INDEX] += next.data[X_INDEX];
output.data[Y_INDEX] += next.data[Y_INDEX];
output.data[Z_INDEX] += next.data[Z_INDEX];
if (count == max - 1){
output.timeStamp = next.timeStamp;
}
++count;
}
output.data[X_INDEX] /= (float)max;
output.data[Y_INDEX] /= (float)max;
output.data[Z_INDEX] /= (float)max;
return output;
}
/* Name getFiltered()
* Description: Takes the sensor data and send it to the appropriate filters
* New returns the updated data.
*/
private Data getFiltered(Data inData){
Data output = new Data(0.0f, 0.0f, 0.0f, inData.timeStamp);
if (currentFilter == FILTER_OFF) {
output = inData;
}
if (currentFilter == FILTER_LOW){
output = lowPass(inData);
}
if (currentFilter == FILTER_IIR){
output = iirFilter(inData);
}
return output;
}
/* Name: updateSurface()
* Description: Redraws the sensor data bitmap. RawDataList and FilteredDataList are
* designed to have the same number of elements so the size of one is
* used to draw the paths of both.
* Parameters: None
*/
public void updateSurface(){
if (canvas != null){
canvas.drawARGB(255, 0, 0, 0);
validateTimeFrame();
int numPaths = rawDataList.size() - 1;
drawCenterLines(numPaths);
if (numPaths > 0){
int currentPath = 0;
while (currentPath < numPaths){
drawRawPath(currentPath);
drawFilteredPath(currentPath);
++currentPath;
}
}
drawAxisSeparators();
img.invalidate();
}
}
/* Name: drawCenterLines()
* Description: Draws three line segments which represent the centerline of each axis.
* The number of data inputs per second is also printed the the upper
* left of the bitmap.
* Parameters: int numPaths this should be the current size of the
* rawDataList - 1
*/
private void drawCenterLines(int numPaths){
separatorPaint.setColor(Color.LTGRAY);
canvas.drawText(Integer.toString(numPaths/(int)MAX_TIME_PERIOD), 10, 60, separatorPaint);
Path centerLines = new Path();
centerLines.moveTo(0.0f, centerLineInterval + BORDER_HEIGHT);
centerLines.lineTo(bitmapWidth, centerLineInterval + BORDER_HEIGHT);
centerLines.moveTo(0.0f, centerLineInterval + separatorInterval + BORDER_HEIGHT);
centerLines.lineTo(bitmapWidth, centerLineInterval + separatorInterval + BORDER_HEIGHT);
centerLines.moveTo(0.0f, centerLineInterval +(separatorInterval*2.0f) + BORDER_HEIGHT);
centerLines.lineTo(bitmapWidth, centerLineInterval +(separatorInterval*2.0f) + BORDER_HEIGHT);
canvas.drawPath(centerLines, separatorPaint);
}
/* Name: dawAxisSeparators()
* Description: Draws the lines that separate each axis on the bitmap
* Parameters: None
*/
private void drawAxisSeparators(){
separatorPaint.setColor(Color.DKGRAY);
Path separator = new Path();
separator.moveTo(0.0f, separatorInterval + BORDER_HEIGHT);
separator.lineTo(bitmapWidth, separatorInterval + BORDER_HEIGHT);
separator.moveTo(0.0f, (separatorInterval*2.0f) + BORDER_HEIGHT);
separator.lineTo(bitmapWidth, (separatorInterval*2.0f) + BORDER_HEIGHT);
canvas.drawPath(separator, separatorPaint);
}
/* Name: drawRawPath()
* Description: Draws a single path segment for each axis in the appropriate color.
* Parameters: int currentPath the next path to be drawn
*/
private void drawRawPath(int currentPath){
Path path = getPath(rawDataList, currentPath, X_INDEX, 0);
if (path != null){
pathPaint.setColor(Color.GREEN);
canvas.drawPath(path, pathPaint);
}
path = getPath(rawDataList, currentPath, Y_INDEX, 0);
if (path != null){
pathPaint.setColor(Color.RED);
canvas.drawPath(path, pathPaint);
}
path = getPath(rawDataList, currentPath, Z_INDEX, 0);
if (path != null){
pathPaint.setColor(Color.BLUE);
canvas.drawPath(path, pathPaint);
}
}
/* Name: drawFilteredPath()
* Description: Draws a single path segment for each axis in the appropriate color.
* The path will only be drawn if one or more of the filters have been
* activated.
* Parameters: int currentPath the next path to be drawn
*/
private void drawFilteredPath(int currentPath){
if (currentFilter != FILTER_OFF || deadzoneCheckBox.isChecked() ||
fpsCheckBox.isChecked() || avgCheckBox.isChecked()){
Path path = getPath(filteredDataList, currentPath, X_INDEX, FILTERED_PATH_OFFSET);
if (path != null){
pathPaint.setColor(Color.YELLOW);
canvas.drawPath(path, pathPaint);
}
path = getPath(filteredDataList, currentPath, Y_INDEX, FILTERED_PATH_OFFSET);
if (path != null){
pathPaint.setColor(Color.MAGENTA);
canvas.drawPath(path, pathPaint);
}
path = getPath(filteredDataList, currentPath, Z_INDEX, FILTERED_PATH_OFFSET);
if (path != null){
pathPaint.setColor(Color.CYAN);
canvas.drawPath(path, pathPaint);
}
}
}
/* Name: validateTimeFrame()
* Description: The maximum time frame to be recorded is set by MAX_TIME_PERIOD.
* rawDataList and filteredDataList are FIFO list. If the total
* time represented by these list exceeds the maximum, then elements
* are removed one at a time from each list until the time frames
* are within the maximum.
* Parameters: None
*/
private void validateTimeFrame(){
long timeFrame = rawDataList.getLast().timeStamp - rawDataList.getFirst().timeStamp;
while (timeFrame > NANOSECOND * (long)MAX_TIME_PERIOD ){
rawDataList.remove();
filteredDataList.remove();
timeFrame = rawDataList.getLast().timeStamp - rawDataList.getFirst().timeStamp;
}
}
/* Name: getPath()
* Description: returns a path between the two points represented by list[pathIndex]
* and list[pathIndex + 1].
* Parameters: LinkedList<Data> list the list to be processed
* int pathIndex the first point of the path
* int axis value between 0-2 representing the x, y,
* or z axis
*/
private Path getPath(LinkedList<Data> list, int pathIndex, int axis, int offset){
Path path = null;
if (pathIndex < list.size() - 1) {
Data point1 = list.get(pathIndex);
Data point2 = list.get(pathIndex + 1);
path = new Path();
long startTime = list.getFirst().timeStamp;
long startDelta = point1.timeStamp - startTime;
float pixelsPerSecond = bitmapWidth / MAX_TIME_PERIOD;
float xPixelsPerNano = pixelsPerSecond / NANOSECOND;
float xpos = (float)startDelta * xPixelsPerNano;
float yDelta = point1.data[axis];
if (axis == Z_INDEX){
yDelta -= SensorManager.GRAVITY_EARTH;
}
yDelta *= MAGNITUDE;
if (yDelta > centerLineInterval) yDelta = centerLineInterval;
if (yDelta < -centerLineInterval) yDelta = -centerLineInterval;
float ypos = BORDER_HEIGHT + offset + centerLineInterval + (separatorInterval * axis) + yDelta;
long moveDelta = point2.timeStamp - startTime;
float xmove = (float)moveDelta * xPixelsPerNano;
float ymoveDelta = point2.data[axis];
if (axis == Z_INDEX){
ymoveDelta -= SensorManager.GRAVITY_EARTH;
}
ymoveDelta *= MAGNITUDE;
if (ymoveDelta > centerLineInterval) ymoveDelta = centerLineInterval;
if (ymoveDelta < -centerLineInterval) ymoveDelta = -centerLineInterval;
float ymove = BORDER_HEIGHT + offset + centerLineInterval + (separatorInterval * axis) + ymoveDelta;
path.moveTo(xpos, ypos);
path.lineTo(xmove, ymove);
}
return path;
}
/* class AccelListener
* Description: This class processes the accelerometer events
*/
class AccelListener implements SensorEventListener {
/* Name: onSensorChanged()
* Description: Overrides
* android.hardware.SensorEventListener#onSensorChanged().
* Each new event is added to rawDataList. It is then
* processed by any filter that has been activated.
* Parameters: SensorEvent event a new sensor event
*/
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
return;
Data rawData = new Data(event.values[X_INDEX], event.values[Y_INDEX], event.values[Z_INDEX], event.timestamp);
rawDataList.add(rawData);
Data filteredData = new Data(event.values[X_INDEX], event.values[Y_INDEX], event.values[Z_INDEX], event.timestamp);
filteredDataList.add(processFilteredData(filteredData));
updateSurface();
}
/* Name processFilterData()
* Description: processes data from latest event through any filter that has
* been selected. The filters are applied in this order.
* 1. fps
* 2. dead zone
* 3. low pass / iir
* 4. rolling average
*/
private Data processFilteredData(Data filteredData){
if (!fpsCheckBox.isChecked()){
filteredData = deadZone(filteredData);
filteredData = getFiltered(filteredData);
updateSensorData(filteredData);
if (avgCheckBox.isChecked()){
filteredData = avgFilter();
}
lastEvent = filteredData.timeStamp;
}
else {
long deltaTime = filteredData.timeStamp - lastEvent;
long timeInterval = NANOSECOND / (long)fps;
if (deltaTime > timeInterval){
filteredData = deadZone(filteredData);
filteredData = getFiltered(filteredData);
updateSensorData(filteredData);
if (avgCheckBox.isChecked()){
filteredData = avgFilter();
}
lastEvent = filteredData.timeStamp;
}
else {
long timeStamp = filteredData.timeStamp;
filteredData = new Data(filteredDataList.getLast());
filteredData.timeStamp = timeStamp;
}
}
return filteredData;
}
/* Name onAccuracyChanged()
* Description: Overrides
* android.hardware.SensorEventListener#onAccuracyChanged().
* This is a required implementation, however it is not used
* Parameters: default (see android documentation)
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
}