Playing around with the OpenDynamicsEngine (ODE) I found it a bit confusing and difficult to cope with both, the physical simulation as well as with the visualization. All relevant data is already included in the physical part, so why cope with both?

Under sourceforge.net/projects/ode-viz you can download a simple wraper for python, that uses pyvtk to visualize a simulation, just pass the “world” and the “space” to ODE_Visualization and let it handle the rest …


The easiest way to install this library is by using pip:

$ pip install odeViz

all dependencies should be installed automatically. For manually installation see section Download …

Basic architecture

You can skip this part, if you just want a quick visualization, but if you want to extend your visualization with further VTK-functionalities … have a look on it.

The used classes can be devided into two parts, a visualization-part and a object-part, as depicted in the uml diagram below (created with umbrello).

VTK_Visualization and the inherited methods are used to handle and define window specifics, like size, title, background-color, etc. ODE-Visualization takes in as parameters, the world, the space, and is responsible to run the simulation. During initialization, the space is scanned for primitive objects, such as boxes, spheres, etc. ODE-Visualization creates a VTK object (encapsulated within a ODE_Object) for every primitive entity. These objects can be seen as glue-objects, each one is bound to a single object/geometry within the space, knowing its position, rotation, and size within the virtual space. By calling update(), the vtk-objects are simply set onto the same position/orientation in the visualization, as the ode-object in the simulation. ODE-Visualization only responsible to maintain a list of ODE_Object and to update the vtk-simulation in a appropriate manner.

VTK_Visualization is furthermore an ancestor of threading.Thread, and thus responsible to start and run the thread for the simulation. You simply have to overwrite method execute with all required stuff, as explained in more detail within the examples…


From XML to VTK

This example is included into the project, which can be simply executed by calling:

python test.py

Within this example, our world an all included objects are defined within a single XML file. Simple capsules on different heights and a plane on the ground. By using xode, it is possible to read in this xml-file and to retrieve all required data for the simulation.

import ode
import xode.parser
import libxml2
import odeViz.ode_visualization as ode_viz

class my_sim(ode_viz.ODE_Visualization):
    def __init__(self, world, space, dt):
        ode_viz.ODE_Visualization.__init__(self, world, space, dt)

        self.contactgroup = ode.JointGroup()

    def execute(self, caller, event):
        self.space[0].collide((self.world,self.contactgroup), self.near_callback)
        self.update() # do not forget ...

    def near_callback(self, args, geom1, geom2):
        # Check if the objects do collide
        contacts = ode.collide(geom1, geom2)

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

# parsing the xml file
xml = libxml2.parseFile("test.xml")
p = xode.parser.Parser()
root = p.parseString(str(xml))
world = root.namedChild('world').getODEObject()
space = root.namedChild('space').getODEObject()

# setting some parameters
world.setGravity( (-0.001,-9.81,-0.001) )

# pass all requred parameters world, space, and time step dt
viz = my_sim(world, [space], 0.005)

# start the simulation

Pass the space and the world, as presented in line 44 to the visualization. Within the constructor it is possible to change the camera parameters, window properties, etc. Have a now a look to the execute method, this is the method which is called from within the working thread. It is everything that is required for the simulation… It check if there occurred some collisions, and calculates the the next step of the simulation, with delta time dt, which was also defined during the initialization.

Watch the resulting simulation …


Changing Tutorial 3

But if you want to add or remove new objects during runtime or change their colors, etc., this has to be done manually. To explain this, I chose the third step of the pyode tutorial from the project site: pyode.sourceforge.net/tutorials/tutorial3.html

Take a look at their example then onto the changed one, presented below:

# pyODE example 3: Collision detection

import random, time
import ode
from math import *
import odeViz.ode_visualization as ode_viz

# 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)

# 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)

    # 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)

    return body, geom

# drop_object
def drop_object():
    """Drop an object into the scene."""
    global viz
    global bodies, geom, counter, objcount

    body, geom = create_box(world, space, 1000, 1.0,0.2,0.2)
    body.setPosition( (random.gauss(0,0.1),2,random.gauss(0,0.1)) )
    theta = random.uniform(0,2*pi)
    ct = cos (theta)
    st = sin (theta)
    body.setRotation([ct, 0., -st, 0., 1., 0., st, 0., ct])



# explosion
def explosion():
    """Simulate an explosion.

    Every object is pushed away from the origin.
    The force is dependent on the objects distance from the origin.
    global bodies

    for b in bodies:
        l=b.getPosition ()
        d = length (l)
        a = max(0, 40000*(1.0-0.2*d*d))
        l = [l[0] / 4, l[1], l[2] /4]
        scalp (l, a / length (l))

# pull
def pull():
    """Pull the objects back to the origin.

    Every object will be pulled back to the origin.
    Every couple of frames there'll be a thrust upwards so that
    the objects won't stick to the ground all the time.
    global bodies, counter

    for b in bodies:
        l=list (b.getPosition ())
        scalp (l, -1000 / length (l))
        if counter%60==0:

# 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:
        j = ode.ContactJoint(world, contactgroup, c)
        j.attach(geom1.getBody(), geom2.getBody())


print "start"

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

# 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 = []

# The geoms for each of the bodies
geoms = []

# 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 = 75
dt = 1.0/fps
running = True
state = 0
counter = 0
objcount = 0
lasttime = time.time()

# idle callback
def _idlefunc ():
    global counter, state, lasttime

    t = dt - (time.time() - lasttime)
    if (t > 0):

    counter += 1

    if state==0:
        if counter==20:
        if objcount==30:
    # State 1: Explosion and pulling back the objects
    elif state==1:
        if counter==100:
        if counter>300:
        if counter==500:

    # Simulate
    n = 2

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

        # Simulation step

        # Remove all contact joints

    lasttime = time.time()

class my_sim(ode_viz.ODE_Visualization):
    def __init__(self, world, space, dt):
        ode_viz.ODE_Visualization.__init__(self, world, space, dt)

    def execute(self, caller, event):


viz = my_sim(world, [space], dt)

We simply removed all the OpenGL stuff and added a new visualization class, in the same way as it was used in the previous example. The original update function is here called from within the execute method. And if you take a look into function drop(), which is responsible for the creation of objects. Every new object is here directly added to the visualization, and their color-properties are changed in the vtk manner (to random colors).

Watch the result in movie below …



download site: http://sourceforge.net/projects/ode-viz/

direct download: http://sourceforge.net/projects/ode-viz/files/latest/download

subversion: svn co https://ode-viz.svn.sourceforge.net/svnroot/ode-viz ode-viz


Readers Comments (3)

  1. Really liked what you had to say in your post, ODE-VIZ | – aiZac -, thanks for the good read!
    — Angelo


  2. Why users still make use of to read news papers when in this technological world
    all is existing on net?

  3. Thanks for sharing your thoughts about 1. Regards


Leave a comment

Your email address will not be published.