Search code examples
androidmultithreadingandroid-sensors

Accelerometer data is mixed with Gyroscope when multiple listeners are registered


PROBLEM

I'm developing an app which sends multiple sensor data via UDP. I've noticed that when I registered multiple listeners simultaneously (accel and gyro), the data I read from either sensor is a mix of the two sensor readouts (when display the accel data, it jumps between accel and gyro values, rather than just displaying the accel values).

WHAT I HAVE TRIED

I've tried putting each sensorlistener on a separate thread, and playing around with different listener parameters, but nothing has made a difference.

IMPORTANT NOTES

  • When I pass my data through another function (lowpass filter in this case), the data becomes much more stable, but still jumps between sensors from time to time (but nowhere near as frequent). This is not because of filtering - if I set the alpha of the lowpass filter to 1 (no filtering), the result is still more stable. Perhaps this is because of an extra delay from passing through the function?

  • When I only register accelerometer (no gyroscope), the data is perfect. There is no gyroscope data within the accelerometer output.

  • This is not a hardware issue. I have downloaded other sensor testing apps that display sensor data, and they do not appear to have any issues reading sensor data off of my phone.

Any ideas as to what I've done wrong? Is it something with how I am interpreting the onSensorChanged event to handle multiple sensors?

// code omitted


Solution

  • I believe you don't have an Android problem but a simple Java problem. The SensorEvent.values is a float array object and you are just passing around its pointer. Consider cloning the whole 'event' oject or explicitly copying relevant elements from the array. For example look at the code below (taken from the Android SDK documentation ) see how the array data is explicitly copying elements discretely.

    http://developer.android.com/reference/android/hardware/SensorEvent.html

     // Class Members
     private float gravity[];
     private float linear_acceleration[];
    
     public void onSensorChanged(SensorEvent event)
     {
          // alpha is calculated as t / (t + dT)
          // with t, the low-pass filter's time-constant
          // and dT, the event delivery rate
    
          final float alpha = 0.8;
    
          // Elements are discretely copied.
          gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
          gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
          gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
    
          linear_acceleration[0] = event.values[0] - gravity[0];
          linear_acceleration[1] = event.values[1] - gravity[1];
          linear_acceleration[2] = event.values[2] - gravity[2];
     }