공학/동역학

[동역학] 오일러 각(Euler Angle)을 Python으로 구현해보기

슬기나무 2024. 7. 23. 22:46
반응형

이번 포스팅에서는 오일러 각(Euler Angle)을 Python으로 구현해보겠습니다.

 

 오일러 각(Euler Angle) 기본

기본적인 내용은 아래 글에서 다룬 바 있습니다.

 

2020.11.19 - [공학/동역학] - [동역학] 오일러 각(Euler angle)

 

[동역학] 오일러 각(Euler angle)

이번 포스팅에서는 오일러 각에 대해 알아보도록 합시다. 오일러 각(Euler angle) 오일러 각은 흔히 오일러 앵글이라고들 많이 부르는데, 3차원 공간에서 강체가 놓인 자세를 표현하기 위해 나타내

study2give.tistory.com

 

다시 한번 간단하게 설명하자면,

 

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을 구현해보았습니다.

반응형