2
$\begingroup$

I've written a JS SDK that listens to mobile device rotation, providing $3$ inputs:

$\alpha$ : An angle can range between $0$ and $360$ degrees
$\beta$ : An Angle between $-180$ and $180$ degrees
$\gamma$ : An Angle between $-90$ to $90$ degrees

Documentation for device rotation

I have tried using Euler Angles to determine the device orientation but encountered the gimbal lock effect, that made calculation explode when the device was pointing up. That lead me to use Quaternion, that does not suffer from the gimbal effect.

I've found a library that converts $\alpha, \beta$ and $\gamma$ to a Quaternion, so for the following values:

$\alpha : 40.3476$
$\beta : 70.3120$
$\gamma : -62.9454$

I get this Quaternion ($ZXY$ order):

$w: 0.7582073853451148$
$x: 0.608178427083661$
$y: -0.23130444560993935$
$z: -0.04169910165995308$

Visualizing the device orientation (Demo, use mobile):
enter image description here

I would like to write a method that gets a Quaternion as an input and outputs if the device is on portrait or landscape mode.

Defining portrait and landscape as a range of $\pm 45^\circ$ around the relevant axes.

What approach should I take?

Update: To elaborate further, my goals are:
To write a method that gets $\alpha, \beta$ and $\gamma$ and outputs if the device is in one of the following orientations:

  • portrait
  • portrait upside down
  • landscape left
  • landscape right
  • display up
  • display down
$\endgroup$
  • 1
    $\begingroup$ I think that you are over complicating the problem. You know which way that gravity is pointing. Just do a dot product against each of the axes and choose the axis with the absolute maximum value. You can also get angle w.r.t. the axis in question using the dot product and some simple trig. $\endgroup$ – Tpofofn Jul 3 at 16:16
0
$\begingroup$

Not a complete solution, but this should provide a method with some tweaks.

Some details are left out in the article, so I cannot say exactly what rotation method is being used. I'll make an example where the rotation order is the extrinsic $xyz$-order.

The quaternion product of quaternions $\mathbf{p}$ and $\mathbf{q}$ is defined as $$ \begin{equation} \begin{split} \mathbf{p} \otimes \mathbf{q} &= \left( p_0 + p_1 i + p_2 j + p_3 k\right) \left( q_0 + q_1 i + q_2 j + q_3 k\right) \\ &= p_0q_0 + p_0q_1 i + p_0q_2 j + p_0q_3 k \\ & + p_1 q_0 i - p_1 q_1 + p_1 q_2 k - p_1 q_3 j \\ & + p_2 q_0 j - p_2 q_1 k - p_2 q_2 + p_2 q_3 i \\ & + p_3 q_0 k + p_3 q_1 j - p_3 q_2 i - p_3 q_3 \\ &= ( p_0 q_0 - p_1 q_1 - p_2 q_2 - p_3 q_3) \\ &+ ({\color{blue} p_0q_1} + {\color{red}p_1 q_0} + p_2 q_3 - p_3 q_2)i \\ &+ ({\color{blue} p_0 q_2} - p_1 q_3 + {\color{red} p_2 q_0} + p_3 q_1)j \\ &+ ({\color{blue} p_0 q_3} + p_1 q_2 - p_2 q_1 + {\color{red}p_3 q_0})k \end{split} \end{equation} $$ This can be written in a matrix form as \begin{equation} \begin{split} \mathbf{p} \otimes \mathbf{q} &= \left[ \begin{array}{cccc} % This is the correct matrix p_0 & -p_1 & -p_2 & -p_3 \\ p_1 & p_0 & -p_3 & p_2 \\ p_2 & p_3 & p_0 & -p_1 \\ p_3 & -p_2 & p_1 & p_0 \\ \end{array} \right] \left[ \begin{array}{c} q_0 \\ q_1 \\ q_2 \\ q_3 \\ \end{array} \right] \\ &= {\color{blue} p_0 } \left[ \begin{array}{c} q_0 \\ {\color{blue} q_1 } \\ {\color{blue} q_2 } \\ {\color{blue} q_3 } \\ \end{array} \right] + \left[ \begin{array}{c|ccc} 0 & -p_1 & -p_2 & -p_3 \\ \hline {\color{red} p_1} & 0 & -p_3 & p_2 \\ {\color{red} p_2} & p_3 & 0 & -p_1 \\ {\color{red} p_3} & -p_2 & p_1 & 0 \\ \end{array} \right] \left[ \begin{array}{c} q_0 \\ q_1 \\ q_2 \\ q_3 \\ \end{array} \right] \end{split} \end{equation} Now we at least know how to multiply quaternions. So what does this have to do with rotations?

