Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
327 views
in Technique[技术] by (71.8m points)

screen orientation - Android SensorManager strange how to remapCoordinateSystem

API Demos -> Graphics -> Compass

It works properly only, until you don't change the device natural orientation. In most phones is the portrait and most 10 inch tablets are the landscape. If you change than need to rotate this with 90 degree. I would like to see a 3D fix for that system.

100% sure need to use remapCoordinateSystem() method.

I would like to see how ( code ) if I could see an explanation with how is calculated those axes mapping ( theoretical math ) it would be nice.

I have tryed to understand, but I forgot all linear algebra.

Here it says why must we use, but doesn't telling how!

float R[] = new float[9];
// X  (product of Y and Z) and roughly points East
// Y: points to Magnetic NORTH and tangential to ground
// Z: points to SKY and perpendicular to ground
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);

It seems those coordinates are to this position: - the device say in a table (x, and y axes are on table)

device orientation

Only and only if

getWindowManager().getDefaultDisplay().getRotation() == Surface.ROTATION_0

The question is how to complete this code: - those case branches

switch (mScreenRotation) {
    case Surface.ROTATION_0:
    Log.v("SurfaceRemap", "0 degree");
    axisX = SensorManager.AXIS_X;// is this valid?
    axisY = SensorManager.AXIS_Y;// is this valid?
    break;

    case Surface.ROTATION_90:
    Log.v("SurfaceRemap", "90 degree");
    // examples says remapCoordinateSystem(inR, AXIS_Y, AXIS_MINUS_X, outR);
    axisX = SensorManager.AXIS_Y;
    axisY = SensorManager.AXIS_MINUS_X;
    break;

    case Surface.ROTATION_180:
    Log.v("SurfaceRemap", "180 degree");
    break;

    case Surface.ROTATION_270:
    Log.v("SurfaceRemap", "270 degree");
    break;

    default:
    Log.v("SurfaceRemap", "don't know the mScreenRotation value: "+mScreenRotation+" you should never seen this message!");
    break;
}


boolean remapped = SensorManager.remapCoordinateSystem(R, axisX, axisY, R);

float orientation[] = new float[3];

SensorManager.getOrientation(R, orientation);// All three angles above are in radians and positive in the counter-clockwise direction.
inclination = SensorManager.getInclination(I);

Edit: I wrote a little test application, where on the screen it display the screen rotation: 0, 90, 270 degrees ( can't make 180 now)

It seems, if Rotation 0 is unchanged (axisX = SensorManager.AXIS_X;axisY = SensorManager.AXIS_Y;) than the 90 degree should be:

axisX = SensorManager.AXIS_MINUS_Y;
axisY = SensorManager.AXIS_X;

than the Google documentation says somewhere wrong values! Question is where?!

getRotationMatrix return this:

enter image description here

X is defined as the vector product Y.Z (It is tangential to the ground at the device's current location and roughly points East).

Y is tangential to the ground at the device's current location and points towards the magnetic North Pole.

Z points towards the sky and is perpendicular to the ground.

See the phone above! I want to to to right from left, with back camera to ground.

getOrientation return this:

enter image description here

X is defined as the vector product Y.Z (It is tangential to the ground at the device's current location and roughly points West).

Y is tangential to the ground at the device's current location and points towards the magnetic North Pole.

Z points towards the center of the Earth and is perpendicular to the ground.

values[0]: azimuth, rotation around the Z axis.

values[1]: pitch, rotation around the X axis.

values[2]: roll, rotation around the Y axis.

How should be the phone?

Finally I would like to have values of angles like aircrafts. My phone (me) heading to North: (yaw is azimuth)

enter image description here

              if ScreenRotation = 0 degree
Pitch axis = -orientationAxisX  =  rotationAxisX
Roll axis  =  orientationAxisY  =  rotationAxisY 
Yaw axis   =  orientationAxisZ  = -rotationAxisZ
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To complete the switch branches I just try to think following the remapCoordinateSystem method javadoc:

X defines on which world axis and direction the X axis of the device is mapped.
Y defines on which world axis and direction the Y axis of the device is mapped.

So take your device rotate it from its natural orientation (90, 180 or 270 degrees) and ask yourself: The X positive axis in the original device orientation to which axis corresponds in the current device orientation?. And same for the Y axis.

So in case your device is rotated 90 degrees you will see that the original X positive axis corresponds to the current positive Y axis and the original positive Y axis corresponds to the current orientation negative X axis.

So It should be:

switch (mScreenRotation) {
    case Surface.ROTATION_0:
        axisX = SensorManager.AXIS_X;
    axisY = SensorManager.AXIS_Y;
        break;

    case Surface.ROTATION_90:
        axisX = SensorManager.AXIS_Y;
    axisY = SensorManager.AXIS_MINUS_X;
        break;

    case Surface.ROTATION_180:
        axisX = SensorManager.AXIS_MINUS_X;
    axisY = SensorManager.AXIS_MINUS_Y;
        break;

    case Surface.ROTATION_270:
        axisX = SensorManager.AXIS_MINUS_Y;
    axisY = SensorManager.AXIS_X;
        break;

    default:
        break;
}

That worked for me, hope that helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...