Very basic question on quaternions use for 3D rotations

171 Views Asked by At

The quaternion $q=\cos(\pi/4) + \sin(\pi/4) \mathbf i + \sin (\pi/4)\mathbf j$ should rotate any 3D vectors around the bisecting line in the first quadrant of the $x,y$ plane $\pi/2 = 90^o.$ From Wolfram Alpha:

enter image description here

However, if I take the vector $(3,-4,7)$ and conjugate it:

$$\begin{align}\small (\cos(\pi/4) + \sin(\pi/4) \mathbf i + \sin (\pi/4)\mathbf j)(0 + 3\mathbf i -4 \mathbf j + 7 \mathbf k)(\cos(\pi/4) - \sin(\pi/4) \mathbf i - \sin (\pi/4)\mathbf j)\\= 0 + 9/2 \mathbf i - 6 \mathbf j - 21/2 \mathbf k\end{align}$$

But the vector $(9/2, -6,-21/2)$ doesn't look like a ninety degree rotation around $(\sin(\pi/4),\sin(\pi/4),0)$:

enter image description here

What obvious issue am I overlooking?

1

There are 1 best solutions below

0
On BEST ANSWER

Of course it had to be a silly overlook, and it was.

For a $3$D vector $\mathbf v=(3,-4,7)$ to rotate around the axis of another vector $(v_1,v_2,v_3)$ using quaternions the vector $\mathbf v$ has to be thought of as pure quaternion (real part equal to zero), $\small 0 + 3 \mathbf i -4 \mathbf j + 7 \mathbf k$ conjugated by the quaternion defined by a unit vector $v_1 \mathbf i + v_2 \mathbf j + v_3 \mathbf k.$ If the axis-angle of the rotation is $\small (v_1,v_2,v_3,\phi)$ the axis vector must $\small v_1^2 + v_2^2 + v_3^2=1,$ and the rotation quaternion will be $\small \cos\left(\frac{\phi}2 \right)+v_1\sin\left(\frac{\phi}2\right) \mathbf i + v_1\sin\left(\frac{\phi}2 \right) \mathbf j + v_1\sin\left(\frac{\phi}2\right) \mathbf k.$ Therefore, $\small \cos(\pi/4) + \sin(\pi/4) \mathbf i + \sin (\pi/4)\mathbf j + 0 \mathbf k,$ in the OP, has to be normalized: this is achieved by simply turning the quaternion into $\small \mathbf q=\left(\cos\left(\frac{\pi}4\right)+ \sin\left(\frac{\pi}4\right)/\sqrt{2}\;\mathbf i + \sin\left(\frac{\pi}4\right)/\sqrt{2}\;\mathbf j + 0 \mathbf k )\right).$

Now the conjugation does what is intended:

enter image description here

Conjugating the vector $(3,-4,7),$

$$\begin{align} &\mathbf q\mathbf v \mathbf q'=\\ &=\Tiny \left(\cos\left(\frac{\pi}4\right)+ \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf i + \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf j + 0 \mathbf k )\right)(0+3\mathbf i-4\mathbf j +7\mathbf k)\left(\cos\left(\frac{\pi}4\right)- \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf i - \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf j + 0 \mathbf k )\right)\\ &=\Tiny \left(\cos\left(\frac{\pi}4\right)+ \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf i + \frac{\sin\left(\frac{\pi}4\right)}{\sqrt{2}}\mathbf j + 0 \mathbf k )\right)(0+3\mathbf i-4\mathbf j +7\mathbf k)\left(\cos\left(-\frac{\pi}4\right) + \frac{\sin\left(-\frac{\pi}4\right)}{\sqrt{2}}\mathbf i + \frac{\sin\left(-\frac{\pi}4\right)}{\sqrt{2}}\mathbf j + 0 \mathbf k )\right)\\ &=\tiny \left(0 -\frac 1 2 +\frac{7}{\sqrt 2}\mathbf i -\frac 1 2 -\frac{7}{\sqrt 2}\mathbf j + -\frac{7}{\sqrt 2} \mathbf k )\right)=\small\color{red}{0 + 4.44975\mathbf i -5.44975\mathbf j -4.94975 \mathbf k}\\ &=\Tiny\color{blue}{\begin{bmatrix}1/2 & 1/2 & 1/\sqrt{2}\\ 1/2 & 1/2 & -1/\sqrt{2}\\ -1/\sqrt{2}& 1/\sqrt{2} &0 \end{bmatrix}}\begin{bmatrix}3\\-4\\7\end{bmatrix} \end{align}$$

The last step is the rotation matrix from angle and axis, which yields the same result as the conjugation with a simple matrix multiplication.


Here is the Wolfram Alpha query


I stitched together some R functions to do all these operations:

