Orientacja może być rozłożona na trzy kąt Eulera: pochylenie, przechylenie i azymutu.
Tylko z danymi przyspieszeniomierza, nie można obliczyć Azymutu, ani znaku twojej wysokości.
Można spróbować czegoś jak to wiedzieć coś o swoim skoku i rolki:
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;
}
postu kod. – Jas
@Jas dodano do pytania – Ircover
można wykorzystać szerokość i wysokość ekranu do określenia orientacji, w trybie poziomym zazwyczaj szerokość jest większa niż wysokość. – ashutiwari4