# Convert from fixed axis $XYZ$ rotations to Euler $ZXZ$ rotations

Because I'm a new user, I can't post images or hyperlinks, there is a complete version with images here:

https://stackoverflow.com/questions/9774958/converting-from-a-euler-zxz-rotation-to-fixed-axis-xyz-rotations

The problem I have, is that I need to convert from $XYZ$ fixed axis rotations, to Euler rotations about $Z$, then $X'$, then $Z''$.

Here are the relevant matricies:

$$X = \left(\begin{matrix} 1 & 0 & 0 \\ 0 & \cos(\theta) & -\sin(\theta) \\ 0 & \sin(\theta) & \cos(\theta)\end{matrix}\right)$$

$$Y = \left(\begin{matrix} \cos(\phi) & 0 & \sin(\phi) \\ 0 & 1 & 0 \\ -\sin(\phi) & 0 & \cos(\phi)\end{matrix}\right)$$

$$Z = \left(\begin{matrix} \cos(\psi) & -\sin(\psi) & 0 \\ \sin(\psi) & \cos(\psi) & 0 \\ 0 & 0 & 1\end{matrix}\right)$$

Combined, as $R_z(\psi) R_y(\phi) R_x(\theta) = R_{xyz}(\theta,\phi,\psi)$; they give:

$R_{xyz}$: i.imgur.com/8UQM6.jpg

And the Rotation matrix for the Specific convention of Euler angles I want; is this:

Euler:

So my initial plan, was to compare matrix elements, and extract the angles I wanted that way; I came up with this (actual current code at the end):

But this doesn't work under several circumstances. The most obvious being when $\cos(\theta)\cos(\phi) = 1$; since then $\cos(\beta) = 1$, and so $\sin(\beta) = 0$. Where $\sin(\beta)$ is s2 in the code. This happens only when $\cos(\theta)$ and $\cos(\phi) = \pm 1$.

So right away I can just rule out the possible situations;

When $\theta$ or $\phi = 0, 180, 360, 540, \ldots$, then $\cos(\theta)$, and $\cos(\phi)$ are $\pm 1$;

so I only need to do it differently for these cases;

And I ended up with this code:

public static double[] ZXZtoEuler(double θ, double φ, double ψ){

θ *= Math.PI/180.0;
φ *= Math.PI/180.0;
ψ *= Math.PI/180.0;

double α = -1;
double β = -1;
double γ = -1;

double c2 = Math.cos(θ) * Math.cos(φ);

β = Math.acos(r(c2));

if(eq(c2,1) || eq(c2,-1)){
if(eq(Math.cos(θ),1)){
if(eq(Math.cos(φ),1)){
α = 0.0;
γ = ψ;
}else if(eq(Math.cos(φ),-1)){
α = 0.0;
γ = Math.PI - ψ;
}
}else if(eq(Math.cos(θ),-1)){
if(eq(Math.cos(φ),1)){
α = 0.0;
γ = -ψ;
}else if(eq(Math.cos(φ),-1)){
α = 0.0;
γ = ψ + Math.PI;
}
}
}else{

//original way

double s2 = Math.sin(β);

double c3 = ( Math.sin(θ) * Math.cos(φ) )/ s2;
double s1 = ( Math.sin(θ) * Math.sin(ψ) + Math.cos(θ) * Math.sin(φ) * Math.cos(ψ) )/s2;

γ = Math.acos(r(c3));
α = Math.asin(r(s1));

}

α *= 180/Math.PI;
β *= 180/Math.PI;
γ *= 180/Math.PI;

return new double[] {r(α), r(β), r(γ)};
}


Where r and eq are just two simple functions;

public static double r(double a){
double prec = 1000000000.0;
return Math.round(a*prec)/prec;
}

static double thresh = 1E-4;
public static boolean eq(double a, double b){
return (Math.abs(a-b) < thresh);
}


eq is just to compare the numbers for tests, and r is to prevent floating point errors pushing numbers outside the range of Math.acos / Math.asin and giving me NaN results;

(i.e. every now and then I'd end up with Math.acos(1.000000000000000004) or something.)

Which takes into account the 4 cases of having rotations around $x$ and $y$ which leave c2==1.

But now is where the problem occurs;

Everything I have done above, makes sense to me, but it does not give the correct angles;

Here is some output, in each pair, the first are the $\theta, \phi, \psi$ angles, and the second of each pair is the corresponding $\alpha, \beta, \gamma$ lines. Ignoring the rounding errors, it seems to be getting some of the angles off by about

[0.0, 0.0, 0.0] - correct! [0.0, 0.0, 0.0]

[0.0, 0.0, 45.0] - correct! [0.0, 0.0, 45.0]

[0.0, 0.0, 90.0] - correct! [0.0, 0.0, 90.0]

[0.0, 0.0, 135.0] - correct! [0.0, 0.0, 135.0]

[0.0, 0.0, 180.0] - correct [0.0, 0.0, 180.0]

[0.0, 0.0, 225.0] - correct [0.0, 0.0, 225.0]

[0.0, 0.0, 270.0] - correct [0.0, 0.0, 270.0]

[0.0, 0.0, 315.0] - correct [0.0, 0.0, 315.0]

[0.0, 45.0, 0.0] - incorrect: should be [90, 45, -90] [90.0, 44.999982, 90.0]

[0.0, 45.0, 45.0] [45.000018, 44.999982, 90.0]

[0.0, 45.0, 90.0] [0.0, 44.999982, 90.0]

[0.0, 45.0, 135.0] [-45.000018, 44.999982, 90.0]

[0.0, 45.0, 180.0] [-90.0, 44.999982, 90.0]

[0.0, 45.0, 225.0] [-45.000018, 44.999982, 90.0]

[0.0, 45.0, 270.0] [0.0, 44.999982, 90.0]

[0.0, 45.0, 315.0] [45.000018, 44.999982, 90.0]

[0.0, 90.0, 0.0] [90.0, 90.0, 90.0]

[0.0, 90.0, 45.0] [45.000018, 90.0, 90.0]

[0.0, 90.0, 90.0] [0.0, 90.0, 90.0]

[0.0, 90.0, 135.0] [-45.000018, 90.0, 90.0]

[0.0, 90.0, 180.0] [-90.0, 90.0, 90.0]

[0.0, 90.0, 225.0] [-45.000018, 90.0, 90.0]

Can anyone think of a solution?

EDIT: I don't know if this helps, but there are a few other ways at looking at these rotations:

A way to rotate about an arbitrary axis, is to reorient that axis as the Z Axis, and then do the inverse of the reorientation; you can apply this over and over, to obtain the Euler rotations in terms of the original fixed axis rotations;

$$R_{Z^{\prime\prime} X^{\prime} Z}(\alpha,\beta,\gamma) = R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha)$$

$$R_{X^{\prime}}(\beta) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)$$

so

$$R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})$$

$$R_{Z^{\prime\prime}} = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)$$

And so the whole thing;

$$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})$$

Which cancels down;

$$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)\mathbf{R_Y(-\frac{\pi}{2})R_Y(\frac{\pi}{2})}R_Z(\beta)R_Y(-\frac{\pi}{2})$$

$$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})\mathbf{R_Z(-\beta)R_Z(\beta)}R_Y(-\frac{\pi}{2})$$

$$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)\mathbf{R_Y(\frac{\pi}{2})R_Y(-\frac{\pi}{2})}$$

$$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)$$

And note that $$R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2}) = R_X(\beta)$$

so we have $$R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_X(\beta)R_Z(\gamma)$$

Now i'm not sure how much this might help... but it's something i guess...

This paper describes exactly what you need.