Define a vector quaternion $(0,\vec{v}) = \mathbf{v}$ and a rotation quaternion $\mathbf{r} = (\cos{\tfrac{\theta}{2}}, \sin{\tfrac{\theta}{2}} \vec{r})$ for some unit vector $\vec{r}$. Now we can calculate the conjugation of $\mathbf{v}$ by $\mathbf{r}$ \begin{equation}\label{eq:euler-rodrigues-derivation} \begin{split} \mathbf{r} \star \mathbf{v} &= \mathbf{r} \otimes \mathbf{v} \otimes \mathbf{r}^* = \mathbf{r} \otimes (0,\vec{v}) \otimes (\cos{\tfrac{\theta}{2}}, - \sin{\tfrac{\theta}{2}} \vec{r}) \\ &= \mathbf{r} \otimes (0 + \vec{v} \cdot \sin{\tfrac{\theta}{2}} \vec{r} , 0 + \cos{\tfrac{\theta}{2}} \vec{v} + \vec{v}\times (- \sin{\tfrac{\theta}{2}} \vec{r})) \\ &= \mathbf{r} \otimes (\sin{\tfrac{\theta}{2}}\vec{v} \cdot \vec{r} , \cos{\tfrac{\theta}{2}} \vec{v} + \sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v}) \\ &= (\cos{\tfrac{\theta}{2}}, \sin{\tfrac{\theta}{2} \vec{r}}) \otimes (\sin{\tfrac{\theta}{2}}\vec{v} \cdot \vec{r} , \cos{\tfrac{\theta}{2}} \vec{v} + \sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v}) \\ &= (\cos{\tfrac{\theta}{2}}\sin{\tfrac{\theta}{2}}\vec{v} \cdot \vec{r} - (\sin{\tfrac{\theta}{2} \vec{r}})\cdot(\cos{\tfrac{\theta}{2}} \vec{v} + \sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v}), \\ & \cos{\tfrac{\theta}{2}}(\cos{\tfrac{\theta}{2}} \vec{v} + \sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v}) + (\sin{\tfrac{\theta}{2}}\vec{v} \cdot \vec{r} )(\sin{\tfrac{\theta}{2} \vec{r}}) + (\sin{\tfrac{\theta}{2} \vec{r}}) \times (\cos{\tfrac{\theta}{2}} \vec{v} + \sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v})) \\ &= (\cos{\tfrac{\theta}{2}}\sin{\tfrac{\theta}{2}}\vec{v} \cdot \vec{r} - \cos{\tfrac{\theta}{2}} \sin{\tfrac{\theta}{2} \vec{r}} \cdot \vec{v} - \sin^2{\tfrac{\theta}{2}} \vec{r} \cdot(\vec{r}\times \vec{v}), \\ & \cos^2{\tfrac{\theta}{2}} \vec{v} + \cos{\tfrac{\theta}{2}}\sin{\tfrac{\theta}{2}}\vec{r}\times \vec{v} + \sin^2{\tfrac{\theta}{2}}(\vec{v} \cdot \vec{r} )\vec{r} + \sin{\tfrac{\theta}{2} \cos{\tfrac{\theta}{2}} \vec{r}} \times \vec{v} + \sin^2{\tfrac{\theta}{2} \vec{r}} \times (\vec{r}\times \vec{v})) \\ &= (0, \\ & \cos^2{\tfrac{\theta}{2}} \vec{v} + \sin^2{\tfrac{\theta}{2}}(\vec{v} \cdot \vec{r} )\vec{r} + 2\sin{\tfrac{\theta}{2}} \cos{\tfrac{\theta}{2}} \vec{r} \times \vec{v} + \sin^2{\tfrac{\theta}{2}} \vec{r} \times (\vec{r}\times \vec{v})) \\ \end{split} \end{equation} Additionally, it is known that $\vec{r} \times ( \vec{r} \times \vec{v}) = (\vec{r} \cdot \vec{v})\vec{r} - (\vec{r} \cdot \vec{r}) \vec{v} = (\vec{r} \cdot \vec{v})\vec{r} - \vec{v} \Rightarrow \sin^2{\tfrac{\theta}{2}}(\vec{r} \cdot \vec{v})\vec{r} = \sin^2{\tfrac{\theta}{2}}\vec{r} \times ( \vec{r} \times \vec{v}) + \sin^2{\tfrac{\theta}{2}}\vec{v}$, resulting in \begin{equation}\label{eq:euler-rodrigues} \mathbf{r} \star \mathbf{v} = \vec{v} + 2\sin{\tfrac{\theta}{2} \cos{\tfrac{\theta}{2}}} \vec{r} \times \vec{v} + 2\sin^2{\tfrac{\theta}{2}} \vec{r} \times (\vec{r}\times \vec{v}) \end{equation} or the so called Euler-Rodrigues formula for rotation. The resulting vector quaternion $\mathbf{v}^{'} = (0,\vec{v}^{'})$ represents the rotation of $\vec{v}$ around an arbitrary vector $\vec{r}$ by angle $\theta$ to produce the rotated vector $\vec{v}^{'}$.

Therefore, this kind of multiplication can be used to represent a rotation about an axis. Now we can use the previous results to actually compute a sequence of rotations. As mentioned in the beginning, the extrinsic $xyz$-rotation will be calculated.

Two quaternion rotations can be coalesced by \begin{equation} \begin{split} \mathbf{r}_2 \star \left(\mathbf{r}_1 \star \mathbf{v} \right) &= \mathbf{r}_2 \otimes \left(\mathbf{r}_1 \otimes \mathbf{v} \otimes \mathbf{r}_1^{-1} \right) \otimes \mathbf{r}^{-1}_2 \\ &= \left(\mathbf{r}_2 \otimes \mathbf{r}_1 \right) \otimes \mathbf{v} \otimes \left(\mathbf{r}_2 \otimes \mathbf{r}_1 \right)^{-1} \\ &=\left( \mathbf{r}_2 \otimes \mathbf{r}_1 \right) \star \mathbf{v} \\\ \end{split} \end{equation} In other words, coalescing two rotation quaternions can be carried out by taking the quaternion product of the two rotation quaternions. The idea is the same as in matrix algebra. Now the formula corresponding to a Euler angle rotation can be derived. As an example, the quaternion corresponding to the $xyz$-rotation order is computed as follows:

\begin{equation} \begin{split} \mathbf{p}_{E \rightarrow Q}^{xyz} = & \left( \left[ \begin{array}{c}\cos{\frac{\psi}{2}} \\ 0 \\ 0 \\ \sin{\frac{\psi}{2}} \\ \end{array} \right] \otimes \left[ \begin{array}{c} \cos{\frac{\theta}{2}} \\ 0 \\ \sin{\frac{\theta}{2}} \\ 0 \\ \end{array} \right] \right) \otimes \left[ \begin{array}{c} \cos{\frac{\phi}{2}} \\ \sin{\frac{\phi}{2}} \\ 0 \\ 0 \\ \end{array} \right] \\ = & \left( \left[ \begin{array}{cccc} \cos{\frac{\psi}{2}} & 0 & 0 & -\sin{\frac{\psi}{2}} \\ 0 & \cos{\frac{\psi}{2}} & -\sin{\frac{\psi}{2}} & 0 \\ 0 & \sin{\frac{\psi}{2}} & \cos{\frac{\psi}{2}} & 0 \\ \sin{\frac{\psi}{2}} & 0 & 0 & \cos{\frac{\psi}{2}} \\ \end{array} \right] \left[ \begin{array}{c} \cos{\frac{\theta}{2}} \\ 0 \\ \sin{\frac{\theta}{2}} \\ 0 \end{array} \right] \right) \otimes \left[ \begin{array}{c} \cos{\frac{\phi}{2}} \\ \sin{\frac{\phi}{2}} \\ 0 \\ 0 \\ \end{array} \right] \\ = & \left[ \begin{array}{c} \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ -\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ \cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ \sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ \end{array} \right] \otimes \left[ \begin{array}{c} \cos{\frac{\phi}{2}} \\ \sin{\frac{\phi}{2}} \\ 0 \\ 0 \\ \end{array} \right] \\ = & \left[ \begin{array}{cccc} \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & \sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & -\cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & -\sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ -\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & -\sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & \cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ \cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & \sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & \sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ \sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} & -\cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & -\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} & \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ \end{array} \right] \left[ \begin{array}{c} \cos{\frac{\phi}{2}} \\ \sin{\frac{\phi}{2}} \\ 0 \\ 0 \\ \end{array} \right] \\ = & \left[ \begin{array}{c} \cos{\frac{\phi}{2}}\cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} + \sin{\frac{\phi}{2}}\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ -\cos{\frac{\phi}{2}}\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}} + \sin{\frac{\phi}{2}}\cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ \cos{\frac{\phi}{2}}\cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} + \sin{\frac{\phi}{2}}\sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} \\ \cos{\frac{\phi}{2}}\sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}} - \sin{\frac{\phi}{2}}\cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}} \\ \end{array} \right] \end{split} \end{equation}

