You are on page 1of 51

# Gaussian Orbit

Determination
Finding the Orbit of Ceres
Aaron Eiben & Gregory Tewksbury

## VERSION 8 NOTEBOOK UPDATED

TO VERSION 9!
VERSION 9 NOTEBOOK UPDATED
TO VERSION 10!
Version 8 functions have been commented out and
replaced with their version 9 counterparts.
Important! Mathematica 9 seems to deal with numerical
precision differently than did version 8. While there is
probably a very good reason for this, it kills this
notebook by returning results that have no significant
figures and are therefore useless for computation!
Thus, the minimum precision is set to machine
precision. This solves the sig. fig. problem and
produces results that are identical to the version 8
notebook, but now Mathematica complains with each
some reason, unit conversions. Therefore, these
complaints will be turned off . . .
\$MinPrecision=\$MachinePrecision;
Off[Precision::precsm,SetPrecision::precsm]

## Load the PhysicalConstants package for easy unit conversions:

EDIT: This package has been integrated!
Page 1

(*<<PhysicalConstants`*)
Nn=3;
Origin={0,0,0};

We enter the times of our observations in year, month, day, hour, minute,
second format:
Clear[NDate]
Evaluate[Table[NDate[i],{i,Nn}]]=
{{1801,1,2,20,39,4.6},
{1801,1,22,19,20,21.7},
{1801,2,11,18,11,58.2}}
{{1801,1,2,20,39,4.6},{1801,1,22,19,20,21.7},{1801,2,11,18,
11,58.2}}

These are converted into our standard units of years, and we find the time
intervals between each observation. Mathematica uses 1900 as the
reference year, however, as we are only interested in time intervals, this
reference is arbitrary:
Clear[Nt]
(*Table[Nt[i]=Convert[AbsoluteTime[NDate[i]]Second,Year]/Ye
ar,{i,Nn}]*)
Table[Nt[i]=QuantityMagnitude[UnitConvert[Quantity[Absolute
Time[NDate[i]],"Second"],"Year"]],{i,Nn}]
{-99.0606562468290208016236,-99.0060114884576357179097,-98.
951347089041095890411}
Clear[Nt]
Evaluate[Append[Table[Nt[i],{i,{3,1}}],Nt[13]]]=
Append[Differences[Table[Nt[i],{i,Nn}]],Sum[Nt[i],{i,{3,1}}
]]
{0.0546447583713850837138,0.054664399416539827499,0.1093091
57787924911213}

## In lieu of making actual observations (which can be done with the

telescopes in the astronomy lab), we obtain the declinations () and right
ascensions () of Ceres in degrees and hours, respectively, at the times
listed above from a Wolfram server:
Clear[CeresData]
Table[CeresData[i]=QuantityMagnitude[AstronomicalData["Cere
s",#,TimeZone->1]]&/@({#,NDate[i]}&/@{"Declination","RightA
scension"}),{i,Nn}]

Page 2

{{10.31907452185567,2.664143042283759},{12.17044962463662,2
.749211879943253},{14.40720484717656,2.978690498437773}}

## These angular coordinates must be converted into radians for later

conversion into Cartesian coordinates. To accomplish this, we note that

Clear[DecRAConverter]
DecRAConverter[{_,_}]:={(90-) Pi/180, Pi/12}
Clear[ConvertedCeresData]
Table[ConvertedCeresData[i]=DecRAConverter[CeresData[i]],{i
,Nn}]
{{1.3906945006298557,0.6974710174792517},{1.358381909396879
6,0.7197419870992923},{1.3193431662023791,0.779819348934152
2}}

The same process is done for the Sun. These data must be obtained from
a reference source, as the Sun will likely be below the horizon at the times
our observations are made. Moreover, students should not be pointing a
telescope anywhere near the Sun without proper solar filters and
competent supervision!
Clear[SunData]
Table[SunData[i]=QuantityMagnitude[AstronomicalData["Sun",#
,TimeZone->1]]&/@({#,NDate[i]}&/@{"Declination","RightAscen
sion"}),{i,Nn}]
{{-22.91901182368604,18.87260407392571},{-19.65550060681863
,20.30877436827272},{-14.00105754545583,21.66277058728244}}
Clear[ConvertedSunData]
Table[ConvertedSunData[i]=DecRAConverter[SunData[i]],{i,Nn}
]
{{1.9708085444217282,4.940836192729485},{1.9138495285116251
,5.316824696564857},{1.8151608797242965,5.671300077783963}}

Additionally, we may look up the distances between the Earth and the Sun
at the given times in astronomical units:
Clear[EarthSunDistance]
Page 3

(*Table[EarthSunDistance[i]=Convert[AstronomicalData["Sun",
{"Distance",NDate[i]},TimeZone 1]Meter,AU]/AU,{i,Nn}]*)
Table[EarthSunDistance[i]=QuantityMagnitude[UnitConvert[Ast
ronomicalData["Sun",{"Distance",NDate[i]},TimeZone->1],"AU"
]],{i,Nn}]
{0.983191072677480,0.984468788380674,0.987625267479505}

With these data, we can construct the Sun s geocentric positions (or

## Earth s heliocentric positions) in spherical coordinates:

Clear[SphericalSunPoints]
Table[SphericalSunPoints[i]=Prepend[ConvertedSunData[i],Ear
thSunDistance[i]],{i,Nn}]
{{0.983191072677480,1.9708085444217282,4.940836192729485},{
0.984468788380674,1.9138495285116251,5.316824696564857},{0.
987625267479505,1.8151608797242965,5.671300077783963}}

Finally, we must define the vernal point (the position of the Sun at the
vernal equinox) for later reference:
VernalPoint={0,0};
ConvertedVernalPoint=DecRAConverter[VernalPoint]
{/2,0}

## These can then be converted into Cartesian coordinates. Mathematica 9

can do this transformation with one simple commandunfortunately, I am
running version eight . . .
EDIT: I am now running version 9! However, for some reason,
CoordinateTransform cannot handle the given solar points:
CoordinateTransform["Spherical" ->
"Cartesian",SphericalSunPoints[1]]
CoordinateTransform::bdpt: Evaluation point
{0.983191072677480,1.9708085444217282,4.940836192729485} is
incompatible with the coordinate assumptions of the specified coordinate
chart. >>

CoordinateTransform[Spherical->Cartesian,{0.983191072677480
,1.9708085444217282,4.940836192729485}]

Nevertheless, the function can obtain the symbolic mapping without issue,
Page 4

which can then be applied to the spherical solar coordinates. That could
have been done by hand (and was in version 8)!
Clear[CartesianSunPoints]
(*Table[CartesianSunPoints[i]={#[[1]]
Sin[#[[2]]]Cos[#[[3]]],#[[1]] Sin[#[[2]]]Sin[#[[3]]],#[[1]]
Cos[#[[2]]]}&[SphericalSunPoints[i]],{i,Nn}]*)
Table[CartesianSunPoints[i]=CoordinateTransform["Spherical"
->
,{i,Nn}]
{{0.2050811956804456,-0.8820467445378197,-0.382883701691789
5},{0.5268722599196133,-0.7628439164108162,-0.3311398137009
807},{0.7844193879680317,-0.5504496040065058,-0.23894586456
53943}}

## The same is done for the vernal point:

(*CartesianVernalUnit={Sin[#[[1]]]Cos[#[[2]]],Sin[#[[1]]]Si
n[#[[2]]],Cos[#[[1]]]}&[ConvertedVernalPoint]*)
CartesianVernalUnit=CoordinateTransform["Spherical" ->
"Cartesian",Prepend[ConvertedVernalPoint,1]]
{1,0,0}

## Let us plot these points:

Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[CartesianSunPoints/@Range[Nn]]},
{Lighter[Blue,0.5],
Point[Origin]}},
Arrow[{CartesianSunPoints[#],Origin}&/@Range[Nn]]}},
Axes->True,
AxesLabel->{x,y,z}]

Page 5

0.0
0.1
z
0.2

0.0
0.2

0.3
0.4
y

0.0
0.6

0.2
0.4
x

0.8

0.6
0.8

Earth (the pale blue dot) sits at the origin. The Sun (yellow dots) moves
around it in the ecliptic plane. Arrows have been drawn from the Suns to
the Earth in anticipation of a shift to a heliocentric reference frame.
We now wish to create unit vectors in the direction of Ceres. This is
achieved via the same spherical to Cartesian coordinate transformation as
before:
Clear[CartesianCeresUnits]
(*Table[CartesianCeresUnits[i]={Sin[#[[1]]]Cos[#[[2]]],Sin[
#[[1]]]Sin[#[[2]]],Cos[#[[1]]]}&[ConvertedCeresData[i]],{i,
Nn}]*)
Table[CartesianCeresUnits[i]=CoordinateTransform["Spherical
" -> "Cartesian",Prepend[ConvertedCeresData[i],1]],{i,Nn}]
{{0.7540716704866178,0.6318927497373350,0.1791297535277473}
,{0.7350749930171924,0.6443752027585923,0.2108206648092110}
,{0.6886796860832983,0.6810382048269793,0.2488116828893994}
}

## Plotting these vectors produces the following:

Graphics3D[
{{PointSize[Large],
Page 6

{Darker[Yellow],
Point[CartesianSunPoints/@Range[Nn]]},
{Lighter[Blue,0.5],
Point[Origin]}},
Arrow[{CartesianSunPoints[#],Origin}&/@Range[Nn]],
Arrow[{Origin,CartesianCeresUnits[#]}&/@Range[Nn]]}},
Axes->True,
AxesLabel->{x,y,z}]
0.5

0.0

0.5

0.2

0.0
0.2

0.0
0.2
0.4
x

0.6
0.8

## We now shift into a heliocentric frame of reference:

Clear[CartesianEarthPoints]
Table[CartesianEarthPoints[i]=Origin-CartesianSunPoints[i],
{i,Nn}]
{{-0.2050811956804456,0.8820467445378197,0.3828837016917895
Page 7

},{-0.5268722599196133,0.7628439164108162,0.331139813700980
7},{-0.7844193879680317,0.5504496040065058,0.23894586456539
43}}

and plot:
Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]},{i,Nn}]]
}},
Axes->True,
AxesLabel->{x,y,z}]

1.5

0.4
z
0.2

1.0

0.0

y
0.5

0.5

0.0
0.5

0.0

At this point, we have positions of Earth relative to the Sun and lines of
sight from Earth to Ceres at three different times. Following the description

Page 8

## of Gauss method as described by Jonathan Tennenbaum and Bruce

Director [1], we can approximate the positions of Ceres along the sight
lines at the specified times. From these positions, one can obtain a
reasonably accurate approximation of Ceres orbit. Let us begin this

## and Ceres lines of sight:

Clear[EarthPointEquations]
Table[EarthPointEquations[{i,e_}]=e
CartesianEarthPoints[i],{i,Nn}]
{{-0.2050811956804456 e,0.8820467445378197
e,0.3828837016917895 e},{-0.5268722599196133
e,0.7628439164108162 e,0.3311398137009807
e},{-0.7844193879680317 e,0.5504496040065058
e,0.2389458645653943 e}}
Clear[CeresVectorEquations]
Table[CeresVectorEquations[{i,c_}]=CartesianEarthPoints[i]+
c CartesianCeresUnits[i],{i,Nn}]
{{-0.2050811956804456+0.7540716704866178
c,0.8820467445378197+0.6318927497373350
c,0.3828837016917895+0.1791297535277473
c},{-0.5268722599196133+0.7350749930171924
c,0.7628439164108162+0.6443752027585923
c,0.3311398137009807+0.2108206648092110
c},{-0.7844193879680317+0.6886796860832983
c,0.5504496040065058+0.6810382048269793
c,0.2389458645653943+0.2488116828893994 c}}

Gauss method for determining Ceres positions hinges upon the ratios of

Page 9

areas of triangles formed by the dwarf planet s positions and the Sun. In
particular, we want to know
(T23/T13).
T12/T13,
As Ceres positions are unknown, these triangular areas are unknown;
however, they can be approximated by the areas of the orbital arcs
between the unknown points, which are proportional to the elapsed times
between observations:
T12/T13 S12/S13=t12/t13,

T23/T13 S23/S13=(t23/t13).

## We define these ratios:

Clear[NSr]
Table[NSr[i]=Nt[i]/Nt[13],{i,{3,1}}]
{0.49991015828155564895,0.50008984171844435105}

and proceed with Gauss method. The first step is to find points F1 and F3
along the first and third Earth position vectors such that
F3/E3=(t12/t13):
F1/E1=t23/t13,
Clear[FPoints]
Evaluate[FPoints/@{1,3}]=EarthPointEquations/@{{1,NSr[1]},{
3,NSr[3]}}
{{-0.1025590226872634,0.4411026168641874,0.1914762497756191
},{-0.3921392203982197,0.2751753486649119,0.119451464975609
4}}

## These vectors are then combined to form a point F:

FPoints[0]=Total[FPoints/@{1,3}]
{-0.4946982430854831,0.7162779655290993,0.3109277147512285}
Graphics3D[
{Point[FPoints/@{1,3}],
Point[FPoints[0]],
{PointSize[Large],
{Darker[Yellow],
Page 10

Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]},{i,Nn}]],
{Dashed,
Arrow[{FPoints[#],FPoints[0]}&/@{1,3}]}}},
Axes->True,
AxesLabel->{x,y,z}]

1.5

0.4
z
0.2

1.0

0.0

y
0.5

0.5

0.0
0.5

0.0

The first and third Ceres lines of sight (L1 and L3) are shifted to point F;
from them, we derive a plane Q that passes through F:
Clear[ShiftedCeresVectorEquations]
Table[ShiftedCeresVectorEquations[{i,sc_}]=FPoints[0]+sc
CartesianCeresUnits[i],{i,{1,3}}]
{{-0.4946982430854831+0.7540716704866178
sc,0.7162779655290993+0.6318927497373350
sc,0.3109277147512285+0.1791297535277473
sc},{-0.4946982430854831+0.6886796860832983
Page 11

sc,0.7162779655290993+0.6810382048269793
sc,0.3109277147512285+0.2488116828893994 sc}}
QNormal=Normalize[Cross@@CartesianCeresUnits/@{1,3}]
{0.3283092197645911,-0.5988619051150029,0.7304638764645345}
Qz=z/.Simplify[Solve[QNormal.({x,y,z}-FPoints[0])==0,z][[1]
]]
-0.4986476801296103-0.4494530535221219 x+0.819837810479433
y
Show[{
Graphics3D[
{Point[FPoints/@{1,3}],
Point[FPoints[0]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]},{i,Nn}]],
{Dashed,
Arrow[{FPoints[#],FPoints[0]}&/@{1,3}],
Arrow[Table[ShiftedCeresVectorEquations[{i,#}]&/@{0,1},{i,{
1,3}}]]}}}],
ParametricPlot3D[{x,y,Qz},{x,-0.5,0.3},{y,0.7,1.4},
PlotStyle->{{Opacity[0.25],Brown}},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]

Page 12

## By construction, the intersection of L2 with plane Q is our first

approximation of the second position of Ceres, P2:
P2Solution=Solve[CeresVectorEquations[{2,c}]=={x,y,Qz}][[1]
]
{c->2.509839169621373,x->1.318047750164093,y->2.38012204022
7045}
CartesianCeresPoints[2]=CeresVectorEquations[{2,c}]/.P2Solu
tion
{1.318047750164093,2.380122040227045,0.8602657760047565}
CeresSunDistance[2]=Norm[CartesianCeresPoints[2]]
2.853469467762402
Show[{
Graphics3D[
Page 13

{Point[FPoints/@{1,3}],
Point[FPoints[0]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]},
{Gray,
Point[CartesianCeresPoints[2]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]},{i,{1,3}}]],
Arrow[CeresVectorEquations[{2,#}]&/@{0,c}/.P2Solution],
{Dashed,
Arrow[{FPoints[#],FPoints[0]}&/@{1,3}],
Arrow[Table[ShiftedCeresVectorEquations[{i,#}]&/@{0,1},{i,{
1,3}}]]}}}],
ParametricPlot3D[{x,y,Qz},{x,-0.5,0.3},{y,0.7,1.4},
PlotStyle->{{Opacity[0.25],Brown}},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]

Page 14

## At this time we have found a first approximation of Ceres second position.

Before proceeding farther, let us deal with the fact that the shallow angle
between the observed line of sight L2 and the constructed plane Q means
that any small error in Q turns into a gigantic error in P2. The former error
stems from our use of orbital sectors to approximate triangular areas.
Fortunately Gauss, being a master of geometry, formulated a correction
factor which goes as follows:
G=1+22 t12t23/r ,
r2 being the second distance between Ceres and the Sun. Initially, one
might be put off by the fact that G, which is used to calculate r2, depends
upon r2. However, we already have one estimate of r2. If we insert this into
G, then we may calculate a better approximation, which can then be used
to recalculate G, and so on. Evidently, Gauss abhorred this kind of brute
force mechanism and developed methods of rapidly converging upon the
true G and r2, but he did not have Mathematica to carry out his calculations
for himwe do:
3
2

NG=1+22 Nt[3]Nt[1]/CeresSunDistance[2]3
Page 15

1.002537833595109918

The first correction factor is quite small, but we can do much better. The
following loop will iteratively calculate r2 and G until they converge on the
limits of machine precision:
Distances={CeresSunDistance[2]};
GaussFactors={NG};
time=AbsoluteTime[];
Catch[Do[
Clear[NSr];
Table[NSr[i]=NG Nt[i]/Nt[13],{i,{3,1}}];
Clear[FPoints];
Evaluate[FPoints/@{1,3}]=EarthPointEquations/@{{1,NSr[1]},{
3,NSr[3]}};
FPoints[0]=Total[FPoints/@{1,3}];
Clear[ShiftedCeresVectorEquations];
Table[ShiftedCeresVectorEquations[{i,sc_}]=FPoints[0]+sc
CartesianCeresUnits[i],{i,{1,3}}];
QNormal=Normalize[Cross@@CartesianCeresUnits/@{1,3}];
Qz=z/.Simplify[Solve[QNormal.({x,y,z}-FPoints[0])==0,z][[1]
]];
P2Solution=Solve[CeresVectorEquations[{2,c}]=={x,y,Qz}][[1]
];
CartesianCeresPoints[2]=CeresVectorEquations[{2,c}]/.P2Solu
tion;
AppendTo[Distances,CeresSunDistance[2]=Norm[CartesianCeresP
oints[2]]];
AppendTo[GaussFactors,NG=1+22
Nt[3]Nt[1]/CeresSunDistance[2]3];
If[Differences[Distances[[-2;;-1]]][[1]]==0,Throw[Null],Nul
l],
{100}]]
(AbsoluteTime[]-time)Second
Length[Rest[Distances]]
{CeresSunDistance[2],NG}
0.03802430000000000 Second
16
{2.750890747152010,1.002832453601296655}
Page 16

## Within sixteen very short steps, we converge onto a value of r2 that is as

precise as our machine can handle! We are now ready to calculate Ceres

## other positions. Again, by construction, Ceres second position (P2) lies

within the plain Q, which was generated by the first and third line of sight
vectors after they had been shifted to the point F. Therefore, we can
express P2 as a linear combination of these vectors. The coefficients of this
expansion are as follows:
Clear[QpScalars]
Table[QpScalars[i]=Qp[i]/.Solve[Total[Qp[#]
CartesianCeresUnits[#]&/@{1,3}]==CartesianCeresPoints[2]-FP
oints[0]][[1]],{i,{1,3}}]
{1.082298159096267,1.33248380866884}
Show[{
Graphics3D[
{Point[FPoints/@{1,3}],
Point[FPoints[0]],
Point[Table[ShiftedCeresVectorEquations[{i,QpScalars[i]}],{
i,{1,3}}]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]},
{Gray,
Point[CartesianCeresPoints[2]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]},{i,{1,3}}]],
Arrow[CeresVectorEquations[{2,#}]&/@{0,c}/.P2Solution],
{Dashed,
Arrow[{FPoints[#],FPoints[0]}&/@{1,3}],
Arrow[Table[ShiftedCeresVectorEquations[{i,#}]&/@{0,QpScala
Page 17

rs[i]},{i,{1,3}}]],
Arrow[Table[{ShiftedCeresVectorEquations[{i,QpScalars[i]}],
CartesianCeresPoints[2]},{i,{1,3}}]]}}}]},
Axes->True,
AxesLabel->{x,y,z}]

0.8
0.6
z
0.4
0.2
0.0

2.0
1.5
1.0 y
0.5
0.0

0.5

0.5
1.0

0.0

It is now a simple matter of working backward and scaling the line of sight
vectors by these coefficients divided by the approximate triangular area
ratios:
Table[CartesianCeresPoints[i]=CartesianEarthPoints[i]+Carte
sianCeresUnits[i]QpScalars[i]/NSr[i],{i,{1,3}}]
{{1.422276912041750,2.245731165718013,0.7694626810473485},{
1.046034831422242,2.360593391870084,0.9002669460230068}}
Norm[CartesianCeresPoints[#]]&/@Range[Nn]
{2.767354856307513,2.750890747152010,2.734423267234036}
Show[{
Graphics3D[
{Point[FPoints/@{1,3}],
Point[FPoints[0]],
Page 18

Point[Table[ShiftedCeresVectorEquations[{i,QpScalars[i]}],{
i,{1,3}}]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]},
{Gray,
Point[CartesianCeresPoints/@Range[Nn]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[Table[(#+CartesianEarthPoints[i])&/@{Origin,Cartesian
CeresUnits[i]QpScalars[i]/NSr[i]},{i,{1,3}}]],
Arrow[CeresVectorEquations[{2,#}]&/@{0,c}/.P2Solution],
{Dashed,
Arrow[{FPoints[#],FPoints[0]}&/@{1,3}],
Arrow[Table[ShiftedCeresVectorEquations[{i,#}]&/@{0,QpScala
rs[i]},{i,{1,3}}]],
Arrow[Table[{ShiftedCeresVectorEquations[{i,QpScalars[i]}],
CartesianCeresPoints[2]},{i,{1,3}}]]}}}]},
Axes->True,
AxesLabel->{x,y,z}]

Page 19

0.8
0.6
z
0.4
0.2
0.0

2.0
1.5
1.0 y

0.5
0.0

0.5

0.5
1.0

0.0

Show[{
Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[CartesianEarthPoints/@Range[Nn]]},
{Gray,
Point[CartesianCeresPoints/@Range[Nn]]}},
Arrow[{Origin,CartesianEarthPoints[#]}&/@Range[Nn]],
Arrow[{Origin,CartesianCeresPoints[#]}&/@Range[Nn]]}}]},
Axes->True,
AxesLabel->{x,y,z}]

Page 20

0.8
0.6
z
0.4
0.2
0.0

2.0
1.5
1.0 y

0.5
0.0

0.5

0.5
1.0

0.0

With that, the three positions of Ceres have been obtained! We are now
ready to calculate Ceres orbit. Let us begin by learning how to rotate our
points in Mathematica:
EarthOrbitNormal=Normalize[Cross@@CartesianEarthPoints/@{1,
3}]
EarthOrbitPlane=EarthOrbitNormal.{x,y,z}==0
EarthOrbitPlaneZ=z/.Solve[EarthOrbitPlane,z][[1]]
EarthInclinationAxis=Normalize[Cross[{0,0,1},EarthOrbitNorm
al]]
EarthRotationMatrix=RotationMatrix[{EarthOrbitNormal,{0,0,1
}}]
{5.133007170822883*10-6,-0.3981872408585286,0.91730415958455
4}
5.133007170822883*10-6 x-0.3981872408585286
y+0.917304159584554 z==0
1.090150948898890 (-5.133007170822883*10-6
x+0.3981872408585286 y)
Page 21

{0.999999999916912,0.00001289093834179405,0}
{{0.999999999986258,1.066026979829785*10-6,-5.13300717082288
3*10-6},{1.066026979829785*10-6,0.917304159598296,0.398187240
8585286},{5.133007170822883*10-6,-0.3981872408585286,0.91730
4159584554}}
CeresOrbitNormal=Normalize[Cross@@CartesianCeresPoints/@{1,
3}]
CeresOrbitPlane=CeresOrbitNormal.{x,y,z}==0
CeresOrbitPlaneZ=z/.Solve[CeresOrbitPlane,z][[1]]
CeresInclinationAxis=Normalize[Cross[{0,0,1},CeresOrbitNorm
al]]
CeresRotationMatrix=RotationMatrix[{CeresOrbitNormal,{0,0,1
}}]
{0.1811690257373910,-0.4195076106284812,0.8894892628571450}
0.1811690257373910 x-0.4195076106284812
y+0.8894892628571450 z==0
1.124240664567306 (-0.1811690257373910 x+0.4195076106284812
y)
{0.918048006825590,0.3964692386094553,0}
{{0.982629054034949,0.04022345434874737,-0.1811690257373910
},{0.04022345434874737,0.906860208822196,0.4195076106284812
},{0.1811690257373910,-0.4195076106284812,0.889489262857145
0}}
Show[{
Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Lighter[Blue,0.5],
Point[(CeresRotationMatrix.CartesianEarthPoints[#])&/@Range
[Nn]]},
{Gray,
Point[(CeresRotationMatrix.CartesianCeresPoints[#])&/@Range
[Nn]]}},
Arrow[{Origin,CeresRotationMatrix.CartesianEarthPoints[#]}&
/@Range[Nn]],
Page 22

Arrow[{Origin,CeresRotationMatrix.CartesianCeresPoints[#]}&
/@Range[Nn]],
{Dashed,
Arrow[{Origin,CeresRotationMatrix.EarthOrbitNormal}],
Arrow[{Origin,CeresRotationMatrix.CeresOrbitNormal}]}}}],
ParametricPlot3D[{x,y,0},{x,-0.8,1.4},{y,0,2.6},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]

Clear[HorizontalCeresPoints]
Table[HorizontalCeresPoints[i]=Chop[CeresRotationMatrix.Car
tesianCeresPoints[i]],{i,Nn}]
{{1.348498877412522,2.416568575138297,0},{1.157410896897420
,2.495556033935053,0},{0.959714951907322,2.560472186038424,
0}}
CeresOrbitVertical=Chop[CeresRotationMatrix.CeresOrbitNorma
Page 23

l]
{0,0,1.000000000000000}
RotatedVernalUnit=CeresRotationMatrix.CartesianVernalUnit
{0.982629054034949,0.04022345434874737,0.1811690257373910}

## At this point, we have obtained a heliocentric coordinate system in which

Ceres orbital plane is horizontal. As the planet s orbit is an ellipse, it can
be represented as a conic sectionthe intersection of a plane U with a
cone. To find this intersection, we first create a right cone that is normal to
the plane whose vertex is located at the Sun:
Show[{
Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
x y
},{x,-3,3},{y,-3,3},
ParametricPlot3D[{x,y,
PlotStyle->{Gray,Opacity[0.25]},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]
2

Page 24

and then project the known Ceres positions onto this cone:
Clear[CeresConeHeights]
Table[CeresConeHeights[{i,r_}]=HorizontalCeresPoints[i]+r
CeresOrbitVertical,{i,Nn}]
{{1.348498877412522,2.416568575138297,1.000000000000000
r},{1.157410896897420,2.495556033935053,1.000000000000000
r},{0.959714951907322,2.560472186038424,1.000000000000000
r}}
Clear[CeresConePointEquations]
x y
}==CeresCone
Table[CeresConePointEquations[{i,r_}]={x,y,
Heights[{i,r}],{i,Nn}]
2

x2 y2

}=={1.348498877412522,2.416568575138297,1.0000000
{{x,y,
00000000
x y
r},{x,y,
}=={1.157410896897420,2.495556033935053,1.00000
0000000000
x y
}=={0.959714951907322,2.560472186038424,1.00000
r},{x,y,
2

Page 25

0000000000 r}}
Clear[CeresConePointSolutions]
Table[CeresConePointSolutions[i]=Solve[CeresConePointEquati
ons[{i,r}]][[1]],{i,Nn}]
{{r->2.767354856307513,x->1.348498877412522,y->2.4165685751
38297},{r->2.750890747152010,x->1.157410896897420,y->2.4955
56033935053},{r->2.734423267234036,x->0.959714951907322,y->
2.560472186038424}}
Clear[CeresConePoints]
Table[CeresConePoints[i]=CeresConeHeights[{i,r/.CeresConePo
intSolutions[i]}],{i,Nn}]
{{1.348498877412522,2.416568575138297,2.767354856307513},{1
.157410896897420,2.495556033935053,2.750890747152010},{0.95
9714951907322,2.560472186038424,2.734423267234036}}
Show[{
Graphics3D[
{Point[CeresConePoints/@Range[Nn]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}],
Arrow[Table[CeresConeHeights[{i,#}]&/@{0,r/.CeresConePointS
olutions[i]},{i,Nn}]]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
x y
},{x,-3,3},{y,-3,3},
ParametricPlot3D[{x,y,
PlotStyle->{Gray,Opacity[0.25]},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]
2

Page 26

One could determine the intersecting plane from these projected points on
the cone. However, because these points are close to being aligned, this
method is prone to large error. Gauss instead opted to determine a fourth
point V along the cone s axis. The height of this point is equal to the
semi-orbital parameter, h (otherwise known as the semilatus rectum),
which appears in the equation form of Kepler s second law:
S= t h
\[DoubleLongRightArrow]
h=(S/( t))2
Unfortunately, exact knowledge of the orbital sector S is unknown until we
have the orbit. In the meantime, we can approximate it as the triangular
area made by two known positions and the Sun, corrected by the G factor:

Page 27

## h((G T)/( t))2.

As before, we shall reflexively use this parameter to determine the orbit,
which we then use to determine the parameter, followed by the orbit, etc.
Finding the area of the T13 is straightforward:
NT[13]=Norm[Cross@@HorizontalCeresPoints/@{1,3}]/2
0.5667884373246028

as is the point V:
VPoint={0,0,Nh=((NG NT[13])/( Nt[13]))2}
{0,0,2.739591956314323}
Show[{
Graphics3D[
{Point[VPoint],
Point[CeresConePoints/@Range[Nn]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}],
Arrow[Table[CeresConeHeights[{i,#}]&/@{0,r/.CeresConePointS
olutions[i]},{i,Nn}]]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
x y
},{x,-3,3},{y,-3,3},
ParametricPlot3D[{x,y,
PlotStyle->{Gray,Opacity[0.25]},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]
2

Page 28

## We now determine the plane U following the usual method:

Clear[CeresUPlanePoints]
Table[CeresUPlanePoints[i]=CeresConePoints[i]-VPoint,{i,Nn}
]
{{1.348498877412522,2.416568575138297,0.02776289999318930},
{1.157410896897420,2.495556033935053,0.01129879083768650},{
0.959714951907322,2.560472186038424,-0.005168689080287674}}
UPlaneNormal=Normalize[Cross@@CeresUPlanePoints/@{1,3}]
UPlane=Simplify[UPlaneNormal.({x,y,z}-VPoint)==0]
UPlaneZ=z/.Solve[UPlane,z][[1]]
UPlaneInclinationAxis=Normalize[Cross[{0,0,1},UPlaneNormal]
]
{-0.07349653070039586,0.02956023706000831,0.996857287860184
}
37.1579744157960+1.000000000000000 x==0.402199080396173
Page 29

y+13.56332439586587 z
-0.07372823732689031 (-37.15797441579597-1.000000000000000
x+0.402199080396173 y)
{-0.3731488411179069,-0.927771492541328,0}
Show[{
Graphics3D[
{Point[VPoint],
Point[CeresConePoints/@Range[Nn]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
Arrow[Table[{#,#+CeresUPlanePoints[i]}&[VPoint],{i,{1,3}}]]
,
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}],
Arrow[Table[CeresConeHeights[{i,#}]&/@{0,r/.CeresConePointS
olutions[i]},{i,Nn}]]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
x y
},{x,-3,3},{y,-3,3},
ParametricPlot3D[{x,y,
PlotStyle->{Opacity[0.25]},Mesh->None],
ParametricPlot3D[{x,y,UPlaneZ},{x,-3,3},{y,-3,3},
PlotStyle->{Brown,Opacity[0.25]},Mesh->None]},
Axes->True,
AxesLabel->{x,y,z}]
2

Page 30

Almost there! We must now find the intersection of the plane U with the
cone. This task is simple, given our parametric representations of each. We
are also better off if we can represent this curve in polar coordinates, which
is nothing that a simple substitution cannot fix:
x2 y2

}=={x,y,UPlaneZ}/.{xUElipseEquation=FullSimplify[{x,y,
>r Cos[],y->r Sin[]},r>0]
{r Cos[],r Sin[],r}=={r Cos[],r
Sin[],2.73959195631432+0.0737282373268903 r
Cos[]-0.02965342925210608 r Sin[]}
UElipseSolution=FullSimplify[Solve[UElipseEquation,r]][[1]]
{r->-(37.15797441579597/(-13.56332439586587+1.0000000000000
00 Cos[]-0.4021990803961730 Sin[]))}
ParametricUElipse=FullSimplify[{x,y,UPlaneZ}/.{x->r
Cos[],y->r Sin[]}/.UElipseSolution]//Chop
Page 31

{2.73959195631432/(-0.07372823732689031+1.00000000000000
Sec[]+0.029653429252106
Tan[]),-(37.15797441579597/(-0.4021990803961730+1.000000000
00000 Cot[]-13.56332439586587
Csc[])),-(37.15797441579597/(-13.56332439586587+1.000000000
000000 Cos[]-0.4021990803961730 Sin[]))}
ParametricCeresOrbit=FullSimplify[{x,y,0}/.{x->r
Cos[],y->r Sin[]}/.UElipseSolution]
{2.73959195631432/(-0.07372823732689031+1.00000000000000
Sec[]+0.029653429252106
Tan[]),-(37.15797441579597/(-0.4021990803961730+1.000000000
00000 Cot[]-13.56332439586587 Csc[])),0}
Show[{
Graphics3D[
{Point[VPoint],
Point[CeresConePoints/@Range[Nn]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
Arrow[Table[{#,#+CeresUPlanePoints[i]}&[VPoint],{i,{1,3}}]]
,
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}],
Arrow[Table[CeresConeHeights[{i,#}]&/@{0,r/.CeresConePointS
olutions[i]},{i,Nn}]]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
x y
},{x,-3,3},{y,-3,3},
ParametricPlot3D[{x,y,
PlotStyle->{Opacity[0.25]},Mesh->None],
ParametricPlot3D[{x,y,UPlaneZ},{x,-3,3},{y,-3,3},
PlotStyle->{Brown,Opacity[0.25]},Mesh->None],
ParametricPlot3D[ParametricUElipse,{,0,2Pi},
PlotStyle->{{Black}}],
ParametricPlot3D[ParametricCeresOrbit,{,0,2Pi},
PlotStyle->{{Black}}]},
Axes->True,
2

Page 32

AxesLabel->{x,y,z}]

## Success! Now, let us see the orbit by itself:

Show[{
Graphics3D[
{{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]]}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle->{Gray,Opacity[0.25]},Mesh->None],
ParametricPlot3D[ParametricCeresOrbit,{,0,2Pi},
PlotStyle->{{Black}}]},
Axes->True,
AxesLabel->{x,y,z}]
Page 33

Wonderful, but we are not finished just yet! Remember that this orbit was
determined using an approximate orbital parameter under the condition that
we would use the orbit to correct the parameter and so on. We shall use
this orbit to calculate the area of the orbital sector S13, which will require
two things:
1 and 3 corresponding to the second and third positions of Ceres,
the orbit as a polar function r(), which can be integrated between 1 and
3.
The latter is easy enough to obtain:
PolarCeresOrbit=Norm[ParametricCeresOrbit]
\[Sqrt](1380.715062684948/Abs[-0.4021990803961730+1.0000000
0000000 Cot[]-13.56332439586587
Csc[]]2+7.505364087102141/Abs[-0.07372823732689031+1.000000
00000000 Sec[]+0.029653429252106 Tan[]]2)
PolarPlot[PolarCeresOrbit,{,0,2Pi}]

Page 34

## However, finding the relevant angles is a different story:

Clear[Equations]
eresPoints[i]],{i,Nn}]
{{2.73959195631432/(-0.07372823732689031+1.00000000000000
Sec[]+0.029653429252106
Tan[])==1.348498877412522,-(37.15797441579597/(-0.402199080
3961730+1.00000000000000 Cot[]-13.56332439586587
Csc[]))==2.416568575138297,True},{2.73959195631432/(-0.0737
2823732689031+1.00000000000000 Sec[]+0.029653429252106
Tan[])==1.157410896897420,-(37.15797441579597/(-0.402199080
3961730+1.00000000000000 Cot[]-13.56332439586587
Csc[]))==2.495556033935053,True},{2.73959195631432/(-0.0737
2823732689031+1.00000000000000 Sec[]+0.029653429252106
Tan[])==0.959714951907322,-(37.15797441579597/(-0.402199080
Page 35

3961730+1.00000000000000 Cot[]-13.56332439586587
Csc[]))==2.560472186038424,True}}
Solve[Equations[#],]&/@Range[Nn]
{{},{},{}}

Nothing! If the orbit that we have derived does not contain the points from
which it was derived, then it is possible that something has gone quite
wrong. Therefore, let us investigate this with care by solving the x and y
components separately:
Clear[Solutions]
Table[Solutions[i]=Quiet[Solve[Equations[i][[#]],]&/@Rang
e[2]],{i,Nn}]
{{{{->-1.089983125354243},{->1.06181491881519}},{{->1.061
81491881519}}},{{{->-1.160838069013211},{->1.1365404302325
3}},{{->1.13650337153816}}},{{{->-1.232436082815825},{->1
.21218389626726}},{{->1.21218389626725}}}}

We see that each x component has two solutions, while the y components
only has one. This should not present an issue, as simultaneously solving x
and y parts ought to whittle the solutions down to a single number. Indeed,
it does appear that each set of solutions do share a number in common,
but let us examine this result with a bit more precision:
Chop[Differences[/.Rest[Flatten[Solutions[#],1]]]&/@Range[
Nn]]
{{0},{-0.00003705869437043291},{0}}

## The discrepancies within the angles corresponding to the x and y

components of the first and third positions are negligible, as should be
expected since these were the points used to calculate the orbit. However,
the difference between the second position angles is quite noticeable!
Minimizing this quantity will be a goal ours whilst fine-tuning the orbit. In the
meantime, let us take solace in the fact that we now know which angles
correspond to Ceres first and third locations:
Clear[N]
Table[N[i]=Mean[/.Rest[Flatten[Solutions[i],1]]],{i,Nn}]
{1.061814918815193,1.136521900885348,1.212183896267255}
Clear[ParametricCeresPoints]
Table[ParametricCeresPoints[i]=ParametricCeresOrbit/.{->N[
i]},{i,Nn}]
Page 36

{{1.348498877412516,2.416568575138300,0},{1.157458847478015
,2.495573796395142,0},{0.959714951907323,2.560472186038423,
0}}
Chop[Table[HorizontalCeresPoints[i]-ParametricCeresPoints[i
],{i,Nn}]]
{{0,0,0},{-0.00004795058059542299,-0.00001776246008829907,0
},{0,0,0}}

## Again, our final orbit should render all of these zero!

Let us remind ourselves of the original approximation of the sectoral area
from which we calculated h:
NG NT[13]
0.5683938392750762

and let us obtain the area within our current orbit. For this, we shall use
NIntegrate, as it is much faster than Integrate and practically produces the
same result:
time=AbsoluteTime[];
NS[13]=NIntegrate[1/2 PolarCeresOrbit2,{,N[1],N[3]}]
(AbsoluteTime[]-time)Second
0.568939
0.07605430000000000 Second
(*time=AbsoluteTime[];
NIS[13]=Integrate[1/2PolarCeresOrbit^2,{,N[1],N[3]}]
(AbsoluteTime[]-time)Second*)
Differences[{NS[13],NIS[13]}]
{-0.568939+NIS[13]}

## Our new semi-orbital parameter is as follows:

(NS[13]/( Nt[13]))2
2.74485

## Compare it to the original:

Nh
2.739591956314323

## With this, we embark upon another iterative process la the determination

of P2:
SemiorbitalParameters={Nh};
SectoralAreas={NS[13]};
time=AbsoluteTime[];
Catch[Do[
AppendTo[SemiorbitalParameters,Nh=(NS[13]/( Nt[13]))2];
VPoint={0,0,Nh};
Page 37

Clear[CeresUPlanePoints];
Table[CeresUPlanePoints[i]=CeresConePoints[i]-VPoint,{i,Nn}
];
UPlaneNormal=Normalize[Cross@@CeresUPlanePoints/@{1,3}];
UPlane=Simplify[UPlaneNormal.({x,y,z}-VPoint)==0];
UPlaneZ=z/.Solve[UPlane,z][[1]];
UElipseEquation=FullSimplify[{x,y,
>r Cos[],y->r Sin[]},r>0];

x2 y2

}=={x,y,UPlaneZ}/.{x-

UElipseSolution=FullSimplify[Solve[UElipseEquation,r]][[1]]
;
ParametricUElipse=FullSimplify[{x,y,UPlaneZ}/.{x->r
Cos[],y->r Sin[]}/.UElipseSolution];
ParametricCeresOrbit=FullSimplify[{x,y,0}/.{x->r
Cos[],y->r Sin[]}/.UElipseSolution];
PolarCeresOrbit=Norm[ParametricCeresOrbit];
Clear[Equations];
eresPoints[i]],{i,Nn}];
Clear[Solutions];
Table[Solutions[i]=Quiet[Solve[Equations[i][[#]],]&/@Rang
e[2]],{i,Nn}];
Clear[N];
Table[N[i]=Mean[/.Rest[Flatten[Solutions[i],1]]],{i,Nn}];
Clear[ParametricCeresPoints];
Table[ParametricCeresPoints[i]=ParametricCeresOrbit/.{->N[
i]},{i,Nn}];
AppendTo[SectoralAreas,NS[13]=NIntegrate[1/2
PolarCeresOrbit2,{,N[1],N[3]}]];
If[Chop[Differences[SectoralAreas[[-2;;-1]]][[1]],10-15]==0,T
hrow[Null],Null],
{100}]]
(AbsoluteTime[]-time)Second
Length[Rest[SectoralAreas]]
{Nh,NS[13]}
Page 38

1.2358553000000000 Second
6
{2.74481,0.568935}

This process has converged upon a value for h, and so let us see whether
or not our new orbit is consistent with our original P2:
Chop[Differences[/.Rest[Flatten[Solutions[#],1]]]&/@Range[
Nn]]
{{0},{-0.0000205673},{0}}
Chop[Table[HorizontalCeresPoints[i]-ParametricCeresPoints[i
],{i,Nn}]]
{{0,0,0},{-0.0000266121,-9.8577*10-6,0},{0,0,0}}

We are clearly moving in the right direction, but we have not reached our
destination just yet. Nevertheless, this is a good point to pause and
calculate Ceres orbital elements for comparison to the known values:
AstronomicalData["Ceres","OrbitRules"]
{SemimajorAxis->4.137811914496967*1011,Eccentricity->0.07976
017327382710,Inclination->10.58671160799540,PeriapsisArgume
nt->73.15073411326651,AscendingNodeLongitude->80.4069591479
2410,PeriapsisLongitude->153.5576932611906,Periapsis->3.807
779319222182*1011,Apoapsis->4.467844509771751*1011}
(*{KnownCeresSemimajorAxis,
KnownCeresEccentricity,
KnownCeresInclination,
KnownCeresPeriapsisArgument,
KnownCeresAscendingNodeLongitude,
KnownCeresPeriapsisLongitude,
KnownCeresPeriapsis,
KnownCeresApoapsis}=
{Convert["SemimajorAxis"Meter,AU]/AU,
"Eccentricity",
"Inclination",
"PeriapsisArgument",
"AscendingNodeLongitude",
"PeriapsisLongitude",
Convert["Periapsis"Meter,AU]/AU,
Convert["Apoapsis"Meter,AU]/AU}/.AstronomicalData["Ceres","
OrbitRules"]*)
Page 39

{KnownCeresSemimajorAxis,
KnownCeresEccentricity,
KnownCeresInclination,
KnownCeresPeriapsisArgument,
KnownCeresAscendingNodeLongitude,
KnownCeresPeriapsisLongitude,
KnownCeresPeriapsis,
KnownCeresApoapsis}=
{QuantityMagnitude[UnitConvert[Quantity["SemimajorAxis","Me
ter"],"AU"]],
"Eccentricity",
"Inclination",
"PeriapsisArgument",
"AscendingNodeLongitude",
"PeriapsisLongitude",
QuantityMagnitude[UnitConvert[Quantity["Periapsis","Meter"]
,"AU"]],
QuantityMagnitude[UnitConvert[Quantity["Apoapsis","Meter"],
"AU"]]}/.AstronomicalData["Ceres","OrbitRules"];

## Obtaining the apsides is easy enough:

{{CeresApoapsis,{CeresApoapsis}},{CeresPeriapsis,{CeresPeri
apsis}}}={Maximize[PolarCeresOrbit,],Minimize[PolarCeresOr
bit,]}
{{2.98201,{->-0.406376}},{2.54256,{->2.73522}}}

## Let us verify that these points occur opposite of each other:

Abs[-Abs[Differences[/.{{CeresApoapsis},{CeresPeriapsis}
}][[1]]]]
1.37838*10-8

## and compare our results to the known values:

100Abs[CeresApoapsis-KnownCeresApoapsis]/KnownCeresApoapsis
0.152676
100Abs[CeresPeriapsis-KnownCeresPeriapsis]/KnownCeresPeriap
sis
0.109258

We are off by between one and two tenths of a percent on eachnot bad!
From these values, we derive the semi-major axis (a):
Page 40

CeresSemimajorAxis=(CeresApoapsis+CeresPeriapsis)/2
2.76229

## which we also compare to the known quantity:

100
Abs[CeresSemimajorAxis-KnownCeresSemimajorAxis]/KnownCeresS
emimajorAxis
0.132698

## This, of course, is as accurate as the previous two quantities. From it and

Kepler s third law, we can obtain Ceres orbital period:

KnownCeresOrbitPeriod=QuantityMagnitude[AstronomicalData["C
eres","OrbitPeriodYears"]]
4.600194590273435
CeresOrbitPeriod=CeresSemimajorAxis3/2
4.59095
100
Abs[CeresOrbitPeriod-KnownCeresOrbitPeriod]/KnownCeresOrbit
Period
0.200866

The orbit's eccentricity (e) follows from the semi-major axis and the
semi-orbital parameter:
CeresEccentricity=
0.0795442

1 Nh CeresSemimajorAxis

## Compared to the known value:

100
Abs[CeresEccentricity-KnownCeresEccentricity]/KnownCeresEcc
entricity
0.270807

## Errors, while still small, seem to be mounting. Nevertheless, it is clear that

the ellipse which we have found very closely matches that of Ceres orbit.
Now we must determine how that ellipse is oriented in space, beginning
with Ceres orbital inclination (i, in degrees) with respect to the ecliptic

Page 41

## plane; i.e. the plane of Earth s orbit:

CeresInclination=(180/)ArcCos[EarthOrbitNormal.CeresOrbitNo
rmal]
10.58742174583762
100Abs[CeresInclination-KnownCeresInclination]/KnownCeresIn
clination
0.006707822679146446

This value is quite good! However, that is because it was essentially known
as soon as we had two (,) data points for both Ceres and the Sun. The
longitude of the ascending node (, the angle between Ceres inclination
axis and the vernal unit) might not be so accurate:
CeresAscendingNode=Normalize[Cross[EarthOrbitNormal,CeresOr
bitNormal]]
{0.1667222217538919,0.904465824243575,0.3926133894161495}
CeresAscendingNodeLongitude=(180/)ArcCos[CeresAscendingNode
.CartesianVernalUnit]
80.40270353352374
100
Abs[CeresAscendingNodeLongitude-KnownCeresAscendingNodeLong
itude]/KnownCeresAscendingNodeLongitude
0.005292594627951980

## I stand corrected! However, the argument of periapsis (, the angle

between the inclination axis the ellipse's major axis in the direction of
periapsis) does not come out quite as nicely:
HorizontalCeresAscendingNode=Chop[CeresRotationMatrix.Ceres
AscendingNode]
{0.1290774535881167,0.991634514816425,0}
CeresPeriapsisUnit=Normalize[ParametricCeresOrbit /.
CeresPeriapsis]
{-0.918559,0.395283,0.}
CeresPeriapsisArgument=(180/)ArcCos[HorizontalCeresAscendin
Page 42

gNode.CeresPeriapsisUnit]
74.1326
100Abs[CeresPeriapsisArgument-KnownCeresPeriapsisArgument]/
KnownCeresPeriapsisArgument
1.3423

## thought leads me to question whether or not the known periapsis

argument is the correct periapsis argument! Remember, our raw data
comes from 1801, and it is quite possible that Ceres orbit has precessed
throughout the last two centuries. In fact, precession should be expected,
given Ceres proximity to mighty Jupiter! Unfortunately, Mathematica is of

## no help in providing Ceres orbital elements from 1801:

AstronomicalData["Ceres","OrbitRules",NDate[2]]
AstronomicalData::notsubprop: {1801, 1, 22, 19, 20, 21.7} is not a known
subproperty of AstronomicalData. Use subproperty "Properties" for a list
of subproperties. >>

AstronomicalData[Ceres,OrbitRules,{1801,1,22,19,20,21.7}]

Thus, I shall either have to look for reference values elsewhere, or use
more modern observations. In the meantime, a quick jaunt over to the
Internet reveals that for Ceres:
Precession of perihelion
54.070272 arcsec / yr
Precession of the ascending node -59.170034 arcsec / yr
From this, we immediately see that the ascending node has been
precessing as well, which means that if precession accounts for the
discrepancy in the argument of periapsis, then we ought to see a similar
error in the longitude of the ascending node, which we do not! Moreover,

Page 43

## Ceres periapsis has evidently precessed by an amount much greater than

that of our discrepancy:
(*Convert[(2013-1801)Year 54.070272ArcSecond/Year,Degree]*)
CeresPeriapsisPrecession=(180/)QuantityMagnitude[UnitConver
3.18414
CeresPeriapsisArgument-KnownCeresPeriapsisArgument
0.981906

Thus it seems that accounting for precession will only increase our error!
Perhaps we shall simply have to accept the fact that our orbit is not yet
perfect. Ignoring this, we can now easily determine the longitude of the
periapsis ( ):

CeresPeriapsisLongitude=CeresAscendingNodeLongitude+CeresPe
riapsisArgument
154.535
100Abs[CeresPeriapsisLongitude-KnownCeresPeriapsisLongitude
]/KnownCeresPeriapsisLongitude
0.636666

This quantity is more successful than the last, but it does not tell us
anything that we did not already know. In that case, perhaps it can be used
as a replacement for the error-ridden periapsis argument!
There is one final element that we need to make this orbit complete: the
mean anomaly at epoch (M0). The mean anomaly
MeanAnomalyEquation=M==(2)/P t+M0;

## is derived from Kepler s second law and establishes the relationship

between time and position along the orbit. Although M varies from 0 to 2
over the course of one orbital period, it is not an angle, unlike the eccentric
and true anomalies (E and , respectively). The mean anomaly at epoch is

Page 44

## simply a known reference that determines the system s initial condition.

The true and eccentric anomalies are related:
1 e
1 e

TrueEccentricEquation=Tan[/2]==

Tan[Ee/2];

## as are the eccentric and mean anomalies, via Kepler s equation:

KeplerEquation=M==Ee-e Sin[Ee];

Combining these expressions with one for the mean anomaly above, we
find that
(*EccentricAnomaly=Ee/.FullSimplify[Quiet[Solve[TrueEccentr
icEquation,Ee][[1]]]]*)
EccentricAnomaly=Ee/.FullSimplify[Quiet[Solve[{TrueEccentri
cEquation,C[1]==0},Ee][[1]]]]
1e
1e

2 ArcTan[Tan[/2]/

Refine[Eliminate[{MeanAnomalyEquation,KeplerEquation},M],P>
0]
Ee==M0+(2 t)/P+e Sin[Ee]
MeanAnomalyAtEpoch=Expand[Solve[Refine[Eliminate[{MeanAnoma
lyEquation,KeplerEquation},M],P>0]/.Ee->EccentricAnomaly,M0
][[1]]]
{M0->-((2 t)/P)+2 ArcTan[Tan[/2]/

1e
1e

]-e Sin[2

1e
1e

ArcTan[Tan[/2]/

]]}

Inserting the known values for the first observation gives us the quantity
which we seek:
CeresMeanAnomalyAtEpoch=M0/.MeanAnomalyAtEpoch/.{P->CeresOr
bitPeriod,e->CeresEccentricity,t->Nt[1],->N[1]}
136.501

Therefore
CeresMeanAnomaly=M/.Expand[Solve[MeanAnomalyEquation,M][[1]
]]/.{M0->CeresMeanAnomalyAtEpoch,P->CeresOrbitPeriod}
Page 45

136.501 +1.3686 t

With this expression (and its rather convoluted relationship with the true
anomaly), we can calculate the position of Ceres along its orbit for a given
time t.

References
[1] http://www.schillerinstitute.org/fid_97-01/982_orbit _ceres.pdf

Future Work
Before proceeding, let us review what we have done so far. First, we
derived the second position of Ceres from our three original observations.
This involved an approximation of the ratios of sectoral areas which were
iteratively corrected by use of the factor G(r2). With the second position in
hand, the first and third positions were obtained using the latest ratio
approximation. From these points, we then derived a first approximation of
Ceres orbit, which was also adjusted iteratively using the semi-orbital
parameter h(S13). This is where we currently stand. Now that we have a
preliminary orbit, we need not approximate the ratios of sectoral areas in
the first step! Instead, we can obtain the ratios from our orbit, calculate P2,
P1, and P3, recalculate the orbit, and so on until the area ratios converge
and all three points lie on the same path. Let the finale begin!
\[DoubleLongRightArrow]
h=(S/( t))2
S= t h
(*Distances={CeresSunDistance[2]};
SemiorbitalParameters={Nh};
SectoralAreas={NS[13]};
time=AbsoluteTime[];
Catch[Do[
Clear[NSr];
Table[NSr[i]= Nt[i]Sqrt[Nh]/NS[13],{i,{3,1}}];
Clear[FPoints];
Evaluate[FPoints/@{1,3}]=EarthPointEquations/@{{1,NSr[1]},{
3,NSr[3]}};
FPoints[0]=Total[FPoints/@{1,3}];
Clear[ShiftedCeresVectorEquations];
Table[ShiftedCeresVectorEquations[{i,sc_}]=FPoints[0]+sc
CartesianCeresUnits[i],{i,{1,3}}];
Page 46

QNormal=Normalize[Cross@@CartesianCeresUnits/@{1,3}];
Qz=z/.Simplify[Solve[QNormal.({x,y,z}-FPoints[0]) 0,z][[1]]
];
P2Solution=Solve[CeresVectorEquations[{2,c}] {x,y,Qz}][[1]]
;
CartesianCeresPoints[2]=CeresVectorEquations[{2,c}]/.P2Solu
tion;
AppendTo[Distances,CeresSunDistance[2]=Norm[CartesianCeresP
oints[2]]];
Clear[QpScalars];
If[Solve[Total[Qp[#]
CartesianCeresUnits[#]&/@{1,3}] CartesianCeresPoints[2]-FPo

ints[0]] {},Throw[Null],Null];
Table[QpScalars[i]=Qp[i]/.Solve[Total[Qp[#]
CartesianCeresUnits[#]&/@{1,3}] CartesianCeresPoints[2]-FPo
ints[0]][[1]],{i,{1,3}}];
Table[CartesianCeresPoints[i]=CartesianEarthPoints[i]+Carte
sianCeresUnits[i]QpScalars[i]/NSr[i],{i,{1,3}}];
CeresOrbitNormal=Normalize[Cross@@CartesianCeresPoints/@{1,
3}];
CeresOrbitPlane=CeresOrbitNormal.{x,y,z} 0;
CeresOrbitPlaneZ=z/.Solve[CeresOrbitPlane,z][[1]];
CeresRotationMatrix=RotationMatrix[{CeresOrbitNormal,{0,0,1
}}];
Clear[HorizontalCeresPoints];
Table[HorizontalCeresPoints[i]=Chop[CeresRotationMatrix.Car
tesianCeresPoints[i]],{i,Nn}];
CeresOrbitVertical=Chop[CeresRotationMatrix.CeresOrbitNorma
Page 47

l];
Clear[CeresConeHeights];
Table[CeresConeHeights[{i,r_}]=HorizontalCeresPoints[i]+r
CeresOrbitVertical,{i,Nn}];
Clear[CeresConePointEquations];
Table[CeresConePointEquations[{i,r_}]={x,y,Sqrt[x^2+y^2]} C
eresConeHeights[{i,r}],{i,Nn}];
Clear[CeresConePointSolutions];
Table[CeresConePointSolutions[i]=Solve[CeresConePointEquati
ons[{i,r}]][[1]],{i,Nn}];
Clear[CeresConePoints];
Table[CeresConePoints[i]=CeresConeHeights[{i,r/.CeresConePo
intSolutions[i]}],{i,Nn}];
AppendTo[SemiorbitalParameters,Nh=(NS[13]/( Nt[13]))^2];
VPoint={0,0,Nh};
Clear[CeresUPlanePoints];
Table[CeresUPlanePoints[i]=CeresConePoints[i]-VPoint,{i,Nn}
];
UPlaneNormal=Normalize[Cross@@CeresUPlanePoints/@{1,3}];
UPlane=Simplify[UPlaneNormal.({x,y,z}-VPoint) 0];
UPlaneZ=z/.Solve[UPlane,z][[1]];
UElipseEquation=FullSimplify[{x,y,Sqrt[x^2+y^2]} {x,y,UPlan

## eZ}/.{x r Cos[],y r Sin[]},r>0];

UElipseSolution=FullSimplify[Solve[UElipseEquation,r]][[1]]
;
ParametricUElipse=FullSimplify[{x,y,UPlaneZ}/.{x r

Cos[],y r Sin[]}/.UElipseSolution];

Page 48

ParametricCeresOrbit=FullSimplify[{x,y,0}/.{x r Cos[],y r
Sin[]}/.UElipseSolution];
PolarCeresOrbit=Norm[ParametricCeresOrbit];
Clear[Equations];
eresPoints[i]],{i,Nn}];
Clear[Solutions];
Table[Solutions[i]=Quiet[Solve[Equations[i][[#]],]&/@Rang
e[2]],{i,Nn}];
Clear[N];
Table[N[i]=Mean[/.Rest[Flatten[Solutions[i],1]]],{i,Nn}];
Clear[ParametricCeresPoints];
Table[ParametricCeresPoints[i]=ParametricCeresOrbit/.{ N[
i]},{i,Nn}];
AppendTo[SectoralAreas,NS[13]=NIntegrate[1/2PolarCeresOrbit
^2,{,N[1],N[3]}]];
Print["NS[13]="<>ToString[NS[13]]];
Print[PolarPlot[PolarCeresOrbit,{,0,2Pi}]];
If[Chop[Differences[SectoralAreas[[-2;;-1]]][[1]],10^-15] 0
,Throw[Null],Null];,
{100}]]
(AbsoluteTime[]-time)Second
Length[Rest[SectoralAreas]]
"{CeresSunDistance[2],SemiorbitalParameters,SectoralAreas}"
{CeresSunDistance[2],SemiorbitalParameters,SectoralAreas}*)
(*Show[{
Graphics3D[
{Point[VPoint],
Point[CeresConePoints/@Range[Nn]],
{PointSize[Large],
{Darker[Yellow],
Point[Origin]},
Page 49

{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},
Arrow[{Origin,HorizontalCeresPoints[#]}&/@Range[Nn]],
Arrow[Table[{#,#+CeresUPlanePoints[i]}&[VPoint],{i,{1,3}}]]
,
{Dashed,
Arrow[{Origin,4CeresOrbitVertical}],
Arrow[Table[CeresConeHeights[{i,#}]&/@{0,r/.CeresConePointS
olutions[i]},{i,Nn}]]}}}],
ParametricPlot3D[{x,y,0},{x,-3,3},{y,-3,3},
PlotStyle {Gray,Opacity[0.25]},Mesh None],
ParametricPlot3D[{x,y,Sqrt[x^2+y^2]},{x,-3,3},{y,-3,3},
PlotStyle {Opacity[0.25]},Mesh None],
ParametricPlot3D[{x,y,UPlaneZ},{x,-3,3},{y,-3,3},
PlotStyle {Brown,Opacity[0.25]},Mesh None],
ParametricPlot3D[ParametricUElipse,{,0,2Pi},
PlotStyle {{Black}}],
ParametricPlot3D[ParametricCeresOrbit,{,0,2Pi},
PlotStyle {{Black}}]},

Axes True,

AxesLabel {x,y,z}]*)
(*Show[{
Graphics3D[
{{PointSize[Large],
Page 50

{Darker[Yellow],
Point[Origin]},
{Gray,
Point[HorizontalCeresPoints/@Range[Nn]]}},