상세 컨텐츠

본문 제목

Hiking: 4주차 Joint Clamping 적용

Computer Graphics/Hiking

by Banjosh 2025. 4. 25. 14:12

본문

 

이번 주는 각 Joint의 회전 각도에 제한을 두는 기능을 구현하였다.

 

1. Quaternion -> Euler -> Quaternion 방법 시도

가장 먼저 시도했던 것은 Quaternion -> Euler -> Quaternion 방법이었다.

이 방법은 2가지로 시도할 수 있다.

 

    1) 현재 Quat -> Euler 변환 -> Euler에 dθ 및 Clamping 반영 -> 새로운 Quat으로 변환

    2) 현재 Quat -> Euler 변환 -> Euler에 dθ 반영후 Clamping 해야하는 정도를 측정 ->
        dθ에 Clamping을 적용한 Quat 생성 -> 새로운 Quat을 현재 Quat과 dθ와 Clamping을 적용한 Quat을 곱해 생성

 

위 경우는 이전 글에서 말했듯이 결국 둘 다 회전 순서 문제에 의해 제대로 작동하기 힘들다.

 

2. Swing-Twist 도입

Swing-Twist이란 특정 Quat을 하나의 축회전과 그 나머지 회전으로 분리하는 것이다. 이를 잘 보여주는 영상이 아래에 있다.

https://www.youtube.com/watch?v=8aQ9x8SQSuM

 

이 영상에서 보이는 것 처럼 하나의 축을 기준으로 Corn 모양의 swing 범위 회전이 가능하다. 물론 twist라는 축을 기준으로 회전하는 것도 가능하다.

 

이를 우리 IK에 적용하자면 축은 뼈 방향의 Y축 회전이라 하고 나머지 X, Z축회전을 Swing회전으로 만들 수 있다.

 

Swing-Twist은 되고 왜 Quaternion-Euler는 안되는가?

 Quaternion-Euler는 각도 기반으로 Quaternion을 Clamping해야하기 때문에 Clamping을 하는 경우 원하는 위치로 이동하기 어렵지만, Swing-Twist는 위치 기반으로 Quaternion을 Clamping할 수 있어 우리 IK에 훨씬 유용하다.

 

3. Swing을 x, z축 회전으로 나눠 Clamping하면 문제 발생

 처음 Swing-Twist를 접했을땐 Twist와 Swing을 여전히 x, y, z각도 기준으로 Clamping해보려 시도했다.

 

 Twist는 기존 y축과 일치하고 Swing과 독립적이므로 y축 회전 제한을 적용해도 문제가 없었다. 하지만 Swing을 x, z축 회전으로 분해한 후 Clamping을하고 다시 합치면 Euler 변환때와 같은 회전 순서 문제가 발생한다. 예를 들면 x -> z 순으로 회전을 적용하는데 x 회전을 Clamping하는 경우 z축도 영향을 받아버린다.

 

 따라서 위에서 말했듯이 이러한 문제를 겪지 않으려면 위치기반으로 Swing을 Clamping을 해야만 한다. 

 

4. 구면 다각형을 이용하여 위치 기반 Clamping

 위치를 기반으로 Clamping을 하기 위해서 구면다각형을 이용하였다.

관절의 활동 범위에 따른 구면 다각형을 간단하게 그려보면 원점을 중심으로 y축인 (0, 1, 0) 을 xMax, xMin, zMax, zMin에 따라 점 4개를 그렸을때 Swing의 범위가 다음과 같이 나올 수 있다.

 

그렇다면 이 구면 다각형으로 어떻게 클램핑을 하면 좋을까? 

A, B, C, E가 Clamping 범위를 나타내는 점이고, 현재 Quat을 Twist-Swing으로 분해했을때 나온 Swing을 y축 (0, 1, 0)에 적용한 결과가 F라고 해보자

우리는 위 F를 Clamping영역의 가장 가까운 방향으로 움직여 다음과 같이 만들고 싶다.

