# Planetary Parameters#

## Planetary Mass Parameters#

Table 8 Mass, gravitational parameter, and mass fraction of the Sun, planets, and other solar system bodies#

Celestial Body

Mass [kg]

$$\mu$$ [km3/s2]

Mass Fraction in Solar System

Sun

1.98842 × 1030 kg

1.32712 × 1011 km3/s2

9.98657 × 10-1

Mercury

3.30101 × 1023 kg

2.20319 × 104 km3/s2

1.65789 × 10-7

Venus

4.86732 × 1024 kg

3.24859 × 105 km3/s2

2.44455 × 10-6

Earth

5.97219 × 1024 kg

3.98600 × 105 km3/s2

2.99946 × 10-6

Moon

7.34581 × 1022 kg

4.90280 × 103 km3/s2

3.68934 × 10-8

Mars

6.41693 × 1023 kg

4.28284 × 104 km3/s2

3.22282 × 10-7

Jupiter

1.89852 × 1027 kg

1.26713 × 108 km3/s2

9.53510 × 10-4

Saturn

5.68460 × 1026 kg

3.79406 × 107 km3/s2

2.85502 × 10-4

Uranus

8.68192 × 1025 kg

5.79456 × 106 km3/s2

4.36039 × 10-5

Neptune

1.02431 × 1026 kg

6.83653 × 106 km3/s2

5.14447 × 10-5

Pluto

1.46158 × 1022 kg

9.75500 × 102 km3/s2

7.34061 × 10-9

The data in Table 8 is generated by the following script, using data from [PFWB21]:

Hide code cell content
from dataclasses import dataclass

import pint
from IPython.display import display
from myst_nb.ext.glue import GLUE_PREFIX

units = pint.UnitRegistry()
Q_ = units.Quantity

@dataclass
class CelestialObject:
G = 6.67428e-11 * units("m**3 / (kg * s**2)")
identifier: str
name: str
GM_in_au: pint.Quantity
GM_ratio: pint.Quantity
GM_in_km: pint.Quantity
mass: pint.Quantity | None = None
mass_fraction: pint.Quantity | None = None

def compute_mass(self):
self.mass = (self.GM_in_km / self.G).to("kg")

def format_units(self, obj):
initial_format = format(obj, ".5~EH")
mantissa, remainder = initial_format.split("E")
remainder = remainder.split(" ", maxsplit=1)
exponent = remainder[0]
if len(remainder) == 1:
units = ""
else:
units = " " + remainder[1]

sign = exponent[0] if exponent[0] == "-" else ""
value = int(exponent[1:])
return f"{mantissa} × 10<sup>{sign}{value}</sup>{units}"  # noqa: RUF001

def glue(self):
assert self.mass is not None, "Mass has not been computed"
assert self.mass_fraction is not None, "Mass fraction has not been computed"
for attr in ("GM_in_km", "mass", "mass_fraction"):
display(
{GLUE_PREFIX + "text/html": self.format_units(getattr(self, attr))},
raw=True,
)

object_identifier_map = {
"GM1": "Mercury",
"GM2": "Venus",
"GM3": "Earth",
"GM4": "Mars",
"GM5": "Jupiter",
"GM6": "Saturn",
"GM7": "Uranus",
"GM8": "Neptune",
"GM9": "Pluto",
"GMS": "Sun",
"GMM": "Moon",
"GMB": "Earth-Moon-Barycenter",
}

celestial_objects = {}

# Mass parameter (GM) for Sun, Moon, and Planets:

#           AU**3/DAY**2                    GMSun/GM(I)         KM**3/SEC**2

data = """\
GM1     4.9125001948893182e-11        6023657.944929           22031.868551
GM2     7.2434523326441187e-10         408523.718656          324858.592000
GM3     8.8876924467071022e-10         332946.048773          398600.435507
GM4     9.5495488297258119e-11        3098703.546737           42828.375816
GM5     2.8253458252257917e-07           1047.348631       126712764.100000
GM6     8.4597059933762903e-08           3497.901801        37940584.841800
GM7     1.2920265649682399e-08          22902.950783         5794556.400000
GM8     1.5243573478851939e-08          19412.259776         6836527.100580
GM9     2.1750964648933581e-12      136045556.167380             975.500000
GMS     2.9591220828411956e-04              1.000000    132712440041.279419
GMM     1.0931894624024351e-11       27068702.952351            4902.800118
GMB     8.9970113929473466e-10         328900.559708          403503.235625
"""

