Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 17:09 02 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MMX - Kepler’s equation

Author Message
cdeagle
Senior Member

Joined: 22/06/2014
Location: United States
Posts: 261
Posted: 12:18am 11 Apr 2017
Copy link to clipboard 
Print this post

This post describes several MMBASIC subroutines for the MicroMite eXtreme that can be used to solve Kepler's equation for circular, elliptical, parabolic and hyperbolic orbits. A short program demonstrates how to interact with each routine.

The following is a typical user interaction with the Kepler subroutines.

numerical solutions of Kepler's equation
----------------------------------------

please input the orbital eccentricity (non-dimensional)
(0 <= eccentricity)

? .78359

please input the mean anomaly in degrees
(0 <= mean anomaly <= 360)

? 221.892

kepler1 solution
----------------

eccentricity = 0.78359000

mean anomaly = 221.89200000 degrees

eccentric anomaly = 203.78501394 degrees

true anomaly = 188.39107605 degrees

iterations = 3

solution error = 0.0000000000

kepler2 solution
----------------

eccentricity = 0.78359000

mean anomaly = 221.89200000 degrees

eccentric anomaly = 203.78501394 degrees

true anomaly = 188.39107605 degrees

iterations = 2

solution error = 0.0000000000

kepler3 solution
----------------

eccentricity = 0.78359000

mean anomaly = 221.89200000 degrees

eccentric anomaly = 203.78501394 degrees

true anomaly = 188.39107605 degrees

iterations = 2

solution error = -0.0000000000

Here's a PDF document that summarizes the mathematics of each numerical method.

2017-04-11_101031_kepler.pdf

Here's the MMBASIC source code for the demo program and subroutines.



' demo_kepler.bas April 11, 2017

' demonstrates how to interact with several MMBASIC
' subroutines which solve Kepler's equation for
' circular, elliptic, parabolic and hyperbolic orbits

' MicroMite eXtreme version

