[ODE] Intro Experiment

Chris Spencer chrisspen at gmail.com
Mon Jun 11 19:58:14 MST 2007


Hi,

I'm new to ODE and I've been using PyODE
(http://pyode.sourceforge.net/) to run some experiments to get a feel
for how the library works. However, I've been getting some very
strange results that don't make any sense to me.

The code below is a simple script based on the 2nd and 3rd PyODE
tutorials, and makes use of PyGame to visualize the results in 2D.
Basically, it creates 3 spheres, 1 box, and 1 plane, and then attempts
to simulate collision detection.

With gravity enabled, I'd expect the spheres and box to fall down onto
the plane, bounce, and eventually stop. However, they appear to fall
indefinitely, as if no collision detection is happening.

Also, even with gravity disabled and no explicit forces being applied,
the bodies move slightly. Does ODE simulate gravitational attraction
of masses, and would this be causing this slight movement?

If anyone could help point out what I'm doing wrong, I'd be very grateful.

Thanks,
Chris

import sys, os, random, time
import pygame
from pygame.locals import *
import ode

bodies = []

def create_box(world, space, position, density, lengths, color, geom=1):
    """Create a box body and its corresponding geom."""

    # Create body
    body = ode.Body(world)
    M = ode.Mass()
    M.setBox(density, *lengths)
    body.setMass(M)

    # Set parameters for drawing the body
    body.shape = "box"
    body.boxsize = lengths
    body.color = color

    # Create a box geom for collision detection
    if geom:
        geom = ode.GeomBox(space, lengths=body.boxsize)
        geom.setBody(body)

    body.setPosition(position)
    return body

def create_sphere(world, space, position, density, radius, color, geom=1):
    """Create a sphere body and its corresponding geom."""

    # Create body
    body = ode.Body(world)
    M = ode.Mass()
    M.setSphere(density, radius)
    body.setMass(M)

    # Set parameters for drawing the body
    body.shape = "sphere"
    body.radius = radius
    body.color = color

    # Create a box geom for collision detection
    if geom:
        geom = ode.GeomSphere(space, radius)
        geom.setBody(body)

    body.setPosition(position)
    return body

def add_body(body):
    """Drop an object into the scene."""

    global bodies
    bodies.append(body)

# Collision callback
def near_callback(args, geom1, geom2):
    """Callback function for the collide() method.

    This function checks if the given geoms do collide and
    creates contact joints if they do.
    """

    # Check if the objects do collide
    contacts = ode.collide(geom1, geom2)

    # Create contact joints
    world,contactgroup = args
    for c in contacts:
        c.setBounce(0.2)
        c.setMu(5000)
        j = ode.ContactJoint(world, contactgroup, c)
        j.attach(geom1.getBody(), geom2.getBody())

pixel_w,pixel_h = pixel_dimensions = 640,480
camera_w,camera_h = camera_position = pixel_w/2,pixel_h/2

def cameraOffset(x,y):
    return camera_w+x, camera_h+y

# Initialize pygame
pygame.init()

# Open a display
srf = pygame.display.set_mode(pixel_dimensions)

# Create a world object
world = ode.World()
#world.setGravity( (0,9.81,0) )
#world.setERP(0.8)
#world.setCFM(1E-5)

# Create a space object
space = ode.Space()

# Create a plane geom which prevent the objects from falling forever
floor = ode.GeomPlane(space, (0,-1,0), 0)

# A list with ODE bodies
bodies = []

# A joint group for the contact joints that are generated whenever
# two bodies collide
contactgroup = ode.JointGroup()

# Some variables used inside the simulation loop
fps = 50
dt = 1.0/fps
running = True
state = 0
counter = 0
objcount = 0
lasttime = time.time()

# create some objects

sphere1 = create_sphere(
    world=world,
    space=space,
    position=(-150,-100,0),
    density=2500,
    radius=50,
    color=(50,0,200)
)
add_body(sphere1)

sphere2 = create_sphere(
    world=world,
    space=space,
    position=(0,-100,0),
    density=2500,
    radius=50,
    color=(255,255,255)
)
add_body(sphere2)

sphere3 = create_sphere(
    world=world,
    space=space,
    position=(150,-100,0),
    density=2500,
    radius=50,
    color=(0,200,50)
)
add_body(sphere3)

box1 = create_box(
    world=world,
    space=space,
    position=(-75,0,0),
    density=500,
    lengths=(200,200,200),
    color=(50,0,200)
)
add_body(box1)
#box1.addForce( (0,-5000,0) )

# Simulation loop...
fps = 30
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))
    srf.fill((0,0,0))

    # Draw the bodies
    for body in bodies:
        if body.shape == 'sphere':
            x1,y1,z1 = body.getPosition()
            #color = (55,0,200)
            pygame.draw.circle(srf, body.color, cameraOffset(x1,y1),
body.radius, 1)
        elif body.shape == 'box':
            x1,y1,z1 = body.getPosition()
            x1,y1 = cameraOffset(x1,y1)
            lx,ly,lz = body.boxsize
            print 'drawing box',body.getPosition(),body.boxsize
            width = 0
            pygame.draw.rect(srf, body.color, Rect(x1,y1,lx,ly), width)
        else:
            print 'unknown body',body

    # Simulate
    n = 2
    for i in xrange(n):
        # Detect collisions and create contact joints
        space.collide((world,contactgroup), near_callback)

        # Simulation step
        world.step(dt/n)

        # Remove all contact joints
        contactgroup.empty()

    pygame.display.flip()

    # Next simulation step
    world.step(dt)

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


More information about the ODE mailing list