8
\$\begingroup\$

I have created a rag doll using dynamic bodies (rectangles) and simple revolute joints (with lower and upper angles). When my rag doll hits the ground (which is a static body) the bodies seem to fidget and the joints separate.

It looks like the bodies are sticking to the ground, and the momentum of the rag doll pulls the joint apart (see screenshot below).

alt text

I'm not sure if it's related, but I'm using the Badlogic GDX Java wrapper for Box2D. Here's some snippets of what I think is the most relevant code:

private RevoluteJoint joinBodyParts(
    Body a, Body b, Vector2 anchor, 
    float lowerAngle, float upperAngle) {

    RevoluteJointDef jointDef = new RevoluteJointDef();

    jointDef.initialize(a, b, a.getWorldPoint(anchor));

    jointDef.enableLimit = true;
    jointDef.lowerAngle = lowerAngle;
    jointDef.upperAngle = upperAngle;

    return (RevoluteJoint)world.createJoint(jointDef);
}

private Body createRectangleBodyPart(
    float x, float y, float width, float height) {

    PolygonShape shape = new PolygonShape();
    shape.setAsBox(width, height);

    BodyDef bodyDef = new BodyDef();
    bodyDef.type = BodyType.DynamicBody;
    bodyDef.position.y = y;
    bodyDef.position.x = x;

    Body body = world.createBody(bodyDef);

    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.shape = shape;
    fixtureDef.density = 10;

    fixtureDef.filter.groupIndex = -1;
    fixtureDef.filter.categoryBits = FILTER_BOY;
    fixtureDef.filter.maskBits = FILTER_STUFF | FILTER_WALL;

    body.createFixture(fixtureDef);
    shape.dispose();

    return body;
}

I've skipped the method for creating the head, as it's pretty much the same as the rectangle method (just using a cricle shape).

Those methods are used like so:

    torso = createRectangleBodyPart(x, y + 5, 0.25f, 1.5f);
    Body head = createRoundBodyPart(x, y + 7.4f, 1);

    Body leftLegTop = createRectangleBodyPart(x, y + 2.7f, 0.25f, 1);
    Body rightLegTop = createRectangleBodyPart(x, y + 2.7f, 0.25f, 1);
    Body leftLegBottom = createRectangleBodyPart(x, y + 1, 0.25f, 1);
    Body rightLegBottom = createRectangleBodyPart(x, y + 1, 0.25f, 1);

    Body leftArm = createRectangleBodyPart(x, y + 5, 0.25f, 1.2f);
    Body rightArm = createRectangleBodyPart(x, y + 5, 0.25f, 1.2f);

    joinBodyParts(torso, head, new Vector2(0, 1.6f), headAngle);

    leftLegTopJoint = joinBodyParts(torso, leftLegTop, new Vector2(0, -1.2f), 0.1f, legAngle);
    rightLegTopJoint = joinBodyParts(torso, rightLegTop, new Vector2(0, -1.2f), 0.1f, legAngle);
    leftLegBottomJoint = joinBodyParts(leftLegTop, leftLegBottom, new Vector2(0, -1), -legAngle * 1.5f, 0);
    rightLegBottomJoint = joinBodyParts(rightLegTop, rightLegBottom, new Vector2(0, -1), -legAngle * 1.5f, 0);

    leftArmJoint = joinBodyParts(torso, leftArm, new Vector2(0, 1), -armAngle * 0.7f, armAngle);
    rightArmJoint = joinBodyParts(torso, rightArm, new Vector2(0, 1), -armAngle * 0.7f, armAngle);
\$\endgroup\$
1
  • \$\begingroup\$ Do you run your physic-simulation with a fixed timestep? If not, you should definitely do that first. \$\endgroup\$
    – bummzack
    Dec 30, 2010 at 12:33

2 Answers 2

6
\$\begingroup\$

Box2D uses an iterative, rather than closed form solver. This means all constraints are somewhat soft. Box2D will try very hard to do what you say, but inaccuracies do occur.

To minimize this, there are several things you can do, in order of importance:

  • Use fixed-size timesteps (the first argument to Step). This makes the solver more stable - your inaccuracies are more likely to cancel each other out, or at least behave the same each time.
  • Use a smaller timestep (1/60 or 1/120 instead of 1/30). Smaller timesteps mean smaller inaccuracies.
  • Use more solver iterations (the 2nd/3rd argument to Step). You should try to get at least 10 of each. More solver iterations means more chances each timestep to find stability and correctly satisfy constraints - roughly, less chance of inaccuracy. However, a smaller, stabler timestep is better than more iterations. Given sufficiently complicated constraints, you might never solve them 100% correctly, so try reducing the timestep before increasing the iterations.
  • Use less dense shapes. Density 10 is pretty heavy. Try standardizing on something smaller - like 1 - as your default density.
\$\endgroup\$
1
  • \$\begingroup\$ Hi Joe, thanks for the advice. I've tried all of your suggestions but unfortunately this didn't appear to make a difference. Here's the full source code (it's just a hacky prototype right now) -- pastebin.com/F6YX3AyV \$\endgroup\$ Dec 30, 2010 at 22:59
0
\$\begingroup\$

I ran into this issue and it was pretty annoying. My workaround was to check to see if the joint got disconnected by comparing the positions of the two bodies, then if they got separated, destroy the body, recreate it, and create the joint again.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .