Rodrigues into Eulerangles and Vice Versa

Rodrigues into Eulerangles and vice versa

First, forget about translation vector, because it is not related with rotation: translation moves things around, rotation changes their orientation.

Rodrigues parameters are also called axis-angle rotation. They are formed by 4 numbers [theta, x, y, z], which means that you have to rotate an angle "theta" around the axis described by unit vector v=[x, y, z].
Looking at cv::Rodrigues function reference, it seems that OpenCV uses a "compact" representation of Rodrigues notation as vector with 3 elements rod2=[a, b, c], where:

  • Angle to rotate theta is the module of input vector theta = sqrt(a^2 + b^2 + c^2)
  • Rotation axis v is the normalized input vector: v = rod2/theta = [a/theta, b/theta, c/theta]

So, Rodrigues vector from solvePnP is not even slightly related with Euler angles notation, which represent three consecutive rotations around a combination of X, Y and Z axes.

How to compare both rotations? This is a good question. Both Euler- and Rodrigues- representations have singularities and other problems. For instance, if you compare two Euler terns, or two Rodrigues parameters, they can look completely different but actually represent almost the same rotation.
If you just need to check if both rotations are the same (or approx.), you can follow the next approach:

  1. Transform both rotations to matrix notation (quaternions are also valid)
    • OpenCV Rodrigues vector can be transformed to matrix using cv::Rodrigues function
    • For transforming Euler to matrix, I suggest you to take a look to conversions section of euclideanspace.com
  2. "Subtract" one rotation from the other, that is concatenating one with the inverse of the other
    • Using rotation matrices, multiply one by the transpose (inverse rotation) of the other one. Null rotation is the identity matrix.
    • Using quaternions, multiply one by the complex conjugate of the other (negate the three last components).
  3. Check if the result is close to a null rotation:
    • Null rotation matrix is the identity.
    • Null quaternion has a 1 or a -1 in the first component

OpenCV Decompose Projection Matrix euler angle wrong direction?

I don't know exactly which permutation is your implementation to get eulerangles from matrix, but it differs from the one decomposeProjectionMatrix uses.
this is the reason for the different angles.

As said before, euler angles depend always on the order. There are 12 different permutations. See Euler Angles for more information.

decomposeProjectionMatrix from opencv uses "XYZ" order for its Euler Angle representation.

there are different rotation libs on pypi. I use for this example transforms3d.
I'm setting the input parameters by hand and the rotation matrix by euler2mat function of the transforms3d package.
I create a Rotation matrix with the XYZ-convention e.g. roll angle (X): 90°, pitch (Y): 45° , yaw(X): 180°

from transforms3d import euler
from math import pi,radians
rotation_matrix = euler.euler2mat(radians(90), radians(45),
radians(180), 'sxyz')
tvec = np.zeros(3).reshape(1,3).T
camera_matrix = np.array([[1500,0,320],[0,1500,256],[0,0,1]])
projection_matrix = camera_matrix.dot(np.hstack((rotation_matrix, tvec)))
rot = cv2.decomposeProjectionMatrix(projection_matrix)

rotation_matrix (input) and rot[1] (output) are the same (but only with the correct euler-order "sxyz"):

array([[-7.07106781e-01, -7.07106781e-01,  7.91668771e-17],
[ 8.65956056e-17, 2.53632657e-17, 1.00000000e+00],
[-7.07106781e-01, 7.07106781e-01, 4.32978028e-17]])

rot[-1] is:

[[90.         ]
[ 45. ]
[ 180. ]]

there are some more pitfalls with 3d rotations. E.g.

  • the coordinate reference system can vary: Reference coordinate system changes between OpenCV, OpenGL and Android Sensor
  • there are active and passive rotations
  • lefthanded and right handed coordinate systems
  • ...

How does this code work?

I'm pretty sure that's psuedocode. It's definitely not C++. All the functions are pretty self explanatory.

acos() --- self explanatory

$V1 * $V2 --- dot product
(note:, that would normally be interpreted as a regular matrix multiplication, but but in the context of "float $angle = acos($V1*$V2);", it doesn't make sense as anything other than a dot product)

cross() --- cross product

normalizeVector() --- self explanatory

sin($angle)*$axis_skewed --- this is a scalar multiply

get it?

EDIT

$R = $eye3 + sin($angle)*$axis_skewed + (1-cos($angle))*$axis_skewed*$axis_skewed;

$eye3 -- is a 3x3 matrix

sin($angle)*$axis_skewed --- this is a scalar multiply, resulting in another 3x3 matrix

(1-cos($angle))*$axis_skewed --- this is a scalar multiply, resulting in another 3x3 matrix

(previous)*$axis_skewed --- this is a regular matrix multiplication, resulting in another 3x3 matrix

That leaves us with:

$R = [3x3 matrix] + [3x3 matrix] + [3x3 matrix]

Which is just regular entrywise matrix addition.



Related Topics



Leave a reply



Submit