/** * @file * @brief Inline helper functions for show program * @author Kai Lingemann. Institute of Computer Science, University of Osnabrueck, Germany. * @author Andreas Nuechter. Institute of Computer Science, University of Osnabrueck, Germany. */ #include "slam6d/globals.icc" /** * converts a quaterion to a 4x4 matrix * in OpenGL style */ template inline void QuaternionToMatrix4(const double *quat, T *mat) { double xy = quat[0] * quat[1] * -1.0; double xz = quat[0] * quat[2]; double yz = quat[1] * quat[2] * -1.0; double wx = quat[3] * quat[0]; double wy = quat[3] * quat[1] * -1.0; double wz = quat[3] * quat[2]; double x2 = sqr(quat[0]); double y2 = sqr(quat[1]); double z2 = sqr(quat[2]); mat[0] = 1.0 - 2.0 * (y2 + z2); mat[4] = 2.0 * (xy - wz); mat[8] = 2.0 * (xz + wy); mat[1] = 2.0 * (xy + wz); mat[5] = 1.0 - 2.0 * (x2 + z2); mat[9] = 2.0 * (yz - wx); mat[2] = 2.0 * (xz - wy); mat[6] = 2.0 * (yz + wx); mat[10] = 1.0 - 2.0 * (x2 + y2); mat[11] = mat[7] = mat[3] = mat[12] = mat[13] = mat[14] = 0.0; mat[15] = 1.0; } /** * converts a 4x4 matrix to a quaternion */ template inline void Matrix4ToQuaternion(const T *mat, double *quat) { double S; double Trace = 1 + mat[0] + mat[5] + mat[10]; if ( Trace > COMPARE_EPSILON ) { S = sqrt(Trace) * 2; quat[0] = -1.0 * ( mat[9] - mat[6] ) / S; // q_x quat[1] = -1.0 * ( mat[2] - mat[8] ) / S; // q_y quat[2] = -1.0 * ( mat[4] - mat[1] ) / S; // q_z quat[3] = 0.25 * S; // q_0 } else if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0: S = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2; quat[0] = -1.0 * 0.25 * S; quat[1] = -1.0 * (mat[4] + mat[1] ) / S; quat[2] = -1.0 * (mat[2] + mat[8] ) / S; quat[3] = (mat[9] - mat[6] ) / S; } else if ( mat[5] > mat[10] ) { // Column 1: S = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2; quat[0] = -1.0 * (mat[4] + mat[1] ) / S; quat[1] = -1.0 * 0.25 * S; quat[2] = -1.0 * (mat[9] + mat[6] ) / S; quat[3] = (mat[2] - mat[8] ) / S; } else { // Column 2: S = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2; quat[0] = -1.0 * (mat[2] + mat[8] ) / S; quat[1] = -1.0 * (mat[9] + mat[6] ) / S; quat[2] = -1.0 * 0.25 * S; quat[3] = (mat[4] - mat[1] ) / S; } } /** * normalizes a quaternion to gain a unit quaternion */ template inline void QuatNormalize(T *q) { T norm = sqrt(sqr(q[0]) + sqr(q[1]) + sqr(q[2]) + sqr(q[3])); q[3] = q[3] / norm; q[2] = q[2] / norm; q[1] = q[1] / norm; q[0] = q[0] / norm; } /** * multiplication of quaternions */ template inline void QuatMult(const T *q, const T *q_new, T *qtemp) { qtemp[3] = q_new[3] * q[3] - q_new[0] * q[0] - q_new[1] * q[1] - q_new[2] * q[2]; qtemp[0] = q_new[3] * q[0] + q_new[0] * q[3] + q_new[1] * q[2] - q_new[2] * q[1]; qtemp[1] = q_new[3] * q[1] + q_new[1] * q[3] + q_new[2] * q[0] - q_new[0] * q[2]; qtemp[2] = q_new[3] * q[2] + q_new[2] * q[3] + q_new[0] * q[1] - q_new[1] * q[0]; } /** * converts a quaternion to an axis angle */ inline void QuaternionToAxisAngle(const double *quat, double *axis, double &angle) { double quaternion_norm = sqrt( sqr(quat[0]) + sqr(quat[1]) + sqr(quat[2]) + sqr(quat[3]) ); double normalized_quat[4]; normalized_quat[0] = quat[0] / quaternion_norm; normalized_quat[1] = quat[1] / quaternion_norm; normalized_quat[2] = quat[2] / quaternion_norm; normalized_quat[3] = quat[3] / quaternion_norm; double cos_a = normalized_quat[3]; angle = deg(acos( cos_a )) * 2.0; double sin_a = sqrt( 1.0 - cos_a * cos_a ); if ( fabs( sin_a ) < DIV_EPSILON ) sin_a = 1; axis[0] = normalized_quat[0] / sin_a; axis[1] = normalized_quat[1] / sin_a; axis[2] = -1.0 * normalized_quat[2] / sin_a; }