quatmul <- function(first.quaternion,second.quaternion){
  p <- first.quaternion; q <- second.quaternion
  stopifnot("Quaternions should be entered as 4-element vectors with real part in the first entry." = is.vector(p)&&is.vector(q))
  mat <- matrix(c(p[1],p[2],p[3],p[4],
                  -p[2],p[1],p[4],-p[3],
                  -p[3],-p[4],p[1],p[2],
                  -p[4],p[3],-p[2],p[1]),4,4,byrow=F)
  as.vector(round(mat%*%q,4))
}

rotmat <- function(quaternion){
  p <- quaternion
    stopifnot("Quaternions should be entered as 4-element vectors with real part in the first entry." = is.vector(p))
  mat <- matrix(c(2*(p[1]^2+p[2]^2)-1,2*(p[2]*p[3]+p[1]*p[4]),2*(p[2]*p[4]-p[1]*p[3]),
                  2*(p[2]*p[3]-p[1]*p[4]), 2*(p[1]^2+p[3]^2)-1,2*(p[3]*p[4]+p[1]*p[2]),
                  2*(p[2]*p[4]+p[1]*p[3]),2*(p[3]*p[4]-p[1]*p[2]),2*(p[1]^2+p[4]^2)-1),
                  3,3,byrow=F)
  round(mat,4)
}

quat3Drot <- function(quaternion1, quaternion2){
  #The second quaternion is just a 3D vector with a 0 in the first entry (real component).
  p <- quaternion1; q <- quaternion2
  stopifnot("Quaternions should be entered as 4-element vectors with real part in the first entry." = is.vector(p)&&is.vector(q))
  mat <- matrix(c(2*(p[1]^2+p[2]^2)-1,2*(p[2]*p[3]+p[1]*p[4]),2*(p[2]*p[4]-p[1]*p[3]),
                  2*(p[2]*p[3]-p[1]*p[4]), 2*(p[1]^2+p[3]^2)-1,2*(p[3]*p[4]+p[1]*p[2]),
                  2*(p[2]*p[4]+p[1]*p[3]),2*(p[3]*p[4]-p[1]*p[2]),2*(p[1]^2+p[4]^2)-1),
                  3,3,byrow=F)
  round(as.vector(mat%*%q[2:4]),4)
}

rotate.theta.around <- function(vector2Brotated, axis.of.rot, angle.degrees){
  r <- axis.of.rot
  q <- vector2Brotated
  stopifnot("Enter the axis of rotation and the 3D vector to be rotated both as 3-element vectors." = is.vector(r)&&is.vector(q))
  ax <- r/(sqrt(r[1]^2 + r[2]^2 + r[3]^2))
  radians <- angle.degrees/360 * 2 * pi
  p <- c(cos(radians/2), sin(radians/2)* ax)
  mat <- matrix(c(2*(p[1]^2+p[2]^2)-1,2*(p[2]*p[3]+p[1]*p[4]),2*(p[2]*p[4]-p[1]*p[3]),
                  2*(p[2]*p[3]-p[1]*p[4]), 2*(p[1]^2+p[3]^2)-1,2*(p[3]*p[4]+p[1]*p[2]),
                  2*(p[2]*p[4]+p[1]*p[3]),2*(p[3]*p[4]-p[1]*p[2]),2*(p[1]^2+p[4]^2)-1),
                  3,3,byrow=F)
  round(as.vector(mat%*%vector2Brotated),4)
}

So I can replicate the rotation matrix (in blue above):

rotmat(c(cos(pi/4),sin(pi/4)/sqrt(2),sin(pi/4)/sqrt(2),0))

A matrix: 3 × 3 of type dbl
0.5000  0.5000  0.7071
0.5000  0.5000  -0.7071
-0.7071 0.7071  0.0000

Or get the rotation in $3$D (as above in red) by using the rotation form of the quaternion:

quat3Drot(c(cos(pi/4),sin(pi/4)/sqrt(2),sin(pi/4)/sqrt(2),0),c(0,3,-4,7))
4.4497-5.4497-4.9497

Or by considering that $(\cos \frac \theta 2 + \sin \frac \theta 2 (v_1 \mathbf i + v_2 \mathbf j + v_3 \mathbf k))$ is the quaternion that allows us to rotate by $\theta$ (after conjugation) around the $3$D vector $\left(v_1,v_2,v_3\right),$ use the alternative function entering the degrees (converted to radians inside the function) to get the same result:

rotate.theta.around(c(3,-4,7), c(1/sqrt(2),1/sqrt(2),0), 90)
4.4497-5.4497-4.9497

Visualized here in reference to the vector $\small (\sin(\pi/2)/\sqrt 2,\sin(\pi/2)/\sqrt 2, 0)=(1/2,1/2,0)$:

enter image description here

We can try using a different axis, say the vector $(2,3,4),$ and going around the clock with two other vectors, for example, $(3,-4,7)$ and $(-4,-3,3)$:

enter image description here

Code here.

One final observation is that while the axis of rotation is normalized (within the function rotate.theta.around()), there is no need to normalize the vector in $3$D that we want to rotate. For example, applying the functions above to $(1,1,1)$ with and without normalizing, and rotating around $(0,1,0)$ around the clock will yield simply scaled vectors:

enter image description here