Edge AI & Cloud/Robotics

로보틱스 강체 회전 제어: 오일러 각(Euler Angle)의 짐벌 락(Gimbal Lock) 해결을 위한 쿼터니언(Quaternion) 수학 기초

임베디드 친구 2026. 8. 10. 16:57
반응형

2D/3D 공간에서의 로보틱스 강체 회전 제어 및 쿼터니언 도입 배경

로봇 제어 시스템(Robotics Control Systems) 및 3D 그래픽스 엔진에서 강체(Rigid Body)의 자세(Orientation)를 정확하게 계산하는 것은 필수적입니다. 로봇 팔(Manipulator), 무인 항공기(UAV), 자율주행 이동 로봇(AMR)은 공간 상에서 회전 움직임을 연속적으로 계산해야 합니다.

초기 로보틱스 제어에서는 이해하기 쉬운 직관적인 오일러 각(Euler Angle: Roll, Pitch, Yaw) 표현법을 주로 사용했습니다. 하지만 특정 회전각에서 좌표축 중 하나가 상실되는 짐벌 락(Gimbal Lock) 현상이 발생하여 로봇의 제어 불능 상태나 발산(Divergence) 오류를 유발하는 치명적인 한계가 존재합니다.

본 포스팅에서는 오일러 각 회전 방식의 한계를 수학적으로 분석하고, 사차원 복소수 형태의 쿼터니언(Quaternion)을 도입하여 특이점(Singularity) 없는 3D 회전을 구현하는 방법을 설명합니다.

3D 공간 회전 표현 방식 및 쿼터니언(Quaternion) 핵심 요약 (Technical Summary)

  • 짐벌 락 예방 (Gimbal Lock Prevention): 쿼터니언(Quaternion)은 3D 공간 회전을 피치(Pitch) 한계 경계가 없는 4차원 단위 구체($S^3$) 초복소수로 표현하여 회전 특이점(Singularity) 현상을 완전히 제거합니다.
  • 연산 효율성 (Computational Efficiency): 쿼터니언 곱셈($q_1 \otimes q_2$)은 $3 \times 3$ SO(3) 회전 행렬(Rotation Matrix) 연산(곱셈 27회, 덧셈 18회)에 비해 적은 부동소수점 연산량(곱셈 16회, 덧셈 12회)을 요구하여 시스템 부하를 줄입니다.
  • 부드러운 보간 (Smooth Interpolation): 쿼터니언 기반의 구면 선형 보간(Spherical Linear Interpolation, Slerp)을 활용하면 로봇의 연속적인 이동 경로에 대해 등각속도 궤적 계획(Constant Angular Velocity Trajectory Planning)을 쉽게 구현할 수 있습니다.

강체 회전 표현 방식 상세 분석 및 SO(3) / 쿼터니언 수학적 변환

3D 공간 회전 기법 비교 분석 (Rotation Representation Methods)

회전 표현 기법 (Method) 메모리 사용량 (Parameters) 특이점 발생 (Gimbal Lock) 보간 용이성 (Interpolation) 주요 활용 분야 (Primary Use Case)
오일러 각 (Euler Angles) 3 (Roll, Pitch, Yaw) 발생 (Pitch = $\pm 90^\circ$) 불가능 (비선형 동작 발생) 사용자 UI 표출, 센서 직관 분석
회전 행렬 (Rotation Matrix) 9 ($3 \times 3$ SO(3) Matrix) 미발생 어려움 (Orthonormal 유지 필요) 좌표 변환 벡터 연산
쿼터니언 (Quaternion) 4 ($q = [w, x, y, z]$) 미발생 우수 (SLERP 보간 가능) 로보틱스 제어, SLAM, Kinematics

오일러 각(Euler Angle) 회전과 짐벌 락(Gimbal Lock) 원리

오일러 각 방식은 $X, Y, Z$ 축을 순차적으로 회전시킵니다. 회전 변환 행렬 $R_{zxy}(\phi, \theta, \psi)$는 다음과 같이 개별 축 회전 행렬의 곱으로 정의됩니다.

$$R_z(\psi) = \begin{bmatrix} \cos\psi & -\sin\psi & 0 \\ \sin\psi & \cos\psi & 0 \\ 0 & 0 & 1 \end{bmatrix}, \quad R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix}$$

Pitch 각도 $\theta = 90^\circ$ ($\pi/2$)에 도달하면, $\cos(90^\circ) = 0$$\sin(90^\circ) = 1$이 되며 $X$축 회전과 $Z$축 회전이 동일한 평면 상에 겹치게 됩니다. 이로 인해 자유도(Degree of Freedom) 하나가 상실되는 짐벌 락(Gimbal Lock) 상태가 발생합니다.

쿼터니언(Quaternion)의 정의 및 3D spatial 회전 연산

쿼터니언 $q$는 하나의 실수부 $w$와 세 개의 허수부 $x, y, z$로 구성된 사차원 복소수입니다.

$$q = w + xi + yj + zk = [w, \mathbf{v}], \quad (\mathbf{v} = [x, y, z]^T)$$

허수 단위 $i, j, k$는 다음 하밀통(Hamilton) 기본 규칙을 만족합니다.

$$i^2 = j^2 = k^2 = ijk = -1$$

임의의 회전축 단위 벡터 $\mathbf{u} = [u_x, u_y, u_z]^T$에 대해 $\theta$ 만큼 회전시키는 단위 쿼터니언(Unit Quaternion)은 다음과 같이 정의됩니다.

