I have a rotation quaternion and want to extract the angle of rotation about the Up axis (the yaw). I am using XNA and as far as I can tell there is no inbuilt function for this. What is the best way to do this?
Thanks for any help, Venatu
Having given a Quaternion q, you can calculate roll, pitch and yaw like this: var yaw = atan2(2.0*(q.y*q.z + q.w*q.x), q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z); var pitch = asin(-2.0*(q.x*q.z - q.w*q.y)); var roll = atan2(2.0*(q.x*q.y + q.w*q.z), q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z);
The simplest statement is that if a quaternion goes to the same orientation twice without going through its inverse (eg it goes from W=1 to W=0, then back to W=1 without reaching W=-1), then it has retraced its path to some degree, for example it rotates 180 clockwise around the X axis, and then rotation 180 counter ...
Combine the quaternion rotations into a single representation, then apply the quaternion rotation to arbitrarily initialized Cartesian points. Combine the rotation matrices into a single representation, then apply the rotation matrix to the same initial Cartesian points.
A quaternion can represent a 3D rotation and is defined by 4 real numbers. x, y and z represent a vector. w is a scalar that stores the rotation around the vector.
The quaternion representation of rotation is a variation on axis and angle. So if you rotate by r radians around axis x, y, z, then your quaternion q is:
q[0] = cos(r/2);
q[1] = sin(r/2)*x;
q[2] = sin(r/2)*y;
q[3] = sin(r/2)*z;
If you want to create a quaternion that only rotates around the y axis, you zero out the x and z axes and then re-normalize the quaternion:
q[1] = 0;
q[3] = 0;
double mag = sqrt(q[0]*q[0] + q[2]*q[2]);
q[0] /= mag;
q[2] /= mag;
If you want the resulting angle:
double ang = 2*acos(q[0]);
This assumes that the quaternion representation is stored: w,x,y,z. If both q[0] and q[2] are zero, or close to it, the resulting quaternion should just be {1,0,0,0}.
Having given a Quaternion q, you can calculate roll, pitch and yaw like this:
var yaw = atan2(2.0*(q.y*q.z + q.w*q.x), q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z);
var pitch = asin(-2.0*(q.x*q.z - q.w*q.y));
var roll = atan2(2.0*(q.x*q.y + q.w*q.z), q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z);
This should fit for intrinsic tait-bryan rotation of xyz-order. For other rotation orders, extrinsic and proper-euler rotations other conversions have to be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With