for line in data.splitlines():
identifier, GM_in_au, GM_ratio, GM_in_km = line.split()
name = object_identifier_map[identifier]
c_object = CelestialObject(
identifier,
name,
Q_(GM_in_au + "au**3/day**2"),
Q_(GM_ratio + "kg/kg"),
Q_(GM_in_km + "km**3/s**2"),
)
c_object.compute_mass()
celestial_objects[name] = c_object

total_mass = sum(c.mass for c in celestial_objects.values())
for c in celestial_objects.values():
c.mass_fraction = c.mass / total_mass
c.glue()


Table 9 Radial parameters for objects in the Solar System. The gas giants assume a surface at the 1-bar pressure altitude.#

Celestial Body

Sun

695700

Mercury

2439.4 ± 0.1

2440.53 ± 0.04

2438.26 ± 0.04

Venus

6051.8 ± 1.0

Same

Same

Earth

6371.0084 ± 0.0001

6378.1366 ± 0.0001

6356.7519 ± 0.0001

Moon

1737.4

Mars

3389.50 ± 0.2

3396.19 ± 0.1

3376.20 ± 0.1

Jupiter

69911 ± 6

71492 ± 4

66854 ± 10

Saturn

58232 ± 6

60268 ± 4

54364 ± 10

Uranus

25362 ± 7

25559 ± 4

24973 ± 20

Neptune

24622 ± 19

24764 ± 15

24341 ± 30

Pluto

1188.3 ± 1.6

The data in Table 9 is generated by the following script, using data from :

Hide code cell content
import csv

from IPython.display import display
from myst_nb.ext.glue import GLUE_PREFIX

planet_data = """\
Sun,,695700,,,,
Mercury,2439.4 ± 0.1,2440.53 ± 0.04,2438.26 ± 0.04,1.0,4.6,2.5
Venus,6051.8 ± 1.0,Same,Same,1.0,11,2
Earth,6371.0084 ± 0.0001,6378.1366 ± 0.0001,6356.7519 ± 0.0001,3.57,8.85,11.52
Mars,3389.50 ± 0.2,3396.19 ± 0.1,3376.20 ± 0.1,3.0,22.64 ± 0.1,7.55 ± 0.1
Mars,3389.50 ± 0.2,3396.19 ± 0.1,N 3373.19 ± 0.1,3.0,22.64 ± 0.1,7.55 ± 0.1
Mars,3389.50 ± 0.2,3396.19 ± 0.1,S 3379.21 ± 0.1,3.0,22.64 ± 0.1,7.55 ± 0.1
Jupiter,69911 ± 6,71492 ± 4,66854 ± 10,62.1,31,102
Saturn,58232 ± 6,60268 ± 4,54364 ± 10,102.9,8,205
Uranus,25362 ± 7,25559 ± 4,24973 ± 20,16.8,28,0
Neptune,24622 ± 19,24764 ± 15,24341 ± 30,8.0,14,0
"""  # noqa: E501

