Timebased movement and acceleration

Started by
21 comments, last by kloffy 16 years, 3 months ago
Quote:Original post by ZeHa
Now, as you can see, the difference for X between frame 4 and 5 is over 1000, but to frame 6 it's only 600, and that is the reason for the speed "loss". But I just don't know how to make a real, working integral version of my "Dead Reckoning"-like getX()-function.


Also, you don't have a speed loss from frames 5 to 6, you have an acceleration loss. You've reached the max speed so your position can only change at a constant 600 meters every time step. The problem is that you are recomputing the position relative to t=0 every time and each time making the velocity over the time since t=0 constant, but larger. For example, in frame 4 your equation for x says you've been traveling at 24 m/s since t=0, but that's not true. You were traveling at 18 m/s in frame 3. So you need another variable to save last position since velocity is not constant anymore.

newX = oldX + newSpeed*(newTime-oldTime)

I don't think you can use timeDiff for newTime - oldTime either, since I think you are saying timeDiff is time since you started moving. You need to know the amount of time that you've been traveling at the newSpeed (which is 1 frame or 20 ms in your example).

Also, use units when you are trying to figure things out. e.g. accel can't have units of ms - it must be length/time^2. So you can't do things like compare accel with time or divide a time by accel because you are comparing/dividing units that make no sense to compare/divide.

Hope that helps some.
Tadd- WarbleWare
Advertisement
Well... first of all, thanks for all your answers :)

I haven't got time at the moment to try it out, but I'll answer the questions you asked:

@ harmless: Yes, those assumptions are correct, but as for delta_time, well, read on ;) I'll come back to that immediately

@ reana1: xDir is the xDirection, it's -1 if the object moves left and it's 1 if it moves right and of course 0 when it doesn't move at all. I rewrote my code so that I'm in fact using xDir for acceleration, letting it increase e.g. from 0 to 1. But it had the same problem, of course.
lastTime is the time since the last directional change.



Well, now, of course I know how to do it if I just use the delta_time from the last frame to the current frame. That's rather easy, because I just have to add a value that gets scaled up over to time to get acceleration.

But, I actually WANT to have it in the "Dead Reckoning" manner, meaning that lastTime is not lastFrameTime but lastTimeSinceDirectionalChange. The advantage is that you can re-create past situations, e.g. for collision checks or other stuff. And, since it's Dead Reckoning, I can also use it to predict when I want to do networking stuff.

