Joonas' Note

Joonas' Note

[Graphics/Math] Euler to Quaternion, Quaternion to Euler 본문

알고리즘

[Graphics/Math] Euler to Quaternion, Quaternion to Euler

2022. 4. 5. 22:06 joonas

    https://stackoverflow.com/questions/11103683/euler-angle-to-quaternion-then-quaternion-to-euler-angle

     

    Euler angle to Quaternion then Quaternion to euler angle

    I'm using lib glm (http://glm.g-truc.net/) for test quaternion but I've a problem; when I convert euler angle to quaternion then immediatly quaternion to euler angles, my result are totally different

    stackoverflow.com

    http://marc-b-reynolds.github.io/math/2017/04/18/TaitEuler.html

     

    Converting to Euler & Tait-Bryan

    A note on reducing errors when converting to Euler angles or Tait-Bryan paramerters.

    marc-b-reynolds.github.io

    http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm

     

    Maths - Conversion Quaternion to Euler - Martin Baker

    Equations heading = atan2(2*qy*qw-2*qx*qz , 1 - 2*qy2 - 2*qz2) attitude = asin(2*qx*qy + 2*qz*qw) bank = atan2(2*qx*qw-2*qy*qz , 1 - 2*qx2 - 2*qz2) except when qx*qy + qz*qw = 0.5 (north pole) which gives: heading = 2 * atan2(x,w) bank = 0 and when qx*qy +

    www.euclideanspace.com

     

    Javascript로 옮기면 이렇다.

    function threeAxisRotote(r11, r12, r21, r31, r32){
        return [
            Math.atan2(r11, r12),
            Math.asin(r21),
            Math.atan2(r31, r32),
        ];
    }
    
    function quaternionToEuler(q, order) {
        switch(order){
        case "ZYX":
            return threeAxisRotote(
                2*(q.x*q.y + q.w*q.z),
                q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                -2*(q.x*q.z - q.w*q.y),
                2*(q.y*q.z + q.w*q.x),
                q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
            );
        case "ZXY":
            return threeAxisRotote(
                -2*(q.x*q.y - q.w*q.z),
                q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                2*(q.y*q.z + q.w*q.x),
                -2*(q.x*q.z - q.w*q.y),
                q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
            );
        case "YXZ":
            return threeAxisRotote(
                2*(q.x*q.z + q.w*q.y),
                q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                -2*(q.y*q.z - q.w*q.x),
                2*(q.x*q.y + q.w*q.z),
                q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z
            );
        case "YZX":
            return threeAxisRotote(
                -2*(q.x*q.z - q.w*q.y),
                q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z,
                2*(q.x*q.y + q.w*q.z),
                -2*(q.y*q.z - q.w*q.x),
                q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z
            );
        case "XYZ":
            return threeAxisRotote(
                -2*(q.y*q.z - q.w*q.x),
                q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z,
                2*(q.x*q.z + q.w*q.y),
                -2*(q.x*q.y - q.w*q.z),
                q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z
            );
        case "XZY":
            return threeAxisRotote(
                2*(q.y*q.z + q.w*q.x),
                q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z,
                -2*(q.x*q.y - q.w*q.z),
                2*(q.x*q.z + q.w*q.y),
                q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z
            );
        }
    }

    Euler --(XYZ)--> Quaternion --(ZYX)--> Euler 로 변환해야 같은 euler 값을 꺼낼 수 있다.

    그리고 위 레퍼런스 코드가 xyz가 아니라 zyx 순으로 읽고 사용하는 것 같다.

    Comments