I need to get device orientation. As I know usually used TYPE_ACCELEROMETER
and TYPE_MAGNETIC_FIELD
sensors. My problem is that SensorManager.getDefaultSensor
returns me null
for geomagnetic sensor. It returns null
for TYPE_ORIENTATION
sensor too.
manager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor sensorAcc = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), //normal object
sensorMagn = manager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); //null
orientationListener = new OrientationSensorListener();
manager.registerListener(orientationListener, sensorAcc, 10);
manager.registerListener(orientationListener, sensorMagn, 10);
I need another ways to get device orientation.
Orientation can be decomposed in three Euler angle : Pitch, Roll and Azimuth.
With only accelerometer datas, you cannot compute your Azimuth, neither the sign of your pitch.
You can try something as this to know something about your pitch and roll :
private final float[] mMagnet = new float[3]; // magnetic field vector
private final float[] mAcceleration = new float[3]; // accelerometer vector
private final float[] mAccMagOrientation = new float[3]; // orientation angles from mAcceleration and mMagnet
private float[] mRotationMatrix = new float[9]; // accelerometer and magnetometer based rotation matrix
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mAcceleration, 0, 3); // save datas
calculateAccMagOrientation(); // then calculate new orientation
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mMagnet, 0, 3); // save datas
break;
default: break;
}
}
public void calculateAccMagOrientation() {
if (SensorManager.getRotationMatrix(mRotationMatrix, null, mAcceleration, mMagnet))
SensorManager.getOrientation(mRotationMatrix, mAccMagOrientation);
else { // Most chances are that there are no magnet datas
double gx, gy, gz;
gx = mAcceleration[0] / 9.81f;
gy = mAcceleration[1] / 9.81f;
gz = mAcceleration[2] / 9.81f;
// http://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/
float pitch = (float) -Math.atan(gy / Math.sqrt(gx * gx + gz * gz));
float roll = (float) -Math.atan(gx / Math.sqrt(gy * gy + gz * gz));
float azimuth = 0; // Impossible to guess
mAccMagOrientation[0] = azimuth;
mAccMagOrientation[1] = pitch;
mAccMagOrientation[2] = roll;
mRotationMatrix = getRotationMatrixFromOrientation(mAccMagOrientation);
}
}
public static float[] getRotationMatrixFromOrientation(float[] o) {
float[] xM = new float[9];
float[] yM = new float[9];
float[] zM = new float[9];
float sinX = (float) Math.sin(o[1]);
float cosX = (float) Math.cos(o[1]);
float sinY = (float) Math.sin(o[2]);
float cosY = (float) Math.cos(o[2]);
float sinZ = (float) Math.sin(o[0]);
float cosZ = (float) Math.cos(o[0]);
// rotation about x-axis (pitch)
xM[0] = 1.0f;xM[1] = 0.0f;xM[2] = 0.0f;
xM[3] = 0.0f;xM[4] = cosX;xM[5] = sinX;
xM[6] = 0.0f;xM[7] =-sinX;xM[8] = cosX;
// rotation about y-axis (roll)
yM[0] = cosY;yM[1] = 0.0f;yM[2] = sinY;
yM[3] = 0.0f;yM[4] = 1.0f;yM[5] = 0.0f;
yM[6] =-sinY;yM[7] = 0.0f;yM[8] = cosY;
// rotation about z-axis (azimuth)
zM[0] = cosZ;zM[1] = sinZ;zM[2] = 0.0f;
zM[3] =-sinZ;zM[4] = cosZ;zM[5] = 0.0f;
zM[6] = 0.0f;zM[7] = 0.0f;zM[8] = 1.0f;
// rotation order is y, x, z (roll, pitch, azimuth)
float[] resultMatrix = matrixMultiplication(xM, yM);
resultMatrix = matrixMultiplication(zM, resultMatrix);
return resultMatrix;
}
public static float[] matrixMultiplication(float[] A, float[] B) {
float[] result = new float[9];
result[0] = A[0] * B[0] + A[1] * B[3] + A[2] * B[6];
result[1] = A[0] * B[1] + A[1] * B[4] + A[2] * B[7];
result[2] = A[0] * B[2] + A[1] * B[5] + A[2] * B[8];
result[3] = A[3] * B[0] + A[4] * B[3] + A[5] * B[6];
result[4] = A[3] * B[1] + A[4] * B[4] + A[5] * B[7];
result[5] = A[3] * B[2] + A[4] * B[5] + A[5] * B[8];
result[6] = A[6] * B[0] + A[7] * B[3] + A[8] * B[6];
result[7] = A[6] * B[1] + A[7] * B[4] + A[8] * B[7];
result[8] = A[6] * B[2] + A[7] * B[5] + A[8] * B[8];
return result;
}
To get the angle of rotation when the device is not flat, implements OrientationEventListener
. onOrientationChanged
will give the device orientation. See https://developer.android.com/reference/android/view/OrientationEventListener.html for detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With