Published on

고급컴퓨터그래픽스 | Forward Kinematics

들어가기 전, 기본적인 Transform matrix에 대해서는 다루지 않을 것이다. 이 부분에 대해서는 컴퓨터그래픽스 관련된 아무 책이나 괜찮으니 한 번 정독하고 읽는 것을 권함.

Affine Transform Matrix

백문이 불여일견! 아래 이미지를 가져와보았다.

Global frame/coordinate system 은 좌표가 고정되어 있다. Local은 그와 달리 object에 내재되어 있는 좌표계라고 보면 된다.

이런 좌표계를 계산할 때에는 동차좌표를 사용하는데, 3차원 공간에서 4차원 행렬로 계산하게 된다.

Affine transformation은 world coordinate 기준으로 변환하는데, translate, rotate, scale이 대표적이다.

위 행렬은 계산시 세로방향(열방향)으로 x,y,z축 그리고 origin point로 해석하면 된다.

p0=Mp1p^{0} = Mp^{1}

행렬은 다음과 같이 좌표가 계산되는데, p1p^{1} local frame에서 위치, p0p^{0}를 global frame 기준에서 위치로 해석한다.

연달아서 연산이 될 때는:

p0=M1M2p2p^{0} = M_1M_2 p^{2}

Interpretation of Composite Transformations

이제 연달아서 연산, 즉 합성 변환에 대해 좀 더 알아보자.

(3,0,0) 좌표예서 global 기준으로 회전(Rotate)한다고 하면 계산 순서는 다음과 같다.

M=TRM = T\cdot{R}

그래서 연산순서가 오른쪽에서 ⬅ 왼쪽으로 연산을 하면 Global transformation이 되는 것이고 왼쪽에서 ➡ 오른쪽으로 연산을 하면 Local transformation이 되는 것이다. 연산을 차근차근 묶어서? 계산하면 이해할 것임..!

Hierarchical Modeling

이 부분은 한정현 교수님의 컴퓨터그래픽스 Ch.13 캐릭터 애니메이션 파트를 보면 이해하기 쉽다..!

모션 데이터인 BVH 확장자 파일을 읽어볼 것인데, 읽기 전에 데이터의 구성을 살펴보자.

이런 hierachical하게 연결이 되어 있는데, 관절 기준으로 local frame으로 표현이 되어 있다. hierarchical한 구조이다보니, 상위 노드 정보에 영향을 받는다.

아 물론 연구실에서 나오는 데이터 별로 BVH 관절명이 각기 다르고 갯수도 다른 것은 알고 넘어가자(CMU, LAFAN, 등등..)

tree 구조에서 Hips를 제외한 frame은 local이고 모션 정보가 움직이는 것은 거의 대부분 hips 부분에서 global frame으로 계산되는 것이라고 생각하면 된다.

