17

Hi I am building a 3D game for Android.

I am currently trying to add a sensor to my game that allows the player to tilt the android as its controls.

Ideally I would like to use the ORIENTATION sensor, but I noticed it has been deprecated. Does anyone know how to detect tilt in the android and doesn't use this sensor?

user1207381
  • 581
  • 2
  • 8
  • 19

1 Answers1

46

There is no actual "orientation" sensor - this is (was) actually a composite sensor, generated from a combination of the accelerometer and the magnometer.

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

"This sensor type exists for legacy reasons, please use getRotationMatrix() in conjunction with remapCoordinateSystem() and getOrientation() to compute these values instead."

public class OrientationTestActivity extends Activity implements SensorEventListener
{
    private SensorManager mSensorManager;
    private Sensor mAccelerometer;
    private Sensor mMagnetometer;

    private float[] mLastAccelerometer = new float[3];
    private float[] mLastMagnetometer = new float[3];
    private boolean mLastAccelerometerSet = false;
    private boolean mLastMagnetometerSet = false;

    private float[] mR = new float[9];
    private float[] mOrientation = new float[3];

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
    }

    protected void onResume() {
        super.onResume();
        mLastAccelerometerSet = false;
        mLastMagnetometerSet = false;
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(this);
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor == mAccelerometer) {
            System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
            mLastAccelerometerSet = true;
        } else if (event.sensor == mMagnetometer) {
            System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
            mLastMagnetometerSet = true;
        }
        if (mLastAccelerometerSet && mLastMagnetometerSet) {
            SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
            SensorManager.getOrientation(mR, mOrientation);
            Log.i("OrientationTestActivity", String.format("Orientation: %f, %f, %f",
                                                           mOrientation[0], mOrientation[1], mOrientation[2]));
        }
    }
}
JesusFreke
  • 19,784
  • 5
  • 65
  • 68
  • Is there anyway to use the getOrientation() command like an event handler like how the other sensors are used? – user1207381 Apr 24 '12 at 05:02
  • 4
    the getOrientation() function requires the values from getRotationMatrix() - which requires the values from both the magnetic and accelerometer sensors. So you set up your sensor listener for those 2 sensors and cache the values you get for them. And then you can recalculate the orientation when you get new data for either sensor. – JesusFreke Apr 24 '12 at 05:24
  • Is their sample code for how these methods are used together? I haven't been able to find any use of these methods together. – user1207381 Apr 26 '12 at 23:50
  • These are good suggestions and I tried something like it. The thing is the values I got were looking like angles, but jumped around and were a bit inconsistent. I was wondering if you have ever experienced anything like that when you've used this sensor? – user1207381 Apr 27 '12 at 21:47
  • 1
    The accelerometer and magnetometer sensors tend to be rather noisy. You can try using a running average to help smooth it out. – JesusFreke Apr 27 '12 at 22:00
  • To smooth out the values I use a running average: `runningValue = runningValue*(1-epsilon) +rawValue*epsilon;` for epsilon<1.0 – Anarchofascist Apr 19 '16 at 03:03