# LibGDX/Box2D orbital mechanics

This topic is 512 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So I'm messing around with Box2D and libgdx again and seem to have run into an issue. I'm calculating the gravitational force of a planet object and trying to apply the appropriate force vector to my "rocket" every step to accelerate it towards the planet but am getting a few unexpected results. I have a planet body at 0,0 in the box2d world. My rocket seems to be pulled toward the planet correctly IF its x value is greater than 0 and I don't try too apply any initial force to the rocket, but the second I move to the other side it has unexpected results. All of the physics I know are self taught so I'm sure I'm making a mistake in the math but am unsure exactly where. Hopefully my explanation of the following will provide enough information for you guys to give me some help!

Every step I apply a force to the center of my rocket object as seen in these two functions:

private void gameUpdate()
{
//If more than 1/45 of a second has passed update the game
if(shouldUpdate(TimeUtils.millis()))
{
//Step Box2D world - Update physics 1/45th of a second.

world.step(1/45f, 6, 2);
applyGravitationalForce();

//	System.out.println("Updating");

//Just updated so set the gameTime to now
gameTime = TimeUtils.millis();
}
//System.out.println("Passed on Updating");
}

private void applyGravitationalForce()
{
rocket.getWorldBody().applyForceToCenter(rocket.getVectorForce(planet), false);
}


The Rocket class and my force calculation function :