So, what I'm really looking for is a way to get acceleration without knowing the last frame's time but rather any starting time that I want to choose. I know it might not be 100% physically correct that way, but it would be great if at least it would accelerate until a certain speed and then stop accelerating without that "loss" (I know it's not a real loss but I think you know what I mean ;)

Hasn't anyone of you ever made something with Dead Reckoning and network prediction and so on? It must be possible...
Ah, sorry I didn't get your real goal. I understand what you're looking for now (or better at least). I don't have an answer though. I had some guesses, but better to find someone that knows than me accidentally mislead you. :) I haven't done any networking type things. I did some looking though and "client-side prediction" or "lag compensation" might be good google terms.

Here's a link that gives the concept (though maybe you already have that part down): click
And here's a nice article on Gamasutra that may have your answer (just have to get an account - but worth it): click

If no one else replies, try posting/searching in the networking forum maybe.
Tadd- WarbleWare
The Gamasutra article really looks good, I'll read it after lunch :)

Btw, is there any reason why Gamasutra needs so much private information (address, etc) for registering?
It's been a while since I registered, and I get the affiliated Game Developers magazine too. So it's hard to say what I get due to Gamasutra alone or due to the magazine subscription (or due to someone else entirely that knows I'm intereseted in Game design). But generally, all I get are things advertising game conferences and occasionally some book. I think they do have a way to opt out if you want to (check the privacy policy).

They also generate lots of survey info, but I think that comes from the magazine subscription where they periodically ask you a TON of info (it's voluntary).
Tadd- WarbleWare
Well, I've got a problem with the article. It's basic thing is clear to me (as it was before), but there's a formula for the dead reckoning algorithm that can also deal with acceleration, and it looks pretty strange to me:

http://www.gamasutra.com/features/19970919/06arfig2.gif

It's the third one. First of all, what does this little bold "r" mean? Is it just "this is a vector"? Or does it mean something else?
If so, then I don't think that formula would work, because it could be transformed like this:

original:    newX = oldX + speed * (newTime - oldTime) + 0.5 * accel * (newTime - oldTime)transformed: newX = oldX + (speed + 0.5 * accel) * (newTime - oldTime)


So, the factor that gets multiplied with the time difference is still one number that doesn't change over time, because speed and accel are constant values (or am I wrong in this point (I guess I am))?
If it's correct, then the movement won't be accelerated at all.
Quote:Original post by DevFred
You don't need complicated integration to calculate x:

x = x0 + v*(t-t0) + a/2*(t-t0)^2

Where t is the current time and t0 is the time of the beginning of the movement. No time deltas anywhere.


Oh, just noticed it kinda looks like this equation, only that this has an additional ^2 in it. This should produce a different result, but one thing still bothers me: as soon as the acceleration stops (a => 0), the position would be something completely else. Or would I have to re-cache the position at that stage? If so, wouldn't also the speed be drastically reduced at that time then? Or would I also have to re-write the speed variable?
Quote:Original post by ZeHa
First of all, what does this little bold "r" mean? Is it just "this is a vector"? Or does it mean something else?

I wondered the same thing and thought it was a typo. I don't recall ever seeing that notation (and can't find it in a quick search). I thought maybe it was just a type problem (i.e. the equation writer meant for it to be a little arrow, but some program that doesn't do arrows drew an "r").

Which, also makes me question whether there's a missing power of 2 off the last time diff. Normally, I'd expect 1/2*a*(t-t0)^2 for the last term (I see you've noticed that too now). Unfortunately, his code example has no acceleration to confirm that. I tried finding his source (the DIS algorithms), but couldn't find it online.

Here's a paper extending the basic DIS dead reckoning, and they use 1/2at^2 - so I'd bet it's a typo in the Gamasutra article image.
http://ieeexplore.ieee.org/iel5/6213/16596/00766164.pdf
http://ducati.doc.ntu.ac.uk/uksim/journal/issue-1/Lee-Turner/B-S%20Lee.pdf

As far as your other comment about it just being a constant velocity, I think even using the squared term, the velocity should be updated at some point otherwise you are basically saying your clients will assume a constant velocity between updates. Let me just talk myself through this since I may be missing something too. But here's what I gather:

You are talking about something like a client and server, where the server controls the true object's state (pos, vel, acc). The server will update the state of object occasionally to clients (these are t0, x0, v0, a0). In between updates you want to use dead reckoning on the various clients to estimate the object's current state (t, x, v, a). So each client needs an estimate of object state (pos, vel, acc):

[Note: I broke the deltas into seperate terms dt, dx, dv hoping that it might make some things clearer, but I'm not sure if it really does. I guess it was to highlight what the delta is relative to (_0 or _Prev).]

Time change:
dt = t - t0
Position estimate:
dx = v0*dt + 0.5*a0*dt*dt
x = x0 + dx
Velocity estimate:
dv = a0*dt
v = v0 + dv
Acceleration assumption (constant):
a = a0

The above is I think how you've been doing it and the only thing that changes each time step is t. Everything is "dead reckoned" relative to the last update (at t0).

So you're right if you just use those equations, you're assuming constant velocity in the position estimate over all the time steps between updates. Maybe in some applications that's good enough - not sure. But you can see the velocity estimate would change (with non-zero a0). So I think you just need to keep a local client estimate of velocity and update relative to the last estimate (instead of at t0). So you'd instead do it this way:

Time change:
dt = t - tPrev
Acceleration assumption (constant):
a = a0
Velocity estimate:
dv = a0*dt
v = vPrev + dv
Position estimate:
dx = v*dt + 0.5*a0*dt*dt
x = xPrev + dx
Save Prev values:
tPrev = t
vPrev = v
xPrev = x

Now t, tPrev, vPrev, and xPrev all are updated each time step, and the calculations are relative to your previous estimate (at tPrev).

At some point server will come back and update again with correct state and you'll have to compensate or just reset the _Prev terms to the updated state (_0 terms).

Like I said, I haven't done networking stuff though (maybe I'm making things too complicated - or simple for that matter). So I may be missing something. This seems reasonable to me though.

The negative here for you may be that recreating the position is not as simple as before where you just needed one equation relative to t0 and you could compute what your algorithm would predict for the position at any time. Now you need to go through the cycle to re-estimate it again. It's still repeatable, but you'll need to know the dt's at each time step (but that variation may be small enough you can assume a constant). But given a list of dt's, you can recreate this estimate by running the dt's through a loop.

Reading back over this I wonder if I'm just suggesting the same as I originally did before I understood your need. And I'm getting confused (plus being interrupted by work). So for what it's worth there's my possibly incoherent thought process on this. Hope it helps.

P.S. I didn't follow your last concern (when a => 0) that you posted while I rambled this long thing out. :)
Tadd- WarbleWare
Thanks for your long answer :)

Well, I think I'll think a bit about your suggestion... re-calculation would be possible, that's correct. But it might get a little more complicated ;)

Maybe there would still be a different solution, it might be possible to update the velocity at the "critical point" to match the velocity that is gained at the frame before (when the object was still in acceleration mode) to create a seemless transition between acceleration mode and "finally walking at constant speed" mode...

The (a => 0) thing is a bit bad written, actually => should be an arrow and simply say "when 'a' becomes zero" ;) because if I use the basic formula (the one with "0.5 * a * dt * dt" at the end), as soon as the acceleration stops (meaning that "a" becomes zero), then of course the X position would be immediately change to some X value that the object has already passed before (since the last part of the formula will then also be zero). I hope it's now a bit clearer ;)



I also found another thing to explain the basic problem, maybe it's good for some of the people here who didn't understand so far :) (or maybe it will lead to another solution, who knows)
Let's assume there are two people standing besides each other. The first one starts walking immediately at constant speed. The second one starts at the same time, but walks very slow and slowly accelerates to reach the other one. If in the end both people should walk a) in the same speed and b) at the same position, it's clear that the second person needs to walk faster than the other one right before the point where he reaches the same position as person one. I think that's a good and imaginable description of the problem, maybe it can also help.

One other thing, do you think it might be a good idea to mail the author of the article (not only for asking about the problem, also for telling him about the mistake in the picture)?
Quote:Original post by ZeHa
One other thing, do you think it might be a good idea to mail the author of the article (not only for asking about the problem, also for telling him about the mistake in the picture)?

Not sure - I considered it, in particular I was interested in his source since it seemed like he was just quoting parts from the DIS algorithms (which you'd think would be freely available since it's some sort of US government standard). But it is 10 years old. Too bad I don't see a "comments on articles" option like GameDev.

Hmm, never mind looks like someone's gone down this path VERY recently:
http://www.gamedev.net/community/forums/topic.asp?topic_id=477945

Try posting (or getting this moved) in(to) the Networking forum. There's gotta be someone that's done this. I'll probably look more tomorrow in between work.

EDIT: left out part of a sentence - added in bold

[Edited by - reana1 on January 14, 2008 6:50:39 PM]
Tadd- WarbleWare

This topic is closed to new replies.

Advertisement