Jump to content
  • Advertisement
Sign in to follow this  
Clobslee

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.

If you intended to correct an error in the post then please contact us.

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();
		circle.setRadius(6f);
		
		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());
		
		
		//Find angel of in radians
		double angleR = Math.atan(sub.y/sub.x);  //<--------------------------- This is my best guess as to where the problem is. 
		System.out.println("Radians: " + angleR);
		//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;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;

public class Planet 
{

	private double mass;
	private double radius;
	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.setRadius(e);
		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();
		circle.setRadius((float)radius/100000);
		
		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("radius: " + radius);
		System.out.println("mass: " + mass);
		System.out.println("gravitational acceleration: " + gravity + " (ship mass: " + f + ")");
		//System.out.println("Box2D radius: " + circle.getRadius());
		
	}

	//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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!