Orbital Mechanics Question
by Jack Stone · in General Discussion · 04/16/2013 (10:28 am) · 25 replies
I don't know if this is the right forum to post this, there doesn't sem to be anything more specific.
I am working on a Space Simulation, for which I need relatively realistic orbital mechanics.
I have used this link:
http://www.arachnoid.com/ruby/gravity/index.html
To implement a simple system, but it doesn't seem to be working at all, my Moon is moving in a straight line away from the Earth with no signs of slowing down or orbiting.
My code is pretty simple, I have global variables:
and then in a loop called from script, I have:
This is very little code, and so it seems simple enough to work. I have tried scaling down the position of the object in script to make it "fit" into my game world, but it didn't seem to change the results.
I would appreciate any help.
I am working on a Space Simulation, for which I need relatively realistic orbital mechanics.
I have used this link:
http://www.arachnoid.com/ruby/gravity/index.html
To implement a simple system, but it doesn't seem to be working at all, my Moon is moving in a straight line away from the Earth with no signs of slowing down or orbiting.
My code is pretty simple, I have global variables:
F64 grav_const = 6.6742e-11; F64 earth_mass = 5.972e24; F64 moon_mass = 7.34767309e22; F64 dt = 50; F64 velX, velY = 0; F64 orbitposX = 0; F64 orbitposY = 356700;//000;
and then in a loop called from script, I have:
ConsoleFunction( testorbit, void, 1, 1, "none")
{
F64 distanceradius = 384400;//assume constant for now
//f = G M m
// ------
// r^2
F64 force = (grav_const * earth_mass * moon_mass)/(distanceradius*distanceradius);
//a = f/m
F64 acceleration = force/moon_mass; //moon is moving, so use it's mass
velX = 0;
velY = 0;
velX = velX + acceleration * dt;
velY = velY + acceleration * dt;
orbitposX = orbitposX + velX * dt;
orbitposY = orbitposY + velY * dt;
//send values to script function to move Moon object:
char value2[256];
dSprintf(value2,sizeof(value2),"%f",orbitposX);
char value3[256];
dSprintf(value3,sizeof(value3),"%f",orbitposY);
//Con::printf("OUTPUT: %f %f ", body_x, body_y);
Con::executef("moveorbits",value2,value3);
}This is very little code, and so it seems simple enough to work. I have tried scaling down the position of the object in script to make it "fit" into my game world, but it didn't seem to change the results.
I would appreciate any help.
#2
Also, did you mean to set velX and velY to zero every update?
04/17/2013 (6:32 am)
The problem is that you're not taking into account the direction of acceleration. Though most equations are written as scalars (for example, F=ma), the quantities you deal with are actually vectors. So this:velX = velX + acceleration * dt;
velY = velY + acceleration * dt;needs to change to reflect the direction of the force. The direction is the vector from the moon to the planet. Something more like (assuming T3D, though I assume T2D has Point3D as well):Point3D sep = moonPos - planetPos; F64 acc = G * M / sep.lenSquared(); Point3D dir = sep; dir.normalize(); moonVel += acc * dir * dt; moonPos += moonVel * dt;Note how using vectors simplifies your code a bit!
Also, did you mean to set velX and velY to zero every update?
#3
@Daniel:
Thank you very much for that!I assumed it was something like that, but I couldn't figure out what!
I changed my code to this:
Unfortunately, I still get similiar results... I don't seem to get an "orbit", just an ever-increasing number for the transform. The code seems fairly simple, I can't see anything obvious that I am missing.
Oh, and I set the velX and velY code to zero when I was playing around with it, I didn't have that in the original code.
04/17/2013 (11:36 am)
Sorry, this is for T3D 1.2, I should have mentioned that, but I'm not integrating this with T3D's existing physics system, so it should be basically standalone.@Daniel:
Thank you very much for that!I assumed it was something like that, but I couldn't figure out what!
I changed my code to this:
//Globals:
F64 grav_const = 6.6742e-11;
Point3D moonPos = Point3D(0,3567,0);
Point3D planetPos = Point3D(0,0,0);
F64 M = 5.972e24;
Point3D moonVel = Point3D(0,0,0);
//and loop:
ConsoleFunction( testorbit, void, 1, 1, "(1)")
{
Point3D sep = moonPos - planetPos;
F64 acc = grav_const * M / sep.lenSquared();
Point3D dir = sep;
dir.normalize();
moonVel += acc * dir * dt;
moonPos += moonVel * dt;
char value2[256];
dSprintf(value2,sizeof(value2),"%f",moonPos.x);
char value3[256];
dSprintf(value3,sizeof(value3),"%f",moonPos.y);
Con::printf("OUTPUT: %f %f ",moonPos.x, moonPos.y);
Con::executef("moveorbits",value2,value3);
}Unfortunately, I still get similiar results... I don't seem to get an "orbit", just an ever-increasing number for the transform. The code seems fairly simple, I can't see anything obvious that I am missing.
Oh, and I set the velX and velY code to zero when I was playing around with it, I didn't have that in the original code.
#4
04/17/2013 (3:47 pm)
Oh, sorry - I think the equation for separation should be planetPos - moonPos. Then you'll see the moon fall into the planet and oscillate. You'll probably then want to give the moon some initial velocity in the right direction to get an orbit going.
#5
This is a snippet of the(scaled) output of the program, showing the XYZ transform of the object:
I'm not sure where to look next... Could the deltaT value be making a difference? I've tried a few combinations already, doesn't seem tobe making a lot of difference.
Thanks again!
04/17/2013 (4:20 pm)
Daniel, I made both of those changes, and I'm still nto seeing any orbits.This is a snippet of the(scaled) output of the program, showing the XYZ transform of the object:
move: 0.005 0.358567 0 move: 0.00995678 0.357335 0 move: 0.0148267 0.352986 0 move: 0.0195626 0.345445 0 move: 0.0241102 0.334581 0 move: 0.0284033 0.320184 0 move: 0.0323555 0.301944 0 move: 0.0358472 0.279407 0 move: 0.0386996 0.251887 0 move: 0.0406201 0.218301 0 move: 0.0410618 0.176768 0 move: 0.038765 0.123446 0 move: 0.0293354 0.0474097 0 move: -0.0475684 -0.137673 0 move: -0.118337 -0.305 0 move: -0.187759 -0.468855 0 move: -0.256599 -0.63126 0 move: -0.325117 -0.792869 0 move: -0.393428 -0.953976 0 move: -0.461597 -1.11474 0 move: -0.529661 -1.27524 0 move: -0.597645 -1.43556 0 move: -0.665566 -1.59572 0 move: -0.733435 -1.75576 0 move: -0.801262 -1.9157 0
I'm not sure where to look next... Could the deltaT value be making a difference? I've tried a few combinations already, doesn't seem tobe making a lot of difference.
Thanks again!
#6
04/17/2013 (6:19 pm)
Okay, well, your acceleration is in the direction of `dir` so try observing whether that is changing in the right way. It should always point right towards the planet, and therefore the acceleration should be in that direction. Actually, printing out your acceleration and velocity might be more helpful.
#7
The Direction vector is always 0,1,0 when I don't specify an initial velocity, which is why the moon is moving off in one direction. This is probably incorrect?
I'm assuming dir should change as the planet moves?
This is a print out from near the beginning of the run:
//output is acceleration, then x and y velocities of the moon, then Dir x, y, and z.
after running the program for a short while, acceleration drops to zero:
I think the main issue is the dir is not changing? Should the acceleration slow so quickly like that?
04/17/2013 (11:23 pm)
Ok, that gave me a lot more informationThe Direction vector is always 0,1,0 when I don't specify an initial velocity, which is why the moon is moving off in one direction. This is probably incorrect?
I'm assuming dir should change as the planet moves?
This is a print out from near the beginning of the run:
//output is acceleration, then x and y velocities of the moon, then Dir x, y, and z.
OUTPUT: 0.184190 0.000000 -156110.171755 0.000000 1.000000 0.000000 OUTPUT: 0.135062 0.000000 -156103.418639 0.000000 1.000000 0.000000
after running the program for a short while, acceleration drops to zero:
OUTPUT: 0.000000 0.000000 -156059.633958 0.000000 1.000000 0.000000 OUTPUT: 0.000000 0.000000 -156059.633958 0.000000 1.000000 0.000000 OUTPUT: 0.000000 0.000000 -156059.633958 0.000000 1.000000 0.000000
I think the main issue is the dir is not changing? Should the acceleration slow so quickly like that?
#8
It seems like your moon is travelling away from the planet, so yeah, gravity will fall off (it's inversely proportional to r^2, so it drops quickly). Unfortunately, your moon should be falling towards the planet with no initial velocity, so it appears dir is in the wrong direction.
04/18/2013 (2:32 am)
With no initial velocity, your moon will just move on a straight line towards the planet. That is expected. Dir should point from the moon towards the planet, so if the moon is on the +ve Y axis then dir should point in the -ve Y direction.It seems like your moon is travelling away from the planet, so yeah, gravity will fall off (it's inversely proportional to r^2, so it drops quickly). Unfortunately, your moon should be falling towards the planet with no initial velocity, so it appears dir is in the wrong direction.
#9
Something I've noticed is that the initial velocity seems to make a big difference to the shape of the final orbit, is this normal? Is there some way I can mathematically determine what values I should use to simulate the orbit of planets in our solar system?
04/18/2013 (5:04 pm)
Daniel, I've figured it out, thank you so much for your help! It was a combination of changing the position values of the moon and changing the initial velocity, it's working great now, thanks again!Something I've noticed is that the initial velocity seems to make a big difference to the shape of the final orbit, is this normal? Is there some way I can mathematically determine what values I should use to simulate the orbit of planets in our solar system?
#10
As for simulating the solar system, there should be sources out there that will give you the orbital radii and speeds of different planets.
04/18/2013 (5:25 pm)
Yes, the initial velocity is incredibly important. An orbit is basically how Douglas Adams described flying: you throw yourself at the ground and miss. Orbit is achieved when your horizontal velocity is such that you constantly fall, but never hit the ground. That's why satellites aren't in zero gravity, they're in 'freefall'.As for simulating the solar system, there should be sources out there that will give you the orbital radii and speeds of different planets.
#11
Now I'm working on "Moving the world, instead of the rocket", as we talked about in the other thread, it's causing some tricky problems!
04/22/2013 (3:33 pm)
Got it, thank you! Now I'm working on "Moving the world, instead of the rocket", as we talked about in the other thread, it's causing some tricky problems!
#12
04/26/2013 (2:20 am)
I suggest letting the rocket rotate freely, instead of trying to matrix-transform everything else to the right position to keep the rocket in a fixed direction!
#13
I have encountered a strange issue with scaling the world as well. I have used the suggestion given in that article you mentioned, and moved distant objects closer to the player, scaling them proportionately. The only problem is, they seem far too small. I can't even see the moon from the Earth, even though I am sure my numbers are right.
04/26/2013 (11:36 pm)
I haven't handled rotation in any detail yet, I am only modelling movement in the vertical direction, that will be the next goal.I have encountered a strange issue with scaling the world as well. I have used the suggestion given in that article you mentioned, and moved distant objects closer to the player, scaling them proportionately. The only problem is, they seem far too small. I can't even see the moon from the Earth, even though I am sure my numbers are right.
#14
04/28/2013 (11:38 am)
I'm with Daniel on this one - just transform the world and let the player rotate at the origin. You can be the center of the universe, but the universe doesn't have to revolve around you....
#15
EDIT:
I think this is probably the function you're looking for to do distance scaling. I implemented it in Haskell here, and here's the output:

So you should be seeing the same apparent angular size of objects.
04/28/2013 (8:41 pm)
Can we see the maths that's doing the scaling?EDIT:
I think this is probably the function you're looking for to do distance scaling. I implemented it in Haskell here, and here's the output:

So you should be seeing the same apparent angular size of objects.
#16
Maybe I'm looking at this the wrong way, but when I am thinking of "rotation", I am also taking into account the camera view.
For example, if the rocket takes off from, say, the south pole, it will be facing "down" the screen. This would be ok when the rocket is in space, but when it is taking off, it would make more sense to rotate the world such that the rocket is always pointing up, or appears to be. Does that make sense?
It doesn't matter from a realism point of view, but I think it would look strange if the rocket was "upside down" so to speak.
Daniel. the scaling code I was using was pretty simple, basically, if the object was more than a certain distance away, it would be scaled proportionately, but your algorithm looks much more effective, thanks a lot for that!!
04/30/2013 (3:47 pm)
Maybe I'm looking at this the wrong way, but when I am thinking of "rotation", I am also taking into account the camera view.
For example, if the rocket takes off from, say, the south pole, it will be facing "down" the screen. This would be ok when the rocket is in space, but when it is taking off, it would make more sense to rotate the world such that the rocket is always pointing up, or appears to be. Does that make sense?
It doesn't matter from a realism point of view, but I think it would look strange if the rocket was "upside down" so to speak.
Daniel. the scaling code I was using was pretty simple, basically, if the object was more than a certain distance away, it would be scaled proportionately, but your algorithm looks much more effective, thanks a lot for that!!
#17
When you render, you convert everything to floats centered on the rocket (or the camera). Which means, basically, subtracting the rocket (or camera)'s position from everything in double-land, then casting the results to floats.
Then you set the position (or render position) of all the Torque objects and let the scene render as usual. Their rotations should be independent of all this logic.
04/30/2013 (7:13 pm)
I think getting the simulation working is more important than the camera rotation. You don't need to change your world coordinates for that, either. Basically, it seems like what the guy in the article was suggesting is to do all your calculations in whatever coordinate system you like, using doubles - so say 0, 0, 0 is the centre of the sun. All this double-precision logic updates object positions.When you render, you convert everything to floats centered on the rocket (or the camera). Which means, basically, subtracting the rocket (or camera)'s position from everything in double-land, then casting the results to floats.
Then you set the position (or render position) of all the Torque objects and let the scene render as usual. Their rotations should be independent of all this logic.
#18
I am then applying the scaling, transformation, etc, to create the "viewable" world. It's an interesting way of doing it, I have never done anything like this for a project before. It allows you to do some very powerful things.
05/02/2013 (10:30 am)
Absolutely, that's what I am concentrating on. I have done exactly what you described, I have all of the sim code in c++, using F64's.I am then applying the scaling, transformation, etc, to create the "viewable" world. It's an interesting way of doing it, I have never done anything like this for a project before. It allows you to do some very powerful things.
#19
05/02/2013 (11:47 am)
If you have trouble getting the moon orbit right you can fake it by just defining an ellipse for the position the moon should be at any given time. Then you can just do a rotation to keep the face of the moon pointed toward the Earth. That way you are not having to simulate the solar system.
#20
05/02/2013 (12:15 pm)
That's a good idea actually! I'm sure most people wouldn't notice the loss in accuracy. I intend to model the other planets in the solar system too though, so it's probably easier in the long run to get Keplers laws working.
Employee Michael Perry
ZombieShortbus