# Computing attitude(roll, pitch & yaw) from solvePnP()

I am using solvePnP() to compute for attitude(roll, pitch & yaw). From solvePnP() I got the rotation vector and I use this to accordingly get roll, pitch and yaw. But the problem is when I rotate the camera 45deg, the measurement gives 25deg.

I think, it might be that I need to integrate the angle value(each roll, pitch & yaw ) over time..am I right, integrating it will resolve the issue?

EDIT

The code snippet:

pose = -rot_vec.at(0);

pose = -rot_vec.at(1);

pose = -rot_vec.at(2);

Note: pose[] is roll, pitch & yaw respectively & rot_vec is raw value of rotation vector obtained from solvePnP()

edit retag close merge delete

You should check if there is either a constant error on your measurements, like always 20 degrees, or if it only applies to the single angle. Also, without sharing code with people on how you calculate it, it is actually quite difficult to say what went wrong :)

@StevenPuttemans: Thanks for the information. I've appended the code snippet in the question.

The output given by solvePnP is the axis-rotation values for the orientation, not eulerangles. They are three elements because opencv uses the reduced notation, being three values to define the rotation axis, and the module of the resultant vector to define the rotation value.

Sort by » oldest newest most voted As @StevenPuttemans says, the out put of solvePnP() is not directly roll, yaw & pitch, but need to calculate using rotation matrix.

I also came through the same problem and found the function decomposeProjectionMatrix which gives euler angles as it's output.

Suppose we already get the rotation Mat from solvePnP()

solvePnP(..,...,rotCamerMatrix,transMatrix,false);
Rodrigues(rotCamerMatrix,rotCamerMatrix1);


Now using the function,

void getEulerAngles(Mat &rotCamerMatrix,Vec3d &eulerAngles){

Mat cameraMatrix,rotMatrix,transVect,rotMatrixX,rotMatrixY,rotMatrixZ;
double* _r = rotCamerMatrix.ptr<double>();
double projMatrix = {_r,_r,_r,0,
_r,_r,_r,0,
_r,_r,_r,0};

decomposeProjectionMatrix( Mat(3,4,CV_64FC1,projMatrix),
cameraMatrix,
rotMatrix,
transVect,
rotMatrixX,
rotMatrixY,
rotMatrixZ,
eulerAngles);
}


Call it like,

   Vec3d eulerAngles;
getEulerAngles(rotCamerMatrix1,eulerAngles);


where

yaw   = eulerAngles;
pitch = eulerAngles;
roll  = eulerAngles;

more

Can you explain more about elements of projMatrix? How to build projMatrix? Thank you.

Hi @mado, you can build the projection matrix by three things. - The camera matrix (3x3). - The rotation matrix (3x3). - The camera centre wrt the world.

• You can get the Rotation matrix ( R ) by using the Rodrigues function.
• You can get the Camera center from this operation --> - R_inverse*Tvec.
• Once done refer to this link](http://)

and fill the corresponding matrix, once you multiply both the matrices, you will end up with a projection matrix.!

I think that what you doing wrong is considering that these angles are actually the exact values for roll, yaw & pitch. Looking at the documentation, the description states:

rvec – Output rotation vector (see Rodrigues() ) that, together with tvec , brings points from the model coordinate system to the camera coordinate system.

tvec – Output translation vector.

This means that for each point you have in your model, you can switch to the camera coördinate system. However, this is NOT the world coördinate system. I think you should still do a second operation to transfer between the camera coordinate system and the world coordinate system.

Maybe take a look at some topics that do exactly what you want, retrieving pitch yaw and roll.

more

Official site

GitHub

Wiki

Documentation