이번 포스팅에서는 오일러 각(Euler Angle)을 Python으로 구현해보겠습니다.
오일러 각(Euler Angle) 기본
기본적인 내용은 아래 글에서 다룬 바 있습니다.
2020.11.19 - [공학/동역학] - [동역학] 오일러 각(Euler angle)
다시 한번 간단하게 설명하자면,
3차원 공간에서 강체가 놓인 자세를 표현하기 위해 나타내는 3개의 각도를 말하며,
3차원 공간에서는 각 축방향으로 회전하는 순서에 따라
같은 각도만큼을 움직이더라도 최종 자세가 달라지기 때문에
그 순서를 정하여 오일러 313(z-x-z), 오일러 321(z-y-x) 좌표 등으로 부릅니다.
Python으로 Euler Angle 구현하기
먼저 matrix 연산을 쉽게 할 수 있도록 numpy 라이브러리를 불러옵니다.
import numpy as np
numpy 라이브러리가 없는 경우,
command 창에서 pip install numpy 명령어를 통해 쉽게 설치할 수 있습니다.
그 다음 본격적으로 Euler angle을 이용해 matrix를 구현해보겠습니다.
각 축 방향 회전에 대한 matrix를 함수로 만들겠습니다.
def rotation_matrix_x(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[1, 0, 0],
[0, c, -s],
[0, s, c]])
def rotation_matrix_y(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, 0, s],
[0, 1, 0],
[-s, 0, c]])
def rotation_matrix_z(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, -s, 0],
[s, c, 0],
[0, 0, 1]])
그런 원하는 회전 순서에 따라 회전 matrix가 지정될 수 있도록
각 rotation matrix를 각 회전 축 방향에 매칭되도록 dictionary 정의하겠습니다.
rotation_matrices = {
'X': rotation_matrix_x,
'Y': rotation_matrix_y,
'Z': rotation_matrix_z
}
그 다음, 입력한 회전 순서에 따라 각 rotation matrix가 지정되어 곱해질 수 있도록
for loop를 활용하여 identity 행렬에 곱합니다.
I = np.eye(3)
for axis, angle in zip(order, angles):
I = np.dot(rotation_matrices[axis](angle), I)
위 코드를 함수화하면 아래와 같은 함수로 구성할 수 있습니다.
def euler_to_matrix(angles, order):
def rotation_matrix_x(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[1, 0, 0],
[0, c, -s],
[0, s, c]])
def rotation_matrix_y(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, 0, s],
[0, 1, 0],
[-s, 0, c]])
def rotation_matrix_z(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, -s, 0],
[s, c, 0],
[0, 0, 1]])
rotation_matrices = {
'X': rotation_matrix_x,
'Y': rotation_matrix_y,
'Z': rotation_matrix_z
}
I = np.eye(3)
for axis, angle in zip(order, angles):
I = np.dot(rotation_matrices[axis](angle), I)
return I
euler_to_matrix라는 함수의 input parameter는 회전각 3개와 회전 순서가 될 것이고,
zip() 함수에 의해 각 회전 순서와 회전 각도가 매칭되어
회전 matrix를 만들고, identity 행렬 I에 곱해져 최종적으로 행렬 I를 return합니다.
예시로 회전각도 45도, 30도, 60도와 회전순서 X-Y-Z축으로 하였을때의 코드는 아래와 같습니다.
import numpy as np
def euler_to_matrix(angles, order):
def rotation_matrix_x(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[1, 0, 0],
[0, c, -s],
[0, s, c]])
def rotation_matrix_y(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, 0, s],
[0, 1, 0],
[-s, 0, c]])
def rotation_matrix_z(angle):
c = np.cos(angle)
s = np.sin(angle)
return np.array([[c, -s, 0],
[s, c, 0],
[0, 0, 1]])
rotation_matrices = {
'X': rotation_matrix_x,
'Y': rotation_matrix_y,
'Z': rotation_matrix_z
}
I = np.eye(3)
for axis, angle in zip(order, angles):
I = np.dot(rotation_matrices[axis](angle), I)
return I
angles = (np.pi / 4, np.pi / 6, np.pi / 3)
order = 'XYZ'
rotation_matrix = euler_to_matrix(angles, order)
print(rotation_matrix)
잘 동작하네요.
사실 Chat GPT의 힘을 빌렸습니다.
이젠 직접 코딩하는 일이 사라질지도 모르겠네요.
여기까지 Python으로 Euler Angle을 구현해보았습니다.
'공학 > 동역학' 카테고리의 다른 글
[동역학] 평면에서의 운동방정식 (with MATLAB) (0) | 2022.01.25 |
---|---|
[동역학] 평면에서의 기구학(Planar kinematics) (0) | 2022.01.24 |
[동역학] 오일러 파라미터(Euler parameters) - (2) (0) | 2022.01.13 |
[동역학] 오일러 파라미터(Euler parameters) - (1) (1) | 2022.01.12 |
[동역학] 기구학적 구속(kinematic constraint) - Four-bar linkage (0) | 2021.11.25 |