Calculating 2D Orbital Paths in Newtonian Gravity Simulation - simulation

I am currently working on a project (for fun) for simulating Newtonian gravity and want to be able to visualize the future path of an object orbiting around a single attractor. At any given simulation step I know
The object's current position relative to the center of the attractor as a 2D Vector
The object's current velocity as a 2D Vector
The mass of the attractor
The mass of the object
Using these parameters I would like to be able to predict up to N steps ahead in the simulation so that I can draw a line between each point along the orbit.
The Position and Velocity in my simulation are measured in m and m/s while the mass is unitless. The Gravitational Constants is set to 1 and the masses for each object is 1000, for the attractor, and 10 for the object.
The simulation itself produces the result that I want, now I just want to be able to predict the future path.
During my own research, I have found that I need to use the Keplerian Elements in some way. The various examples, questions etc... I have found on stackexchange and elsewhere do not provide sufficient explanation for me to be able to work it into my simulation or they are specific for 3-dimensional geometry and provide incorrect outputs when I attempt to calculate them (NaN and Infinities).
For example, in a few places I have read that the semi-major axis and the total orbital energy should remain constant and from these I can get the eccentricity and various other properties, but when calculating them at any given step using the above-mentioned properties I have access to, they vary wildly or produce numbers that are so ridiculously high or low that they are essentially useless. I resolved the last problem and have a semi-major axis value that makes sense in the context of my simulation, but again it varies from step to step.
As an example:
Initial conditions
Attractor
Mass = 1000
Position = 0,0
Object
Mass = 10
Position = 5, 0
Velocity = 0, 5
This produces an elliptical orbit. The semi-major axis should remain constant as no other forces are acting on the object, however, the value of the semi-major axis varies from 2-4 meters.

