내가 테스트로 오일러각을 쿼터니온으로 변환하고, 아무것도 안한다음 다시 오일러각으로 변환해봤음.
내가 생각하기로는 첫 오일러 각이랑 최종 오일러 각은 값이 동일해야하는데, 동일하지 않음.
원래 이런거임???
오일러 to 쿼터니온, 쿼터니온 to 오일러 코드는 위키피디아에 있는 코드임.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include "pch.h" #include <iostream> #define _USE_MATH_DEFINES #include <cmath> struct Quaternion { double w, x, y, z; }; Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X) { // Abbreviations for the various angular functions double cy = cos(yaw * 0.5); double sy = sin(yaw * 0.5); double cp = cos(pitch * 0.5); double sp = sin(pitch * 0.5); double cr = cos(roll * 0.5); double sr = sin(roll * 0.5); Quaternion q; q.w = cr * cp * cy + sr * sp * sy; q.x = sr * cp * cy - cr * sp * sy; q.y = cr * sp * cy + sr * cp * sy; q.z = cr * cp * sy - sr * sp * cy; return q; } struct EulerAngles { double roll, pitch, yaw; }; EulerAngles ToEulerAngles(Quaternion q) { EulerAngles angles; // roll (x-axis rotation) double sinr_cosp = 2 * (q.w * q.x + q.y * q.z); double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y); angles.roll = std::atan2(sinr_cosp, cosr_cosp); // pitch (y-axis rotation) double sinp = 2 * (q.w * q.y - q.z * q.x); if (std::abs(sinp) >= 1) angles.pitch = std::copysign(math::PI / 2, sinp); // use 90 degrees if out of range else angles.pitch = std::asin(sinp); // yaw (z-axis rotation) double siny_cosp = 2 * (q.w * q.z + q.x * q.y); double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z); angles.yaw = std::atan2(siny_cosp, cosy_cosp); return angles; } int main() { EulerAngles Rotation = { math::PI / 2, math::PI / 2, math::PI / 2 }; std::printf("Roll, Pitch, Yaw: %f %f %f\n", Rotation.roll, Rotation.pitch, Rotation.yaw); Quaternion quat = ToQuaternion(Rotation.yaw, Rotation.pitch, Rotation.roll); std::printf("QUAT(w, x, y ,z): %f %f %f %f\n", quat.w, quat.x, quat.y, quat.z); Rotation = ToEulerAngles(quat); std::printf("Roll, Pitch, Yaw: %f %f %f\n", Rotation.roll, Rotation.pitch, Rotation.yaw); } | cs |
Output:
Roll, Pitch, Yaw: 1.570796 1.570796 1.570796
QUAT(w, x, y ,z): 0.707107 -0.000000 0.707107 -0.000000
Roll, Pitch, Yaw: -1.570796 1.570796 -1.570796
단순히 변환만 했을 뿐인데 값이 다르네... 내가 잘못 이해하고있는건가?
하나의 3차원 회전을 나타내는 Euler angle 조합이 유일하지 않아서 그럼. 회전 행렬로 변환해서 동일하면 문제 없음
하나의 회전행렬을 나타낼 수 있는 오일러각 조합과 쿼터니언이 여러개라는 의미인거죠??
오일러각도 그렇고 쿼터니언도 그렇고 회전행렬이랑 일대일 대응이 아님
하나의 회전행렬을 나타낼 수 있는 오일러각 조합과 쿼터니언이 여러개라는 의미인거죠??
ㅇㅇ 쿼터니언의 경우엔 q랑 -q가 나타내는 회전이 똑같음
하나만 더 질문 해도 됨???
최종적으로 얻어진 오일러각을 다시 쿼터니언으로 변환하니까 값이 똑같네... 연산 오차는 있지만..
기준이 되는 값이 변하면 안됨