I tried to execute "Tutorial 2" of Honke PyODE-sama site.
-- Click here for other tutorial implementation articles ↓ ・ "Tutorial 1" (Falling object, Matplotlib drawing added) ・ "Tutorial 3" (multibody contact, OpenGL)
--
The main subject is "Tutorial 2", The original content is -Construct a pendulum by connecting ** 3 objects ** with 2 hinges. ・ Angular velocity / torque is set for one hinge -Visualization is ** 2D drawing by Pygame **.
The angular velocity setting is commented out here. I also changed the screen size and coloring to output a GIF movie.
・ Win10 ・ Python 3.8.0 64bit ・ Pyo de 0.15.2 ・ Pygame 1.9.6 ・ Pillow 7
In my environment, the code on the PyODE site was executed as it was.
Pygame error message excerpt
pygame.draw.circle(srf, rgb, coord( xyz ), 20, 0)
TypeError: integer argument expected, got float
Action: In the routine called coord () at the beginning of the code I've enclosed each of the two returned values in int ().
Deal with pygame errors
def coord(x,y):
"Convert world coordinates to pixel coordinates."
return int(320+170*x), int(400-170*y)
When executed, a 2D video table by Pygame is displayed. Here, the file saved in GIF format is posted.
There are only three ODE objects. The line is just drawn. Black objects are fixed in space. (This object does not have to be.) Changes have been made to joint settings, drawing settings, etc.
There are some unnecessary parts left Since it is a small cord, I will put it on the whole.
Python3
# pyODE example 2: Connecting bodies with joints
## Modified: Window-sizing, jointing-condition, and others.
import pygame
from pygame.locals import *
import ode
W = 640
H = 640
CX = 320
CY = 320
S = 80.
def coord(xyz):
(x,y,z) = xyz
"Convert world coordinates to pixel coordinates."
return int( CX +S*x ), int( CY -S*y)
from PIL import Image, ImageDraw
def storeImage( srfc, images ):
if NI_MAX <= len(images):
return
s = srfc
buf = s.get_buffer()
im = Image.frombytes( "RGBA", s.get_size(), buf.raw )
B,G,R,A = im.split()
img = Image.merge("RGBA",(R,G,B,A))
images.append(img)
def gif(images):
print(' @ gif(), ')
savepath = 'tutorial_2.gif'
image0 = images[0]
image_end = images[-1]
for i in range( 5 ):
images.insert(0,image0)
for i in range( 5 ):
images.append(image_end)
images[0].save( savepath, save_all=True, append_images=images[1:], optimize=not False, duration=100, loop=0 )
print(' Exported : [%s]'%savepath)
NI_MAX = 10000
images=[]
# Initialize pygame
pygame.init()
# Open a display
srf = pygame.display.set_mode( (W,H) )
#
# Create a world object
world = ode.World()
world.setGravity((0,-9.81,0))
#
# Create two bodies
body0 = ode.Body(world)
M = ode.Mass()
M.setSphere(2500, 0.05)
body0.setMass(M)
body0.setPosition( (0,0,0) )
body1 = ode.Body(world)
M = ode.Mass()
M.setSphere(2500, 0.05)
body1.setMass(M)
body1.setPosition( (1,1,0) )
body2 = ode.Body(world)
M = ode.Mass()
M.setSphere(2500, 0.05)
body2.setMass(M)
body2.setPosition( (0,2,0) )
bodys = [body0,body1,body2]
# Connect body0 with the static environment
if True:
j0 = ode.BallJoint(world)
j0.attach(body1, ode.environment)
j0.setAnchor( body0.getPosition() )
if False:
j0 = ode.HingeJoint(world)
j0.attach(body1, ode.environment)
j0.setAnchor( body0.getPosition() )
j0.setAxis( (0,0,1) )
#j0.setParam(ode.ParamVel, 3)
#j0.setParam(ode.ParamFMax, 22)
# Connect body1 with body0
j01 = ode.BallJoint(world)
j01.attach(body0, body1)
j01.setAnchor( body0.getPosition() )
# Connect body2 with body1
j12 = ode.BallJoint(world)
j12.attach(body1, body2)
j12.setAnchor( body1.getPosition() )
joints = [j0, j01, j12]
RGBs = { body0:(63, 63, 63), body1:(127, 63, 63), body2:(63, 127, 63) }
####################################################
# Simulation loop...
fps = 50
dt = 1.0/fps
loopFlag = True
clk = pygame.time.Clock()
ti = -1
while loopFlag:
ti += 1
events = pygame.event.get()
for e in events:
if e.type==QUIT:
loopFlag=False
if e.type==KEYDOWN:
gif( images )
loopFlag=False
# Clear the screen
srf.fill((255,255,255))
for joint in joints:
if joint is j0:
continue
rgb = (127,127,127)
SIMPLE=False
if SIMPLE:
p0 = coord( joint.getBody(0).getPosition() )
p1 = coord( joint.getBody(1).getPosition() )
else: #### joint.attach(body, ode.environment)Correspondence to the anchor position in the case of, and color coding of the line
b_move = None
b0 = joint.getBody(0)
if b0:
if b0.getPosition() != joint.getAnchor():
b_move = b0
if None is b0:
p0 = coord( joint.getAnchor() )
if None is p0:
p0 = coord( body0.getPosition() )
else:
p0 = coord( b0.getPosition() )
b1 = joint.getBody(1)
if b1:
if b1.getPosition() != joint.getAnchor():
b_move = b1
if None is b1:
p1 = coord( joint.getAnchor() )
if None is p1:
p1 = coord( body0.getPosition() )
else:
p1 = coord( b1.getPosition() )
rgb = RGBs[b_move]
lw = 5
pygame.draw.line( srf, rgb, p0,p1, lw)
for body in bodys:
xyz = body.getPosition()
rgb = RGBs[body]
pygame.draw.circle(srf, rgb, coord( xyz ), 20, 0)
pygame.display.flip()
if ti % 4 == 0:
storeImage(srf,images)
# Next simulation step
world.step(dt)
# Try to keep the specified framerate
clk.tick(fps)
#if not loopFlag:
# gif( images )
Recommended Posts