moon_data = """\
Earth,,Moon,1737.4,Same,Same,Same,2.5,7.5,5.6
Mars,I,Phobos,11.08 ± 0.04,13.0,11.4,9.1,0.5,,
Mars,II,Deimos,6.2 ± 0.25,7.8,6.0,5.1,0.2,,
Jupiter,XVI,Metis,21.5 ± 4,30,20,17,,,
Jupiter,V,Amalthea,83.5 ± 3,125,73,64,3.2,,
Jupiter,XIV,Thebe,49.3 ± 4,58,49,42,,,
Jupiter,I,Io,1821.49,1829.4,1819.4,1815.7,,13.0,3.0
Jupiter,II,Europa,1560.8 ± 0.3,1562.6,1560.3,1559.5,0.32,,
Jupiter,III,Ganymede,2631.2± 1.7,Same,Same,Same,,,
Jupiter,IV,Callisto,2410.3± 1.5,Same,Same,Same,0.6,,
Jupiter,XIII,Leda,5,,,,,,
Jupiter,VI,Himalia,85 ± 10,,,,,,
Jupiter,X,Lysithea,12,,,,,,
Jupiter,VII,Elara,40 ± 10,,,,,,
Jupiter,XII,Ananke,10,,,,,,
Jupiter,XI,Carme,15,,,,,,
Jupiter,VIII,Pasiphae,18,,,,,,
Jupiter,IX,Sinope,14,,,,,,
Saturn,XVIII,Pan,14.0 ± 1.2,17.2 ± 1.7,15.4 ± 1.2,10.4 ± 0.9,,,
Saturn,XXXV,Daphnis,3.8 ± 0.8,4.6 ± 0.7,4.5 ± 0.9,2.8 ± 0.8,,,
Saturn,XV,Atlas,15.1 ± 0.8,20.5 ± 0.9,17.8 ± 0.7,9.4 ± 0.8,,,
Saturn,XVI,Prometheus,43.1 ± 1.2,68.2 ± 0.8,41.6 ± 1.8,28.2 ± 0.8,,,
Saturn,XVII,Pandora,40.6 ± 1.5,52.2 ± 1.8,40.8 ± 2.0,31.5 ± 0.9,,,
Saturn,XI,Epimetheus,58.2 ± 1.2,64.9 ± 1.3,57.3 ± 2.5,53.0 ± 0.5,,,
Saturn,X,Janus,89.2 ± 0.8,101.7 ± 1.6,93.0 ± 0.7,76.3 ± 0.4,,,
Saturn,I,Mimas,198.2 ± 0.4,207.8 ± 0.5,196.7 ± 0.5,190.6 ± 0.3,,,
Saturn,LIII,Aegaeon,0.33 ± 0.06,0.7 ± 0.05,0.25 ± 0.06,0.2 ± 0.08,,,
Saturn,XXXII,Methone,1.45 ± 0.03,1.94 ± 0.02,1.29 ± 0.04,1.21 ± 0.02,,,
Saturn,XLIX,Anthe,0.5,,,,,,
Saturn,XXXIII,Pallene,2.23 ± 0.07,2.88 ± 0.07,2.08 ± 0.07,1.8 ± 0.07,,,
Saturn,II,Enceladus,252.1 ± 0.2,256.6 ± 0.6,251.4 ± 0.2,248.3 ± 0.2,0.4,,
Saturn,III,Tethys,531.0 ± 0.6,538.4± 0.3,528.3 ± 1.1,526.3 ± 0.6,,,
Saturn,XIII,Telesto,12.4 ± 0.4,16.3 ± 0.5,11.8 ± 0.3,9.8 ± 0.3,,,
Saturn,XIV,Calypso,9.6 ± 0.6,15.3 ± 0.3,9.3 ± 2.2,6.3 ± 0.6,,,
Saturn,IV,Dione,561.4 ± 0.4,563.4 ± 0.6,561.3 ± 0.5,559.6 ± 0.4,0.5,,
Saturn,XII,Helene,18.0 ± 0.4,22.5 ± 0.5,19.6 ± 0.3,13.3 ± 0.2,,,
Saturn,XXXIV,Polydeuces,1.3 ± 0.4,1.5 ± 0.6,1.2 ± 0.4,1.0 ± 0.2,,,
Saturn,V,Rhea,763.5 ± 0.6,765.0 ± 0.7,763.1 ± 0.6,762.4 ± 0.6,,,
Saturn,VI,Titan,2575.0,2575.15 ± 0.02,2574.78 ± 0.06,2574.47 ± 0.06,0.26,,
Saturn,VII,Hyperion,135 ± 4,180.1 ± 2.0,133.0 ± 4.5,102.7 ± 4.5,,,
Saturn,VIII,Iapetus,734.3 ± 2.8,745.7 ± 2.9,745.7 ± 2.9,712.1 ± 1.6,,,
Saturn,IX,Phoebe,106.5 ± 0.7,109.4 ± 1.4,108.5 ± 0.6,101.8 ± 0.3,,,
Uranus,VI,Cordelia,13 ± 2,,,,,,
Uranus,VII,Ophelia,15 ± 2,,,,,,
Uranus,VIII,Bianca,21 ± 3,,,,,,
Uranus,IX,Cressida,31 ± 4,,,,,,
Uranus,X,Desdemona,27 ± 3,,,,,,
Uranus,XI,Juliet,42 ± 5,,,,,,
Uranus,XII,Portia,54 ± 6,,,,,,
Uranus,XIII,Rosalind,27 ± 4,,,,,,
Uranus,XIV,Belinda,33 ± 4,,,,,,
Uranus,XV,Puck,77 ± 51.9,,,,1.9,,
Uranus,V,Miranda,235.8 ± 0.7,240.4 ± 0.6,234.2 ± 0.9,232.9 ± 1.2,1.6,5.0,8.0
Uranus,I,Ariel,578.9 ± 0.6,581.1 ± 0.9,577.9 ± 0.6,577.7 ± 1.0,0.9,4.0,4.0
Uranus,II,Umbriel,584.7 ± 2.8,Same,Same,Same,2.6,,6.0
Uranus,III,Titania,788.9 ± 1.8,Same,Same,Same,1.3,4.0,
Uranus,IV,Oberon,761.4 ± 2.6,Same,Same,Same,1.5,12.0,2.0
Neptune,IV,Thalassa,40 ± 8,,,,,,
Neptune,V,Despina,74 ± 10,,,,,,
Neptune,VI,Galatea,79 ± 12,,,,,,
Neptune,VII,Larissa,96 ± 7,104,,89,2.9,6.0,5.0
Neptune,VIII,Proteus,208 ± 8,218,208,201,7.9,18.0,13.0
Neptune,I,Triton,1352.6 ± 2.4,,,,,,
Neptune,II,Nereid,170 ± 25,,,,,,
"""  # noqa: E501