표를 해석하면 pp^{'}은 global, pp는 local 좌표(local frame)라고 해석하면 됨!.

위 강의 영상에서는 bone space(local) 에서 character space(global, Hip이 원점이라 가정) 이런 식으로 해석하는데, 계산을 하는 순서를 보면 오른쪽에서 ⬅ 왼쪽 에서 계산되기 때문에 왼쪽에 있는 변수가 global로 변환되었다..라고 생각하면 들어맞는 말이다.

Forward Kinematics

FK는 아래와 같이 구성한다

  • Joint: 관절
  • Link: Limb 부분
  • End effector: tree 구조에서 leaf node라 볼 수 있다.

Forward Kinematic의 반대 용어인 Inverse Kinematic도 있는데, Forward kinematics는 어떤 각도가 주어졌을 때 end-effector의 위치나 방향을 결정한다. Inverse는 그 반대.

J0J_0 좌표계를 월드 좌표에서 (0,0,0)라고 가정하자. 그러면 얼추 global과 거의 일치함 🤓.

연산순서가 왼쪽에서 오른쪽으로 연산하기 때문에 local transform이 되는 상황. 이게 순서가 헷깔릴 수 있는데, ㅠㅠ 그냥 영문법처럼 일차적으로 이해하면,

Hip쪽으로 갈 수록 global에 더 가깝고 멀 수록 local이다..라고 먼저 이해하면 연산 방향을 이해할 수 있음..! 강의와 같이 보면서 이해해보고 정 이해를 못하겠으면 댓글로 남겨주시면 숟가락 떠드리겠음 😘

Representations of 3D Orientation & Rotation

회전하는데 있어서 행렬로 계산하는 외 다양한 방법이 존재한다.

  • Euler angles (오일러 각도)
  • Rotation vector (회전 축 기준)
  • Rotation matrix (행렬로 계산!)
  • Unit quaternions

Euler angles

오일러 각도회전은 yaw pitch row 회전으로 익히 다들 알고 있을 것이다.

ZXZ 축 회전 등등 12가지 조합이 있는데, 이는 회전 변환된 축을 기준으로 회전을 한다라고 이해를 하면 된다.

하지만 이러한 방법은 gimbal lock이라고 degree loss라고 회전이 더 이상 이루어지지 않는 경우가 발생한다. 보통 연구에서는 웬만해서는 오일러 각도를 활용하지 않는 편이다.

Rotation vector

회전하는 각도와 회전하는 축

이 두 개의 정보만으로 구성되어 있다.

Rotation Matrix

이 부분은 컴퓨터그래픽스 회전 변환에서 잘 다뤄져 있어서 패스! 추가적으로 달자면

Rotation Matrix의 기하학적 속성으로 Orthogonal하다고 한다.

RT=R1R^{T} = R^{-1}

pf. Rv2=(Rv)T(Rv)=vTRTRv=vTv=v2||Rv||^2 = (Rv)^T(Rv)=v^TR^TRv=v^Tv=||v||^2

Quaternions

연구에서 가장 많이 쓰이는 회전 방법이다. 나도 내 연구에서도 이걸 활용하기도 했었고..

복소수 개념을 이용하는 회전 방식인데, 아래와 같이 활용된다.

Motion Capture Data

모션 데이터는 보통 모션 슈트를 입고 데이터를 추출하는데, BVH(BioVision Hierarchical data)는 크게

  1. Skeleton(static data)로 hierarchy로 표현하고
  2. Motion(time-varying data)로 구성되어 있다.

Skeleton에서는 보통 T pose라고 디폴트 포즈로 처음 표현된다.

내부 데이터는 보통

  • Root(Pelvis, Hip): rotation, translation으로 6DOF
  • Others: rotation으로 3DOF

여기서 DOF은 Degree of Freedom으로 축의 자유도라고 보면된다. 3차원이므로 축이 3개고 그에 대한 움직임의 자유도가 있다라고 해석하면 됨!

Skeleton

괄호 기준으로

  • OFFSET: parent 입장에서 joint가 떨어진 위치라고 보면된다.
  • CHANNELS: XYZ인 경우도 있고 다양하다. 순서가 굉장히 중요함!
  • JOINT: 다음 child 관절이 이름

Motion

  • frames: 총 프레임수
  • frame time: 1 프레임당 소요시간이다.

아래 숫자들은 한 행 기준으로 = 1 프레임이고 그 안에 있는 정보들은 관절 순서에 따라 관절의 각도를 XZY축 순서대로 풀어놓은 것이라고 보면된다. 데이터 상에서는 CHANNEL이라고 표시되어 있는 거 순서대로 해석하면 된다.

Wrapup & Conclusion

배웠던 것들을 토대로 Project 2를 수행했었다. 사실 이 뒤에 Motion Viewer를 지난 시간에 배운 Clean coding을 통해 이런 식으로 설계하면 된다! 라는 내용이 있는데, 난 솔직히 감흥이 없었고 딱히 안 와닿아서 ㅋㅋ ㅠ 내 식으로 그냥 만들었다. 굉장히 빡셌던 것으로 기억한다.

Project 2 - Motion Viewer

Python, Pygame, dearimgui 이 셋을 이용하여 만들었다. 사실 fairmotion이라고 facebook에서 원정담 박사님(현재는 교수님..)이 제작하신 걸로 아는데, 좋은 모션 라이브러리가 있다. 한 번 코드 뜯어서 읽어보는 것도 나쁘지 않음.

하지만.. 이 수업은 거의 scratch로 만드는 수업이라 읽는 거 부터 죽는 줄 알았다..ㅋㅋ 그렇다! fairmotion은 일절 쓰지 않았음!!

처음에는 많이 애먹었는데 dearimgui 쓰는게 젤 고역이었다. 지금은 앱이나 웹 코딩할 때 공부가 의외로 많이 도움이 되었다.

Pytest를 까먹고 프로젝트를 했는데, 솔직히 어떤 부분을 단위 테스트하라는 건지 몰랐다. 지금 와서야 고민해보는 거지만 관절 하나하나 값을 불러와 보고 테스트를 하는 걸 의미하는게 아닐까 싶음.(근데 내 기준에서 그렇게 따지면 개발하다가 세월아 내월아 할 듯..)

지금 도표를 다시보니 합성관계..는 아닌 것 같은데 그래도 최대한 영향 안가게 짜도록 노력한 것 같다. 웬만해서는 그냥.. fairmotion 쓰세요..네..

Authors