Troubles with setAngularVelocity on rigid body

Post Reply
neodelphi
Posts: 8
Joined: Sun Aug 05, 2007 6:20 pm

Troubles with setAngularVelocity on rigid body

Post by neodelphi » Sat Dec 22, 2018 12:57 pm

Hi,

I'm trying to implement a character controller with rigid bodies. I'm not using bullet's kinematic character controller since it does not interact properly with other rigid bodies (or I'm missing something..).

I currently have a rigid body with a capsule shape, and I set angular factor to 0 to lock rotation (maybe this is not a good idea ?). I then drive the rigid body angular velocity by using setAngularVelocity before running world->stepSimulation(...); The angular velocity is set turn the character to reach a target angle, and depends from the time step.

This almost works, but I have instability troubles because the velocity I set is took into account by bullet one frame later, and not during the first call to stepSimulation, so when the character reaches the target angle, it will continue to turn for one frame and will exceed target angle.

I also tried to implement this using btActionInterface, but it is even worse (effect of setAngularVelocity is visible 4 frames laters).

I also tried to directly set the transformation of the rigid body, but it seems to be hacky and it fucks up the character rigid body speed.

Is there any explanation why setting velocity has delayed effect ? Is there any better way to implement characters ?

Also, I really need to set character angle, even if shape is a capsule. This is because I use constraints when my character picks up objects.

Thanks in advance for any help

User avatar
drleviathan
Posts: 475
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Troubles with setAngularVelocity on rigid body

Post by drleviathan » Sun Dec 23, 2018 2:51 pm

Setting the angularFactor to zero and slamming the angularVelocity should work. I've used that trick myself. Any instability or lag must be coming from your calculation of the velocity. I've experienced instability (my own fault), but never lag, so dunno what is going on there.

Here is one way to do it that is absolutely stable and might work for you: exponential decay toward the target orientation. Every frame do the following:

(1) Given your character's orientation q and its target orientation qT, compute the rotation dq that would move it to its target:

dq = qT * q_inverse

(2) Obtain angle and axis from dq

(3) If angle is less than some small threshold set angularVelocity to zero, else compute the angularVelocity assuming exponential decay:

angularSpeed = angle * timeStep / exponentialTimeScale
angularVelocity = angularSpeed * axis

You tune the rate of alignment by choosing a correct exponentialTimeScale. It represents the time it takes for your character to reduce the value of angle to be 1/e (about 0.36788) of what it was. After three timescales your character will have reduced alpha to (1/e)^3 = 0.049787, which is pretty small. So you ask yourself: "How long should it take for my character to turn 180 degrees?" If the answer is "about one second" then set your exponentialTimeScale to be "about 1/3 of a second".

Remember, long timeScales make for slow alignment and short timeScales make it fast. Danger: exponentialTimeScale cannot be less than the substep timeStep, else the method is unstable. For best results never set it less than twice the substep timeStep.

Note: in many circumstances this method can be used in an Action without bothering to set angularFactor to zero: since it slams the angularVelocity it will override any perturbing collisions. The exception being: if your object will suffer from extreme collisions with large objects it might be possible to pump energy into the simulation and cause "explosions" when things go bad.

neodelphi
Posts: 8
Joined: Sun Aug 05, 2007 6:20 pm

Re: Troubles with setAngularVelocity on rigid body

Post by neodelphi » Sun Dec 23, 2018 10:09 pm

Hi drleviathan,

Thank you for your fast and detailed response. I'm happy to see I'm not the only one trying to perform such tricks with the angular velocity. As you mentioned this should work as expected, I investigated a bit more to find the cause of my lag. I do have lag, and this is not related to my calculation.

Indeed, I changed my code when calling world->stepSimulation and set the maxSubSteps parameter to 0. This removed the lag issue and I then had correct behavior with my character!

The doxygen documentation of stepSimulation mentions the motion is interpolated between fixed time steps when maxSubSteps is greater than 0. I guess this was the source of my lag problem. I will try later to make my code work with maxSubSteps (if possible) but for the moment things works.

Thanks again for you support.

Post Reply