It is fairly easy to see that the quaternion returned by this process is always unitary length. Next, we are interested in reversing this process, or extracting the Euler angles from this result. Without going throught a proof, the solution is

$$\left\{ \begin{array}{ccc} \tan{\phi} &=& \frac{2\left(p_0 p_1 + p_2 p_3 \right)}{p_0^2 - p_1^2 - p_2^2 + p_3^2} \\ \sin{\theta}&=& 2 \left( p_0 p_2 - p_1 p_3 \right) \\ \tan{\psi} &=& \frac{ 2 \left( p_0 p_3 + p_1 p_2 \right) }{ p_0^2 + p_1^2 - p_2^2 - p_3^2 } \end{array} \right.$$ where $p_i$ are the components of the orientation quaternion. I'm not completely sure which of these angles would represent the angle that you're interested in, but this should give you plenty of material to work with.

POST SCRIPTUM

I figured out that the rotation order used in the library that you used, it's probably the extrinsic $yxz$-rotation order. This would give the transformations $$ \mathbf{p}^{yxz} = \left[ \begin{array}{c} \cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}}\cos{\frac{\phi}{2}} -\sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}}\sin{\frac{\phi}{2}} \\ \cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}}\cos{\frac{\phi}{2}} -\sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}}\sin{\frac{\phi}{2}} \\ \sin{\frac{\psi}{2}} \sin{\frac{\theta}{2}}\cos{\frac{\phi}{2}} +\cos{\frac{\psi}{2}} \cos{\frac{\theta}{2}}\sin{\frac{\phi}{2}} \\ \sin{\frac{\psi}{2}} \cos{\frac{\theta}{2}}\cos{\frac{\phi}{2}} +\cos{\frac{\psi}{2}} \sin{\frac{\theta}{2}}\sin{\frac{\phi}{2}} \\ \end{array} \right] $$ and to extract the Euler angles, you use $$ \left\{ \begin{array}{ccc} \tan{\phi} &=& \frac{2\left(p_0 p_2 - p_1 p_3 \right)}{p_0^2 - p_1^2 - p_2^2 + p_3^2} \\ \sin{\theta}&=& 2 \left( p_0 p_1 + p_2 p_3 \right) \\ \tan{\psi} &=& \frac{ 2 \left( p_0 p_3 - p_1 p_2 \right) }{ p_0^2 - p_1^2 + p_2^2 - p_3^2 } \end{array} \right. $$ You can double-check to see if these equations work.

$\endgroup$
  • $\begingroup$ Thank you for your reply, so, if I understood, I have to convert back to Euler angels in order to find the right angle? $\endgroup$ – Shlomi Schwartz Jun 25 at 11:03
  • 1
    $\begingroup$ Yes, that's what I would do. The components of the quaternion representation don't have a simple-to-visualize geometric representation. $\endgroup$ – Matti P. Jun 25 at 11:05
0
$\begingroup$

Suppose the phone is in a global coordinate system with the origin located at the center of mass of the phone, the positive $Y$ axis in the direction of the longest side of the phone, the $X$ axis in the direction of the phone's screen width and the $Z$ axis in the direction of the screen's normal vector.

So, the identity rotation gives the portrait orientation of the phone in the global coord. system.

Note that a single rotation of $\pi/2$ around the $Z$ axis give us the landscape orientation. If we decompose the phone orientation in two rotations, one about $Z$ axis and other about one of the other axis, I think that looking at the $Z$ axis rotation angle we could discover the phone's orientation.

A rotation can be factorized in two rotations around two orthogonal axis, in our case we are interested in factorize phone rotation in two rotations around $ZY$ and $ZX$.

Let us define three axis vectors:

$$E_1 = (1, 0, 0)$$ $$E_2 = (0, 1, 0)$$ $$E_3 = (0, 0, 1)$$

Given a unit quaternion $Q$ the goal is to deconpose it in two rotations rotating an angle $a$ around axis $E_2$ and an angle $b$ around axis $E_3$:

$$Q = \exp(a E_2) \exp(b E_3)$$

Multiplying both sides by $E_3 Q^*$

$$Q E_3 Q^* = \exp(a E_2) \exp(b E_3) E_3 Q^*$$

Taking into account that $Q^* = \exp(b E_3)^* \exp(a E_2)^*$

$$Q E_3 Q^* = \exp(a E_2) \exp(b E_3) E_3 \exp(b E_3)^* \exp(a E_2)^*$$

Noting that $E_3$ is an eigenvector of $\exp(b E_3)$ such that $E_3 = \exp(b E_3) E_3 \exp(b E_3)^*$, we get:

$$W = \exp(a E_2) E_3 \exp(a E_2)^*$$

Where $W$ is the vector $E_3$ rotated by $Q$: $W = Q E_3 Q^*$

$$a = atan2( W \cdot E_1, W \cdot E_3)$$

Where $(\cdot)$ is the dot product.

Now, departing from the conjugate of $Q$:

$$Q^* = \exp(b E_3)^* \exp(a E_2)^*$$

Multiplying both sides by $E_2 Q$:

$$Q^* E_2 Q = \exp(b E_3)^* \exp(a E_2)^* E_2 Q$$

$$Q^* E_2 Q = \exp(-b E_3) \exp(-a E_2) E_2 \exp(a E_2) \exp(b E_3)$$

$$S = \exp(-b E_3) E_2 \exp(b E_3)$$

Where $S$ is the vector $E_2$ rotated by $Q^*$: $S = Q^* E_2 Q$

$$b = - atan2( S \cdot E_1, S \cdot E_2)$$

An analogous calculation can be done for factorizing $Q$ in two rotations around $E_1$ and $E_3$.

My guess is that having a measure of $b$ close enough to $\pm \pi/2$ then the phone is in landscape orientation.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.