4.2 Isaac Sim/USD, ROS 2, OpenCV 좌표 변환

4.2.1 축 이름을 추측하지 않는다

ROS REP 103의 로봇 몸체 관례는 x-forward, y-left, z-up이다. ROS optical frame은 z-forward, x-right, y-down을 사용하며 OpenCV의 카메라 좌표 관례와 맞는다. OpenUSD Stage는 up axis를 메타데이터로 갖고, 카메라와 자산의 로컬 축 의미는 schema와 importer 설정을 함께 확인해야 한다. Isaac Sim 장면이 흔히 Z-up이라고 해서 모든 USD 파일이 Z-up인 것은 아니다.

ROS body frame 벡터를 optical frame으로 바꾸는 한 가지 회전은 다음과 같다.

optRbody=[0−1000−1100] {}^{opt}R_{body}= \begin{bmatrix} 0&-1&0\\ 0&0&-1\\ 1&0&0 \end{bmatrix}

즉 xopt=−ybodyx_{opt}=-y_{body}, yopt=−zbodyy_{opt}=-z_{body}, zopt=xbodyz_{opt}=x_{body}다. 코드에서 축을 swap하는 세 줄로 숨기지 말고 이름 있는 행렬로 표현한다.

4.2.2 동차 변환의 방향

두 변환을 합성할 때 오른쪽 변환이 먼저 적용된다.

worldTcamera=worldTbase baseTtool toolTcamera {}^{world}T_{camera}={}^{world}T_{base}\,{}^{base}T_{tool}\,{}^{tool}T_{camera}

월드 점을 카메라 좌표로 만들려면 이 행렬을 그대로 곱하는 것이 아니라 역변환 cameraTworld=(worldTcamera)−1{}^{camera}T_{world}=({}^{world}T_{camera})^{-1}을 사용한다. 코드 리뷰에서 변수 이름 camera_pose만으로는 방향을 알 수 없으므로 T_world_camera처럼 source와 target을 모두 쓴다.

4.2.3 쿼터니언과 행렬

ROS geometry_msgs/Quaternion 필드는 (x, y, z, w)다. 다른 라이브러리는 (w, x, y, z)를 생성자 순서로 사용한다. 쿼터니언 qq와 −q-q는 같은 회전을 뜻하므로, 시계열 비교나 SLERP 전에 내적이 음수면 한쪽 부호를 뒤집어 최단 경로를 택한다.

회전 행렬은 다음 조건을 만족해야 한다.

RTR=I,det⁡(R)=+1 R^TR=I,\qquad \det(R)=+1

축 swap을 직접 작성한 뒤 이 조건을 확인하면 reflection을 회전으로 잘못 사용한 오류를 찾을 수 있다.

4.2.4 프레임 계약 표

프레임부모축 의미단위소유자
world없음Stage up-axis 명시m, radsimulator
base_linkworldx forward, y left, z upm, radlocalization/static
tool0base_linkURDF 정의m, radrobot state publisher
camera_linktool0카메라 기구 프레임m, radcalibration
camera_optical_framecamera_linkz forward, x right, y downm, radstatic transform

좌표 프레임 변환

그림 4-2. 기구 프레임과 optical frame을 분리하면 ROS·OpenCV 관례를 유지하면서 마운트 자세를 독립적으로 캘리브레이션할 수 있다.

이 장의 예제 코드·설정 파일 (12)

이 장의 자가 점검·가상실습