제1부 수학적 기초
1.5 회전의 표현 II: 축-각·로드리게스 공식·쿼터니언
1.5.1 이 장에서 배우는 것 / 선수 지식 / 특히 중요한 독자
이 장은 3차원 회전의 특이점 없는 표현 — 축-각(회전 벡터)과 단위 쿼터니언 — 의 정의·변환·연산과, 라이브러리마다 갈리는 쿼터니언 성분 순서 규약을 다룬다. 쿼터니언은 4개의 수로 회전을 나타내고 합성이 곱 하나이며 특이점이 없어 자세 추정·보간·제어에서 내부 표현으로 널리 사용된다. 앞 장(1.4)에서 확인한 오일러각의 특이점과 회전 행렬의 오차 표류가 이 표현을 선택하는 이유이다. 리군·지수 사상은 1.7, 이중 쿼터니언은 1.11가 다룬다. 다룰 질문은 네 가지다. 로드리게스 공식과 축-각 변환은 어디서 정밀도를 잃는가, 쿼터니언의 대수와 회전 적용은 어떻게 이루어지는가, 행렬에서 쿼터니언을 어떻게 안정하게 구하는가, 보간에서 각속도가 일정한 방법은 무엇인가.
배우는 것:
- 축-각과 로드리게스 공식 — $R=I+\sin\theta\,[n]_\times+(1-\cos\theta)[n]_\times^2$, 역변환의 특이 경우.
- 쿼터니언의 대수 — 해밀턴 곱, 켤레, 노름, 회전 적용 $qvq^*$, 합성, 이중 덮개.
- 변환과 수치 — 쿼터니언↔행렬, 셰퍼드 방법, 각 추출의 acos·atan2 정밀도, 노름 표류.
- 보간 — SLERP(각속도 일정)와 NLERP의 차이.
- 규약 — 해밀턴 규약, 성분 순서(ROS 메시·Eigen·SciPy·이 책).
- 풀이 예제 — 연산 검증, 각 추출 오차, 셰퍼드 방법, SLERP 대 NLERP, 곱 표류.
선수 지식: 1.3(프레임·회전 행렬), 1.4(오일러각·재직교화). 표기는 BK-05와 A.2을 따른다.
특히 중요한 독자: 엔지니어·연구자(자세 추정·보간·제어), 소프트웨어 개발자(라이브러리 간 쿼터니언 순서), 인증 독자(자세 표현의 수치 검증).
출처 방침. 정리는 교과서와 원 논문에 근거하며 서지는 Crossref·arXiv 응답으로 확인했다(목록은 이 장 끝). 직접 읽은 자료: ① ROS 2
geometry_msgs/msg/Quaternion.msg(ros2/common_interfaces), ② Eigen의Eigen/src/Geometry/Quaternion.h(GitLablibeigen/eigen마스터), ③ SciPy의scipy/spatial/transform/_rotation.py(GitHubmain)의from_quat문서, 조회 2026-11-03. 교과서 본문과 JPL 규약의 원 문서는 읽지 않았다(확인 필요). 수치는 모두 이 장의 순수 파이썬 구현으로 계산했다.
1.5.2 개념 — 회전을 4개의 수로
회전 행렬의 9개 원소와 오일러각의 3개 값 사이에 4개의 수가 있다. 회전은 축 $n$과 각 $\theta$로 정해지며, 이 둘을 $(\cos\tfrac\theta2,\ n\sin\tfrac\theta2)$로 묶은 것이 단위 쿼터니언이다. 이 묶음이 특이점을 없애는 이유는 각 $0$에서 축이 정해지지 않아도 $q\to(1,0,0,0)$으로 연속이기 때문이다.
| 표현 | 변환 비용 | 합성 | 보간 | 주된 용도 |
|---|---|---|---|---|
| 회전 행렬 | 기준 | 행렬 곱(27 곱셈) | 직접 불가 | 기구학·벡터 변환 |
| 축-각·회전 벡터 | 로드리게스 공식 | 변환 필요 | 각을 선형 보간 | 입력·미분(1.7) |
| 단위 쿼터니언 | 행렬 변환 식 | 쿼터니언 곱(16 곱셈) | SLERP | 자세 추정·보간 |
1.5.3 원리
1.5.3.1 축-각과 로드리게스 공식
오일러 회전 정리에 따르면 3차원의 모든 회전은 한 축 $n$ ($\lVert n\rVert=1$)을 중심으로 한 각 $\theta$의 회전이다. 회전 벡터는 $\omega=\theta n$이고 지수 사상 $R=\exp([\omega]_\times)$이다(1.7). 행렬 표현은 로드리게스 공식
$$R=I+\sin\theta\,K+(1-\cos\theta)\,K^2,\qquad K=[n]_\times,\quad K^2=nn^\top-I$$
이다. 정의로부터 $K^3=-K$이므로 지수 급수가 사인·코사인으로 묶인다. 역변환은
$$\theta=\operatorname{atan2}\!\Bigl(\tfrac12\lVert R-R^\top\rVert_{\mathrm{vee}},\ \tfrac12(\operatorname{tr}R-1)\Bigr),\qquad n=\frac{\operatorname{vee}(R-R^\top)}{2\sin\theta}$$
이다($\operatorname{vee}$는 반대칭 행렬의 세 성분, $\lVert\cdot\rVert_{\mathrm{vee}}$는 그 노름). 두 특이 경우가 있다. $\theta=0$이면 축이 정해지지 않고, $\theta=\pi$이면 $R-R^\top=0$이므로 $R+I=2nn^\top$에서 축을 구하며 부호가 모호하다($\pm n$). 각을 $\arccos\bigl(\tfrac12(\operatorname{tr}R-1)\bigr)$로 구하면 $\theta$가 0이나 $\pi$ 근방에서 정밀도를 잃는다(1.5.5).
1.5.3.2 쿼터니언의 대수
쿼터니언 $q=q_w+q_xi+q_yj+q_zk$는 $i^2=j^2=k^2=ijk=-1$을 따른다(해밀턴 규약). 성분 순서는 $(q_w,q_x,q_y,q_z)$(BK-05)이다. 해밀턴 곱은 구현의 qmul과 같고 교환되지 않는다($qp\ne pq$). 켤레는 $q^*=(q_w,-q_x,-q_y,-q_z)$, 노름은 $\lVert q\rVert^2=qq^*$, 역은 $q^{-1}=q^*/\lVert q\rVert^2$이다. 곱의 비용은 16번의 곱셈이다(구현의 항 수).
1.5.3.3 회전과 쿼터니언
단위 쿼터니언 $q=(\cos\tfrac\theta2,\ n\sin\tfrac\theta2)$가 축 $n$ 둘레 각 $\theta$의 회전을 나타낸다. 벡터 $v$를 순허수 쿼터니언 $(0,v)$로 두면 능동 회전은
$$v'=q\,(0,v)\,q^*$$
이고 합성은 행렬 곱과 같은 순서이다: ${}^{A}q_{C}={}^{A}q_{B}\,{}^{B}q_{C}$. $q$와 $-q$는 같은 회전을 나타내므로 단위 쿼터니언은 회전군을 두 번 덮는다(이중 덮개, 아래 그림). 보간·비교에서는 부호를 맞추어야 한다.
쿼터니언에서 행렬은 다음과 같다.
$$R(q)=\begin{bmatrix}1-2(q_y^2+q_z^2)&2(q_xq_y-q_zq_w)&2(q_xq_z+q_yq_w)\\2(q_xq_y+q_zq_w)&1-2(q_x^2+q_z^2)&2(q_yq_z-q_xq_w)\\2(q_xq_z-q_yq_w)&2(q_yq_z+q_xq_w)&1-2(q_x^2+q_y^2)\end{bmatrix}$$
반대로 행렬에서 쿼터니언을 구하려면 $q_w=\tfrac12\sqrt{1+\operatorname{tr}R}$와 $q_x=(R_{32}-R_{23})/(4q_w)$ 등을 사용할 수 있으나 $\theta\approx\pi$에서 $q_w\approx0$이므로 0으로 나눈다. 셰퍼드 방법(Shepperd, 1978)은 $\operatorname{tr}R$, $R_{11}$, $R_{22}$, $R_{33}$ 가운데 가장 큰 것에 해당하는 성분을 먼저 제곱근으로 구하고 나머지를 그것으로 나누어 항상 큰 수로 나눈다.
1.5.3.4 규약 — 성분 순서와 해밀턴·JPL
같은 회전이라도 라이브러리와 문서가 쿼터니언 성분을 다르게 적는다. 이 장이 소스에서 직접 읽은 사항은 다음과 같다.
| 출처 | 읽은 서술 | 성분 순서 |
|---|---|---|
ROS 2 Quaternion.msg | 필드 x, y, z, w, 기본값 $w=1$ | 스칼라 후행 |
Eigen Quaternion.h | 생성자 Quaternion(w, x, y, z), 내부 저장은 [x, y, z, w]라는 경고, coeffs()는 (x, y, z, w), coeffsScalarFirst()는 (w, x, y, z) | 생성자는 스칼라 선행, 저장은 후행 |
SciPy Rotation.from_quat | scalar_first=False가 기본(스칼라 후행), True이면 (w, x, y, z) | 기본 스칼라 후행 |
| 이 책(BK-05) | 해밀턴 규약, $q=(q_w,q_x,q_y,q_z)$ | 스칼라 선행 |
세 소프트웨어의 저장·기본 순서가 스칼라 후행이고 생성자 인자만 선행인 경우(Eigen)도 있어, 성분을 배열로 주고받을 때 순서를 확인하지 않으면 회전이 바뀐다. 이 책의 식을 코드로 옮길 때는 성분을 바꿔 넣는다. 우주 분야에서 사용하는 JPL 규약은 스칼라 후행이고 곱의 정의(부호·순서)가 해밀턴 규약과 달라 같은 성분이 다른 회전이나 역회전을 나타낼 수 있다 (확인 필요: 원 문서 미열람). Solà(2017)는 쿼터니언과 회전의 개념·공식과 오차상태 칼만 필터에서의 사용을 정리한 문서이다(초록).
1.5.3.5 보간 — SLERP와 NLERP
두 자세 $q_0$, $q_1$ 사이를 $t\in[0,1]$로 보간할 때 SLERP(구면 선형 보간)는
$$\operatorname{slerp}(q_0,q_1,t)=\frac{\sin((1-t)\Omega)}{\sin\Omega}\,q_0+\frac{\sin(t\Omega)}{\sin\Omega}\,q_1,\qquad\cos\Omega=q_0\cdot q_1$$
이며 단위 4차원 구 위의 대원호를 따라가므로 회전각이 $t$에 선형이다(각속도가 일정하다). 4차원 내적 $q_0\cdot q_1<0$이면 $q_1$을 $-q_1$로 바꾸어 짧은 호를 선택한다. 이 보간은 Shoemake(1985)가 회전 애니메이션에 도입했다. NLERP는 $q_0$와 $q_1$을 선형 보간해 정규화한다. 비용이 작으나 각속도가 일정하지 않다(1.5.5). $\Omega\to0$이면 $\sin\Omega\to0$이므로 NLERP로 대체한다.
1.5.3.6 수치 — 정규화와 비용
쿼터니언은 곱을 거듭하면 노름이 1에서 벗어난다. 정규화(노름으로 나누기)는 SVD 재직교화(1.4)보다 훨씬 싸다. 비용은 곱셈 수로 보면 쿼터니언 곱 16회, 행렬 곱 27회이고 벡터를 행렬로 변환하는 데 9회이다. 쿼터니언 미분과 각속도의 관계, 오차 상태 표현은 1.7와 9.4이 다룬다.
1.5.4 알고리즘
축-각·행렬 변환과 셰퍼드 방법
각 추출(행렬 R):
c ← (tr R − 1)/2
s ← ½ ‖(R32−R23, R13−R31, R21−R12)‖
θ ← atan2(s, c) (arccos 사용 금지)
θ가 0이 아니고 π가 아니면 n ← (R32−R23, R13−R31, R21−R12) / (2 sin θ)
셰퍼드(행렬 R → 쿼터니언):
후보 ← (tr R, R11, R22, R33)에서 가장 큰 것의 번호 k
k = 0이면 w ← √(1+tr R)/2, x, y, z ← (반대칭 성분)/(4w)
k = 1이면 x ← √(1+R11−R22−R33)/2, 나머지를 x로 나눔 (y, z, w도 같은 방식)
SLERP(q0, q1, t):
d ← q0·q1; d < 0이면 q1 ← −q1, d ← −d
Ω ← arccos d; Ω가 매우 작으면 NLERP로 대체
반환 [sin((1−t)Ω) q0 + sin(tΩ) q1] / sin Ω
구현은 1.5.5의 코드에 있다.
1.5.5 풀이 예제 — 연산 검증·각 추출·셰퍼드·보간·노름 표류
쿼터니언 연산과 변환을 구현해 정리를 수치로 확인하고, 정밀도가 갈리는 지점과 보간의 각속도를 계산한다. 결론부터 적으면 다음과 같다. ① 해밀턴 곱은 $ijk=-1$이고 행렬 변환·로드리게스 공식·회전 적용 $qvq^*$과 $10^{-16}$ 안에서 일치하며 $q$와 $-q$는 같은 행렬을 준다. ② $\theta=10^{-8}$에서 acos 방식은 상대 오차 1(정보 전부 손실), atan2 방식은 0이다. ③ 단순한 쿼터니언 추출은 $\theta=\pi-10^{-6}$에서 복원 오차 $1.6\times10^{-4}$, $\pi-10^{-8}$에서 0으로 나누고 셰퍼드 방법은 전 구간에서 $10^{-16}$ 수준이다. ④ NLERP는 170° 회전에서 각이 선형 보간에서 최대 6.60° 벗어난다. ⑤ 곱 $10^5$번 후 쿼터니언 노름 오차가 $3.9\times10^{-12}$이고 100번마다 정규화하면 0이다.
구현. qmul·qconj·from_axis_angle·to_axis_angle·rotate·to_matrix·from_matrix(셰퍼드)·nlerp·slerp. 파이썬 표준 라이브러리와 1.1의 행렬 곱
| 항목 | 값 |
|---|---|
| 입력 1 | $q$: $z$축 70°, $p$: 축 $(1,2,2)/3$ 둘레 110°, 벡터 $(0.3,-1.2,0.8)$ |
| 입력 2 | 축 $(1,2,2)/3$ 둘레 각 $\theta=10^{-8}$~$\pi-10^{-8}$의 로드리게스 행렬 |
| 입력 3 | $\theta=\pi-\delta$ ($\delta=10^{-1}$~$10^{-10}$)의 로드리게스 행렬 |
| 입력 4 | $q_0=(1,0,0,0)$, $q_1$: $z$축 170°, $t=0$~1 |
| 입력 5 | 증분 쿼터니언(축 $(0,0.6,0.8)$, 0.37°)을 $10^5$번 곱함 |
import math
def qmul(a, b):
"""해밀턴 곱, 성분 순서 (w, x, y, z)"""
aw, ax, ay, az = a
bw, bx, by, bz = b
return (aw * bw - ax * bx - ay * by - az * bz,
aw * bx + ax * bw + ay * bz - az * by,
aw * by - ax * bz + ay * bw + az * bx,
aw * bz + ax * by - ay * bx + az * bw)
def qconj(q):
return (q[0], -q[1], -q[2], -q[3])
def from_axis_angle(n, th):
"""q = (cos(th/2), n sin(th/2)), n은 단위 벡터"""
s = math.sin(th / 2)
return (math.cos(th / 2), n[0] * s, n[1] * s, n[2] * s)
def to_axis_angle(q):
"""(축, 각): 각을 atan2로 구해 0 근방에서도 정확하다"""
s = math.sqrt(q[1] ** 2 + q[2] ** 2 + q[3] ** 2)
n = [t / s for t in q[1:]] if s > 0 else [1.0, 0.0, 0.0]
return n, 2 * math.atan2(s, q[0])
def rotate(q, v):
"""v' = q (0, v) q*"""
p = qmul(qmul(q, (0.0,) + tuple(v)), qconj(q))
return list(p[1:])
def to_matrix(q):
w, x, y, z = q
return [[1 - 2 * (y * y + z * z), 2 * (x * y - z * w),
2 * (x * z + y * w)],
[2 * (x * y + z * w), 1 - 2 * (x * x + z * z),
2 * (y * z - x * w)],
[2 * (x * z - y * w), 2 * (y * z + x * w),
1 - 2 * (x * x + y * y)]]
def from_matrix(R):
"""셰퍼드 방법: 가장 큰 후보로 나눠 0 나눗셈을 피한다"""
t = R[0][0] + R[1][1] + R[2][2]
c = [t, R[0][0], R[1][1], R[2][2]]
k = c.index(max(c))
a, b = R[2][1] - R[1][2], R[0][2] - R[2][0]
d = R[1][0] - R[0][1]
if k == 0:
w = math.sqrt(1 + t) / 2
return (w, a / (4 * w), b / (4 * w), d / (4 * w))
if k == 1:
x = math.sqrt(1 + R[0][0] - R[1][1] - R[2][2]) / 2
return (a / (4 * x), x, (R[0][1] + R[1][0]) / (4 * x),
(R[0][2] + R[2][0]) / (4 * x))
if k == 2:
y = math.sqrt(1 - R[0][0] + R[1][1] - R[2][2]) / 2
return (b / (4 * y), (R[0][1] + R[1][0]) / (4 * y), y,
(R[1][2] + R[2][1]) / (4 * y))
z = math.sqrt(1 - R[0][0] - R[1][1] + R[2][2]) / 2
return (d / (4 * z), (R[0][2] + R[2][0]) / (4 * z),
(R[1][2] + R[2][1]) / (4 * z), z)
def nlerp(a, b, t):
"""정규화 선형 보간(짧은 경로 선택)"""
if sum(x * y for x, y in zip(a, b)) < 0:
b = tuple(-x for x in b)
q = [(1 - t) * x + t * y for x, y in zip(a, b)]
n = math.sqrt(sum(x * x for x in q))
return tuple(x / n for x in q)
def slerp(a, b, t):
"""구면 선형 보간: 각속도가 일정하다"""
d = sum(x * y for x, y in zip(a, b))
if d < 0:
b, d = tuple(-x for x in b), -d
om = math.acos(min(1.0, d))
if om < 1e-9:
return nlerp(a, b, t)
s0 = math.sin((1 - t) * om) / math.sin(om)
s1 = math.sin(t * om) / math.sin(om)
return tuple(s0 * x + s1 * y for x, y in zip(a, b))
① 연산의 정합.
| 항목 | 결과 |
|---|---|
| $ijk$ (해밀턴 곱) | $(-1, 0, 0, 0)$ |
| $\lVert qp-pq\rVert_\infty$ (교환 불가) | 0.626 |
| $R(qp)-R(q)R(p)$ 최대 오차 | 2.2e-16 |
| $R(q)$ 대 로드리게스 공식 최대 오차 | 2.2e-16 |
| $qvq^*$ 대 $R(q)v$ 최대 오차 | 2.2e-16 |
| $R(-q)-R(q)$ (이중 덮개) | 0.0e+00 |
| $\lVert qp\rVert-1$ | 0.0e+00 |
② 각 추출의 정밀도. 로드리게스 행렬에서 각을 되구한 상대 오차는 다음과 같다(0은 구한 값이 입력과 같게 나왔다는 뜻이다).
| 각 $\theta$ | acos 방식의 상대 오차 | atan2 방식의 상대 오차 | 쿼터니언 경유 상대 오차 |
|---|---|---|---|
| 1e-08 | 1.0e+00 | 0.0e+00 | 0.0e+00 |
| 1e-06 | 4.4e-05 | 0.0e+00 | 0.0e+00 |
| 0.0001 | 2.6e-09 | 0.0e+00 | 0.0e+00 |
| 0.01 | 2.4e-12 | 1.7e-16 | 1.7e-16 |
| 1 | 1.1e-16 | 0.0e+00 | 1.1e-16 |
| 3 | 1.5e-16 | 0.0e+00 | 0.0e+00 |
| 3.14159165 | 1.4e-11 | 0.0e+00 | 0.0e+00 |
| 3.14159264 | 3.2e-09 | 0.0e+00 | 0.0e+00 |
acos 방식의 오차는 $\theta$가 0에 가까우면 상대 오차가 $\varepsilon/\theta^2$ 비율로, $\pi$에 가까우면 절대 오차가 $\varepsilon/(\pi-\theta)$ 비율로 커진다. $\cos\theta=1-\theta^2/2$가 부동소수점에서 1로 반올림되기 때문이다. atan2 방식과 쿼터니언을 거치는 방식은 전 범위에서 $10^{-16}$ 수준이다.
③ 행렬에서 쿼터니언.
| $\pi-\theta$ | 단순 방법의 복원 오차 $\lVert R(q)-R\rVert_\infty$ | 셰퍼드 방법의 복원 오차 |
|---|---|---|
| 0.1 | 1.4e-14 | 2.2e-16 |
| 0.001 | 2.8e-11 | 2.2e-16 |
| 1e-06 | 1.6e-04 | 2.2e-16 |
| 1e-08 | 실패(0으로 나눔) | 0.0e+00 |
| 1e-10 | 실패(0으로 나눔) | 0.0e+00 |
④ SLERP와 NLERP.
| $t$ | SLERP 각 (°) | NLERP 각 (°) | NLERP − 선형 (°) |
|---|---|---|---|
| 0.0 | 0.00 | 0.00 | +0.00 |
| 0.1 | 17.00 | 12.51 | −4.49 |
| 0.2 | 34.00 | 27.40 | −6.60 |
| 0.3 | 51.00 | 44.74 | −6.26 |
| 0.4 | 68.00 | 64.23 | −3.77 |
| 0.5 | 85.00 | 85.00 | +0.00 |
| 0.6 | 102.00 | 105.77 | +3.77 |
| 0.7 | 119.00 | 125.26 | +6.26 |
| 0.8 | 136.00 | 142.60 | +6.60 |
| 0.9 | 153.00 | 157.49 | +4.49 |
| 1.0 | 170.00 | 170.00 | +0.00 |
NLERP 각의 선형 보간에서의 최대 편차 6.60°
SLERP의 각은 $170^\circ\times t$로 정확히 선형이고, NLERP는 시작과 끝에서 느리고 중간에서 빠르다(각속도가 일정하지 않다). 두 방법의 경로(대원호)는 같고 속도만 다르다.
⑤ 곱의 노름 표류.
| 곱의 횟수 | 재정규화 없음 $\lVert q\rVert-1$ | 100번마다 재정규화 $\lVert q\rVert-1$ |
|---|---|---|
| 10 | +6.7e−16 | +6.7e−16 |
| 100 | +5.3e−15 | +0.0e+00 |
| 1,000 | +4.1e−14 | +0.0e+00 |
| 10,000 | +3.9e−13 | +0.0e+00 |
| 100,000 | +3.9e−12 | +0.0e+00 |
곱 $10^5$번에서 노름 오차가 $3.9\times10^{-12}$이고, 100번마다 정규화하면 0에 머문다(1.4의 행렬 직교성 표류 $1.5\times10^{-11}$과 같은 자리 수). 이 증가는 이 장의 입력(고정 증분)에 대한 것이다.
한계. 구현은 소규모 교육 코드이며 쿼터니언의 시간 미분·적분(각속도와의 관계)과 오차 상태 표현은 다루지 않았다. 라이브러리의 성분 순서는 소스 서술을 읽은 것이며 동작을 실행해 확인하지 않았다. JPL 규약은 원 문서를 읽지 않았다.
견해: 이 책은 자세를 내부에서 단위 쿼터니언(또는 회전 행렬)으로 저장하고, 각 추출은 atan2로, 행렬 변환은 셰퍼드 방법으로 하며, 경계(파일·통신·라이브러리)마다 성분 순서를 명시하는 것을 기본으로 둔다고 본다. 근거는 위 예제에서 acos 방식이 $\theta=10^{-8}$에서 정보를 전부 잃고 단순한 추출이 $\pi$ 근방에서 실패하며, 읽은 세 소스 중 Eigen의 생성자 순서가 저장 순서와 다르다는 점이다.
1.5.6 설계 트레이드오프 — 자세 표현의 선택
자료에서 확인되는 선택지는 네 가지다.
- ① 회전 행렬. 특이점이 없고 벡터 변환이 직접적이다. 9개 원소와 재직교화가 필요하다(1.4).
- ② 오일러각. 읽기·입력에 적합하나 특이점과 24가지 규약이 있다.
- ③ 축-각·회전 벡터. 3개 값으로 미분·최적화에 적합하다(1.7). 각 0과 $\pi$ 근방의 처리가 필요하다.
- ④ 단위 쿼터니언. 4개 값, 합성·보간이 가볍고 특이점이 없다. 이중 덮개와 성분 순서·규약이 쟁점이다.
| 방식 | 장점 | 한계 | 알맞은 경우 |
|---|---|---|---|
| ① 행렬 | 직접 변환 | 9개, 재직교화 | 기구학 계산 |
| ② 오일러각 | 읽기·입력 | 특이점, 24가지 | 설정·표시 |
| ③ 회전 벡터 | 3개, 미분 | 0·π 근방 처리 | 최적화·섭동 |
| ④ 쿼터니언 | 가벼움, 보간 | 부호·순서 규약 | 자세 추정·보간·통신 |
견해: 쿼터니언이 낫다는 순위보다 한 시스템 안에서 한 규약을 정하고 문서화하는 것이 중요하다고 본다. 근거는 이 장에서 확인한 오류 원인(성분 순서·부호·acos 정밀도)이 모두 규약이나 구현 선택에서 왔다는 점이다.
1.5.7 응용 축 비교
| 응용 축 | 쿼터니언이 맡는 일 | 요구 | 관련 장 |
|---|---|---|---|
| 산업·제조 | 도구 자세 보간 | 보간의 부드러움 | 1.6 |
| 물류·이동 | 평면 자세(요)가 주로 | 단순성 | 2.15 |
| 도로 주행 | 자세 추정(IMU) | 수치 안정 | 9.4 |
| 서비스 | 센서 자세 | 규약 일관성 | 1.3 |
| 의료·헬스케어 | 도구 자세의 보간·정합 | 정밀도 | 1.6 |
| 휴머노이드·범용 | 부유 기저 자세 | 특이점 없음 | 1.7 |
| 필드 | 비행·수중체 자세 | 특이점 없음 | 9.4 |
| 국방·안보 | 비행체 자세 추정 | 결정성 | 9.4 |
이 표는 이 책의 정리이며 장별 요구는 다르다.
1.5.8 관련 규격·프로토콜
| 문서 | 발행 | 무엇을 정하나 | 상세 장 |
|---|---|---|---|
| REP-103 | ROS(작성 2010-10-07) | 회전 표현 우선순위 첫째가 쿼터니언 | 1.3 |
geometry_msgs/msg/Quaternion | ROS 2 | 필드 x, y, z, w | 15.8 |
Eigen Quaternion | Eigen | 생성자 (w, x, y, z), 저장 [x, y, z, w] | — |
SciPy Rotation.from_quat | SciPy | 기본 (x, y, z, w), scalar_first 선택 | — |
| 수학 표기·기호표 | 이 책 | 해밀턴·스칼라 선행 | A.2 |
1.5.9 관련 규제·인증 요구와의 연결
직접 적용되는 규제는 없다. 쿼터니언의 성분 순서·부호 오류는 자세 기반 안전 기능(방위·기울기 한계)의 오작동으로 이어질 수 있으므로 인터페이스 규약의 문서화와 시험이 검증 항목이 된다. 안전 관련 소프트웨어의 개발 요구는 26.20이 다룬다.
1.5.10 한계·유의점·미해결
- 구현·문서의 범위. 세 소프트웨어의 서술은 소스·문서의 문장을 읽은 것이며 실행해 확인하지 않았다. 버전에 따라 바뀔 수 있다.
- JPL 규약. 해밀턴과의 정확한 차이는 원 문서로 확인하지 않았다
(확인 필요). - 시간 미분·적분. 각속도와 쿼터니언 미분의 관계, 적분의 오차는 다루지 않았다(1.7, 9.4).
- 정리의 출처. 교과서의 정리 번호는 확인하지 않았다
(확인 필요). 서지는 Crossref·arXiv로 확인했다.
1.5.11 체크포인트·연구 질문
체크포인트:
- 로드리게스 공식을 적고 $K^2=nn^\top-I$를 사용해 두 형태가 같음을 보일 수 있는가.
- 각을 acos 대신 atan2로 구해야 하는 이유와 $\theta=0$·$\theta=\pi$의 특이 경우를 설명할 수 있는가.
- 해밀턴 곱의 성질(비가환, 노름, 켤레)과 $v'=qvq^*$, 합성 순서를 쓸 수 있는가.
- $q$와 $-q$가 같은 회전임과 이중 덮개의 의미를 설명할 수 있는가.
- 행렬에서 쿼터니언을 구할 때 $\theta\approx\pi$에서 단순 방법이 실패하는 이유와 셰퍼드 방법의 원리를 설명할 수 있는가.
- SLERP와 NLERP의 차이(각속도)와 짧은 호 선택의 부호 처리를 설명할 수 있는가.
- ROS 메시·Eigen·SciPy·이 책의 쿼터니언 성분 순서를 말할 수 있는가.
연구 질문(47.12에 수록한다):
- 해밀턴 규약과 JPL 규약이 로봇·우주·그래픽 소프트웨어에서 어떻게 섞여 사용되며 변환 오류는 얼마나 자주 보고되는가.
- 쿼터니언 정규화의 최적 주기는 비용·정밀도 측면에서 응용별로 어떻게 달라지는가.
- 쿼터니언 보간의 대안(NLERP·가우시안 근사)이 로봇 궤적에서 SLERP와 얼마나 다른가.
1차 출처
- J. Shepperd, 「Quaternion from rotation matrix」, Journal of Guidance and Control 1(3), 1978, 223–224.
- K. Shoemake, 「Animating rotation with quaternion curves」, ACM SIGGRAPH Computer Graphics 19(3), 1985, 245–254.
- J. Solà, 「Quaternion kinematics for the error-state Kalman filter」, arXiv:1711.02508, 2017(초록만 읽음).
- ROS 2
common_interfaces의geometry_msgs/msg/Quaternion.msg; EigenEigen/src/Geometry/Quaternion.h(GitLablibeigen/eigen); SciPyscipy/spatial/transform/_rotation.py(조회 2026-11-03). - REP-103 「Standard Units of Measure and Coordinate Conventions」(1.3).
- K. M. Lynch, F. C. Park, 『Modern Robotics』, Cambridge University Press, 2017
(확인 필요: 장 번호). - J. B. Kuipers, 『Quaternions and Rotation Sequences』, Princeton University Press, 1999
(확인 필요: 장 번호). - 서지 확인 경로: Crossref REST API, arXiv API(조회 2026-11-03).
다음 장. 1.6는 동차변환과 $SE(3)$를 다룬다. 이 장까지의 회전 표현에 위치를 더한 강체 변환 $4\times4$ 행렬의 구조, 합성·역, 자유 벡터와 점의 변환 차이를 정리한다.