본문 바로가기

Software/Python

Python에서 Open Dynamics Engine을 이용한 Two Link Pendulum 시뮬레이션

Python에서 얼머전에 Runge Kutta를 직접 코드로 구현하고 pygame 모듈을 이용해서 시뮬레이션을 애니메이션처럼 보이는 예제를 한번 다루었는데요[바로가기] 이리 저리 돌아다니다 보니 좀 더 멋진 아이들이 많이 보이더군요. 그 중에서 눈에 띄는 건 바로 Open Dynamics Engine이었습니다. 제가 세팅한 Python은 3.4버젼이고 사용환경운 윈도우인데요. 그러다보니 [바로가기]에서 윈도우 실행활일 형태로 배포되는 모듈을 많이 받게 됩니다. 그런데 이 사이트에서



라는 모듈을 발견한거죠. 응? ODE? Open Dynamics Engine이라~~ 흠.. Rigid Body를 시뮬레이션할 수 있다고?? ... 라고 생각하며 시작되었습니다. ㅎㅎ^^




[바로가기]가 공식 사이트입니다. 근데 여기는 C++라이브러리를 제공하더군요. 그냥 위의 처음 제가 이야기한 사이트에서 받아야겠습니다. 메뉴얼은 [바로가기]에 있습니다. 그리고 pyODE에서 제공되는 에제를 하나 보면서 ODE모듈을 소개할께용^^


# pyODE example 2: Connecting bodies with joints

import pygame
from pygame.locals import *
import ode

def coord(x,y):
    "Convert world coordinates to pixel coordinates."
    return 320+170*x, 400-170*y

# Initialize pygame
pygame.init()

# Open a display
srf = pygame.display.set_mode((640,480))

# Create a world object
world = ode.World()
world.setGravity((0,-9.81,0))

# Create two bodies
body1 = ode.Body(world)
M = ode.Mass()
M.setSphere(2500, 0.05)
body1.setMass(M)
body1.setPosition((1,2,0))

body2 = ode.Body(world)
M = ode.Mass()
M.setSphere(2500, 0.05)
body2.setMass(M)
body2.setPosition((2,2,0))

# Connect body1 with the static environment
j1 = ode.BallJoint(world)
j1.attach(body1, ode.environment)
j1.setAnchor( (0,2,0) )

# Connect body2 with body1
j2 = ode.BallJoint(world)
j2.attach(body1, body2)
j2.setAnchor( (1,2,0) )

# Simulation loop...

fps = 50
dt = 1.0/fps
loopFlag = True
clk = pygame.time.Clock()

while loopFlag:
    events = pygame.event.get()
    for e in events:
        if e.type==QUIT:
            loopFlag=False
        if e.type==KEYDOWN:
            loopFlag=False

    # Clear the screen
    srf.fill((255,255,255))

    # Draw the two bodies
    x1,y1,z1 = body1.getPosition()
    x2,y2,z2 = body2.getPosition()
    pygame.draw.circle(srf, (55,0,200), (int(coord(x1,y1)[0]), int(coord(x1,y1)[1])), 20, 0)
    pygame.draw.line(srf, (55,0,200), coord(0,2), coord(x1,y1), 2)
    pygame.draw.circle(srf, (55,0,200), (int(coord(x2,y2)[0]), int(coord(x2,y2)[1])), 20, 0)
    pygame.draw.line(srf, (55,0,200), coord(x1,y1), coord(x2,y2), 2)

    pygame.display.flip()

    # Next simulation step
    world.step(dt)

    # Try to keep the specified framerate    
    clk.tick(fps)


일단 간단하죠? 흠... 딴 이야기인데 Processing을 제가 취미처럼 사용하는 이유중 하나가 간편한 그래픽 표현인데, 살짝 pygame이라는 모듈도 그런것 같아요. 

뭐 아무튼.. 일단 살짝 예제를 보면... 일단 기구학 적인 좌표를 화면에 표현되는 좌표와 매칭시켜줘야 하니까, def coord라는 함수를 정의해 둔 것이구요. 

22번행 body1은 구 모양으로 정의되고 위치도 정해졌네요. 1,2,0으로 말이죠. 그리고 28번행 body2는 동일하지만, 위치가 2,2,0으로 정의되었네요. 

이제 body1을 볼조인트로 0,2,0에 연결해두는 것이 35번행이구요. body1과 body2를 볼조인트로 1,2,0지점에서 연결해두는 것이 39번행이네요.

흠.. 여기까지 하니까 딱 Two Link Pendulum이 되네요^^. 그리고 19번행에서 중력 방향을 잡아주었네요. 

이제 pygame으로 그림을 그리는 것은 정말 간단합니다. ODE한테 두 질량체 body1, body2의 좌표를 물어서 갱신하면 되거든요. 그게 63, 64번행입니다. 그렇게 갱신된 좌표를 그리는 거지요.



위 그림이 실행했을때구요. 살짝 실행된 동영상을 보시면...



너무 쉽죠??? Two Link를 이전에 제가 한데로 Runge Kutta로 하면 시간도 꽤 걸리지만, 중요한건 틀린지 아닌지 불안하기도(^^) 하고 말이죠. ㅋㅋㅋㅋ. 아무튼 또 이렇게 데리고 놀기 괜찮은 아이하나 소개합니다.^^


반응형