I have figured it out and to any future visitors to this question I am (hopefully) going to make your life much, much easier.
If you are like me, fairly lay in terms of astrodynamics then the sheer number of equations, their very technical explanations, and usage is a little daunting. With a little bit of effort, I now know how to iterate equations to be able to calculate future orbital positions.
What we will need are the velocity and positional coordinates of the object you want to predict as well as the mass of the orbital body and the mass of the object itself.
These need to be in m and m/s for no other reason than for this implementation they are assumed to be m and m/s but the mass can be unitless (at first).
Terms:
Attractor - The nearest massive body that is attracting the Object.
Object - The orbital body that is being attracted to the Attractor.
Step 1: Calculate the True Mass of your objects
True mass is defined as the KG mass of your Attractor and Object. To find this value you need to convert your unitless mass, using the gravitational constant, into kilograms.
If you don't know how to do this, first calculate the ratio of unitless mass to the gravitational constant in your simulation and use the value of that ratio to find true mass using the real gravitational constant.
(I cannot post images or else I would include the equations)
After this point when I refer to the gravitational constant, I will be using our real universe's value.
Step 2: Calculate μ
μ is a ratio of masses and the gravitational constant. If the mass of the attractor is large enough μ = GM, where G is the gravitational constant and M is the mass of the attractor. For my own implementation I found that μ can be calculated as:
μ = G ( M * M * M) / ((M+m)*(M+m))
Where:
M is the mass of the Attractor
m is the mass of the Object
G is the gravitational constant.
It is very very important that this value is correct. If what you are rendering looks weird, it is probably because this value was not calculated correctly and it would be the first thing I check. In my initial attempts, this was off by an order of magnitude, it should have been around 100 but it was outputting as 1000 because the mass unit conversion value I calculated was 10x larger than it should have been.
Step 3: Calculate the Orbital Elements
First up is the Semi-Major Axis. This is the radius from the furthest point in the orbit to the center (Aprox). It is represented with the symbol a and calculated as:
a = -(μ * len(pos)) / (len(pos) * len(vel) * len(vel) - (2 * μ))
Man I wish I could post images so these equations looked better, sorry!
Next up is the period of the orbit. This is used later so that we can step through the orbit incrementally. It is represented by the symbol T and its formula is:
T = 2 * π * sqrt((a * a * a) / μ)
Next, we need angular momentum. Now, I know that the post says 2D but in my own code, I am using Vector3's to store my information in case I decide to make it 3D later. This is important because normally to get the angular momentum you would take the cross product of the velocity and position. Since we are in 2D there is no true cross product for vectors. Instead, you can calculate the momentum as:
p = pos.x * vel.y - pos.y * vel.x
Now onto orbital energy, represented by the symbol ε. We use this to find the eccentricity of the orbit.
ε = (len(vel) * len(vel)) / 2 - (μ / len(pos))
After that we can get eccentricity, represented with the symbol e:
e = sqrt(1 + ((2 * ε * p * p) / (μ * μ)))
The second to last thing we need to calculate is the eccentricity vector, represented with ev:
ev = ((((len(vel) * len(vel)) / μ) - (1 / len(pos))) * pos) - ((dot(pos, vel) / μ) * vel)
I know, there are a lot of brackets but I want to make it clear what goes where. Blame StackOverflow for not letting me post equation images.
The final value is the argument of periapsis. Because we are in 2D we need to use this formula to calculate it:
w = atan2(ev.y, ev.x)
we will use this to orient our orbital path correctly.
Step 4: Keplers Equation
Now is where we get to predict the orbital positions using all the information we calculated above.
First, we need n. n is the radians / second that the Object is traveling around the Attractor. It is fairly straightforward to calculate, it is 2π/T where T is the period. This value is used when we calculate the mean anomaly in the predictive step.
Now we get into the loop. You can set the number of steps you want to integrate over to whatever you want, the higher the number the closer each point along the orbit will be. In my case, I have a step of 100, so in my for loop declaration, I will loop 100 times before exiting. In addition, you will want to define a max tries value because we need to do an integration (don't worry, not as scary as it sounds) to be able to get the correct Eccentric Anomaly.
Now that we are in the loop, we need to calculate the current mean anomaly:
ma = n * (T * (i / steps))
Where:
T is the period of the orbit in seconds
i is the current iterative step
n is speed from earlier (radians/second)
Now we do the integration to solve Kepler's Equation. This can be done using Newton's method. Basically, we take Kepler's Equation and its derivative and iterate over them until the delta value between the two of them is arbitrarily low.
This is why we need max tries, it is possible that this while loop iterates forever and never converges on a value in which case we need to bail out so we don't get stuck.
//Eccentric Anomaly
var ea = ma;
while(tries < maxTries)
{
tries++;
//Keplers equation
var dx = ea - e * sin(ea) - ma;
//Derivative of Keplers equation
var dy = 1 - e * cos(ea);
var dt = dx / dy;
ea -= dt;
if(abs(dt) < 10^-8) break;
}
See, the integration wasn't so hard. This loop is an implementation of Newton's method and will oscillate toward to correct value. It should be noted that his method is quick and dirty and produces okay results. But this is the only method I understand so this is why I used it.
Step 5: Calculating Orbital Position
Next up is where we calculate the orbital position. This is simple and I stole it directly from this post.
p = a * (cos(ea) - e)
q = a * sin(ea) * sqrt(1 - (e * e))
You can plot these two values as X and Y and you will get an orbit that looks correct in some cases, but we need to rotate it using the argument of periapsis we calculated earlier. Again, stolen from this post.
x = cos(w) * p - sin(w) * q
y = sin(w) * p - cos(w) * q
And that's it. You're done. You have the X and Y coordinate at the current step and you can plot it on the screen however you like. As the for loop continues to iterate, you will get the full orbital path from start to finish.
I hope this essay helps someone out there!
All the equations I used can be found on Wikipedia just by going to this page and navigating to the corresponding element.

Related

fitness in inverted pendulum

What is the fitness function used to solve an inverted pendulum ?
I am evolving neural networks with genetic algorithm. And I don't know how to evaluate each individual.
I tried minimize the angle of pendulum and maximize distance traveled at the end of evaluation time (10 s), but this won't work.
inputs for neural network are: cart velocity, cart position, pendulum angular velocity and pendulum angle at time (t). The output is the force applied at time (t+1)
thanks in advance.
I found this paper which lists their objective function as being:
Defined as:
where "Xmax = 1.0, thetaMax = pi/6, _X'max = 1.0, theta'Max =
3.0, N is the number of iteration steps, T = 0.02 * TS and Wk are selected positive weights." (Using specific values for angles, velocities, and positions from the paper, however, you will want to use your own values depending on the boundary conditions of your pendulum).
The paper also states "The first and second terms determine the accumulated sum of
normalised absolute deviations of X1 and X3 from zero and the third term when minimised, maximises the survival time."
That should be more than enough to get started with, but i HIGHLY recommend you read the whole paper. Its a great read and i found it quite educational.
You can make your own fitness function, but i think the idea of using a position, velocity, angle, and the rate of change of the angle the pendulum is a good idea for the fitness function. You can, however, choose to use those variables in very different ways than the way the author of the paper chose to model their function.
It wouldn't hurt to read up on harmonic oscillators either. They take the general form:
mx" + Bx' -kx = Acos(w*t)
(where B, or A may be 0 depending on whether or not the oscillator is damped/undamped or driven/undriven respectively).

Finite Difference Time Domain (FTDT) method for 1D EM Wave

I have attempted to write a code in order to solve the following coupled partial differential EM wave equations:
The code employs finite difference time domain using the Yee algorithm which can be read about in the following two online documents:
http://www.eecs.wsu.edu/~schneidj/ufdtd/ufdtd.pdf
http://www.eecs.wsu.edu/~schneidj/ufdtd/chap3.pdf
I want my source at the left hand side boundary to be a sinusoidal wave with parameters as such:
Ex(0,t) = E0 sin(2πft) for 0 ≤ t ≤ 1/f
The code updates the electric and magnetic field properties of the wave with each loop.
My initial code is as follows:
%FDTD Yee algorithm to solve coupled EM wave equations
clear
clc
G=50; %Specify size of the grid
f=10^3; %choose initial frequency of wave in hertz
e=1; %specify permitivity and permeability (normalised condition)
u=1;
Nt=150; %time steps
E0=1; %Electric Field initial amplitude
%Specify step sizes using corruant condition
c=3*10^8;
dx=0.01;
dt=dx/2*c;
%make constant terms
c1=-dt/(dx*e);
c2=-dt/(dx*u);
%create vgector place holders
Ex=zeros(1,G);
Hy=zeros(1,G);
%create updating loop
M=moviein(Nt);
for t=1:Nt
% Spatial Ex
for k=2:G-1
Ex(k)=Ex(k)+c1*(Hy(k)-Hy(k-1));
end
Ex(G)=0; %PEC boundary condition
%E Source at LHS boundary
Ex(1)=E0*sin(2*pi*f*t);
%Spatial Hy
for n=1:G-1
Hy(n)=Hy(n)+c2*(Ex(n)-Ex(n+1));
end
Hy(G)=0; %PMC boundary condition
plot(Ex);
M(:,t) = getframe;
end
movie(M,1);
Basically I want to create an updating movie which shows the sinusoidal wave propagating to the right hand side boundary coded as a perfect electrical conductor; therefore reflecting the wave, and then propagating back to the left hand side boundary coded as a perfect insulator; absorbing the wave.
The problems I have are as follows:
1) I'm not sure how to properly implement my desired source. It don't appear to be purely sinusoidal.
2) The wave I've coded begins to propagate but it quickly disappears for the majority of the simulation. I do not know why this is occurring
3) I do not know much about running a movie simulation and the plot oscillates as the solution is being run. How can I stop this?
Your wave attenuates because the diference equations are not correctly implemented; instead:
Ex(k)=Ex(k)+c1*(Hy(k)-Hy(k-1));
you should use
Ex1(k)=Ex(k)+c1*(Hy(k)-Hy(k-1));
and instead of:
Hy(n)=Hy(n)+c2*(Ex(n)-Ex(n+1));
you should use:
Hy1(n)=Hy(n)+c2*(Ex(n)-Ex(n+1));
and, in the end of the loop update the current "dataframe":
Hy = Hy1;
Ey = Ey1;
(you should take care also the boundary conditions).
If you want a fixed plot frame that doesn't change when your data changes, create first a axis where you can plot into, with a defined xmin/max and ymin/max, see http://www.mathworks.com/help/matlab/ref/axis.html
You should set the Courant number closer to 1 say 0.995. Thus delta_t = 0.995*delta_x/c.
Also assuming delta_x is in METRIC units then e and u should be in metric units.
I do not know about the specific coding language used but in c or c++ there is no need for intermediate variable Ey1 etc.
Also there should be at least 10 samples per wavelength for accuracy ( preferably 60). Thus wavelength = 60*delta_x and thus the frequency equals roughly of the order 10 to power of 9. Also, I think the sinesoidal source should be E0 * sin(2* pi * f * t * delta_t). You need to adjust your constants, and try it again