'''''''''''''''''''''''''''

option default float

option base 1

const pi2 = 2.0 * pi, pidiv2 = 0.5 * pi

const dtr = pi / 180.0, rtd = 180.0 / pi

print " "
print "numerical solutions of Kepler's equation"
print "----------------------------------------"

do

print " "
print "please input the orbital eccentricity (non-dimensional)"
print "(0 <= eccentricity)"
print " "
input ecc

loop until (ecc >= 0.0)

if (ecc <> 1.0) then

do

print " "
print "please input the mean anomaly in degrees"
print "(0 <= mean anomaly <= 360)"
print " "
input manom

loop until (manom >= 0.0 and manom <= 360.0)

manom = dtr * manom

end if

print " "

if (ecc <> 1.0) then

' circular, elliptic and hyperbolic orbits

print "kepler1 solution"
print "----------------"
print " "

kepler1(manom, ecc, eanom, tanom, niter%)

kprint(ecc, manom, eanom, tanom, niter%)

print "kepler2 solution"
print "----------------"
print " "

kepler2 (manom, ecc, eanom, tanom, niter%)

kprint(ecc, manom, eanom, tanom, niter%)

if (ecc < 1.0) then

print "kepler3 solution"
print "----------------"
print " "

kepler3 (manom, ecc, eanom, tanom)

kprint(ecc, manom, eanom, tanom, 2)

end if

else

' parabolic orbits

do

print " "
print "please input the time relative to perihelion passage (days)"
print " "
input tpp

loop until (tpp >= 0.0)

do

print " "
print "please input the perihelion radius (AU)"
print " "
input rp

loop until (rp > 0.0)

kepler4(tpp, rp, ecc, rmag, tanom, niter%)

print " "
print "kepler4 solution"
print "----------------"
print " "
print "time wrt perihelion ", str$(tpp, 0, 8), " days"
print " "
print "eccentricity ", str$(ecc, 0, 10)
print " "
print "perihelion radius ", str$(rp, 0, 8), " AU"
print " "
print "heliocentric distance ", str$(rmag, 0, 8), " AU"
print " "
print "true anomaly ", str$(rtd * tanom, 0, 8), " degrees"
print " "
print "iterations ", niter%
print " "

end if

end

''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''

sub kepler1 (manom, ecc, eanom, tanom, niter%)

' solve Kepler's equation for circular,
' elliptic and hyperbolic orbits

' Danby's method

' input

' manom = mean anomaly (radians)
' ecc = orbital eccentricity (non-dimensional)

' output

' eanom = eccentric anomaly (radians)
' tanom = true anomaly (radians)
' niter% = number of algorithm iterations

''''''''''''''''''''''''''''''''''''''''''

local ktol, xma, s, c, f, fp, fpp, fppp

local delta, deltastar, deltak, sta, cta

' define convergence criterion

ktol = 1.0e-10

xma = manom - pi2 * fix(manom/pi2)

' initial guess

if (ecc = 0.0) then

' circular orbit

tanom = xma

eanom = xma

return

elseif (ecc < 1.0) then

' elliptic orbit

eanom = xma + 0.85 * sgn(sin(xma)) * ecc

else

' hyperbolic orbit

eanom = log(2.0 * xma / ecc + 1.8)

end if

' perform iterations

niter% = 0

do

if (ecc < 1.0) then

' elliptic orbit

s = ecc * sin(eanom)

c = ecc * cos(eanom)

f = eanom - s - xma

fp = 1.0 - c

fpp = s

fppp = c

else

' hyperbolic orbit

s = ecc * sinh(eanom)

c = ecc * cosh(eanom)

f = s - eanom - xma

fp = c - 1.0

fpp = s

fppp = c

end if

niter% = niter% + 1

' check for convergence

if (abs(f) <= ktol or niter% > 20) then exit do

' update eccentric anomaly

delta = -f / fp

deltastar = -f / (fp + 0.5 * delta * fpp)

deltak = -f / (fp + 0.5 * deltastar * fpp + deltastar * deltastar * fppp / 6.0)

eanom = eanom + deltak

loop

if (niter% > 20) then

print " "

print "more than 20 iterations in kepler1"

stop

end if

' compute true anomaly

if (ecc < 1.0) then

' elliptic orbit

sta = sqr(1.0 - ecc * ecc) * sin(eanom)

cta = cos(eanom) - ecc

else

' hyperbolic orbit

sta = sqr(ecc * ecc - 1.0) * sinh(eanom)

cta = ecc - cosh(eanom)

end if

tanom = atan3(sta, cta)

end sub

''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''

sub kepler2 (manom, ecc, eanom, tanom, niter%)

' solve Kepler's equation for circular,
' elliptic and hyperbolic orbits

' Danby's method with Mikkola's initial guess

' input

' manom = mean anomaly (radians)
' ecc = orbital eccentricity (non-dimensional)

' output

' eanom = eccentric anomaly (radians)
' tanom = true anomaly (radians)
' niter% = number of algorithm iterations

''''''''''''''''''''''''''''''''''''''''''

local ktol, den, xma, alpha, beta, z, s, ds

local f, fp, fpp, fppp

local delta, deltastar, deltak, sta, cta

' define convergence criterion

ktol = 1.0e-10

if (ecc = 0.0) then

' circular orbit

tanom = manom

eanom = manom

return

end if

den = 1.0 / (4.0 * ecc + 0.5)

if (ecc < 1.0) then

xma = manom - pi2 * fix(manom / pi2)

alpha = (1.0 - ecc) * den

else

xma = manom

alpha = (ecc - 1.0) * den

end if

beta = 0.5 * xma * den

z = (sqr(alpha * alpha * alpha + beta * beta) + beta) ^ (1.0/3.0)

s = 2 * beta /(z * z + alpha + alpha * alpha / (z * z))

if (ecc > 1.0) then

' hyperbolic orbit

ds = 0.071 * s ^ 5 / (ecc * (1.0 + 0.45 * s ^ 2) * (1.0 + 4.0 * s ^ 2))

else

' elliptic orbit

ds = -0.078 * s * s * s * s * s / (1.0 + ecc)

end if

s = s + ds

' initial guess

if (ecc > 1.0) then

' hyperbolic orbit

eanom = 3 * log(s + sqr(1 + s ^ 2))

else

' elliptic orbit

eanom = xma + ecc * (3.0 * s - 4.0 * s * s * s)

end if

' perform iterations

niter% = 0

do

if (ecc < 1.0) then

' elliptic orbit

s = ecc * sin(eanom)

c = ecc * cos(eanom)

f = eanom - s - xma

fp = 1.0 - c

fpp = s

fppp = c

else

' hyperbolic orbit

s = ecc * sinh(eanom)

c = ecc * cosh(eanom)

f = s - eanom - xma

fp = c - 1.0

fpp = s

fppp = c

end if

niter% = niter% + 1

' check for convergence

if (abs(f) <= ktol) then exit do

' update eccentric anomaly

delta = -f / fp

deltastar = -f / (fp + 0.5 * delta * fpp)

deltak = -f / (fp + 0.5 * deltastar * fpp + deltastar * deltastar * fppp / 6.0)

eanom = eanom + deltak

loop

if (niter% > 20) then

print " "

Print "more than 20 iterations in kepler2"

stop

end if

' compute true anomaly

if (ecc < 1.0) then

' elliptic orbit

sta = sqr(1 - ecc * ecc) * sin(eanom)

cta = cos(eanom) - ecc

else

' hyperbolic orbit

sta = sqr(ecc * ecc - 1) * sinh(eanom)

cta = ecc - cosh(eanom)

end if

tanom = atan3(sta, cta)

end sub

''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''

sub kepler3 (manom, ecc, eanom, tanom)

' solve Kepler's equation for elliptic orbits

' Gooding's two iteration method

' input

' manom = mean anomaly (radians)
' ecc = orbital eccentricity (non-dimensional)

' output

' eanom = eccentric anomaly (radians)
' tanom = true anomaly (radians)

'''''''''''''''''''''''''''''''''

