orbitr orbitr logo

Tidy N-body orbital mechanics for R.

Early betaorbitr is functional and the physics engine is stable, but this is an early release. Function names, defaults, and behavior may change between versions. Feedback, bug reports, and contributions are welcome on GitHub.

Full documentation, examples, and guides at orbit-r.com

Installation

# Development version from GitHub:
# install.packages("devtools")
devtools::install_github("DRosenman/orbitr")

The Full Solar System in Two Lines

library(orbitr)

load_solar_system() |>
  simulate_system(time_step = seconds_per_day, duration = seconds_per_year) |>
  plot_orbits(three_d = FALSE)

load_solar_system() builds the Sun, all eight planets, the Moon, and Pluto with real orbital data from JPL — eccentricities, inclinations, and all. One line to build it, one line to simulate and plot.

Four Lines to an Orbit

library(orbitr)

sim <- create_system() |>
  add_sun() |>
  add_body("Earth", mass = mass_earth, x = distance_earth_sun, vy = speed_earth) |>
  simulate_system(time_step = seconds_per_day, duration = seconds_per_year)

sim |> plot_orbits()

Built-in constants like mass_sun, distance_earth_sun, and speed_earth are real-world values in SI units — no Googling needed. simulate_system() returns a tidy tibble, ready for dplyr, ggplot2, plotly, or anything else.

Animated

animate_system(sim, fps = 15, duration = 5)

More Examples

Build Your Own System with add_planet()

Pick and choose real solar system bodies without looking up any numbers:

create_system() |>
  add_sun() |>
  add_planet("Earth", parent = "Sun") |>
  add_planet("Mars",  parent = "Sun") |>
  simulate_system(time_step = seconds_per_day, duration = seconds_per_year * 2) |>
  plot_orbits(three_d = FALSE)

Every planet’s mass, eccentricity, inclination, and orbital orientation are filled in from JPL data. Override any element to explore “what if” scenarios:

# What if Mars had a perfectly circular orbit?
create_system() |>
  add_sun() |>
  add_planet("Mars", parent = "Sun", e = 0) |>
  simulate_system(time_step = seconds_per_day, duration = seconds_per_year * 2) |>
  plot_orbits(three_d = FALSE)

Earth-Moon

create_system() |>
  add_body("Earth", mass = mass_earth) |>
  add_planet("Moon", parent = "Earth") |>
  simulate_system(time_step = seconds_per_hour, duration = seconds_per_day * 28) |>
  plot_orbits()

Keplerian Orbital Elements

For full control, add_body_keplerian() lets you specify orbits using classical elements — semi-major axis, eccentricity, inclination, and orientation angles — instead of raw positions and velocities:

# A comet on a highly eccentric, tilted orbit
create_system() |>
  add_sun() |>
  add_planet("Earth", parent = "Sun") |>
  add_body_keplerian(
    "Comet", mass = 1e13, parent = "Sun",
    a = 3 * distance_earth_sun, e = 0.85,
    i = 60, lan = 45, arg_pe = 90, nu = 0
  ) |>
  simulate_system(time_step = seconds_per_hour, duration = seconds_per_year * 5) |>
  plot_orbits()

Kepler-16: A Real Circumbinary Planet

Kepler-16b orbits two stars — a real-life Tatooine.

G  <- gravitational_constant
AU <- distance_earth_sun

m_A <- 0.68 * mass_sun
m_B <- 0.20 * mass_sun
a_bin <- 0.22 * AU

r_A <- a_bin * m_B / (m_A + m_B)
r_B <- a_bin * m_A / (m_A + m_B)
v_A <- sqrt(G * m_B^2 / ((m_A + m_B) * a_bin))
v_B <- sqrt(G * m_A^2 / ((m_A + m_B) * a_bin))

r_planet <- 0.7048 * AU
v_planet <- sqrt(G * (m_A + m_B) / r_planet)

create_system() |>
  add_body("Star A",      mass = m_A,                 x = r_A,      vy = v_A) |>
  add_body("Star B",      mass = m_B,                 x = -r_B,     vy = -v_B) |>
  add_body("Kepler-16b",  mass = 0.333 * mass_jupiter, x = r_planet, vy = v_planet) |>
  simulate_system(time_step = seconds_per_hour, duration = seconds_per_day * 228.8 * 3) |>
  plot_orbits()

Features

Learn More

Acknowledgments & Further Reading

The physics and numerics in orbitr were informed by Classical Dynamics of Particles and Systems by Thornton & Marion, Computational Physics by Mark Newman, and Data Structures & Algorithms in Python by Canning, Broder & Lafore. The C++ engine was built with help from the official Rcpp documentation on CRAN. See the full Further Reading article for details on how each resource was used.

Shoutout to The College of New Jersey, where I first got hooked on this stuff. Go Lions.

License

MIT