Orbital mechanics simulator in Flash

cr1

Promoting vegetables in space
I'm thinking to make an orbital mechanics / gravity simulator in (Adobe) Flash, similar to the one found here: http://www.dan-ball.jp/en/ (which is in Java).
The features will be the same as the Java version of the simulator to start with.

Does anyone have any tips and/or any ideas about the equations that would have to be involved in this?

Thanks

Scarecrow

New member
Does anyone have any tips and/or any ideas about the equations that would have to be involved in this?

Well for any gravity/orbital mechanics simulator, there's not much you really need to know. Here's some of it:

F=GMm/(r^2)
Force of gravity = Gravitational constant(google can help) * mass of object 1 * mass of object 2 / square of distance between them
Use this on every pair of objects, and add the resulting force to both objects.

a=F/m
acceleration = Force/mass
Use this to find how much each object accelerates as a result of the total force on it.

V=v+at
Final velocity = initial velocity + acceleration*timestep length
Use this to find out what the new velocity of each object is at each timestep. The length of one timestep is your program's approximation of "instantaneous". This should be a small amount of time, for obvious reasons.

P=p+vt
Final position = initial position + velocity * timestep
Use this to find out how the velocity changes the position of the objects involved.

Repeat for each object, for each timestep.

There are more sophisticated ways of doing all of the above, but this is a good first order approximation, and if your timestep is small enough, you should get pretty good results. And remember, that's Newtonian physics, using only the force of gravity, and force, acceleration, velocity, and position are all vectors.

Scrooge McDuck

Does anyone have any tips and/or any ideas about the equations that would have to be involved in this?

I often use:
http://www.braeunig.us/space/orbmech.htm
This is a very nice site, including practical/useful/realistic example problems! Used it for my own orbital mechanics simulator.

Also, I remember comming across some site with tutorials on gravity simulators for flash games, will try to look it up!
At a first look, googling for flash gravity simulation reveals some interesting tutorials to start with.

regards,
mcduck

Linguofreak

Well-known member

P=p+vt+(1/2)at^2

Without the (1/2)at^2 term the simulator will act as if the velocity were being applied instantaneously once per timestep, rather than smoothly over the whole timestep.

Scarecrow

New member
P=p+vt+(1/2)at^2

Without the (1/2)at^2 term the simulator will act as if the velocity were being applied instantaneously once per timestep, rather than smoothly over the whole timestep.

An example of the more sophisticated methods of doing things. While this does give more precision for a given timestep length, in the limit as the length of the timestep approaches 0, they yield the same results.

Quick_Nick

Passed the Turing Test
Donator
I'm thinking to make an orbital mechanics / gravity simulator in (Adobe) Flash, similar to the one found here: http://www.dan-ball.jp/en/ (which is in Java).
The features will be the same as the Java version of the simulator to start with.

Does anyone have any tips and/or any ideas about the equations that would have to be involved in this?

Thanks
I've done something similar to this in Flash. (a simple version though) I was working on a Java version too that would involve as many objects as you want. Let me know if 'anything goes wrong.'