local athird, ahalf, e1, emr, e, ee, sta, cta

local w, f, fd, fdd, fddd, dee

athird = 1.0 / 3.0

ahalf = 1.0 / 2.0

' convert to original algorithm argument

e1 = 1.0 - ecc

if (ecc = 0.0) then

' circular orbit

tanom = manom

eanom = manom

return

end if

' mod mean anomaly

emr = manom - pi2 * fix(manom / pi2)

if (emr < -pi) then

emr = emr + pi2

end if

if (emr > pi) then

emr = emr - pi2

end if

ee = emr

if (ee < 0.0) then

ee = -ee

elseif (ee = 0) then

eanom = ee + (manom - emr)

sta = sqr(1.0 - ecc * ecc) * sin(eanom)

cta = cos(eanom) - ecc

tanom = atan3(sta, cta)

return

end if

e = 1.0 - e1

' solve cubic equation

dcbsol(e, 2.0 * e1, 3.0 * ee, w)

ee = (ee * ee + (pi - ee) * w) / pi

if (emr < 0.0) then

ee = -ee

end if

for i% = 1 to 2

fdd = e * sin(ee)

fddd = e * cos(ee)

if ((e1 + ee * ee / 6.0) >= 0.25) then

f = (ee - fdd) - emr

fd = 1.0 - fddd

else

emkep(e1, ee, etmp)

f = etmp - emr

fd = e1 + 2.0 * e * sin(ahalf * ee) ^ 2

end if

dee = f * fd / (ahalf * f * fdd - fd * fd)

w = fd + ahalf * dee * (fdd + athird * dee * fddd)

fd = fd + dee * (fdd + ahalf * dee * fddd)

ee = ee - (f - dee * (fd - w)) / fd

next i%

eanom = ee + (manom - emr)

' compute true anomaly

sta = sqr(1.0 - ecc * ecc) * sin(eanom)

cta = cos(eanom) - ecc

tanom = atan3(sta, cta)

end sub

'''''''''''''''''''''
'''''''''''''''''''''

sub dcbsol (a, b, c, y)

' solve cubic equation function

'''''''''''''''''''''''''''''''

local bsq, d

if (a = 0.0 and b = 0.0 or c = 0) then

y = 0.0

else

bsq = b * b

d = sqr(a) * abs(c)

d = dcubrt(d + sqr(b * bsq + d * d)) ^ 2

y = 2.0 * c / (d + b + bsq / d)

end if

end sub

'''''''''''''''''''''''''
'''''''''''''''''''''''''

function dcubrt(x) as float

' cube root function

''''''''''''''''''''

local athird, yy, tmp

athird = 1.0 / 3.0

yy = abs(x)

if (x = 0.0) then

tmp = 0.0

else

tmp = yy ^ athird

tmp = tmp - athird * (tmp - yy / tmp ^ 2)

tmp = sgn(x) * tmp

end if

dcubrt = tmp

end function

''''''''''''''''''
''''''''''''''''''

sub emkep(e1, ee, y)

' solves ee - (1 - e1) * sin(ee)
' when (e1, ee) is close to (1, 0)

''''''''''''''''''''''''''''''''''

local ee2, term, d, y0

y = e1 * ee

ee2 = -ee * ee

term = ee * (1.0 - e1)

d = 0.0

do

d = d + 2

term = term * ee2 / (d * (d + 1))

y0 = y

y = y - term

if (y0 = y) then

exit do

end if

loop

end sub

''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''

sub kepler4(t, q, ecc, r, tanom, niter%)

' Kepler's equation for heliocentric,
' parabolic and near-parabolic orbits

' input

' t = time relative to perihelion passage (days)
' q = perihelion radius (AU)
' ecc = orbital eccentricity (non-dimensional)

' output

' r = heliocentric distance (AU)
' tanom = true anomaly (radians)
' niter% = number of algorithm iterations

''''''''''''''''''''''''''''''''''''''''''

local e2, fac, tau, e20, a, b, u, u2

local c1, c2, c3, x, y

const kgauss = 0.01720209895

e2 = 0.0

fac = 0.5 * ecc

niter% = 0

tau = kgauss * t

do

niter% = niter% + 1

e20 = e2

a = 1.5 * sqr(fac / (q * q * q)) * tau

b = (sqr(a * a + 1.0) + a)^(1.0/3.0)

u = b - 1.0 / b

u2 = u * u

e2 = u2 * (1.0 - ecc) / fac

stumpff(e2, c1, c2, c3)

fac = 3.0 * ecc * c3

' check for convergence

if (abs(e2 - e20) < 1.0e-9) then exit do

loop

if (niter% > 15) then

print " "

print "more than 15 iterations in kepler4"

stop

end if

' heliocentric distance (AU)

r = q * (1.0 + u2 * c2 * ecc / fac)

' x and y coordinates

x = q * (1.0 - u2 * c2 / fac)

y = q * sqr((1.0 + ecc) / fac) * u * c1

' true anomaly (radians)

tanom = atan3(y, x)

end sub

'''''''''''''''''''''''''
'''''''''''''''''''''''''

sub stumpff(e2, c1, c2, c3)

' Stumpff functions for argument E^2

' input

' e2 = eccentric anomaly squared

' output

' c1, c2, c3 = Stumpff functions

'''''''''''''''''''''''''''''''''

local deltac, n%

c1 = 0.0

c2 = 0.0

c3 = 0.0

deltac = 1.0

n% = 1

do

c1 = c1 + deltac

deltac = deltac / (2.0 * n%)

c2 = c2 + deltac

deltac = deltac / (2.0 * n% + 1.0)

c3 = c3 + deltac

deltac = -e2 * deltac

n% = n% + 1

' check for convergence

if (abs(deltac) < 1.0e-12) then exit do

loop

end sub

''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''

sub kprint(ecc, manom, eanom, tanom, niter%)

' print results subroutine

''''''''''''''''''''''''''

local kerror

if (ecc < 1.0) then

' circular and elliptic orbits

print "eccentricity = ", str$(ecc, 0, 8)
print " "
print "mean anomaly = ", str$(rtd * manom, 0, 8), " degrees"
print " "
print "eccentric anomaly = ", str$(rtd * eanom, 0, 8), " degrees"
print " "
print "true anomaly = ", str$(rtd * tanom, 0, 8), " degrees"
print " "
print "iterations = ", niter%
print " "

kerror = eanom - ecc * sin(eanom) - manom

print "solution error = ", str$(kerror, 0, 10)
print " "

else

' hyperbolic orbits

print "eccentricity = ", str$(ecc, 0, 8)
print " "
print "hyperbolic anomaly = ", str$(rtd * manom, 0, 8), " degrees"
print " "
print "eccentric anomaly = ", str$(rtd * eanom, 0, 8), " degrees"
print " "
print "true anomaly = ", str$(rtd * tanom, 0, 8), " degrees"
print " "
print "iterations = ", niter%
print " "

kerror = ecc * sinh(eanom) - eanom - manom

print "solution error = ", str$(kerror, 0, 10)
print " "

end if

end sub

'''''''''''''''''''''''
'''''''''''''''''''''''

function cosh(x) as float

' hyperbolic cosine function

''''''''''''''''''''''''''''

cosh = 0.5 * (exp(x) + exp(-x))

end function

'''''''''''''''''''''''
'''''''''''''''''''''''

function sinh(x) as float

' hyperbolic sine function

''''''''''''''''''''''''''

sinh = 0.5 * (exp(x) - exp(-x))

end function

'''''''''''''''''''''''''''
'''''''''''''''''''''''''''

function atan3(a, b) as float

' four quadrant inverse tangent function

' input

' a = sine of angle
' b = cosine of angle

' output

' atan3 = angle (0 =< atan3 <= 2 * pi; radians)

''''''''''''''''''''''''''''''''''''''''''''''''

local c

if (abs(a) < 1.0e-10) then

atan3 = (1.0 - sgn(b)) * pidiv2

exit function

else

c = (2.0 - sgn(a)) * pidiv2

endif

if (abs(b) < 1.0e-10) then

atan3 = c

exit function

else

atan3 = c + sgn(a) * sgn(b) * (abs(atn(a / b)) - pidiv2)

endif

end function
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024