level log regression interpretation?

If I want to estimate a level-log regression by OLS, I do that because I believe that my x value (the independend variable) displays a diminishing marginal return on my y value (the dependend variable).
For example hours = beta0 + beta1*log(wage)
where
hours = hour worked per week
wage = hourly wage
Then OLS fits a linear line.
To interpret my beta1 cofficient I divide it by 100 by saying a 1 % increase in wage has a XX effect on hours worked per week.
But from my estimated beta1 cofficient, how can I see the diminishing effect the independend variable has on the dependend now that it is a linear line?
Suddenly after the estimation I cannot see how I can interpret this constant to be a diminishing effect on the dependend variable?
Kind Regards Maria
This should have been posted into the stat version of StackOverflow.
Anyways my suggestion is to try this (start with a basic linear model):
1) Check the plot of the residuals. If there is no sign of heteroscedasticity in the linear model, then stop. Otherwise if you can see a pattern in the residuals (funnel, sinusoids or anything else) continue. -> E[sigma_i]!=sigma for i=1..k where k = model dimensions.
2) Try with a squared model. In this case I would do:
Y = beta[0]+beta[1]*X+beta[2]*X^2
Then if your ideas are correct you should get a positive beta[1] and a negative beta[2]. Most likely with abs(beta[1])>abs(beta[2]). This mean that with for small value or X the effect of the squared component (negative) will be little to none, while with for a big value of X the negative squared component will be very strong.
Now go back to 1) if you get normal residuals you are done.
3) Try with:
Y = beta[0]+beta[1]*log(X)
and with:
Y = beta[0]+beta[1]*log(X^2)
And see which one gives you the best residuals.
There is only one issue in your reasoning. You don't have anymore a linear line, but a curve, as denoted by the relationship Y = b*LN(X). Therefore the log curve itself explains your "diminishing returns".