Basically: Find the atan2 of the delta-x and delta-y between two planets. Then take the sine of that angle and multiply it by the other planet's 'gravity', and add all that to your x-velocity. Then take the cosine of the angle and multiply it by the other planet's 'gravity', and add that to your y-velocity. (DON'T FORGET THAT FLASH USES RADIANS FOR ATAN2, SIN, AND COS!) The 'gravity' of the other planet should be some number divided by the distance between the two planets sqared. (ex: 100/(Math.pow(distance, 2)) These steps should at least get you on track and let you get one object orbiting another. Do this to your second object as well (maybe with a different gravity value) to get your two objects interacting. You should initialize a velocity at the beginning though or else they will just fall straight towards each other.

P.S. Woops. I don't know why I thought you were talking about the Earth Sim. I fixed my post before posting it.

EDIT: I recently cleaned out my hard drive and forgot to backup the Flash or the Java program! Woops. :lol: Still, I can help.

tblaxland

Webmaster
An example of the more sophisticated methods of doing things. While this does give more precision for a given timestep length, in the limit as the length of the timestep approaches 0, they yield the same results.
Ah, I can only wish my timesteps would approach zero... :lol:

cjp

Donator
Let me know if 'anything goes wrong.'

Basically: Find the atan2 of the delta-x and delta-y between two planets. Then take the sine of that angle and multiply it by the other planet's 'gravity', and add all that to your x-velocity. Then take the cosine of the angle and multiply it by the other planet's 'gravity', and add that to your y-velocity. (DON'T FORGET THAT FLASH USES RADIANS FOR ATAN2, SIN, AND COS!) The 'gravity' of the other planet should be some number divided by the distance between the two planets sqared. (ex: 100/(Math.pow(distance, 2))

Don't know if anything goes wrong, except I don't see the timestep appearing in your equations. And it seems unnecessarily complicated.

This is how I would do it, for each body B separately:

First calculate the acceleration caused by a body A onto body B:
Code:
dx = xa - xb
dy = ya - yb
r = sqrt(dx^2 + dy^2)

ax = dx * G * Ma / r^3
ay = dy * G * Ma / r^3
Note that it says r^3 instead of r^2. This is because I also multiply with dx and dy, and I need an extra r to compensate for the size of these. The total effect of dx, dy and the extra r only changes the direction of the acceleration.
Also, I calculated the acceleration directly, instead of calculating the force first. This is because the acceleration contains Mb in the denominator (a = F/Mb), and the gravity force contains it in the numerator, so we can cancel them out.

Then, if you have more than two bodies, add all accelerations of different bodies A together:
Code:
ax = sum(ax_1 + ax_2 + ...)
ay = sum(ay_1 + ay_2 + ...)
Here, you should sum over all bodies, escept for B itself. Don't try to calculate the gravity of a body onto itself (you'll get a division by zero).

Finally, do the "numerical integration":
Code:
vx = vx + ax * dt
vy = vy + ay * dt
px = px + vx * dt
py = py + vy * dt
This is the most simple integration method. There are much more accurate methods, but this one is the easiest to understand for beginners.

In each timestep, you should do this for each body. So, in pseudo code:
Code:
array ax_total[], ay_total[]

foreach body B:
ax_total[B] = 0
ay_total[B] = 0
foreach body A:
if A == B: skip this A
Calculate ax and ay for A and B
Add ax and ay to ax_total[B] and ay_total[B]

foreach body B:
Do numerical integration for B

Last edited:

Calsir

New member
Hi, a couple of pointers:

First, in the link cr1 provided there is a central fixed gravity attractor that makes all the particles orbit around it rather than get off the screen. You can even add other attractors or repellers.

Moreover, I think that the scattering of the bodies initial velocities and positions is quite important.

Secondly, about the unit of measures and the magnitude of the constants, you can easily put the masses to be equal to 1 and tweak the gravitational constant to give meaningful and aesthetic orbits . For instance, from cjb's post we can write:

Code:
ax = -dx * G * Mb / r^3
ay = -dy * G * Mb / r^3
the constants G and Mb, if the masses of your bodies are all equal, can be simply included in a single constant "k". The minus sign is to make the force attractive rather than repulsive.

Lastly, but it's getting a little advanced, you can play with the exponent of the force equation. if

F = -G m M / r^2, you can state generally that

a = -k r^n, where k is any constant you like, and play with the exponent. For instance, n = -2 is like gravity. With n = 1 the bodies will behave as if they were linked by springs.

Quick_Nick

Passed the Turing Test
Donator
In each timestep, you should do this for each body. So, in pseudo code:
Code:
array ax_total[], ay_total[]

foreach body B:
ax_total[b] = 0
ay_total[b] = 0
foreach body A:
if A == B: skip this A
Calculate ax and ay for A and B
Add ax and ay to ax_total[b] and ay_total[b]

foreach body B:
Do numerical integration for B
Cool.

Here's a section of my Java code (I wrote the program again):
Code:
for(int i = 0; i < objects; i++) {
for(int j = 0; j < objects; j++) {
if(i != j) {
angle = Math.atan2(xpos[i] - xpos[j], ypos[i] - ypos[j]);
distance = Math.hypot(xpos[i] - xpos[j], ypos[i] - ypos[j]);
xvel[i] += Math.sin(angle) * (100/Math.pow(distance, 2));
yvel[i] += Math.cos(angle) * (100/Math.pow(distance, 2));
}
}
xpos[i] -= xvel[i];
ypos[i] -= yvel[i];
}
I don't think this could be much more complicated than your way.
'objects' is the number of bodies to be displayed. (placed at random positions with slight random velocity) The '100' in (100/Math.pow(distance, 2)) can be changed to affect the acceleration of gravity. (every planet in this program is equal in mass) I have it set to 100 because it looks good at this timestep. (100FPS) Basically saying 100/d^2 is just leaving out the step of multiplying the acceleration of gravity and one divided by the distance sqared.

cjp

Donator
Code:
ax = -dx * G * Mb / r^3
ay = -dy * G * Mb / r^3
We both made a mistake here.
I swapped Ma and Mb (already fixed that in my post)
You incorrectly placed minus signs in front of dx and dy

To give you an example for the minus signs:
suppose A is right of B (xa > xb, ya == yb).
Then, in my convention, dx > 0 and dy = 0.
Gravity is an attracting force, so B will accelerate to the right.
So, ax has to become positive.
G, Ma and r are all positive, so G*Ma/r^3 is positive.
dx is also positive, so everything is OK without the minus sign.

Lastly, but it's getting a little advanced, you can play with the exponent of the force equation. if

F = -G m M / r^2, you can state generally that

a = -k r^n, where k is any constant you like, and play with the exponent. For instance, n = -2 is like gravity. With n = 1 the bodies will behave as if they were linked by springs.
You are a mathematician, aren't you?

I don't think this could be much more complicated than your way.
Not much more complicated, but it uses trigonometry, while I use vector calculus. I prefer (cartesian) vector calculus, because it doesn't have as many nasty singularities (e.g. the direction of a line of length 0) and things like multiple representations of the same position (e.g. 0 degree == 360 degree). Further, if you want to do number crunching, it's usually faster. Finally, for me it's more straightforward to understand, but maybe that's different for other people.

I also use two loops for a slightly more accurate numerical integration. When I leave that away, and also use some other of your simplifications, for comparison with your code, my code would look like this:
Code:
for(int i = 0; i < objects; i++) {
for(int j = 0; j < objects; j++) {
if(i == j) continue;
dx = xpos[j] - xpos[i];
dy = ypos[j] - ypos[i];
distance = sqrt(dx*dx + dy*dy);
xvel[i] += dx * 100 / Math.pow(distance, 3);
yvel[i] += dy * 100 / Math.pow(distance, 3);
}
}
xpos[i] += xvel[i];
ypos[i] += yvel[i];
}
(Why do you have -= instead of += on the velocity-to-position integration?)