dwarf_data = """\
(1) Ceres,470,487.3,487.3,446,(a)
(4) Vesta,,289 ± 5,280 ± 5,229 ± 5,
(16) Psyche,113 ± 23,139.5 ± 10%,116 ± 10%,94.5 ± 10%,(b)
(21) Lutetia,52.5 ± 2.5,62.0 ± 2.5,50.5 ± 2.0,46.5 ± 6.5,
(52) Europa,157.5 ± 7,189.5 ± 16,165 ± 8,124.5 ± 10,
(243) Ida,15.65 ± 0.6,26.8,12.0,7.6,
(253) Mathilde,26.5 ± 1.3,33,24,23,
(433) Eros,8.45 ± 0.02,17.0,5.5,5.5,
(511) Davida,150,180,147,127,(c)
(951) Gaspr,6.1 ± 0.4,9.1,5.2,4.4,
(2867) Šteins,2.70,3.24,2.73,2.04,
(4179) Toutatis,,2.13,1.015,0.85,
(25143) Itokawa,,0.268,0.147,0.104,
(134340) Pluto,1188.3 ± 1.6,Same,Same,Same,
(134340) Pluto: I Charon,606.0 ± 1.0,Same,Same,Same,
1P/Halley,,8.0 ± 0.5,4.0 ± 0.25,4.0 ± 0.25,
9P/Tempel 1,3.0 ± 0.1,3.7,2.5,,(d)
19P/Borrelly,4.22 ± 0.05,3.5 ± 0.2,–,–,(e)
67P/Churyumov–Gerasimenko,1.65,2.40,1.55,1.20,(f)
81P/Wild 2,1.975,2.7,1.9,1.5,
103P/Hartley 2,0.58,0.34,1.16,1.16,(g)
"""  # noqa: E501, RUF001

def glue(row: dict[str, str], name: str, object: str) -> None:
meta_name = f"{object}_{name.replace(' ', '_').replace('(', '').replace(')', '')}"
value = row[name]
display(
{GLUE_PREFIX + "text/html": value},
raw=True,
)

did_mars = False
if did_mars and row["Planet"] == "Mars":
continue
elif row["Planet"] == "Mars":
did_mars = True

# Just want Earth's Moon

body = row["Body"]
if "Pluto" not in body or "Charon" in body:
continue
body = body.split()[1]


## Planetary Orbital elements#

Table 10 Orbital elements for objects in the Solar System. The values for the Moon are relative to Earth; all other values are relative to the Sun.#

Celestial Body

Semi-Major Axis (km)

Perihelion (km)

Aphelion (km)

Period (days)

Velocity (km/s)

Eccentricity

Inclination (degrees)

Mercury

5.79091 × 107

4.60009 × 107

6.98173 × 107

87.97

47.87

0.20564

7.01

Venus

1.08209 × 108

1.07477 × 108

1.08940 × 108

224.70

35.02

0.00676

3.39

Earth

1.49598 × 108

1.47100 × 108

1.52096 × 108

365.26

29.78

0.01670

0.00

Moon

3.83398 × 105

3.62106 × 105

4.04689 × 105

27.18

1.03

0.05555

23.71

Mars

2.27939 × 108

2.06645 × 108

2.49233 × 108

686.97

24.13

0.09342

1.85

Jupiter

7.78321 × 108

7.40603 × 108

8.16038 × 108

4332.52

13.06

0.04846

1.30

Saturn

1.42910 × 109

1.35096 × 109

1.50724 × 109

10783.05

9.64

0.05468

2.49

Uranus

2.87479 × 109

2.73854 × 109

3.01104 × 109

30768.84

6.79

0.04739

0.77

Neptune

4.50489 × 109

4.46384 × 109

4.54594 × 109

60357.05

5.43

0.00911

1.77

Pluto

5.91540 × 109

4.44212 × 109