public class Rocket {

private Vector2 pos;
private Texture rocketTexture;
private BodyDef body;
private CircleShape circle;
private FixtureDef fixtureDef;
private Fixture fixture;
private Body worldBody;
private double mass;

public Rocket(World world)
{
setPos(new Vector2(100,-100));
createWorldBody(world);
setMass(5);
}

private void createWorldBody(World world)
{
body = new BodyDef();
body.type = BodyType.DynamicBody;
body.position.set(this.pos);

setWorldBody(world.createBody(body));

circle  = new CircleShape();

fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = .5f;
fixtureDef.friction = .4f;
fixtureDef.restitution = .6f;

fixture = getWorldBody().createFixture(fixtureDef);

}

public Vector2 getVectorForce(Planet planet2)
{
//rocket -> planet force vector
//rocket pos
Vector2 posOfRocket = new Vector2(getPos());

System.out.println("Rocket: " + this.getWorldBody().getPosition().toString());
System.out.println("Planet: " + planet2.getLocation().toString());

//rockets pos - planets pos
Vector2 sub = new Vector2(posOfRocket.sub(planet2.getWorldBody().getPosition()));

System.out.println("sub: " + sub.toString());
//System.out.println("Local pos: " + posLocal.toString());

double angleR = Math.atan(sub.y/sub.x);  //<--------------------------- This is my best guess as to where the problem is.
//convert to degrees
double angleD = Math.toDegrees(angleR);
System.out.println("Degrees: " + angleR);

Vector2 force = new Vector2(0,0);

//Calculate force vector using planets gravitational force *no idea why I have to multiply by -1 here*
force.x = (float) ((planet2.calcgravity(this)  * Math.cos(angleD)) * -1);
force.y = (float) ((planet2.calcgravity(this ) * Math.sin(angleD)) * -1);

System.out.println("Force Vector: " + force.toString());

return force;
}


My planet class with its function to calculate gravitational force based on mass and rockets mass

package com.orbyte.game;

public class Planet
{

private double mass;
private double gravity;
private String name;
private Vector2 location;

//calculate gravitational constant
private final double gravityConstant = 1;//6.673 * (java.lang.Math.pow(10, -11));

//box2d imports
private Body worldBody;
private BodyDef body;
private CircleShape circle;
private FixtureDef fixtureDef;
private Fixture fixture;

//	name, mass of new planet, radius, mass of object, loc in 2D space
public Planet(String name, double d, double e, double f, Vector2 loc, World world)
{
this.setName(name);
this.setMass(d);
//this.setgravity(calcgravity(f));
this.setLocation(loc);
createWorldBody(world);

debugObj(f);
}

private void createWorldBody(World world)
{
body = new BodyDef();
body.type = BodyType.DynamicBody;
body.position.set(this.location);

worldBody = world.createBody(body);

circle  = new CircleShape();

fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = .5f;
fixtureDef.friction = .4f;
fixtureDef.restitution = .6f;

fixture = worldBody.createFixture(fixtureDef);

}

private void debugObj(double f)
{
System.out.println("Planet - " + name);
System.out.println("mass: " + mass);
System.out.println("gravitational acceleration: " + gravity + " (ship mass: " + f + ")");

}

//Calculate the gravitational pull of the planet on the rocket object
public double calcgravity(Rocket rocket)
{
double gravityForce = 0;

//Calculate the gravitational force in Newtons

System.out.println("GC: " + gravityConstant + ", Planet mass: " + this.mass + ", RocketMass: " + rocket.getMass());

//force in N
gravityForce = (gravityConstant * this.mass * rocket.getMass()) / (Math.pow(rocket.getPos().x, 2) + Math.pow(rocket.getPos().y, 2));
System.out.println("G Force: " + gravityForce);

this.gravity = gravityForce;

return gravityForce;
// TODO Auto-generated method stub

}


I think I already mentioned it but applying any initial force seems to bring it completely out of whack... Any help or suggestions are appreciated! Thanks in advance.

##### Share on other sites

You've multiplied -1 because the force direction should be planet_position - rocket_position.

I haven't read the rest of the code but as a beginner you should learn how to build or use a 2D math library before digging into game physics. If you're using Box2D for educational purposes I would just use its own.

With a math lib what you wrote becomes:

Vec2 displacement = planet.position - rocket.position;

Vec2 force_direction = Normalize(displacement);

float force_magnitude = planet.gravity * (rocket.mass * planet.mass) / LenghtSquared(displacement);

Vec2 F1 = force_magnitude * force_direction;

Vec2 F2 = -F1;

rocket.ApplyForce(F1);

planet.ApplyForce(F2);

Also...

When needed to calculate the angle between two vectors, don't use atan(y / x). Use atan2(y, x) if your math library has it because it can map to a larger angle range and handle x = 0.

You're passing degrees instead of radians to the cos and sin functions. I think in Java these functions also assume radians are given.

Don't use pow if the exponent is 2. Use base * base.

Edited by Irlan Robson

##### Share on other sites

You've multiplied -1 because the force direction should be planet_position - rocket_position.

I haven't read the rest of the code but as a beginner you should learn how to build or use a 2D math library before digging into game physics. If you're using Box2D for educational purposes I would just use its own.

With a math lib what you wrote becomes:

Vec2 displacement = planet.position - rocket.position;

Vec2 force_direction = Normalize(displacement);

float force_magnitude = planet.gravity * (rocket.mass * planet.mass) / LenghtSquared(displacement);

Vec2 F1 = force_magnitude * force_direction;

Vec2 F2 = -F1;

rocket.ApplyForce(F1);

planet.ApplyForce(F2);

Also...

When needed to calculate the angle between two vectors, don't use atan(y / x). Use atan2(y, x) if your math library has it because it can map to a larger angle range and handle x = 0.

You're passing degrees instead of radians to the cos and sin functions. I think in Java these functions also assume radians are given.

Don't use pow if the exponent is 2. Use base * base.

Hey thanks for the reply, made a few changes based on your recommendations and it now acts as expected regardless of initial position of the rocket. I appreciate it!

Edit: That's all I needed! I can now orbit small masses around the larger mass. Thanks again.

Edited by Clobslee

1. 1
2. 2
Rutin
19
3. 3
JoeJ
16
4. 4
5. 5

• 35
• 23
• 13
• 13
• 17
• ### Forum Statistics

• Total Topics
631700
• Total Posts
3001808
×