14

I testing the accelerometer output on 2 different devices(Elocity A7 and Archos 7 Home tablet) but the sensor seems to be giving different results. I have it programmed to set to landscape mode but the x and y axis seem to be the oppisite between the 2 devices. The x axis returns 10 when held perpendicular to the ground and the Archos X axis returns 0. The Elocity tablet is android 2.2 and the Archos is 2.1. Can someone point me in the right direction as how to get orientation from the accelerometer in sync between these 2 devices?

Community
  • 1
  • 1
pth
  • 141
  • 1
  • 1
  • 4

4 Answers4

16

In fact, the accelerometer axises are relative to the default orientation of the device.

Here how to deal with it:

static void canonicalOrientationToScreenOrientation(
         int displayRotation, float[] canVec, float[] screenVec) 
{ 
    final int axisSwap[][] = { 
    {  1,  -1,  0,  1  },     // ROTATION_0 
    {-1,  -1,  1,  0  },     // ROTATION_90 
    {-1,    1,  0,  1  },     // ROTATION_180 
    {  1,    1,  1,  0  }  }; // ROTATION_270 

    final int[] as = axisSwap[displayRotation]; 
    screenVec[0]  =  (float)as[0] * canVec[ as[2] ]; 
    screenVec[1]  =  (float)as[1] * canVec[ as[3] ]; 
    screenVec[2]  =  canVec[2]; 
} 

This solution was provided by NVidia. Check their white paper about Android Accelerometer for more details.

Hartok
  • 2,147
  • 20
  • 37
  • I'm sorry but what do you add on canVec and on screenVec? displayrotation I assume is for PROTRAIT or LANDSCAPE constants, right? – Dante Apr 10 '14 at 03:31
  • 2
    For more detail, check this link http://developer.download.nvidia.com/tegra/docs/tegra_android_accelerometer_v5f.pdf – Hartok Apr 10 '14 at 04:47
12

just wanted to add something to Hartok's answer as I couldn't understand it at first...

I've rewritten the method to be:

public static float[] adjustAccelOrientation(int displayRotation, float[] eventValues) 
{ 
    float[] adjustedValues = new float[3];

    final int axisSwap[][] = {
    {  1,  -1,  0,  1  },     // ROTATION_0 
    {-1,  -1,  1,  0  },     // ROTATION_90 
    {-1,    1,  0,  1  },     // ROTATION_180 
    {  1,    1,  1,  0  }  }; // ROTATION_270 

    final int[] as = axisSwap[displayRotation]; 
    adjustedValues[0]  =  (float)as[0] * eventValues[ as[2] ]; 
    adjustedValues[1]  =  (float)as[1] * eventValues[ as[3] ]; 
    adjustedValues[2]  =  eventValues[2];

    return adjustedValues;
}

Exactly the same thing, just with more user friendly variable names and I recreate the float internally because I needed it like that... Simply call this function, put in the getRotation and the event.values float array, check the values of its return float array and pick whatever number you prefer...

Hope this helps someone!

user1504495
  • 666
  • 8
  • 17
  • sorry but what do I put on the displayRotation int? I've put the SensorEvent called event from the public void onSensorChanged(SensorEvent event). What am I missing? What should I add? – Dante Apr 10 '14 at 01:13
  • 2
    You need the display rotation. (WindowManager)this.getSystemService(WINDOW_SERVICE).getDefaultDisplay().getRotation() – user1504495 Apr 11 '14 at 13:51
7

As far as I know this is because of default orientation of device. F.e. new android tablets with Honeycomb have portrait orientation when held like in landscape on phones.

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

In android documentation there is information that:

The coordinate-system is defined relative to the screen of the phone in its default orientation. The axes are not swapped when the device's screen orientation changes.

The X axis is horizontal and points to the right, the Y axis is vertical and points up and the Z axis points towards the outside of the front face of the screen. In this system, coordinates behind the screen have negative Z values.

Maybe one of this devices has also landscape as a portrait (default) orientation?

Hope it helps you somehow.

cannehal
  • 71
  • 2
  • 3
4

As stated before, the default screen orientation can vary from device to device. The accelerometer coordinates will always match the devices default orientation. This behavior is different for screen coordinates. As the device rotates the screen coordinates rotates as well, such that (0, 0) is always the current top left corner of the screen. On a device with a default orientation of portrait, locking the orientation to portrait will ensure that the sensor coordinates run along the same axis as the screen coordinates regardless of the rotation. On the other hand, locking the screen orientation to portrait on a device with a default landscape orientation will cause the sensor axis to run in a different direction than the screen axis.

This article: http://android-developers.blogspot.com/2010/09/one-screen-turn-deserves-another.html explains this in greater depth as well as gives a solution for dealing with the problem.

Aholio
  • 273
  • 3
  • 8