Pinocchio의 WORLD와 LOCAL_WORLD_ALIGNED는 모두 월드 좌표축으로 속도를 표현하지만, 선속도를 표현하는 기준점이 다릅니다. WORLD는 월드 원점과 일치하는 점을, LOCAL_WORLD_ALIGNED는 움직이는 프레임의 원점을 기준으로 합니다. 그래서 회전 운동이 있으면 같은 좌표축을 쓰더라도 선형 성분 사이에 ω × p 항이 생깁니다.
공식 ReferenceFrame 정의는 두 선택을 분리합니다. 하나는 어느 점의 속도를 나타내는가이고, 다른 하나는 그 속도를 어느 기저, 즉 어느 좌표축에 투영하는가입니다. WORLD라는 이름만 보고 “말단 원점의 속도를 월드 축으로 표현한 값”이라고 읽으면 이 둘이 섞입니다.
기준점과 좌표축을 두 칸으로 나눠 읽는다
세 가지 표현을 표로 놓으면 차이가 분명합니다. 여기서 움직이는 프레임은 로봇 손목이나 도구에 붙인 좌표계처럼 이해할 수 있습니다.
| 표현 | 선속도의 기준점 P | 성분을 표현하는 좌표축 |
|---|---|---|
LOCAL |
움직이는 프레임의 원점 | 움직이는 프레임의 축 |
LOCAL_WORLD_ALIGNED |
움직이는 프레임의 원점 | 월드 축 |
WORLD |
월드 원점과 일치하는 점 | 월드 축 |
LOCAL과 LOCAL_WORLD_ALIGNED는 같은 점을 보면서 축만 바꿉니다. 반대로 WORLD와 LOCAL_WORLD_ALIGNED는 축을 유지하면서 기준점을 바꿉니다. 이 두 변환은 필요한 계산이 다릅니다.
여기서 WORLD의 선형 성분은 “월드 좌표계 자체가 움직이는 속도”를 뜻하지 않습니다. 움직이는 프레임의 공간 운동을 월드 원점 기준으로 표현한 성분입니다. 강체의 회전이 있으면 서로 떨어진 두 점의 선속도는 다르므로, 어디를 기준점으로 골랐는지가 선형 성분에 들어갑니다.
같은 점에서 축만 바꾸면 두 성분에 회전을 적용한다
공식 changeReferenceFrame 구현은 LOCAL→LOCAL_WORLD_ALIGNED에서 linear()와 angular()에 각각 placement.rotation()을 곱합니다. 반대 방향에서는 그 회전행렬의 전치를 곱합니다.
움직이는 프레임의 월드 자세를 (R, p)라고 적으면, 이 경우의 변환은 다음과 같습니다. v는 선형 성분, ω는 각 성분입니다.
v_LWA = R v_LOCAL
ω_LWA = R ω_LOCAL
v_LOCAL = Rᵀ v_LWA
ω_LOCAL = Rᵀ ω_LWA
두 표현이 같은 프레임 원점을 기준으로 하기 때문에 이 변환에는 위치 p가 들어가지 않습니다. 그 점의 운동을 회전한 좌표축으로 다시 적는 계산입니다. 손목이 월드 원점에서 멀리 떨어져 있어도, LOCAL과 LWA 사이의 기준점은 계속 같은 손목 원점입니다.
WORLD에서 LWA로 갈 때는 ω × p를 더한다
WORLD와 LWA는 모두 월드 축을 사용합니다. 공식 구현의 WORLD→LWA 분기는 각 성분을 그대로 복사하고, 선형 성분에는 각속도와 위치의 외적을 더합니다. 역방향은 같은 항을 뺍니다.
ω_LWA = ω_WORLD
v_LWA = v_WORLD + ω_WORLD × p
ω_WORLD = ω_LWA
v_WORLD = v_LWA - ω_LWA × p
여기서 p는 월드 원점에서 움직이는 프레임 원점으로 향하는 위치 벡터이며, 월드 축으로 표현합니다. 따라서 ω × p의 두 벡터도 같은 축에서 계산됩니다. p × ω로 순서를 바꾸면 부호가 반대가 되므로, 코드의 angular().cross(translation()) 순서를 그대로 읽는 것이 좋습니다.
가상의 좌표변환 계산으로 p=(1,0,0)m, ω_WORLD=(0,0,1)rad/s, v_WORLD=(0,0,0)m/s라고 하겠습니다. 월드 z축을 중심으로 회전하고, 대상 프레임 원점이 x 방향으로 1m 떨어진 조건입니다.
| 계산 | 값 |
|---|---|
ω × p |
(0,1,0)m/s |
v_LWA = v_WORLD + ω × p |
(0,1,0)m/s |
역변환 v_LWA - ω × p |
(0,0,0)m/s |
WORLD의 선형 성분이 0이어도 움직이는 프레임 원점은 y 방향으로 이동합니다. 이 원점이 회전 중심에서 떨어져 있기 때문입니다. 두 결과가 다른 것은 같은 속도를 잘못 계산해서가 아니라, 서로 다른 기준점의 선형 성분을 적었기 때문입니다.
각속도가 0이거나 두 원점이 일치해 p=0이면 이동항도 0입니다. 이 경우 WORLD와 LWA의 수치가 같아져서 구현상의 혼동이 눈에 띄지 않을 수 있습니다. 원점에서 떨어진 회전 사례를 함께 비교하면 기준점 선택의 차이가 드러납니다.
LOCAL과 WORLD 사이에는 회전과 기준점 이동이 함께 들어간다
공식 코드의 LOCAL→WORLD 분기는 placement.act(m_in)을, WORLD→LOCAL 분기는 placement.actInv(m_in)을 사용합니다. 앞의 두 경우를 연결하면 이 변환에는 축 회전과 기준점 이동이 모두 필요하다는 것을 이해할 수 있습니다. 회전행렬만 곱하는 LOCAL↔LWA 분기와 구별되는 이유입니다.
변환할 때는 placement가 어느 프레임의 자세인지도 해당 motion과 맞춰야 합니다. 손목에 대한 motion에 다른 도구 원점의 위치를 끼워 넣으면 외적 항이 다른 점을 향하게 됩니다. 데이터를 비교할 때 motion 값 옆에 표현 방식과 대상 프레임을 같이 두면 이런 불일치를 찾기 쉽습니다.
Jacobian을 읽을 때도 이 구분이 이어집니다. 각 열을 특정 관절 변화가 만드는 공간 속도 반응으로 보면, WORLD와 LWA 사이의 선형 행은 같은 기준점 이동의 영향을 받습니다. 말단 원점이 얼마나 이동하는지를 보고 싶은지, 월드 원점 기준의 공간 운동 성분을 쓰려는지 먼저 정해야 비교 대상이 맞습니다.
반면 자세 오차의 로그를 줄이기 위한 미분은 또 다른 계산입니다. Pinocchio CLIK와 Jlog6 설명은 그 잔차와 Jacobian의 연결을 다룹니다. 여기서의 ReferenceFrame 선택은 그에 앞서, 속도 또는 Jacobian의 공간 운동을 어느 점에서 어느 축으로 읽는가를 정하는 문제입니다.
2026년 10월 16일 확인한 Pinocchio 공식 master 문서와 changeReferenceFrame의 전체 분기를 기준으로 설명했습니다. 라이브러리 실행이나 실제 로봇 속도 측정은 수행하지 않았습니다.