I am trying to create a dynamic body that orbits around a static body in Box2D.
I have a zero-gravity world, and a DistanceJoint
that connects the two bodies. I have removed all friction and damping from the bodies and the joint, and am applying an initial linear velocity to the dynamic body. The result is that the body starts orbiting, but its velocity diminishes over time - which I do not expect in a zero gravity environment without friction.
Am I doing something wrong? Should the linear velocity be recreated at each step, or can I delegate this work to Box2D?
Here is the relevant code:
// positions of both bodies
Vector2 planetPosition = new Vector2(x1 / Physics.RATIO, y1 / Physics.RATIO);
Vector2 satellitePosition = new Vector2(x2 / Physics.RATIO, y2 / Physics.RATIO);
// creating static body
BodyDef planetBodyDef = new BodyDef();
planetBodyDef.type = BodyType.StaticBody;
planetBodyDef.position.set(planetPosition);
planetBodyDef.angularDamping = 0;
planetBodyDef.linearDamping = 0;
planetBody = _world.createBody(planetBodyDef);
CircleShape planetShapeDef = new CircleShape();
planetShapeDef.setRadius(40);
FixtureDef planetFixtureDef = new FixtureDef();
planetFixtureDef.shape = planetShapeDef;
planetFixtureDef.density = 0.7f;
planetFixtureDef.friction = 0;
planetBody.createFixture(planetFixtureDef);
// creating dynamic body
BodyDef satelliteBodyDef = new BodyDef();
satelliteBodyDef.type = BodyType.DynamicBody;
satelliteBodyDef.position.set(satellitePosition);
satelliteBodyDef.linearDamping = 0;
satelliteBodyDef.angularDamping = 0;
satelliteBody = _world.createBody(satelliteBodyDef);
CircleShape satelliteShapeDef = new CircleShape();
satelliteShapeDef.setRadius(10);
FixtureDef satelliteFixtureDef = new FixtureDef();
satelliteFixtureDef.shape = satelliteShapeDef;
satelliteFixtureDef.density = 0.7f;
satelliteFixtureDef.friction = 0;
satelliteBody.createFixture(satelliteFixtureDef);
// create DistanceJoint between bodies
DistanceJointDef jointDef = new DistanceJointDef();
jointDef.initialize(satelliteBody, planetBody, satellitePosition, planetPosition);
jointDef.collideConnected = false;
jointDef.dampingRatio = 0;
_world.createJoint(jointDef);
// set initial velocity
satelliteBody.setLinearVelocity(new Vector2(0, 30.0f)); // orthogonal to the joint
Physically, you are correct. Conservation of energy should ensure that the speed of the body remains constant.
However, Box2D cannot perfectly represent physics. There will be a small error in every frame, and these errors add up. I don't know how Box2D handles joints, but if it projects the object's position onto a circle, this would cause the distance travelled during a frame to be slightly smaller than it would have been without the joint.
Bottom line: it's not reasonable to expect the speed to remain exactly the same as what you started with, and you will need to compensate. Depending on your needs, you can either set the velocity manually each frame, or maybe use a revolute joint, anchored on the planet, with a motor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With