very accurate timing

I have some data where there are 30 samples per second. As such, to run real time, I want to perform an action accordingly. I currently have something like:

self.taskMgr.doMethodLater((1.0/30.0), self.doSomething, 'tickTask')

doSomething returns task.again.

The problem - I’m losing time as compared to a stop watch. The reason - I suspect - is the actual duration/amount of time it takes to execute the method doSomething.

So to my question…

…is there a way of getting this absolutely accurate in Panda? i.e., doSomething to be called every 1/30th of a second irrespective of how long doSomething itself takes to execute?

Hope I explained that well and apologies if it’s a basic question - I’ve not dabbled much with tasks, intervals and similar to date.


You’re asking for real-time scheduling, for which the answer is no: it’s not possible to guarantee that a task is run at precisely the specified interval. The operating system itself cannot guarantee this, so Panda can’t do any better than that. (It is possible to come a lot closer than the default behavior, but this requires threads and introduces a lot of complexity which you probably don’t need. And it still won’t be close enough.)

So, the right solution is to know that your task is not going to run at precisely 1/30 second intervals, but instead to examine the time at which it does run, and then do the appropriate thing. For instance, if you really require it to run 30 times a second, you can simply run a loop each time your task runs to do your thing the appropriate number of times since the last time it was invoked. If it was last invoked 1/15 of a second ago, for instance, you should do your thing twice.

Or, if all you need to do is make an appropriate computation based on the amount of time elapsed since the last frame, that’s even easier; just look at the clock and see how much time has elapsed.


Thanks David.

In the end, I did more or less what you said and built in “catch up code”. i.e.:

    def updateScene(self,task):
        diff = globalClock.getFrameTime() - self.lastUpdate
        self.lastUpdate = globalClock.getFrameTime()

        # we don't want to lose this residual bit
        remainder = diff % (1.0/self.unitsPerPoint)
        self.lastUpdate = self.lastUpdate - remainder

        updates = diff / (1.0/self.unitsPerPoint)
        updates = int(math.floor(updates))
        for i in range(updates):

It’s now keeping time very well!