위 결과를 만들기 위해서는 다음 반복을 거쳐야한다.

 

  1. BC와 원점 O로 만들어지는 삼각형의 Normal 벡터를 N을 구한다. (Clamping 영역 밖을 향하는 normal)

  2. F와 N을 내적했을때 양수가 나오면 F는 Clamping 영역 밖에 존재한다 판단한다. (0이하면 영역 내부에 있다 판단)

  3. F에 -N벡터에 내적 크기만큼 스칼라곱을 해준 벡터를 빼준다. (BCO 평면으로 클램핑

  4. BCO 평면에 클램핑된 F가 OB와 OC 사이에 있는지 판단한다. (외적을 이용)

  5. 만약 클램핑된 F가 OB와 OC 밖에 있는경우 OB나 OC중 가까운쪽으로 F를 클램핑한다.

  6. 클램핑된 F를 후보에 추가한다.

  7. 다음은 CA와 O로 만들어지는 삼각형에 대해 위 과정을 반복한다.

 

위 과정을 모두 거친후 F가 Clamping 영역 내부에 있었다면 기존 F위치를 Swing의 결과로 사용하고, 그게 아니면 클램핑 후보 중 F에서 가장 각도변화가 적은 후보를 Swing의 결과로 사용한다.

 

5. 위치 기반으로 새로운 Swing 만들기

 구면 다각형으로 구한 Swing의 결과를 F라 하자. 이제 F를 찾았으니 y축 (0, 1, ,0)에 Swing을 적용한 결과가 F가 될 수 있게 Swing을 찾아야한다. 

 

y축과 F의 외적을 회전축으로 하는 쿼터니언으로 회전시키기 시도

 y축 점을 Y라 하고 Swing의 결과가 되어야하는 점을 F라 하자.

 

Y에서 F로 회전하는 가장 짧은 경로는 Y와 F를 외적하여 구한 회전축으로 회전시키는 것이다.

따라서 회전축은 외적으로 회전각은 내적으로 구하여 회전을 시키면 간단하게 Swing 쿼터니언을 구할 수 있다.

 

 하지만 이 경우 문제가 발생할 수 있다.

결론만 말하자면 우리가 생각하는 자연스러운 다리의 움직임이 나오지 않는다.

발목의 위치 자체는 정확히 옮겼지만 회전을 통한 front 방향이 바뀌게 된다.

 

아래 그림을 봤을때 Y가 발목이고 Y1이 발끝이라고 했을때 회전 결과가 F와 F1으로 나오고 이는 부자연스러운 다리움직임의 결과를 초래한다. Y1

 

 

실제 원하는 움직임은 아래와 같았기에 아래와 같은 회전이다.

 

x, z축회전으로 나누어 회전시키기 시도

 위 문제를 해결하기 위해 F를 zy평면에 포함시키는 z축 회전 각도를 구한뒤 그 F를 B로 만드는 x축 회전 각도를 구하여 B가 F가 될 수 있는 X축 회전 각도와 Z축 회전 각도를 구하였다. 

 

 아래 그림을 보면 F를 Y로 이동시키는 과정을 다음과 같이 진행하였다.

 

  1. F를 z축회전을 통해 zy평면 위에 올리기 (z축 회전 각도 구하기)

  2. A를 x축회전을 통해 Y에 올리기 (x축 회전 각도 구하기)

 

 

 그러나 이 방법도 결국 z축 회전에서 front 벡터가 바뀌는 방법이었고 아래 예시에서 이를 쉽게 볼 수 있다.

 

z축회전시 기존 발의 방향을 유지하기 위한 y축 회전 추가

사실 swing이란게 y축 회전이 없지만 우리가 원하는 결과(x축 회전에 의한 front 변경은 허용 But z축 회전에 의한 front 변경은 불허)를 도출하기 위해서는 z축회전에의한 발의 방향이 올바르게 보이기 위해 y축 회전을 추가해준 후 x, z축 회전을 적용해주면 된다.

 

6. Clamping에 의해 수렴하지 못하는 경우 발생

다음 상황을 보면 클램핑에 의해 수렴하지 못하는 경우를 볼 수 있다.

모든 관절이 현재 Target에 닿기 위해 Clamp 방향으로 움직이려다보니 목표에 도달하지 못하는 교착상태가 발생한다.

아직 수렴을 완벽히 구현하지 못해서 다양한 상황의 테스트를 해볼 수는 없지만, 이론적으로 IK를 위한 수렴방향을 Clamping이 없을 경우 가장 빠른 방향이라 생각하는 부분으로 가려다 발생하는 교착상태라 생각한다.

 

 

7. 사람이 발을 내려놓는 방법을 고안하여 문제 수렴 문제 해결

 사람이 발을 지면에 자연스럽게 올려놓는 방법을 생각해봤을때, 무릎을 앞으로 쭉 올리고 정강이는 뒤로 확접어 관절을 풀면서 위치시키는 것이 가장 자연스럽다 생각하였다.

 그 결과 무릎을 올리는 자연스러운 모습까지 구현이 될 수 있었다.

 

 

 

8. 현재 발생한 문제

 위의 사진을 보면 왼발의 지면에 빨간색 공이 있는것을 볼 수 있는데 저기가 Target이다. 사실 그럴싸해 보이지만 아직 target으로 수렴을 하지 못하고 있다. 해당 사진을 각도를 다르게 해서 보면 다음과 같다

 

x축 회전은 잘 적용되고 있지만 z축 회전이 수렴방향으로 가지 못하고 있는 것을 볼 수 있다.

디버깅을 해보니 Clamping은 잘 되고 있으나 Clamping 전의 결과부터 Target을 위해 z축이 제대로 이동하고 있지 않는 것을 확인하였다. 

 이 다음은 Clamping이 제대로 작동한다는 가정 하에 Jacobian IK 과정의 오류를 찾아볼 생각이다.
(위 문제 해결시 자연스럽게 수렴이 안 되는 문제도 해결될 수 있을지도)

 

 

현재 구현된 IK 결과

 

관련글 더보기