Hi, For my Thesis, I had reason to perform a number of identical experiments with simple variations: displacements in space or time. One set of experiments was using ODE:
I did a simple rigid body physics experiment using pyode: dropped a box near a stationary box onto a plane. I saved an image of the rest position of the box. The experiment is repeatable: the box lands in same place each time relative to the stationary one. Then I moved the whole experiment by (10,10,10) and repeated it. The box rest position was different. I also repeated the first experiment with the only difference being that I programmed it to wait 8000 seconds before dropping the box. Again the rest position was difference. What do the developers of ODE have to say as to the cause of the sensitivity of ODE to changes in position or time? Attached are images of the rest position in the first and second experiments and the code used to produce each. Also image of the time displaced version and its code. The hardware I was using was a VAIO notebook: intel 770 CPU with radeon x600 GPU. For python install I followed the steps from Miriam English: 1. installed python 2.4 python-2.4.3.msi http://www.python.org/ftp/python/2.4.3/ 2. edited autoexec.bat to add: SET PATH=%PATH%;C:\python SET PYTHON=C:\PYTHON\ 3. installed pyOpenGL PyOpenGL-2.0.2.01.py2.4-numpy23.exe http://pyopengl.sourceforge.net 4. Copied glut32.dll to the C:\python\Lib\site-packages\OpenGL directory. (This is a *crucial* step.) glut32.dll http://www.xmission.com/%7Enate/glut.html 5. installed OpenGLContext OpenGLContext-2.0.0c1.win32-py2.4.exe http://pyopengl.sourceforge.net/context/ (downloaded from http://pyopengl.sourceforge.net/ ) 6. installed PIL (python Image Library) PIL-1.1.5.win32-py2.4.exe http://www.pythonware.com/products/pil/ 7. installed pyODE PyODE-1.1.0.win32-py2.4.exe http://pyode.sourceforge.net/ Now I can double-click on the tutorial3.py from http://pyode.sourceforge.net/ and it simply runs! thanks, chris
# pyODE example 3: Collision detection # origin # Originally by Matthias Baas. # Updated by Pierre Gay to work without pygame or cgkit. import sys, os, random, time from math import * from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * import ode # geometric utility functions def scalp (vec, scal): vec[0] *= scal vec[1] *= scal vec[2] *= scal def length (vec): return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2) # prepare_GL def prepare_GL(): """Prepare drawing. """ # Viewport glViewport(0,0,640,480) # Initialize glClearColor(0.8,0.8,0.9,0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glEnable(GL_LIGHTING) glEnable(GL_NORMALIZE) glShadeModel(GL_FLAT) # Projection glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective (45,1.3333,0.2,20) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Light source glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) glEnable(GL_LIGHT0) # View transformation gluLookAt (2.4, 3.6, 4.8, 0.5, 0.5, 0, 0, 1, 0) # draw_body def draw_body(body): """Draw an ODE body. """ x,y,z = body.getPosition() R = body.getRotation() #rot = [R[0], R[3], R[6], 0., # R[1], R[4], R[7], 0., # R[2], R[5], R[8], 0., # x, y, z, 1.0] rot = [1, 0.0, 0.0, 0.0, 0.0, 1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0] glPushMatrix() glMultMatrixd(rot) if body.shape=="box": sx,sy,sz = body.boxsize glScale(sx, sy, sz) glutSolidCube(1) glPopMatrix() # create_box def create_box(world, space, density, lx, ly, lz): """Create a box body and its corresponding geom.""" # Create body body = ode.Body(world) M = ode.Mass() M.setBox(density, lx, ly, lz) body.setMass(M) # Set parameters for drawing the body body.shape = "box" body.boxsize = (lx, ly, lz) # Create a box geom for collision detection geom = ode.GeomBox(space, lengths=body.boxsize) geom.setBody(body) return body # create box object def create_object(posx, posy, posz): """create one box at a given position.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # drop_object def drop_object(posx, posy, posz): """Drop an object into the scene.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # 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()) ###################################################################### # Initialize Glut glutInit ([]) # Open a window glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE) x = 0 y = 0 width = 640 height = 480 glutInitWindowPosition (x, y); glutInitWindowSize (width, height); glutCreateWindow ("(0,0,0)") # 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() # keyboard callback def _keyfunc (c, x, y): sys.exit (0) glutKeyboardFunc (_keyfunc) # draw callback def _drawfunc (): # Draw the scene prepare_GL() for b in bodies: draw_body(b) glutSwapBuffers () glutDisplayFunc (_drawfunc) # idle callback def _idlefunc (): global counter, state, lasttime t = dt - (time.time() - lasttime) if (t > 0): time.sleep(t) counter += 1 if state==0: create_object(0.0,0.5,0.0) state = 1 if state==1: if counter==20: drop_object(1.29,5.0,0.0) state = 2 # if objcount==30: # state=1 # counter=0 # State 1: Explosion and pulling back the objects #elif state==1: # if counter==100: # explosion() # if counter>300: # pull() # if counter==500: # counter=20 glutPostRedisplay () # Simulate n = 2 for i in range(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() lasttime = time.time() glutIdleFunc (_idlefunc) glutMainLoop ()
# pyODE example 3: Collision detection # 1000 # Originally by Matthias Baas. # Updated by Pierre Gay to work without pygame or cgkit. import sys, os, random, time from math import * from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * import ode # geometric utility functions def scalp (vec, scal): vec[0] *= scal vec[1] *= scal vec[2] *= scal def length (vec): return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2) # prepare_GL def prepare_GL(): """Prepare drawing. """ # Viewport glViewport(0,0,640,480) # Initialize glClearColor(0.8,0.8,0.9,0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glEnable(GL_LIGHTING) glEnable(GL_NORMALIZE) glShadeModel(GL_FLAT) # Projection glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective (45,1.3333,0.2,20) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Light source glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) glEnable(GL_LIGHT0) # View transformation gluLookAt (12.4, 13.6, 14.8, 10.5, 10.5, 10, 0, 1, 0) # draw_body def draw_body(body): """Draw an ODE body. """ x,y,z = body.getPosition() R = body.getRotation() #rot = [R[0], R[3], R[6], 0., # R[1], R[4], R[7], 0., # R[2], R[5], R[8], 0., # x, y, z, 1.0] rot = [1, 0.0, 0.0, 0.0, 0.0, 1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0] glPushMatrix() glMultMatrixd(rot) if body.shape=="box": sx,sy,sz = body.boxsize glScale(sx, sy, sz) glutSolidCube(1) glPopMatrix() # create_box def create_box(world, space, density, lx, ly, lz): """Create a box body and its corresponding geom.""" # Create body body = ode.Body(world) M = ode.Mass() M.setBox(density, lx, ly, lz) body.setMass(M) # Set parameters for drawing the body body.shape = "box" body.boxsize = (lx, ly, lz) # Create a box geom for collision detection geom = ode.GeomBox(space, lengths=body.boxsize) geom.setBody(body) return body # create box object def create_object(posx, posy, posz): """create one box at a given position.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # drop_object def drop_object(posx, posy, posz): """Drop an object into the scene.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # 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()) ###################################################################### # Initialize Glut glutInit ([]) # Open a window glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE) x = 0 y = 0 width = 640 height = 480 glutInitWindowPosition (x, y); glutInitWindowSize (width, height); glutCreateWindow ("(10,10,10)") # 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), 10) # 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() # keyboard callback def _keyfunc (c, x, y): sys.exit (0) glutKeyboardFunc (_keyfunc) # draw callback def _drawfunc (): # Draw the scene prepare_GL() for b in bodies: draw_body(b) glutSwapBuffers () glutDisplayFunc (_drawfunc) # idle callback def _idlefunc (): global counter, state, lasttime t = dt - (time.time() - lasttime) if (t > 0): time.sleep(t) counter += 1 if state==0: create_object(10.0,10.5,10.0) state = 1 if state==1: if counter==20: drop_object(11.29,15.0,10.0) state = 2 # if objcount==30: # state=1 # counter=0 # State 1: Explosion and pulling back the objects #elif state==1: # if counter==100: # explosion() # if counter>300: # pull() # if counter==500: # counter=20 glutPostRedisplay () # Simulate n = 2 for i in range(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() lasttime = time.time() glutIdleFunc (_idlefunc) glutMainLoop ()
# pyODE example 3: Collision detection # origin # Originally by Matthias Baas. # Updated by Pierre Gay to work without pygame or cgkit. import sys, os, random, time from math import * from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * import ode # geometric utility functions def scalp (vec, scal): vec[0] *= scal vec[1] *= scal vec[2] *= scal def length (vec): return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2) # prepare_GL def prepare_GL(): """Prepare drawing. """ # Viewport glViewport(0,0,640,480) # Initialize glClearColor(0.8,0.8,0.9,0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) glEnable(GL_LIGHTING) glEnable(GL_NORMALIZE) glShadeModel(GL_FLAT) # Projection glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective (45,1.3333,0.2,20) # Initialize ModelView matrix glMatrixMode(GL_MODELVIEW) glLoadIdentity() # Light source glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) glEnable(GL_LIGHT0) # View transformation gluLookAt (2.4, 3.6, 4.8, 0.5, 0.5, 0, 0, 1, 0) # draw_body def draw_body(body): """Draw an ODE body. """ x,y,z = body.getPosition() R = body.getRotation() #rot = [R[0], R[3], R[6], 0., # R[1], R[4], R[7], 0., # R[2], R[5], R[8], 0., # x, y, z, 1.0] rot = [1, 0.0, 0.0, 0.0, 0.0, 1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0] glPushMatrix() glMultMatrixd(rot) if body.shape=="box": sx,sy,sz = body.boxsize glScale(sx, sy, sz) glutSolidCube(1) glPopMatrix() # create_box def create_box(world, space, density, lx, ly, lz): """Create a box body and its corresponding geom.""" # Create body body = ode.Body(world) M = ode.Mass() M.setBox(density, lx, ly, lz) body.setMass(M) # Set parameters for drawing the body body.shape = "box" body.boxsize = (lx, ly, lz) # Create a box geom for collision detection geom = ode.GeomBox(space, lengths=body.boxsize) geom.setBody(body) return body # create box object def create_object(posx, posy, posz): """create one box at a given position.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # drop_object def drop_object(posx, posy, posz): """Drop an object into the scene.""" global bodies, counter, objcount body = create_box(world, space, 1000, 1.0,1.0,1.0) body.setPosition((posx, posy, posz)) bodies.append(body) #counter=0 objcount+=1 # 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()) ###################################################################### # Initialize Glut glutInit ([]) # Open a window glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE) x = 0 y = 0 width = 640 height = 480 glutInitWindowPosition (x, y); glutInitWindowSize (width, height); glutCreateWindow ("(0,0,0), startTime=8000") # 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() # keyboard callback def _keyfunc (c, x, y): sys.exit (0) glutKeyboardFunc (_keyfunc) # draw callback def _drawfunc (): # Draw the scene prepare_GL() for b in bodies: draw_body(b) glutSwapBuffers () glutDisplayFunc (_drawfunc) # idle callback def _idlefunc (): global counter, state, lasttime t = dt - (time.time() - lasttime) if (t > 0): time.sleep(t) counter += 1 if state==0: create_object(0.0,0.5,0.0) state = 1 if state==1: #20000 is different #10000 is different a little less #7000 no diff from 0 time #5000 no diff from 0 time if counter==8000: drop_object(1.29,5.0,0.0) state = 2 # if objcount==30: # state=1 # counter=0 # State 1: Explosion and pulling back the objects #elif state==1: # if counter==100: # explosion() # if counter>300: # pull() # if counter==500: # counter=20 glutPostRedisplay () # Simulate n = 2 for i in range(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() lasttime = time.time() glutIdleFunc (_idlefunc) glutMainLoop ()