Collision event doesnt get fired every ode-frame

Hi everyone,

today i encountered (once again) a strange behaviour of ode. What i am doing is creating two objects - a static plane and a ray - that collide with each other. Since ode should run framerate-independent i let it do so. As you can see i set a variable true everytime a collision-event gets fired and false every ode-frame. The curious thing is, since the two objects dont move, they should collide each ode-frame with each other but in fact they dont do. The event only gets fired every 5-6 frames. Ode runs with a very high framerate of 300 frames per second because the error only seems to appear when ode runs with a higher framerate than panda.

Any ideas why ode is behaving like this? Did i do any coding-errors or is it the fault of ode?

Thanks alot and greetings

Blaz

Heres my code:

# -*- coding: utf-8 -*-
###################################################################
## this module is the main one, which contains the game class
###################################################################

from direct.showbase.ShowBase import ShowBase
from pandac.PandaModules import * #Load all PandaModules

# -----------------------------------------------------------------

class Game(ShowBase):
    '''
    '''
    def __init__(self):
        '''
        '''
        ShowBase.__init__(self)
        loadPrcFileData("", "notify-level-x11display fatal")

        ##This variable gets set to true when a collision-event gets fired and to false every ode-frame
        self.ode_collisiontest = False
        
        base.setFrameRateMeter(True) #Show the Framerate
        self.world = OdeWorld()
        self.deltaTimeAccumulator = 0.0 #this variable is necessary to track the time for the physics
        self.stepSize = 1.0 / 300.0 # This stepSize makes the simulation run at 300 frames per second
        
        #Initialize Collisions (ODE)
        self.space = OdeSimpleSpace()
        #Initialize the surface-table, it defines how objects interact with each other
        self.world.initSurfaceTable(1)
        self.world.setSurfaceEntry(0, 0, 150, 0.0, 9.1, 0.9, 0.00001, 0.0, 0.002)
        self.space.setAutoCollideWorld(self.world)
        self.contactgroup = OdeJointGroup()
        self.space.setAutoCollideJointGroup(self.contactgroup)
        
        self.startGame()

    # -----------------------------------------------------------------

    def startGame(self):
        '''
        Start the game
        '''
        #Load the Lights
        ambilight = AmbientLight('ambilight')
        ambilight.setColor(VBase4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(ambilight))

        #Create the Plane that the model collides with
        self.plane = OdePlaneGeom(self.space,0,0,1,-5)
        self.plane.setCollideBits(0)
        self.plane.setCategoryBits(1)
        
        self.space.setCollisionEvent("ode-collision")
        base.accept("ode-collision", self.onCollision)
        #Set up a model, that collides with the plane, i use a vector instead because it should always collide
##        self.model = loader.loadModel("panda")
##        self.model.reparentTo(render)
##        self.model.setPos(0,50,2)
##        #Initialize the physics-simulation
##        self.physics_model = OdeBody(self.world)
##        self.physics_model.setPosition(self.model.getPos(render))
##        self.physics_model.setQuaternion(self.model.getQuat(render))        
##        
##        #Initialize the mass
##        physics_mass = OdeMass()
##        physics_mass.setBox(1,1,1,1)
##        self.physics_model.setMass(physics_mass)
##        
##        self.collision_model = OdeBoxGeom(self.space, 1,1,1)
##        self.collision_model.setBody(self.physics_model)
##        self.collision_model.setCollideBits(1)
##        self.collision_model.setCategoryBits(0)

        #Set up a vector that collides with the plane
        self.ray = OdeRayGeom(self.space, 100)
        self.ray.setCollideBits(1)
        self.ray.setCategoryBits(0)
        self.ray.set(Vec3(0,2,50),
                    Vec3(0,0,-1))

        #add the game task
        taskMgr.add(self.gameTask, "gameTask")
        self.world.setGravity(0, 0, -0.81)
    
    # -----------------------------------------------------------------
    
    def onCollision(self, entry):
        '''
        Handles Collision-Events
        '''
        #set the variable true when a collision happens
        self.ode_collisiontest = True
    
    # -----------------------------------------------------------------
    
    def gameTask(self, task):
        '''
        this task runs x-times per second if the game is running
        '''
        #calculate the physics
        self.deltaTimeAccumulator += globalClock.getDt()
        while self.deltaTimeAccumulator > self.stepSize: # Step the simulation
            self.space.autoCollide() # Setup the contact joints
            self.deltaTimeAccumulator -= self.stepSize # Remove a stepSize from the accumulator until the accumulated time is less than the stepsize
            self.world.quickStep(self.stepSize)
            self.contactgroup.empty() # Clear the contact joints
            ##Here we print the variable that should be True when a collision event is fired
            print self.ode_collisiontest
            #Now we set it False again
            self.ode_collisiontest = False
        
        #set the new position
        #self.model.setPosQuat(render, self.physics_model.getPosition(), Quat(self.physics_model.getQuaternion())) 
        return task.cont
        
    # -----------------------------------------------------------------

game = Game()
game.run()

Ok i played around a bit and i altered the gameTask a little bit:

for i in range (5):
      print self.space.autoCollide()
      print "test"

when running the program it gives me back this lines:

Any ideas what could cause that behaviour? I really dont know what could cause that behaviour. I even looked at the C-Sources but as far as i can see everything seems alright there. I also tried the code on other computers and it behaves exactly the same.

Greetz Blaz


edit: ah my bad i looked over it found out that i had still prints in my collision-handler. I can say for sure now that every collision event gets fired, but they get all executed at the end of a panda-frame. I need to change that behaviour somehow so that the collision-event gets instantly fired when a collision happens…