2.2 좌표계와 4×4 동차 변환
2.2.1 pose의 의미부터 고정한다
3차원 pose는 위치(position)와 방향(orientation)의 쌍이다. 회전행렬 는 B 좌표계의 벡터를 A 좌표계에서 표현하도록 바꾸고, 변위 는 A 원점에서 본 B 원점 위치다. 두 값을 합치면 다음 동차 변환을 얻는다.
B 좌표계 점 를 동차 좌표 로 만들면 A 좌표계 표현은 다음과 같다.
변환 체인의 곱셈 순서는 오른쪽부터 적용된다.
여기서 W는 world, T는 table, O는 object 좌표계다. code/transforms.py의 Transform.compose()가 이 계산을 구현한다.
역변환은 일반 4×4 역행렬을 구하지 않고 회전행렬의 정규 직교 성질을 이용해 안정적으로 계산한다.
이해 도움말 — 변환 이름을 문장처럼 읽기
를 “B에서 A로 좌표를 표현하는 변환”이라고 읽는다. 점 오른쪽에 가장 가까운 변환부터 적용되므로 는 “Object의 점을 Table로, 다시 World로” 옮긴다. 첨자를 지워도 되는지 확인하려면 인접한 와 , 와 가 연결되는지 본다. 코드 변수도 world_from_table처럼 같은 방향으로 읽히게 만들면 역변환 실수를 줄일 수 있다.
그림 2-2. 점에 가까운 변환부터 적용하고, 인접 프레임 이름이 이어지는지 확인한다.
2.2.2 active rotation과 passive rotation
같은 행렬이 두 문맥에서 사용되기 때문에 혼동이 생긴다.
- Active rotation: 한 좌표계 안에서 물체 또는 벡터를 회전한다.
- Passive rotation: 같은 물리 벡터를 다른 좌표계 성분으로 다시 표현한다.
두 연산은 서로 전치 관계다. API 문서가 rotate vector, transform pose, express in frame 중 어떤 의미를 쓰는지 확인해야 한다. 코드 리뷰에서는 변수명을 world_from_camera, camera_from_object처럼 읽을 수 있게 정한다. T_wc처럼 짧은 이름만 쓰면 첨자의 방향을 팀원이 다르게 해석할 수 있다.
2.2.3 Euler angle의 convention
Euler angle은 roll, pitch, yaw 세 값으로 방향을 설명해 사람이 이해하기 쉽다. 그러나 다음 정보를 함께 기록하지 않으면 값만으로 회전을 재현할 수 없다.
- 축 순서: XYZ, ZYX 등
- intrinsic 회전인지 extrinsic 회전인지
- right-handed/left-handed 좌표계
- radian/degree 단위
이 장의 예제는 오른손 좌표계에서 고정 world 축에 대한 extrinsic Z-Y-X 합성, 즉 을 사용한다. pitch가 ±90° 근처가 되면 서로 다른 두 회전축이 정렬되어 자유도 하나를 구분할 수 없게 된다. 이것이 짐벌 락(gimbal lock)이다. 실제 물체가 자유도를 잃는 것이 아니라 Euler 파라미터화가 특이해지는 것이다.
2.2.4 quaternion과 순서 문제
단위 쿼터니언은 네 성분으로 3차원 회전을 표현한다.
쿼터니언은 Euler angle처럼 특정 자세에서 자유도를 잃지 않고, spherical linear interpolation(SLERP)을 사용할 수 있다. 그러나 다음 함정이 있다.
- 라이브러리마다
(x,y,z,w)와(w,x,y,z)순서가 다르다. - 와 는 같은 회전을 나타낸다.
- 수치 적분 후 norm이 1에서 벗어날 수 있어 정규화가 필요하다.
- 두 쿼터니언의 선형 보간은 일정 각속도 회전을 보장하지 않는다.
code/transforms.py는 외부 인터페이스를 (x,y,z,w)로 고정하고 입력을 정규화한다. 실제 Isaac Sim/ROS/OpenCV 경계에서는 각 API의 순서를 어댑터 함수 하나로 격리하는 것이 좋다.