I want to implement rotation vector sensor. I searched as much as I could about this sensor but I confused some points. I understand that I need to use quaternions other than Euler angles for my app to be more stable. I will use this sensor datas for gesture recognition. So I want to use quaternions but I don’t understand how can I convert them to quaternions after using remapCoordinateSystem method? Or am I wrong about what I want to do? Even a little bit help will be very useful for me.
#Override
public void onSensorChanged(SensorEvent event) {
float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values);
float[] adjustedRotationMatrix = new float[9];
SensorManager.remapCoordinateSystem(rotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, adjustedRotationMatrix);
float[] orientation = new float[3];
SensorManager.getOrientation(adjustedRotationMatrix, orientation);
float pitch = orientation[1];
float roll = orientation[2];
float yaw = orientation[0];
yawTextView.setText(getResources().getString(
R.string.yaw_sensor,yaw));
pitchTextView.setText(getResources().getString(
R.string.pitch_sensor,pitch));
rollTextView.setText(getResources().getString(
R.string.roll_sensor,roll));
}
Thank you.
See Euler angles to quaternion conversion.
Or otherwise, if you'd like to calculate quaternion components directly from the rotation matrix, see this page.
Related
In my app I am calculating azimuth, pitch and roll using accelerometer and magnetometer values:
float[] rotationMatrix = new float[9];
float[] inclinationMatrix = new float[9];
private float[] mMagnetometerValue = new float[3]; //event.values
private float[] mAccelerometerValue = new float[3]; //event.values
SensorManager.getRotationMatrix(rotationMatrix, inclinationMatrix, mAccelerometerValue, mMagnetometerValue);
// Orientation.
float[] orientation = new float[3];
SensorManager.getOrientation(rotationMatrix, orientation);
Now orientation array returns azimuth, pitch and roll.
As documentation says getOrientation function:
values[0]: Azimuth, angle of rotation about the -z axis
values1: Pitch, angle of rotation about the x axis
values2: Roll, angle of rotation about the y axis.
Now good.
But testing in another phone failed, because this phone has only accelerometer, not magnetometer, nor gyroscope or rotation vector sensor. After debugging I found that phone has device orientation sensor. Only doc I am found is this google gist.
Okay give a try. But this sensor returns only one float value, not float array.
So I can not pass this as parameter to SensorManager.getRotationMatrix function.
Now question:
How to retrieve pitch and roll with SensorManager.getRotationMatrix and SensorManager.getOrientation or without this functions using accelerometer and this device orientation sensor.
I want to get the rotation on x, y and z axis
I want to get these values
You can obtain Azimuth, Pitch and Roll in this way:
private SensorManager sensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrix(rotationMatrix, null,
accelerometerReading, magnetometerReading);
// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
SensorManager.getOrientation(rotationMatrix, orientationAngles);
source https://developer.android.com/guide/topics/sensors/sensors_position#java
I need to extract rotation of an Android device about the device Z-axis
I am currently using the ROTATION_VECTOR sensor and the following code, where rotVec is cloned from the values member of the SensorEvent:
float[] q = new float[4];
float[] globalRot = new float[9];
float[] localRot = new float[9];
float[] euler = new float[3];
SensorManager.getQuaternionFromVector(q, rotVec);
SensorManager.getRotationMatrixFromVector(globalRot,q);
SensorManager.remapCoordinateSystem(globalRot, SensorManager.AXIS_Y, SensorManager.AXIS_Z, localRot);
SensorManager.getOrientation(localRot, euler);
float rotation = euler[1];
As the device gets closer to flat, the value reported drifts from the true value. Also, the value is inverted after +- 90 degrees (0 is defined as Y pointing straight up).
What am I doing wrong, and what calls should I be using?
I have implemented listener for both Rotation Vector and Orientation Vector though i know it's depreciated i wanted to test both.
I know Rotation Vector is a fusion sensor & recommended but according to it the NORTH (the value[0] returned by getOrientation(rotationMatrix,value) geaving bearing 0) doesn't matches with NORTH from Orientation sensor.
I've also tallied from different apps from playstore, orientation sensor values seem to be more close to them.
Moreover many times my azimuth value[0] from Rotation_Vector then getOrientation just shoots up and keep oscillating between -180 to 180
P.S "getRotationMatrix(float[] R, float[] I, float[] gravity, float[] geomagnetic)" also gives same result as Rotation Vector.
public final void onSensorChanged(SensorEvent event)
{
float rotationMatrix[];
switch(event.sensor.getType())
{
.
.
.
case Sensor.TYPE_ROTATION_VECTOR:
rotationMatrix=new float[16];
mSensorManager.getRotationMatrixFromVector(rotationMatrix,event.values);
determineOrientation(rotationMatrix);
break;
case Sensor.TYPE_ORIENTATION:
sensorZValue.setText(""+event.values[0]); //rotation about geographical z axis
sensorXValue.setText(""+event.values[1]); //rotation about geographical x axis
sensorYValue.setText(""+event.values[2]); //rotation about geographical y axis
}//switch case ends
}
private void determineOrientation(float[] rotationMatrix)
{
float[] orientationValues = new float[3];
SensorManager.getOrientation(rotationMatrix, orientationValues);
double azimuth = Math.toDegrees(orientationValues[0]);
double pitch = Math.toDegrees(orientationValues[1]);
double roll = Math.toDegrees(orientationValues[2]);
sensorZValue.setText(String.valueOf(azimuth)); //rotation about geographical z axis
sensorXValue.setText(String.valueOf(pitch)); //rotation about geographical x axis
sensorYValue.setText(String.valueOf(roll)); //rotation about geographical y axis
}
I want to determine the angle between phone's Y axis and the Vector pointing North so that was my initial implementation.
Please suggest.
I think this will help...
Android Compass that can Compensate for Tilt and Pitch
This calculates North using more reliable sources.
Hope this helps.
I'm using android's TYPE_ROTATION_VECTOR sensor to determine rotation around x,y and z and use these measures in my application in a certain way. But when I rotate phone around X axis, roll value (rotation around Y) also changes. And I don't want that. How can I ignore changes in roll when I rotate around X? Here is piece of my code
private final float[] mRotationMatrix = new float[16];
private float[] orientationVals = new float[3];
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(
mRotationMatrix , event.values);
SensorManager.getOrientation(mRotationMatrix, orientationVals);
azimuthVal = (Math.round((Math.toDegrees(orientationVals[0]))*100.0)/100.0);
pitchVal= (Math.round((Math.toDegrees(orientationVals[1]))*100.0)/100.0);
rollVal = (Math.round((Math.toDegrees(orientationVals[2]))*100.0)/100.0);
}