Quick_Nick

Passed the Turing Test
Donator
(Why do you have -= instead of += on the velocity-to-position integration?)
Well I have to put a negative somewhere (just about anywhere ) so that y is increasing if the other object is lower on the screen. (y increases as you go down on a computer screen) I honestly have no idea why I had to put a negative on the x. :lol: Doing the math, I shouldn't have to. And I don't think I did have to the first time I made the program. But this time around, it seems necessary.

I just tried your version of the code and it works just fine. I'm not sure how you got an exponent of 3 to get rid of the need for the angle.

Calsir

New member
We both made a mistake here.

Unlikely, I hardly _ever_ make mistakes . Sorry, it was too good to miss

We both made a mistake here.
I swapped Ma and Mb (already fixed that in my post)
You incorrectly placed minus signs in front of dx and dy

From your equations, I assumed that 'A' was the object undergoing acceleration. That is, if the acceleration is proportional to the mass of body B (assuming that Mb is the mass of body b, of course) then my convention is correct. Nobody made mistakes, here.

Also, since Gravitation is a central force field, the usual _convention_ is to write r = ro - R, where ro is the position of the object undergoing acceleration and R is the gravity source, so as to explicitly state the minus sign, which is an useful reminder. Of course, it is just a convention.

You are a mathematician, aren't you?
Not really, engineer. Does that still qualifies for nerdity? :lol: I must admit that I loved the parts about physics and calculus.

