Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the euler-angles from the rotation vector (Sensor.TYPE_ROTATION_VECTOR)

I rotated my android device in x direction (from -180 degree to 180 degree), see image below. enter image description here
And I assume only Rotation vector x value is changed. Y and z maybe have some noise, but it should be not much difference among the values.

However, I receive this. Kindly see

https://docs.google.com/spreadsheets/d/1ZLoSKI8XNjI1v4exaXxsuMtzP0qWTP5Uu4C3YTwnsKo/edit?usp=sharing

I suspect my sensor has some problem.

Any idea? Thank you very much.

Jimmy

like image 798
Charles Brown Avatar asked May 16 '15 18:05

Charles Brown


People also ask

How do you extract Euler angles from a rotation matrix?

Given a rotation matrix R, we can compute the Euler angles, ψ, θ, and φ by equating each element in R with the corresponding element in the matrix product Rz(φ)Ry(θ)Rx(ψ). This results in nine equations that can be used to find the Euler angles. Starting with R31, we find R31 = − sin θ.

How do you find the angle of a vector rotation?

Therefore, the unit vector in the direction of Θ is k=Θ/‖Θ‖=(1/√2,1/√2,0), which should be the axis of rotation that you're looking for. The angle should just be the norm of Θ, that is, θ=‖Θ‖=2√2. Note that kθ gives you your original vector Θ.

What are the 3 Euler angles?

The relative orientation between two orthogonal righthanded 3D cartesian coordinate systems, let's call them xyz and ABC, is described by a real orthogonal 3x3 rotation matrix R, which is commonly parameterized by three so-called Euler angles α, β and γ.


1 Answers

Your sensor is fine.
Well, the rotation vector entries cannot simply be related to the rotation angle around a particular axis. The SensorEvent structure constitutes of timestamp, sensor, accuracy and values. Depending on the vector the float[] of values vary in size 1-5.
The rotation vectors values are based on unit quaternions, all together forming a vector representing the orientation of this world frame relative to your smartphone fixed frame above enter image description here They are unitless and positive counter-clockwise.

The orientation of the phone is represented by the rotation necessary to align the East-North-Up coordinates with the phone's coordinates. That is, applying the rotation to the world frame (X,Y,Z) would align them with the phone coordinates (x,y,z).

If the vector would be a Rotation-Matrix one could write it as
v_body = R_rot_vec * v_world (<--)
pushing the world vector into a smartphone fixed description.
Furthermore about the vector:

The three elements of the rotation vector are equal to the last three components of a unit quaternion <cos(θ/2), xsin(θ/2), ysin(θ/2), z*sin(θ/2)>.

Q: So what to do with it?
Depending on your Euler-angles convention (possible 24 sequences, valid 12 ones) you could calculate the corresponding angles u := [ψ,θ,φ] by e.g. applying
the 123 sequence:
enter image description here
If you already have the rotation matrix entries get euler like so:
123 seq euler angles
the 321 sequence:
321 seq euler angles
with q1-3 always being the values[0-2] (Dont get confused by u_ijk as ref(Diebel) uses different conventions comp. to the standard)

But wait, your linked table only does have 3 values, which is similar to what I get. This is oneSensorEvent of mine, the last three are printed from values[]

timestamp      sensortype accuracy values[0]    values[1]   values[2]
23191581386897 11         -75      -0.0036907701 -0.014922042 0.9932963

4q - 3 values = 1q unknown. The first q0 is redundant info (also the doku says it should be there under values[3], depends on your API-level). So we can use the norm (=length) to calculate q0 from the other three.
unit-norm
Set the equation ||q|| = 1 and solve for q0. Now all q0-3 are known.
Furthermore my android 4.4.2 does not have the fourth estimated heading Accuracy (in radians) inside value[4], so I evaluate the event.accuracy:

for (SensorEvent e : currentEvent) {
    if (e != null) {
        String toMsg = "";
        for(int i = 0; i < e.values.length;i++) {
            toMsg += " " + String.valueOf(e.values[i]);
        }
        iBinder.msgString(String.valueOf(e.timestamp) + " "+String.valueOf(e.sensor.getType()) + " " + String.valueOf(e.accuracy) + toMsg, 0);
    }
}

Put those equations into code and you will get things sorted.

Here is a short conversion helper, converting Quats. using either XYZ or ZYX. It can be run from shell github. (BSD-licensed)
The relevant part for XYZ

/*quaternation to euler in XYZ (seq:123)*/
double* quat2eulerxyz(double* q) {
  /*euler-angles*/
  double psi = atan2( -2.*(q[2]*q[3] - q[0]*q[1]) , q[0]*q[0] - q[1]*q[1]- q[2]*q[2] + q[3]*q[3] ); 
  double theta = asin( 2.*(q[1]*q[3] + q[0]*q[2]) );
  double phi = atan2( 2.*(-q[1]*q[2] + q[0]*q[3]) , q[0]*q[0] + q[1]*q[1] - q[2]*q[2] - q[3]*q[3] );   
  /*save var. by simply pushing them back into the array and return*/
  q[1] = psi; 
  q[2] = theta;
  q[3] = phi;
  return q;
}

Here some examples applying quats to euls: enter image description here



**Q:** What do the sequence ijk stand for?
Take two coordinate-frames A and B superposing each other(all axis within each other) and start rotating frame B through i-axis having angle `psi`, then j-axis having angle `theta` and last z-axis having `phi`. It could also be α, β, γ for i,j,k. *I don't pick up the numbers as they are confusing (Diebel vs other papers).*
R(psi,theta,phi) = R_z(phi)R_y(theta)R_x(psi) (<--)

The trick is elementary rotations are applied from right to left, although we read the sequence from left to right. Those are the three elementary rotations youre going through to go from

A to B: *v_B = R(psi,theta,phi) v_A*


**Q:** So how to get the euler angles/quats turn from [0°,0°,0°] to eg. [0°,90°,0°]?
First align both frames from the pictures, respective the known device frame B to the "invisible" worldframe A. Your done superposing when the angles all get to [0°,0°,0°]. Just figure out where is north, south and east where you are sitting right now and point the devices frame B into those directions. Now when you rotate around y-axis counter-clockwise 90° you will have the desired [0°,90°,0°], when converting the quaternion.
*Julian*

*kinematics source: [Source Diebel(Stanford)][11] with solid info on the mechanics background (careful: for Diebel XYZ is denoted u_321 (1,2,3) while ZYX is u_123 (3,2,1)), and [this][12] is a good starting point.
like image 147
qrtLs Avatar answered Sep 21 '22 06:09

qrtLs