Chaining quaternion rotations

Started by
0 comments, last by alvaro 12 years, 3 months ago
Hey all,

I'm trying to convert two axis rotations into Quaternion rotations. When I constrain the rotations to one axis i can get it to work properly, but it requires I multiply it by a second quaternion of 90degres to get it to work. Note, this code doesn't compile, I will have the whichever two I'm not using commented out when running.


if(cameraXRotate > 180) {
mult = -1;
}
/* rotation around the x axis*/
Quaternion cameraX = new Quaternion(mult * cameraXRotate * (float)(Math.PI / 180.0), new XYZ(1,0,0));
Quaternion camera = new Quaternion(90 * (float) (Math.PI / 180.0), new XYZ(0, 1, 0));
/* Rotation around the y axis*/
Quaternion cameraY = new Quaternion(-cameraYRotate * (float) (Math.PI / 180.0), new XYZ(0, 1, 0));
Quaternion camera = new Quaternion(90 * (float) (Math.PI / 180.0), new XYZ(1, 0, 0));
/* rotation around the z axis*/
Quaternion cameraZ = new Quaternion(cameraZRotate * (float)(Math.PI / 180.0), new XYZ(0,0,1));
Quaternion camera = new Quaternion(90 * (float) (Math.PI / 180.0), new XYZ(1, 0, 0));


Now, firstly, I'm not sure why I have to multiply by 90 to get all these to work, and I'm not sure why I have to reverse the rotation on the X axis if it's greater than 180. All I know, is that these seem to work properly on single axis rotation.

This is the standard rotation code in openGL for the cameraX and Y, the negative cameraX is deliberate-

glRotatef(-cameraXRotate, 1, 0, 0);
glRotatef(cameraYRotate, 0, 1, 0);


Now, when I try to multiple the two rotations together, I get weird angles. This is my rotation code:


/* x axis rotation */
Quaternion cameraX = new Quaternion(mult * cameraXRotate * (float)(Math.PI / 180.0), new XYZ(1,0,0)).mul(new Quaternion(90 * (float)(Math.PI / 180.0), new XYZ(1,0,0)));
/* y axis rotation */
Quaternion cameraY = new Quaternion(cameraYRotate * (float) (Math.PI / 180.0), new XYZ(0, 1, 0)).mul(new Quaternion(90 * (float)(Math.PI / 180.0), new XYZ(1,0,0)));
Quaternion result = Quaternion.IDENTITY.mul(cameraX.mul(cameraY));


Any ideas? I'm really stuck on this one sad.png

Thanks!
Advertisement
The quaternion corresponding to a rotation of alpha around the axis (x,y,z) is

q = cos(alpha/2) + sin(alpha/2)*(xi+yj+zk)

I don't see cos(alpha/2) and sin(alpha/2) anywhere in your code, so it's probably not right.


This is roughly how I would do it:
#include <iostream>
#include <cmath>
#include <boost/math/quaternion.hpp>

typedef boost::math::quaternion<double> Q;

struct Vector3 {
double x, y, z;

Vector3(double x, double y, double z) : x(x), y(y), z(z) {
}
};

std::ostream &operator<<(std::ostream &os, Vector3 const &v) {
return os << '(' << v.x << ',' << v.y << ',' << v.z << ')';
}

Q axis_and_angle_to_quaternion(double angle, Vector3 axis) {
double sin_angle_halfs = std::sin(angle * 0.5);
return Q(std::cos(angle * 0.5),
sin_angle_halfs*axis.x,
sin_angle_halfs*axis.y,
sin_angle_halfs*axis.z);
}

Vector3 apply(Q q, Vector3 v) {
Q r = q * Q(0, v.x, v.y, v.z) * conj(q);
return Vector3(r.R_component_2(), r.R_component_3(), r.R_component_4());
}

int main() {
double const degrees = std::atan(1.0)/45.0;
Q rx = axis_and_angle_to_quaternion(90*degrees, Vector3(1,0,0));
Q ry = axis_and_angle_to_quaternion(90*degrees, Vector3(0,1,0));
Q r = rx*ry;
std::cout << apply(r, Vector3(1,2,3)) << '\n';
}

This topic is closed to new replies.

Advertisement