$$q = \left[ \cos\left(\frac{\theta}{2}\right), \mathbf{u} \sin\left(\frac{\theta}{2}\right) \right]$$

3D 위치 벡터 $\mathbf{p} = [0, p_x, p_y, p_z]$를 쿼터니언 $q$로 회전 변환한 결과 벡터 $\mathbf{p}'$는 Sandwich Product 연산을 적용합니다.

$$\mathbf{p}' = q \otimes \mathbf{p} \otimes q^*$$

여기서 $q^*$는 $q$의 켤레 쿼터니언(Conjugate Quaternion, $[w, -\mathbf{v}]$)입니다.

C++ Eigen 라이브러리를 활용한 Quaternion 및 Euler Angle 변환 코드

다음 소스코드는 C++ Eigen 라이브러리를 사용하여 오일러 각을 쿼터니언으로 변환하고 3D 벡터 회전을 수행하는 예제입니다.

#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Geometry>

int main() {
    // 1. Define Euler Angles in Radians (Roll, Pitch, Yaw)
    double roll = 0.1;   // X-axis rotation
    double pitch = 1.570796; // Y-axis rotation (near 90 degrees)
    double yaw = 0.5;    // Z-axis rotation

    // 2. Convert Euler Angles (ZYX order) to Quaternion
    Eigen::AngleAxisd rollAngle(roll, Eigen::Vector3d::UnitX());
    Eigen::AngleAxisd pitchAngle(pitch, Eigen::Vector3d::UnitY());
    Eigen::AngleAxisd yawAngle(yaw, Eigen::Vector3d::UnitZ());

    Eigen::Quaterniond q = yawAngle * pitchAngle * rollAngle;
    q.normalize(); // Ensure Unit Quaternion property

    // 3. Define 3D Vector to rotate
    Eigen::Vector3d point(1.0, 0.0, 0.0);

    // 4. Perform Quaternion Rotation: p' = q * p * q^-1
    Eigen::Vector3d rotatedPoint = q * point;

    // 5. Output Result
    std::cout << "Quaternion (w, x, y, z): " 
              << q.w() << ", " << q.x() << ", " 
              << q.y() << ", " << q.z() << std::endl;
    std::cout << "Rotated Point Vector: " 
              << rotatedPoint.transpose() << std::endl;

    return 0;
}

로보틱스 파이프라인 개발 및 Quaternion 처리 디버깅 팁

1) Normalize 과정 누적을 통한 수치적 오차 예방

연속적인 회전 곱셈 연산($q_{new} = q_1 \otimes q_2 \otimes \dots \otimes q_n$)을 수행할 때 부동 소수점 오차(Floating-point Drift)가 누적될 수 있습니다. 쿼터니언의 크기가 1에서 벗어나면 전단 변형(Shear) 혹은 스케일 변형이 발생합니다. 매 연산 주기마다 다음과 같이 강제로 정규화를 수행해야 합니다.

// Normalize Quaternion to maintain Unit Quaternion property
q.normalize();

2) ROS 2 (Robot Operating System) tf2 패키지 디버깅 명령

ROS 2 환경에서 로봇 관절 및 IMU 쿼터니언 자세 데이터를 모니터링할 때 다음 CLI 도구를 활용합니다.

# Echo IMU Quaternion topic data
ros2 topic echo /imu/data --field orientation

# Monitor TF tree transformation
ros2 run tf2_tools view_frames

Quaternion 회전 구현 시 흔히 발생하는 실수 및 예외 해결법

1) Unit Quaternion 정규화 누락으로 인한 3D Transform Distortion

  • 현상: 로봇 시뮬레이션(Gazebo, Isaac Sim) 환경에서 링크(Link)의 크기가 왜곡되거나 3D 메쉬가 찌그러지는 현상이 발생합니다.
  • 원인: 회전 연산 후 $\vert{}\vert{}q\vert{}\vert{} = \sqrt{w^2 + x^2 + y^2 + z^2} \neq 1$ 상태인 비정규화 쿼터니언이 변환 행렬로 넘겨졌기 때문입니다.
  • 해결 방법: 쿼터니언 회전 연산 적용 전/후로 norm 값을 확인하고 정규화를 수행합니다.
if (std::abs(q.norm() - 1.0) > 1e-6) {
    // Re-normalize when norm deviates from 1.0
    q.normalize();
}

2) Quaternion Multiplication 순서 오인으로 인한 좌표계 왜곡

  • 현상: 회전 변환 적용 후 좌표계가 의도한 방향의 반대로 회전합니다.
  • 원인: 쿼터니언 곱셈은 교환 법칙이 성립하지 않습니다 ($q_1 \otimes q_2 \neq q_2 \otimes q_1$).
  • 해결 방법: 기준 좌표계(Global Frame) 회전은 좌측 곱셈($q_{global} \otimes q_{local}$), 자체 좌표계(Local Body Frame) 회전은 우측 곱셈($q_{local} \otimes q_{delta}$)을 엄격히 준수합니다.

로보틱스 수학 기초 강체 회전 제어 결론

로보틱스 및 3D spatial 제어 시스템에서 오일러 각(Euler Angle)의 짐벌 락(Gimbal Lock) 한계를 극복하기 위해 쿼터니언(Quaternion) 사용은 표준 아키텍처로 자리 잡았습니다. 4차원 단위원 복소수 체계를 활용하면 연산 효율성을 극대화하고 연속적인 궤적 보간(SLERP)을 연산 불능 상태 없이 안정적으로 수행할 수 있습니다.

반응형