Not much more complicated, but it uses trigonometry, while I use vector calculus. I prefer (cartesian) vector calculus, because it doesn't have as many nasty singularities....
Good point. I completely agree.

I just tried your version of the code and it works just fine. I'm not sure how you got an exponent of 3 to get rid of the need for the angle.
Because the force, hence the acceleration, has to be proportional to the inverse of the square of the distance between the bodies. Since the distance magnitude "r" is the norm of the distance vector (dx,dy), the norm of the vector (dx,dy)/r^3 is
Code:
|| (dx,dy)/r^3 || = || (dx,dy) || / r^3 = r / r^3 = 1 / r^2
I hope it is clear.

Related, computing the force that acts on B from A and then doing the same for the force that acts on A from B is a waste of resources. You can compute an antisymmetrical force matrix and then easily apply it on each body.

cr1

Promoting vegetables in space
All right here's some of the progress so far (after putting this project on hold for so many months...)

Basically there's a heavy (as in about 10e13kg) planet in the middle and two 1kg rocks orbiting it.

Should the trajectories look like that normally? They spiral inwards until they get VERY close to the center of the big planet, but because there was no collision detection here they basically had near-infinite force acting on them so both 1kg rocks got ejected.

This simulation only uses vector calculations and the equations "F = GMm/r^2" and "F = ma". Timesteps are not really implemented, runs on 30fps.

Last edited:

tblaxland

Webmaster
Should the trajectories look like that normally? They spiral inwards until they get VERY close to the center of the big planet, but because there was no collision detection here they basically had near-infinite force acting on them so both 1kg rocks got ejected.

This simulation only uses vector calculations and the equations "F = GMm/r^2" and "F = ma". Timesteps are not really implemented, runs on 30fps.
Do you mean you are running fixed interval (sim time) timesteps?

You do not have any sort of non-spherical gravity model, so the trajectories should not degrade like that. Looks like an integration problem of some sort.

Quick_Nick

Passed the Turing Test
Donator
Can you upload the swf file somewhere so we/I can check it out?
I'm having a hard time seeing clearly what is happening just from that picture.

Do you mean you are running fixed interval (sim time) timesteps?
I'm pretty sure he just means that the Flash attempts to run at 30FPS, doing 'the math' (which could be on no particular scale) each frame. Flash doesn't always perfectly maintain a certain framerate, but running something like this locally should make it pretty close.

tblaxland

Webmaster
I'm pretty sure he just means that the Flash attempts to run at 30FPS, doing 'the math' (which could be on no particular scale) each frame. Flash doesn't always perfectly maintain a certain framerate, but running something like this locally should make it pretty close.
OK, but if you don't know the time step, then you really have an integration problem

cr1

Promoting vegetables in space
All right here's the file: http://contland.110mb.com/perso/ob/test20090429.swf

What I think is happening is that the 1kg rock may have some gravitational effects on that planet in the middle. And when this middle planet moves, then the rocks' orbit changes. Maybe... I don't know :O

Every pixel here counts as 1 meter distance. (Waaayyy too close!)

EDIT: By the way, the middle planet does not respond to the rock on the left's gravity, I'll have to fix that.

Last edited:

Quick_Nick

Passed the Turing Test
Donator
Seems fine when I run it. All three objects' orbits slowly drift to the left which looks correct to me. After a while though, the left 'moon' seems to do some strange things. Maybe this is correct, but maybe you just need a little tweaking. The right moon looks perfect. (although I don't know why after a while it's orbit starts to rotate )

EDIT: By the way, the middle planet does not respond to the rock on the left's gravity, I'll have to fix that.
That might be important in getting things more accurate.

cr1

Promoting vegetables in space
Strange... today on another computer the sim runs fine. It was Flash player 9 instead of 10.

Screenshot of it running for 15 minutes: