Revolute Joint: how to maintain two bodies distance stable?

Apr 30, 2012 at 3:18 PM
Edited Apr 30, 2012 at 3:19 PM

Hello, I am trying to create a 2D platform character by using a Rectangle and a Circle, connected by a revolute joint (motor enabled). The problem I am encountering is that when the character falls to the ground the two bodies don't maintain their distance, as shown in the following video:

http://www.youtube.com/watch?v=zBv22ocZzkk

The code for creating the two bodies and the joint is the following:

 

// Create the character rec body part
recBodyPart = BodyFactory.CreateRectangle(world, recWidth / MeterInPixels, recHeight / MeterInPixels, 1f, recPosition);
recBodyPart.BodyType = BodyType.Dynamic;
recBodyPart.Restitution = 0f;
recBodyPart.Friction = 0.5f;
recBodyPart.FixedRotation = true;

// Create the character circle body part
circleBodyPart = BodyFactory.CreateCircle(world, circleRadius / (2f * MeterInPixels), 0.1f, circlePosition);
circleBodyPart.BodyType = BodyType.Dynamic; circleBodyPart.Restitution = 0f; circleBodyPart.Friction = 0.5f; //Connect the two bodies RevoluteJoint joint = JointFactory.CreateRevoluteJoint(world, recBodyPart, circleBodyPart, Vector2.Zero); joint.MotorEnabled = true; joint.MaxMotorTorque = 3;

 

I searched the forum and I tried to use a DistanceJoint but with no lack, can someone please help me? Thanks.

Apr 30, 2012 at 3:43 PM

Why is the circle 10 times less dense than the rectangle? Light bodies supporting heavy bodies is difficult for the solver. What happens if you make them roughly the same mass?

May 1, 2012 at 12:43 PM

That was a mistake indeed, I put the circle density back to 1f and the problem is not so vast, but it is still there, as you can see:

http://www.youtube.com/watch?v=Qtbn68BhO7o

Any other ideas to fix it completely?

May 1, 2012 at 1:56 PM
Edited May 1, 2012 at 4:14 PM

Well I think we can agree that what happens is that the solver takes a few iterations to satisfy the no-relative-translation constraint of the revolute joint. It gets there eventually but unless you use pixel-perfect solver there will always be error and that's proportional to the impulse of the upper body since the lower comes to rest because of 0 restitution. You can try several things that may help:

- increase solver iterations - that should definitely make it better but at the cost of CPU

- lower the mass of the upper object (the opposite of what you had initially)

- stick a distance joint between the two to provide a further stabilizing impulse each iteration. That is a hack but in my experience a combination of strategically placed joints leads to very convincing results. For example 2 revolutes (if you can place them) is sometimes better than one, a soft weld joint increases rigidity etc.

[EDIT] PS: apart from the physics issue which is interesting you can also change the way you draw the sprite by doing it relative to the circle rather than the rectangle. Then you won't have a visual problem at all. You know Occam's razor and all...

May 6, 2012 at 11:42 AM

Thanks a lot for your help.

 

First of all I followed your last advice and now I am drawing the animations relative to the circle.

My intention was to use also a distance joint (although I have tried before and it didn't work). But when I was trying to solve other problems by chance I minimized this problem. In the code above I added these two lines

 

recBodyPart.Mass = 1f;

circleBodyPart.Mass = 1f;

Because this code runs in every animation creation, I wanted all the animations to have the same mass ( a total of 2), since they represent the same character. Then I noticed that the problem for a simple jump had been fixed, now the character has to fall for a long time for the problem to appear.