[ODE] Framerate problem *again*

skjold@cistron.nl skjold at cistron.nl
Wed Feb 12 06:31:02 2003


Hi Marco

> Hi (what's your name?)!!!

My name is Mark Meijer :)


> Thank you for your useful reply! You made me find a couple of bugs :)
> I didn't delete contact joints after every dWorldStep()! :)
> This was a bug, sure, but nothing has changed anyway. :(

Well, I had given that option some thought (to do multiple dWorldSteps per dSpaceCollide), and about whether to remove those contact joints early or not. The way I figured it is as follows (warning - long story ahead):

The timestep relevant to the simulation is the rate at which interaction (collision between bodies) takes place. This time-resolution at which action-reaction is determined, has consequences for the movements of those bodies which is calculated by dWorldStep. In effect, dSpaceCollide takes a sampling of the simulated world at a regular interval, and what happens in between the samplings is mathematically solved by dWorldStep.

So, let's say we have a time-resolution of 100 steps per simulated second (meaning dSpaceCollide samples the world at an interval of 10 milliseconds). Normally, you would call dWorldStep once right after calling dSpaceCollide, to solve that 10ms timespan in between collision testing. Finally you delete all the contact joints, and loop back to dSpaceCollide at the start of a new 10ms timespan. This means that those contact joints have 'existed' for 10ms in the simulated world.

The reason to do multiple dWorldSteps between dSpaceCollide is to improve accuracy of the calculated motion that results from all those forces in the simulation. It might as well have been integrated into ODE (perhaps an adaptive time-step behind the scenes, or a higher-order solver, for example), but in this case we need to do it ourselves. So let's say we call dWorldStep twice to solve that 10ms timespan, in other words we divide those 10ms into two 5-ms dWorldSteps.

Now here comes the big conclusion I made for myself (and I hope it makes sense): We are not actually increasing the time-resolution at which the world is sampled and interaction is determined (dSpaceCollide), so it seems logical that the contact joints should still 'exist' during the whole 10ms timespan. In other words, the contact joints should then *not* be deleted after the first call to dWorldStep. That would leave the second call to dWorldStep without contact joints, but we already know that ODE can take multiple steps to recover from inter-penetration constraint violations, which means it needs those contact joints during the second dWorldStep call also. I think...

At least, this was my theory :o) but I tried this and it only resulted in the rigid bodies to jerk around incoherently (it became worse the more dWorldSteps I did per timespan). So I decided not to do that anymore. Anyway, that's a long story for a small conclusion :P But I thought maybe it would shed some light on the subject. If anyone knows why my reasoning is wrong, I'd be happy to hear about it.


> The big bug is still there though.

Come to think of it: Could it be that your "frame of the missing collision" is a call to dWorldStep without a preceding call to dSpaceCollide? Just a wild thought.


> By the way I would like to ask you:
> 
> - You say ODE could take more than one frame to bounce off. Ok. But
>   I have to create contact joints in the NearCallback every frame the
>   bouncing goes on? Or only the first one?

Yes, you create those contact joints every frame. That's because, first of all, you delete those contact joints at the end of each frame, and second of all the contact properties change every frame (which is represented by creating a new joint for it every frame). In essence, no contact info is preserved from one frame to the next, so each frame starts with a rigid-dynamics state and a clean contacts-slate... So to speak. :P


> - If I have to create joints EVERYTIME a collision is detected during
>   a bouncing, what happens if I change bouncing parameters between?

If you change bouncing parameters for the same pair of colliding bodies, then they will probably not bounce very naturally, in other words it would effectively foil the simulation. What the exact resulting behaviour would be depends on how you change the parameters, I guess. I suspect ODE can handle it normally, since it views all contacts in a single frame as a new and unique set of contacts from the previous frame.


> - Is actually ONE the call to NearCallback that affect the bouncing or
>   all the group of calls are important?

The callback is called for every pair of potentially colliding bodies. That means you might get a lot of calls that actually do nothing. But if any single call does actually cause a collision contact to be made, it will always involve at most two bodies. The dCollide function can generate several contacts, but they all relate to the same pair. If more than two bodies collide, then your callback is called at least twice (at most once for each pair, plus any "false alarms").


> I'm trying to log all the info again and figure out what happens
> exactly in my NearCallback that's a bit complex now.

Maybe you could post the code of your callback?


Greets,
Mark