Programming a 3 Body Problem using matlab

I am trying to program a 3 body problem using matlab. I was given the formula for the moon's trajectory in its rotational frame in space. It's basically the ydotdot, xdotdot=GM/(x^2+y^2)^3/2 formula. What the formula is, is not that important.
THe problem I am facing is that, I am supposed to code up a program that will numerically solve the moon's trajectory equation. I'm using ODE45 to compare with since my goal is to get the same results as ODE45. My ultimate problem is that, I want to iterate through time in terms of days so tspan= [0 365]. The thins is when I convert Gravitational constant to seconds and then do tspace= [0 365] I get a completely different result then If I were to do [0 365*3600*34] representing the seconds in a year and G= 6.67e-11. It seems that my units are very weird.
I was wondering if anyone can explain why this is happening when I use ODE 45. Why can't I convert seconds to days clearly using ODE45? Is there an extra step I have to do? The only other variables in my problem is radius, distance, and the mass of the 3 bodies.
Thank you so much. I've been working on this for a very very long time. Any help would be much appreciated.
That formula for gravitational acceleration along each axis isn't correct.
Put the earth, with mass M_e, at the origin, with the moon (mass M_m) at (x,y). Then
the earth-moon distance is given by:
R_em = sqrt(x^2 + y^2)
The total earth-moon force is given by:
F_em = G*M_e*M_m/R_em^2
The total acceleration due to Earth's gravity is given by:
a_em = F_em/M_m = G*M_e/R_em^2
and is directed toward the origin. The acceleration along
each axis is then:
xdotdot = -F_em*cos(theta) = -F_em*x/R_em = -G*M_e*x/R_em^(3/2)
ydotdot = -F_em*sin(theta) = -F_em*y/R_em = -G*M_e*y/R_em^(3/2)
Note the x and y factors, which are missing from the formula you stated.
I'm not sure what you mean by "converting the gravitational constant to seconds".
The value you're using for G has units of newton-meter^2/kg^2. So it's already
expressed in the MKS (meter-kilogram-second) system, and the accelerations calculated
using this value will have units of meters/sec^2.
With a third body (say, the sun) at (x_s, y_s), you compute a new R_s representing
the moon-sun distance, and compute new acceleration vectors as above, using the
sun's mass M_s (except the acceleration is now in the direction of (x_s, y_s), rather than (0,0)). The accelerations of the moon from the gravity of the earth and the sun just add component-wise, once everything is put into a common coordinate system (here,
geocentric coordinates -- although heliocentric might be a more convenient choice, if you're simulating the sun-earth-moon system). That, plus the initial positions and velocities, should be all you need to compute the positions and velocities at the next time step.

How to vectorize a random walk simulation in MATLAB

I am rewriting a Monte Carlo simulation model in MATLAB with an emphasis on readability. The model involves many particles, represented as (x,y,z), following a random walk over a small set of states with certain termination probabilities. The information relevant for output is the number of particles that terminate in a given state.
The simulation requires enough particles that running it for each particle individually is cost prohibitive. Vectorization seems to be the way to get performance out of MATLAB, but is there any idiomatic way of creating a vectorized version of this simulation in MATLAB?
I'm beating my head against the wall to accomplish this - I've even tried creating a (nStates x nParticles) matrix representing each particle-state combination, but this approach quickly spirals out of control in terms of readability since particles bounce from state to state independently of one another. Should I just bite the bullet and switch to a language more suitable for this?
Just write the code as you normally would. Almost all matlab functions can accept and return vectorized input. For instance, to simulate a brownian motion of N particles in 1 dimension
position = zeros([N 1]); %start at origin
sigma = sqrt(D * dt); %D is diffusion coefficient, dt is time step
for j = 1:numSteps
position = position + sigma*randn(size(position));
end
if you wanted to have a different sigma for each position, you would make sigma a vector the same size as position and use "dot times" notation to indicate element by element operation
position = position + sigma.*randn(size(position));
if the scattering was an arbitrary function of position and some random element, you would just have to write a vectorized function, e.g.
function newstep = step(position)
%diffusion in a overdamped harmonic potential
newstep = -dt*k*position + D*randn(size(position));
for j = 1:numsteps; position = position + step(position);
and so on