7.38868 × 109

90821.51

4.74

0.24906

17.14

The data in Table 10 is generated by the following script, using data from [PFWB21, Rho19]:

Hide code cell content
import re
from datetime import datetime
from pathlib import Path

import numpy as np
from dateutil import tz
from dateutil.rrule import DAILY, rrule
from IPython.display import display
from myst_nb.ext.glue import GLUE_PREFIX
from skyfield.elementslib import OsculatingElements, osculating_elements_of
from skyfield.framelib import build_ecliptic_matrix
from skyfield.units import Distance, Velocity

class CelestialObject:
def __init__(
self, identifier: int | None, name: str, elems: OsculatingElements
) -> None:
self.identifier = identifier
self.name = name
self.aphelion: np.float64 = np.average(elems.apoapsis_distance.km)
self.semimajor_axis: np.float64 = np.average(elems.semi_major_axis.km)
self.perihelion: np.float64 = np.average(elems.periapsis_distance.km)
self.period_in_days: np.float64 = np.average(elems.period_in_days)
self.orbital_velocity: np.float64 = np.sqrt(elems._mu / self.semimajor_axis)
self.eccentricity: np.float64 = np.average(elems.eccentricity)
self.inclination: np.float64 = np.average(elems.inclination.degrees)

def format_units(self, obj: float):
initial_format = format(obj, ".5E")
mantissa, exponent = initial_format.split("E")
sign = exponent[0] if exponent[0] == "-" else ""
value = int(exponent[1:])
return f"{mantissa} × 10<sup>{sign}{value}</sup>"  # noqa: RUF001

def glue(self):
for attr in ("aphelion", "semimajor_axis", "perihelion"):
display(
{GLUE_PREFIX + "text/html": self.format_units(getattr(self, attr))},
raw=True,
)
for attr in (
"period_in_days",
"orbital_velocity",
"inclination",
):
display(
{GLUE_PREFIX + "text/html": f"{getattr(self, attr):.2F}"},
raw=True,
)
display(
{GLUE_PREFIX + "text/html": f"{self.eccentricity:.5F}"},
raw=True,
)

def parse_pck_file(filename: Path) -> dict[int | None, float]:
m = re.compile(
r"^\s+BODY(?P<identifier>\d+)_GM\s+=\s+$$\s(?P<value>[\d.ED+-]+)\s$$\$"
)
for line in lines:
if "begindata" in line:
break
GM_dict: dict[int | None, float] = {None: 0.0}
for line in lines:
mat = m.search(line)
if mat is not None:
identifier = mat.group("identifier")
value = mat.group("value")
if isinstance(value, str) and isinstance(identifier, str):
identifier = int(identifier)
value = value.replace("D", "E")
GM_dict[identifier] = float(value)
else:
raise ValueError(value)

return GM_dict

HERE = Path.cwd()  # .joinpath("reference", "scripts")
if HERE.name == "reference":
HERE /= "scripts"
elif HERE.name == "orbital-mechanics":
HERE = HERE.joinpath("reference", "scripts")
GM_dict = parse_pck_file(HERE / "gm_Horizons.pck")
start_date = datetime(1770, 10, 29, tzinfo=tz.UTC)
end_date = datetime(2271, 11, 1, tzinfo=tz.UTC)
dates: list[datetime] = list(rrule(DAILY, dtstart=start_date, until=end_date))
t = ts.from_datetimes(dates)
ecliptic_frame = build_ecliptic_matrix(t)

sun = planets["Sun"]
for planet_name in (
"Mercury",
"Venus",
"Earth",
"Mars",
"Jupiter",
"Saturn",
"Uranus",
"Neptune",
"Pluto",
):
planet = planet_name + " Barycenter"
position = (planets[planet] - sun).at(t)

# This is broken, see
# https://github.com/skyfielders/python-skyfield/issues/655#issuecomment-960377889
# osculating_elements_of(position, ecliptic_frame)

# So we have to do things manually
elems = OsculatingElements(
Distance(np.einsum("mnr,nr->mr", ecliptic_frame, position.position.au)),  # type: ignore
Velocity(np.einsum("mnr,nr->mr", ecliptic_frame, position.velocity.au_per_d)),  # type: ignore
position.t,
GM_dict[position.center] + GM_dict[position.target],
)
c_object = CelestialObject(position.target, planet_name, elems)
c_object.glue()

position = (planets["Moon"] - planets["Earth"]).at(t)
elems = osculating_elements_of(position)
c_object = CelestialObject(position.target, "Moon", elems)
c_object.glue()