Extrapolating orientation

Hey all!
I’m working on a networking interpolation implementation, and i’ve found that the best way to do it is to move the objects using the original networking plugins, and saving the last and new position etc…
However, i cannot think of how to extrapolate ORIENTATION
To extrapolate position, just use interpolation to determine the displacement in one second, then add that to the position * by time since latest packet.
However, orientation i know nothing of. I have read slew for interpolation, but i don’t know how to combine this with extrapolating.

Could anyone post a code snippet, assuming i have Rotation 1 in EULER (but i can convert to QUATERNION) and Rotation 2 in EULER (Same again), Time between packets and time since last packet?
Thanks :slight_smile:

The mathutils.Matrix comes with a lerp method.

mat_lerp = mat_t0.lerp(mat_t1, 0.1)

# update orientation by lerp slice (there are 10 in this case):

game_object.worldOrientation  = mat_t0 * mat_lerp # this runs 10 times -> you are at t1

Simple example is attached.


lerp_inter.blend (403 KB)

That is correct! But, how can i use two quaternions to predict a future orientation?

Just continue the multiplication by the last derived lerp matrix.

You can convert quaternions to matrices on the client.

But, if you want to do the math in Quaternions, you can use the slerp method.

Would it be better to send position and velocity and set those. Then send orientation and angular velocity and set those. That way you don’t need to calculate where the object will be because the velocity will move it there anyway.

However, as the step is linear - (0 to 1), i cannot use a delta time change for it.
I beleive i may be better off sending lin and ang velocity, However, they won’t work for Loc or Rot movements. This is why i chose this method in the first place. Any ideas?
If i can calculate the Angular Velocity from two frames, that would be just as good - it sounds more feasible!

… Why not?

You really shouldn’t be using dloc or drot, if its an exception situation than:

lin_vel = (pos_old - pos_new) / (time_new - time_old)
ang_vel = (ori_old.to_euler() - ori_old.to_euler()) / (time_new - time_old)

Its definitely not worth trying to work out the difference in the orientation matrices, I think convert to eulers and work with that.

Edit: Not 100% sure on angular velocity

Hmm, you can’t average euler angles :confused:

Then do:

ang_vel = (Vector(ori_old.to_euler())) - Vector(ori_new.to_euler())) / (time_new - time_old)

I assumed Euler extended Vector.

Thanks andrew!
So, assuming that this works, how can i update the object’s transformation matrix, because static objects don’t have dynamics.
I don’t expect everyone to use LOC and ROT, but many beginners do, and simple examples also.
Here’s what i could use, yet i can’t understand it :S

Here’s what i’ve got working (i think):

rot = last_ori.rotation_difference(new_ori)
#rot = transition
dt = (time.time() - last_time) / (new_time - last_time)
angles = mathutils.Euler([math.radians((math.degrees(a) * dt) % 360) for a in rot.to_euler()]).to_quaternion()
orientation = angles * last_ori
self.object.worldOrientation = orientation.to_matrix()

Just in case anyone else looks for help like i did, here is my implementation:
You’d replace the time.time and mathutils.Quaternion objects with their actual values, by storing the orientation from the last two packets and times received…

new_ori, new_time = [mathutils.Quaternion, time.time]
last_ori, last_time = [mathutils.Quaternion, time.time]

displacement = last_ori.rotation_difference(new_ori)
time_delta = (time.time() - last_time) / (new_time - last_time)

if not time_delta:
transition = mathutils.Euler([math.radians((math.degrees(a) * time_delta) % 360) for a in displacement.to_euler()]).to_quaternion()
orientation = transition * last_ori

object.worldOrientation = orientation.to_matrix()