본문 바로가기

Robot/Robot Program - ROS

역기구학을 풀 때 도움을 줄 수 있는 Python 모듈 - ikpy -

로봇에서 로봇팔을 이야기하려고 하면 꼭 등장하는 것은 기구학(kinematics)입니다. 힘의 관계를 생각하지 않고 연결된 링크와 조인트만 가지고 좌표를 해석하는 분야인데요. 저도 이 기구학을 공부하는 학생이라면 누구나 보는 Craig의 책을 Python으로 공부한 관련 글들을 올린 적이 있습니다. 그러나 기구학에서 복잡한 분야인 역기구학은 참 어렵습니다. 물론 이것을 손으로 푸는 경우는 요즘 (공부를 위한게 아니라면) 잘 못 봤습니다. 다들 좋은 툴을 사용하는 것 같습니다. 특히 MATLAB을 많이들 사용하죠. 저는 오늘 Python으로 기구학을 역으로 풀려는 분들께 도움이 될 만한 모듈을 하나 소개하려고 합니다.

Phylliade라는 분(?)인데요. 한 때 제가 관심을 가졌던 Poppy 프로젝트에서 발견한 Inverse Kinematics 도구입니다.

여기서 ikpy의 github 페이지를 가면 설치와 소스코드를 볼 수 있습니다. 이제 간편히 설치가 되었다면 간단한 예제를 한 번 보도록 하죠. 한가지 아쉬운건 쉬운 예제가 없어서 제가 일단 얼기설기 만들어 보았습니다. URDF파일을 바로 읽을 수 있다는 큰 장점이 있지만, 오늘 소개할 투토리얼 수준의 소개는 직접 만들려고 합니다.

%matplotlib notebook
import matplotlib.pyplot as plt

from ikpy.chain import Chain
from ikpy.link import OriginLink, URDFLink
from ikpy import plot_utils
import numpy as np

먼저 설치후 필요 모듈을 import 하구요~

test_link = Chain(name='test_arm', links=[
    OriginLink(),
    URDFLink(
      name="first_link",
      translation_vector=[1, 1, 0],
      orientation=[0, 0, 0],
      rotation=[0, 0, 1],
    ),
    URDFLink(
      name="second_link",
      translation_vector=[1, 0, 0],
      orientation=[0, 0, 0],
      rotation=[0, 0, 1],
    )
])

그리고 frame은 세 개... 링크는 두 개인 심플한 모델을 시험용으로 잡았습니다. first_link의 translation_vector가 (1, 1)이어서 사선으로 한 번 올라가 있어 보일겁니다.

import matplotlib.pyplot
from mpl_toolkits.mplot3d import Axes3D
ax = matplotlib.pyplot.figure().add_subplot(111, projection='3d')

test_link.plot([0,30*np.pi/180,0], ax)
matplotlib.pyplot.show()

Forward Kinematics에선 간략하게 0도, 30도, 0도로 각 관절의 회전각도를 명령으로 주었습니다.

네.. 그래프로 보니 시험용 링크들이 잘 자리를 잡은 것 같습니다. 이제 역기구학을 슬쩍 테스트해봐야죠.

target_vector  = [ 1, 0, 0]
target_frame = np.eye(4)
target_frame[:3, 3] = target_vector
target_frame

이렇게 (1, 0, 0)을 끝단(end effector)의 목표 좌표로 보고 homogeneous tranform으로 표현합니다.

잘 되었네요~^^

print("The angles of each joints are : ", test_link.inverse_kinematics(target_frame))

슬쩍... inverse_kinematics를 풀면~

이렇게 각 관절이 가져야하는 각도를 계산해줍니다. 역기구학의 목적이죠?^^

real_frame  = test_link.forward_kinematics(test_link.inverse_kinematics(target_frame))
print("--> Computed position vector : %s" % real_frame[:3, 3])
print("--> original position vector : %s" % target_frame[:3, 3])

이걸.. 이렇게 내 의도와 맞는지 확인할 수 있습니다.

이 과정이 필요한 이유는 도착이 불가능한 지점이 명령으로 주어졌을때 아직 ikpy 모듈을 에러를 주지 못하기 때문인 것 같습니다. (이 부분은 좀 더 모듈을 공부해야할 것 같습니다. 정확하지 않습니다.)

ax = plot_utils.init_3d_figure()
test_link.plot(test_link.inverse_kinematics(target_frame), ax, target=target_vector)
plt.xlim(-1, 2)
plt.ylim(-1, 2)

그려야죠~

와우~ 제가 원한 (1, 0, 0)으로 기구의 끝단을 가져 놓도록 각 관절의 각도를 잘 잡았음을 알 수 있네요^^. 사용이 간편하지만.. 뭐 있어야할 기능은 다 있는 것 같습니다. 꽤 .. 멋지네요^^

반응형