Note that there are some explanatory texts on larger screens.

plurals
  1. POConverting from a Euler ZXZ rotation, to fixed axis XYZ rotations
    primarykey
    data
    text
    <p>The problem i have, is that i need to convert from XYZ fixed axis rotations, to Euler rotations about Z, then X', then Z''.</p> <p>Here are the relevant matrices:</p> <p>X: <img src="https://i.imgur.com/J5G1f.jpg" alt="X"></p> <p>Y: <img src="https://i.imgur.com/9pDts.jpg" alt="Y"></p> <p>Z: <img src="https://i.imgur.com/o67aJ.jpg" alt="Z"></p> <p>Combined, as Rz(psi) Ry(phi) Rx(theta) = Rxyz(theta,phi,psi); they give:</p> <p>Rxyz: <img src="https://i.imgur.com/8UQM6.jpg" alt="Rxyz"></p> <p>And the Rotation matrix for the Specific convention of Euler angles i want; is this:</p> <p>Euler: <img src="https://i.imgur.com/jSSGL.jpg" alt="Euler"></p> <p>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):</p> <p><img src="https://i.imgur.com/yQhmL.jpg" alt="Code"></p> <p>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) = +/- 1.</p> <p>So right away I can just rule out the possible situations;</p> <p>When theta or phi = 0, 180, 360, 540, ..., then Cos(theta), and Cos(phi) are +/- 1;</p> <p>so I only need to do it differently for these cases;</p> <p>And i ended up with this code:</p> <pre><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(γ)}; } </code></pre> <p>Where r and eq are just two simple functions;</p> <pre><code>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) &lt; thresh); } </code></pre> <p>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;</p> <p>(i.e. every now and then i'd end up with Math.acos(1.000000000000000004) or something.)</p> <p>Which takes into account the 4 cases of having rotations around x and y which leave c2==1.</p> <p>But now is where the problem occurs;</p> <p>Everything I have done above, makes sense to me, but it does not give the correct angles;</p> <p>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 </p> <pre><code>[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] </code></pre> <p>i think it's due to the way Math.acos and Math.asin work, Can anyone think of a solution?</p> <p>EDIT: math.asin and math.acos return values between -pi/2 and pi/2 and 0 and pi respectively. This is not ambiguous, so i don't think the problem is here. It seems like i might have the maths wrong somewhere, but i can't see a hole in my reasoning...</p> <p>EDIT2: To anyone how doesn't know how Euler rotations work, it's like this:</p> <p><img src="https://upload.wikimedia.org/wikipedia/commons/c/c5/Euler2.gif" alt="Euler Angles Gif"></p> <p>That is, rotate around <em>Z</em>, then around the new <em>X</em> axis (<em>X'</em>) then around the new <em>Z''</em> axis.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload