I'm trying to understand quaternions and am having a lot of trouble converting it into something actually useful. I've watched some 3blue1brown videos and read some tutorials, but I can't seem to translate what I see into something simple which means I don't really understand it at all.
Starting with the simplest example I can think of, I want to start with a point at xyz (1, 0, 0) and rotate 90 degrees around the Z axis. This should give me the point (0, 1, 0).
Using trigonometry, doing the rotation is simple (doSimple()
).
As I said I am lacking in understanding of the fundamentals of quaternions, but from what I understand a point in 3d space can be represented using x, y, z and 0 for the w. And gl-matrix has a 'quat.rotateZ' method that seems like it should rotate around that axis by an angle. My results seem to indicate that it only rotates by 1/2 the angle and in the wrong direction (repl.it):
const { quat } = require('gl-matrix');
const doSimple = () => {
// simple using trig:
const x = 1, y = 0;
const angle = Math.PI / 2; // 15 degrees
const newX = x * Math.cos(angle) - y * Math.sin(angle);
const newY = x * Math.sin(angle) + y * Math.cos(angle);
console.log({ angle, x, y, newX, newY });
}
const doQuat = () => {
let [x, y, z, w] = [1, 0, 0, 0];
const a = quat.fromValues(x, y, z, w);
const ninetyDegrees = Math.PI / 2;
const b = quat.create();
quat.rotateZ(b, a, ninetyDegrees);
const results = { a, b }
console.log(results)
}
const doAngle = () => {
let [x1, y1, z1, w1] = [1, 0, 0, 0];
let [x2, y2, z2, w2] = [0, 1, 0, 0];
const q1 = quat.fromValues(x1, y1, z1, w1);
const q2 = quat.fromValues(x2, y2, z2, w2);
const angle = quat.getAngle(q1, q2);
console.log({ angle });
}
doSimple();
doQuat();
doAngle();
doSimple()
looks good to me:
{
angle: 1.5707963267948966,
x: 1,
y: 0,
newX: 6.123233995736766e-17,
newY: 1
}
doQuat()
uses quat.rotateZ()
and seems to only rotate 45 degrees and in the wrong direction:
{
a: Float32Array(4) [ 1, 0, 0, 0 ],
b: Float32Array(4) [ 0.7071067690849304, -0.7071067690849304, 0, 0 ]
}
doAngle()
seems to report that there are 180 degrees between (1,0,0) and (0,1,0):
{ angle: 3.141592653589793 }
So I know I'm totally misunderstanding something, but I don't know what it is...
---Edit---
I think a lot of my confusion stems from different terminology in examples. gl-matrix
uses x,y,z,w. 3blue1brown uses <blank>
, i,j,k. This paper uses q0,q1,q2,q3. This calculator from the paper doesn't seem to make sense in that Yaw rotates around the Z axis, Pitch around the Y axis, and Roll around the X axis?
If I'm thinking in 3d space the normal way I think of things would be Z facing out of the screen and X and Y representing a normal 2d graph on the screen (X points 'right', Y points 'up'). Yaw should rotate around the Y axis and pitch should rotate around the X axis.
Am I thinking wrong? Are there a set (or sets) of standard ways of looking at the coordinate system, rotations, and quaternions that I should use when trying to learn? For example I think that since gl-matrix uses x,y,z,w and the paper uses q0,q1,q2,q3 and 3b1b uses blank,i,j,k, I think the conversions are as follows:
- q0 -> blank -> w
- q1 -> i -> x
- q2 -> j -> y
- q3 -> k -> z