Ryan
Ryan

Reputation: 957

Remapping sensor coordinates

What I want to happen, is to remap the coordinate system, when the phone is turned away from it's "natural" orientation. So that when using a phone, and it's in landscape, it should read the same values, as if it were being held in portrait.

I'm checking to see if rotation equals Surface.ROTATION_90, and if so, then remap the coordinate system.

I admit I don't quite understand how to do it properly, and could use a little guidance.

So, you need to run these two methods:

SensorManager.getRotationMatrix(inR, I, grav, mag); 
SensorManager.remapCoordinateSystem(inR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outR);

What's required to pass into these methods? I created a new float array, then passed just the orientationsensor data to the mag field, which didn't work. So, I registered both the accelerometer and magnetic field sensors. Fed the data from both of those to the getRotatioMatrix method, and I always get a NullPointerException (even though the JavaDoc says some arguments can be null). I even tried passing data to each argument, and still got a NullPointerException.

My question is, what is the proper data that I need to pass into the getRotationMatrix method?

Upvotes: 1

Views: 2922

Answers (2)

Simon
Simon

Reputation: 3730

I found that a very simple way to do this is the one used in the SDK sample AccelerometerPlay.

First you get your display like this, for example in onResume():

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mDisplay = windowManager.getDefaultDisplay();

Then in onSensorChanged() you can use this simple code:

@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)
        return;

    switch (mDisplay.getRotation()) {
        case Surface.ROTATION_0:
            mSensorX = event.values[0];
            mSensorY = event.values[1];
            break;
        case Surface.ROTATION_90:
            mSensorX = -event.values[1];
            mSensorY = event.values[0];
            break;
        case Surface.ROTATION_180:
            mSensorX = -event.values[0];
            mSensorY = -event.values[1];
            break;
        case Surface.ROTATION_270:
            mSensorX = event.values[1];
            mSensorY = -event.values[0];
            break;
    }
}

Hope this will help.

Upvotes: 6

Ridcully
Ridcully

Reputation: 23655

this is my code, and it works without NPEs. Note, that I have just one Listener, but you have to register it to listen to both sensors (ACCELEROMETER and MAGNETICFIELD).

private SensorEventListener mOrientationSensorsListener = new SensorEventListener() {

    private float[] mR = new float[9];
    private float[] mRemappedR = new float[9];
    private float[] mGeomagneticVector = new float[3];
    private float[] mGravityVector = new float[3];

    @Override
    public void onSensorChanged(SensorEvent event) {
        synchronized(this) {
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                mGravityVector = Util.exponentialSmoothing(event.values, mGravityVector, 0.2f);
            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                mGeomagneticVector = Util.exponentialSmoothing(event.values, mGeomagneticVector, 0.5f);

                SensorManager.getRotationMatrix(mR, null, mGravityVector, mGeomagneticVector);
                SensorManager.remapCoordinateSystem(mR, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, mRemappedR);
            }
        }
    }

The exponentialSmoothing method does some smoothing of the sensor results and looks like that (the alpha value can go from 0 to 1, where 1 means no smoothing at all):

public static float[] exponentialSmoothing(float[] input, float[] output, float alpha) {
    for (int i=0; i<input.length; i++) {
        output[i] = output[i] + alpha * (input[i] - output[i]);
    }
    return output;
} 

As for the synchronized bit -- I'm not sure that it is needed, just read it somewhere and added it.

Upvotes: 0

Related Questions