659.61 변환 행렬의 역변환 (Inverse)
1. 개요
로봇 시스템에서 좌표 프레임 간의 변환은 양방향으로 요구되는 경우가 빈번하다. 프레임 A에서 프레임 B로의 변환 {}^{A}T_{B}가 주어졌을 때, 그 역방향인 프레임 B에서 프레임 A로의 변환 {}^{B}T_{A}를 구하는 연산이 바로 역변환(inverse transformation)이다. 역변환은 TF2에서 변환 트리의 역방향 경로를 순회할 때 핵심적으로 사용되며, 센서 데이터의 좌표 변환, 역기구학(inverse kinematics) 계산, 그리고 상대 자세 추정 등 다양한 응용에서 필수적이다.
2. 동차 변환 행렬의 역변환
2.1 일반적 역행렬과의 차이
4 \times 4 동차 변환 행렬의 역행렬은 일반적인 행렬 역변환 알고리즘(예: 가우스 소거법, LU 분해)을 사용하여 계산할 수 있으나, 이는 계산 비용이 O(n^3)이며 수치적으로도 비효율적이다. 동차 변환 행렬은 SE(3) 군(Special Euclidean group)에 속하는 특수한 구조를 가지므로, 이 구조를 활용하면 훨씬 효율적이고 수치적으로 안정적인 역변환을 계산할 수 있다.
2.2 구조적 역변환 공식
동차 변환 행렬 T \in SE(3)가 다음과 같이 주어졌을 때,
T = {}^{A}T_{B} = \begin{bmatrix} R & \mathbf{t} \\ \mathbf{0}^{\top} & 1 \end{bmatrix}
여기서 R \in SO(3)는 회전 행렬이고, \mathbf{t} \in \mathbb{R}^{3}는 병진 벡터이다. 이 행렬의 역변환은 다음과 같이 해석적(analytic) 형태로 구할 수 있다.
T^{-1} = {}^{B}T_{A} = \begin{bmatrix} R^{\top} & -R^{\top}\mathbf{t} \\ \mathbf{0}^{\top} & 1 \end{bmatrix}
2.3 유도 과정
역변환 공식의 유도는 T \cdot T^{-1} = I_{4 \times 4}의 조건으로부터 출발한다.
\begin{bmatrix} R & \mathbf{t} \\ \mathbf{0}^{\top} & 1 \end{bmatrix} \begin{bmatrix} R^{\prime} & \mathbf{t}^{\prime} \\ \mathbf{0}^{\top} & 1 \end{bmatrix} = \begin{bmatrix} I_{3 \times 3} & \mathbf{0} \\ \mathbf{0}^{\top} & 1 \end{bmatrix}
블록 행렬 곱을 전개하면 다음 두 조건을 얻는다.
R \cdot R^{\prime} = I_{3 \times 3} \quad \Rightarrow \quad R^{\prime} = R^{-1} = R^{\top}
R \cdot \mathbf{t}^{\prime} + \mathbf{t} = \mathbf{0} \quad \Rightarrow \quad \mathbf{t}^{\prime} = -R^{-1}\mathbf{t} = -R^{\top}\mathbf{t}
첫 번째 조건에서 회전 행렬의 직교성(orthogonality), 즉 R^{-1} = R^{\top}이라는 성질이 활용된다. 이는 R \in SO(3)의 정의적 성질이며, 전치 연산만으로 역행렬을 구할 수 있어 계산 비용이 매우 낮다.
두 번째 조건에서는 역변환의 병진 성분이 단순히 -\mathbf{t}가 아니라, 원래 회전 행렬의 전치가 적용된 -R^{\top}\mathbf{t}임에 유의해야 한다. 이는 회전과 병진이 독립적이지 않고 상호 결합되어 있기 때문이다.
3. 역변환의 물리적 해석
3.1 회전의 역변환
회전 행렬의 역변환 R^{\top}는 원래 회전의 반대 방향 회전을 나타낸다. 프레임 A에서 프레임 B로 \theta만큼 회전한 변환의 역변환은, 프레임 B에서 프레임 A로 -\theta만큼 회전하는 것과 동치이다.
축-각(axis-angle) 표현으로 보면, 회전축 \hat{\mathbf{n}}을 중심으로 각도 \theta만큼 회전하는 변환 R(\hat{\mathbf{n}}, \theta)의 역변환은 R(\hat{\mathbf{n}}, -\theta) = R^{\top}(\hat{\mathbf{n}}, \theta)이다.
3.2 병진의 역변환
역변환의 병진 성분 -R^{\top}\mathbf{t}는 다음과 같이 해석된다. 원래 변환에서의 병진 벡터 \mathbf{t}는 프레임 A의 좌표계에서 표현된 프레임 B의 원점 위치이다. 역변환에서는 프레임 B의 좌표계에서 프레임 A의 원점 위치를 구해야 하므로, 먼저 R^{\top}를 적용하여 \mathbf{t}를 프레임 B의 좌표계로 변환한 후 부호를 반전시켜야 한다.
4. 역변환 계산의 효율성
4.1 계산 비용 비교
| 방법 | 곱셈 횟수 | 덧셈 횟수 | 추가 연산 |
|---|---|---|---|
| 일반 역행렬 (가우스 소거법) | ~64 | ~48 | 피벗 선택 |
| 일반 역행렬 (LU 분해) | ~43 | ~32 | 전진/후진 대입 |
| 구조적 역변환 (R^{\top}, -R^{\top}\mathbf{t}) | 9 | 9 | 전치 연산 |
구조적 역변환은 일반적인 4 \times 4 행렬 역변환에 비해 약 4~7배의 계산 효율성을 제공한다. 회전 행렬의 전치 R^{\top}는 메모리 내 원소의 인덱스 교환만으로 수행되므로 사실상 연산 비용이 0에 가깝다. 병진 역변환 -R^{\top}\mathbf{t}는 하나의 3 \times 3 행렬-벡터 곱(9회 곱셈, 6회 덧셈)과 부호 반전(3회 부정)으로 구성된다.
4.2 수치 안정성
구조적 역변환 방식은 수치 안정성(numerical stability) 측면에서도 우수하다. 일반 역행렬 알고리즘은 행렬의 조건수(condition number)에 민감하며, 부동소수점 오차가 누적될 수 있다. 반면, 직교 행렬의 전치는 정확한 역변환을 보장하므로 수치 오차의 누적이 최소화된다.
5. 쿼터니언 기반 역변환
5.1 쿼터니언의 역원
TF2 내부에서 회전은 쿼터니언(quaternion)으로 표현되므로, 역변환의 회전 성분은 쿼터니언의 역원(inverse)으로 계산된다. 단위 쿼터니언(unit quaternion) q = (w, x, y, z)에 대하여, 그 역원은 켤레 쿼터니언(conjugate quaternion)과 동일하다.
q^{-1} = q^{*} = (w, -x, -y, -z) \quad (\text{단, } \|q\| = 1)
일반적인 (비단위) 쿼터니언의 경우에는 다음과 같이 정규화가 필요하다.
q^{-1} = \frac{q^{*}}{\|q\|^{2}}
5.2 쿼터니언 기반 전체 역변환
쿼터니언 q와 병진 벡터 \mathbf{t}로 표현된 변환 (q, \mathbf{t})의 역변환은 다음과 같다.
q_{\text{inv}} = q^{*}
\mathbf{t}_{\text{inv}} = -R(q^{*}) \cdot \mathbf{t} = -(q^{*} \otimes \mathbf{t} \otimes q)
여기서 q^{*} \otimes \mathbf{t} \otimes q는 순수 쿼터니언(pure quaternion) (0, \mathbf{t})에 대한 쿼터니언 회전 연산이다.
6. TF2에서의 역변환 구현
6.1 lookupTransform()의 역방향 조회
TF2의 lookupTransform() 함수는 변환 트리에서 소스 프레임과 대상 프레임 사이의 경로를 탐색할 때, 필요에 따라 자동으로 역변환을 적용한다. 변환 트리에서 부모→자식 방향의 변환만이 발행(broadcast)되지만, lookupTransform()은 자식→부모 방향의 변환도 역변환을 통해 투명하게 제공한다.
예를 들어, 트리에서 map → odom → base_link의 변환이 발행되었을 때, lookupTransform("base_link", "map", time)을 호출하면 TF2는 다음을 수행한다.
{}^{\text{base\_link}}T_{\text{map}} = \left({}^{\text{map}}T_{\text{odom}} \cdot {}^{\text{odom}}T_{\text{base\_link}}\right)^{-1}
6.2 rclcpp에서의 역변환
C++ 환경에서 tf2::Transform 객체의 역변환은 inverse() 메서드를 통해 수행된다.
#include <tf2/LinearMath/Transform.h>
tf2::Transform T_A_B;
T_A_B.setOrigin(tf2::Vector3(1.0, 2.0, 3.0));
T_A_B.setRotation(tf2::Quaternion(0.0, 0.0, 0.707, 0.707));
// 역변환 계산
tf2::Transform T_B_A = T_A_B.inverse();
// 검증: T_A_B * T_B_A == Identity
tf2::Transform identity = T_A_B * T_B_A;
// identity.getOrigin() ≈ (0, 0, 0)
// identity.getRotation() ≈ (0, 0, 0, 1)
tf2::Transform::inverse()는 내부적으로 쿼터니언 기반의 구조적 역변환을 수행하므로, 일반적인 행렬 역변환에 비해 효율적이다.
6.3 rclpy에서의 역변환
Python 환경에서는 numpy를 사용하여 4 \times 4 동차 변환 행렬의 역변환을 구조적으로 계산할 수 있다.
import numpy as np
def inverse_transform(T):
"""SE(3) 변환 행렬의 구조적 역변환을 계산한다."""
R = T[:3, :3]
t = T[:3, 3]
T_inv = np.eye(4)
T_inv[:3, :3] = R.T # 회전의 역변환: 전치
T_inv[:3, 3] = -R.T @ t # 병진의 역변환
return T_inv
# 사용 예
T_A_B = np.array([
[0, -1, 0, 1.0],
[1, 0, 0, 2.0],
[0, 0, 1, 3.0],
[0, 0, 0, 1.0]
])
T_B_A = inverse_transform(T_A_B)
# 검증
identity = T_A_B @ T_B_A
# identity ≈ I_4x4
numpy.linalg.inv(T)를 사용하여 일반 역행렬을 계산하는 것도 가능하나, 구조적 역변환 함수를 사용하는 것이 계산 효율과 수치 안정성 모두에서 우수하다.
7. 역변환의 대수적 성질
7.1 합성의 역변환
두 변환의 합성에 대한 역변환은 각 변환의 역변환을 역순으로 합성한 것과 같다.
(T_1 \cdot T_2)^{-1} = T_2^{-1} \cdot T_1^{-1}
이 성질은 변환 트리에서 다수의 프레임을 경유하는 역방향 경로를 계산할 때 본질적으로 사용된다. 예를 들어, map → odom → base_link → sensor의 역변환은 다음과 같다.
({}^{\text{map}}T_{\text{sensor}})^{-1} = ({}^{\text{base\_link}}T_{\text{sensor}})^{-1} \cdot ({}^{\text{odom}}T_{\text{base\_link}})^{-1} \cdot ({}^{\text{map}}T_{\text{odom}})^{-1}
7.2 이중 역변환
역변환의 역변환은 원래의 변환과 동일하다.
(T^{-1})^{-1} = T
이는 SE(3) 군의 자기 역원성(involutory property)에 해당한다.
7.3 항등 변환의 역변환
항등 변환 I_{4 \times 4}는 스스로의 역변환이다.
I^{-1} = I
8. 역변환 관련 일반적 오류
8.1 병진 성분 오류
가장 빈번하게 발생하는 오류는 역변환의 병진 성분을 단순히 -\mathbf{t}로 계산하는 것이다. 올바른 역변환 병진 성분은 -R^{\top}\mathbf{t}이며, 회전 행렬의 전치가 반드시 적용되어야 한다. 이 오류는 회전이 없거나 무시할 수 있을 정도로 작을 때에는 겉으로 드러나지 않지만, 유의미한 회전이 포함된 경우 심각한 좌표 오차를 초래한다.
8.2 쿼터니언 정규화 누락
쿼터니언 기반 역변환에서 켤레 쿼터니언을 사용할 때, 입력 쿼터니언이 정규화되지 않은 경우(즉, \|q\| \neq 1) 역원이 올바르게 계산되지 않는다. 쿼터니언 연산 전에 항상 정규화를 수행하는 것이 안전하다.
8.3 동차 좌표의 마지막 행 오류
구조적 역변환을 수동으로 구현할 때, 결과 행렬의 마지막 행이 [0, 0, 0, 1]로 정확히 설정되어야 한다. 부동소수점 연산의 누적 오차로 인해 이 값이 미세하게 벗어나면, 이후의 합성 연산에서 오차가 증폭될 수 있다.
9. 응용 사례
9.1 상대 자세 계산
두 프레임의 세계 좌표계에서의 자세가 각각 {}^{W}T_{A}, {}^{W}T_{B}로 주어졌을 때, 프레임 A에서 본 프레임 B의 상대 자세는 역변환을 통해 계산된다.
{}^{A}T_{B} = ({}^{W}T_{A})^{-1} \cdot {}^{W}T_{B}
이 패턴은 다중 로봇 시스템에서 로봇 간 상대 위치 추정, 핸드-아이 캘리브레이션(hand-eye calibration), 그리고 루프 폐합(loop closure) 검출 등에 광범위하게 활용된다.
9.2 역기구학에서의 활용
매니퓰레이터의 역기구학 해석에서, 목표 말단 자세 {}^{0}T_{\text{goal}}과 현재 말단 자세 {}^{0}T_{\text{current}}의 오차를 계산할 때 역변환이 사용된다.
T_{\text{error}} = ({}^{0}T_{\text{current}})^{-1} \cdot {}^{0}T_{\text{goal}}
이 오차 행렬에서 회전 오차와 병진 오차를 추출하여 제어 입력을 산출한다.
9.3 센서 캘리브레이션
외부 센서(예: 고정 카메라)에서 관측한 로봇의 자세를 로봇 자체의 좌표계로 변환할 때, 센서의 설치 자세에 대한 역변환이 필요하다.
{}^{\text{robot}}T_{\text{object}} = ({}^{\text{camera}}T_{\text{robot}})^{-1} \cdot {}^{\text{camera}}T_{\text{object}}
10. 참고 문헌
- R. M. Murray, Z. Li, and S. S. Sastry, A Mathematical Introduction to Robotic Manipulation, CRC Press, 1994.
- B. Siciliano, L. Sciavicco, L. Villani, and G. Oriolo, Robotics: Modelling, Planning and Control, Springer, 2009.
- J. J. Craig, Introduction to Robotics: Mechanics and Control, 4th ed., Pearson, 2018.
- Open Robotics, “tf2 Documentation,” ROS 2 Documentation, https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Tf2.html
버전: 2026-03-26