A tidy physics engine for building and visualizing orbital simulations in R.
New: the orbitr book. Orbital Mechanics with R — simulating planets, binary stars, chaotic systems, and the N-body problem with orbitr. Free to read online at book.orbit-r.com.
Version 1.0 — the function names, arguments, and defaults are now stable; anything that changes in a future version will be deprecated first. Feedback, bug reports, and contributions are welcome on GitHub.
orbitr is a lightweight N-body gravitational simulator built for the R ecosystem. Simulate planetary orbits, binary star systems, or chaotic three-body problems in a few lines of pipe-friendly code. Under the hood it ships a compiled C++ engine via Rcpp and falls back gracefully to a pure-R implementation.
Installation
# Install from CRAN:
install.packages("orbitr")
# Or install the development version from GitHub:
# install.packages("devtools")
devtools::install_github("DRosenman/orbitr")Four Lines to an Orbit
For solar system bodies like the Sun and planets, you can use convenience functions like add_sun() and add_planet() — they use real masses and orbital data from JPL automatically:
library(orbitr)
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()Or build the whole solar system in one line with load_solar_system():
load_solar_system() |>
simulate_system(time_step = seconds_per_day, duration = seconds_per_year) |>
plot_orbits()Don’t need every body? Use remove_body() to drop them:
load_solar_system() |>
remove_body(c("Pluto", "Moon")) |>
simulate_system(time_step = seconds_per_day, duration = seconds_per_year) |>
plot_orbits()You can also specify positions and velocities manually with add_body() — useful for custom or fictional systems, or when you want full control:
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()
And animated:
animate_system(sim, fps = 15, duration = 5)
Features
-
Tidy output —
simulate_system()returns a standard tibble (one row per body per time step), ready fordplyr,ggplot2,plotly, or anything else in the R ecosystem. - Built-in physical constants — real-world masses, distances, and orbital speeds for the Sun, all eight planets, and the Moon, so you don’t have to look anything up. See Physical Constants.
-
C++ engine — a compiled
Rcppacceleration kernel handles the gravity loop, with automatic fallback to vectorized R if the compiled code isn’t available. - Three integrators — Velocity Verlet (default, symplectic, energy-conserving), Euler-Cromer (fast preview), and standard Euler (educational comparison). See The Physics.
-
2D and 3D plotting —
plot_orbits()returns aggplotfor planar sims and auto-dispatches to an interactiveplotlywidget when any body has Z-axis motion. See 3D Plotting. -
Animations —
animate_system()renders orbits as GIFs with fading trails viagganimate, or as interactive 3D animations withplotly. -
Reference frame shifting —
shift_reference_frame("Earth")re-centers the simulation on any body, turning a heliocentric view into a geocentric one. See Reference Frames. -
Save and share —
save_system()/load_system()round-trip a full system to an.rdsfile, andexport_bodies()writes the body table to CSV for collaborators, Python, or Excel.
Kepler-16: A Real Circumbinary Planet
Kepler-16b orbits two stars — a real-life Tatooine. orbitr handles multi-body gravitational interactions natively, no special setup needed:
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) |>
animate_system(fps = 15, duration = 6)
Learn More
- Get Started — install, simulate, and plot your first orbit
- Building Two-Body Orbits — the physics of choosing positions, velocities, and masses
- Examples — Earth-Moon, Sun-Earth-Moon, Kepler-16, and more
- Unstable Orbits — why most random configurations are chaotic
- Custom Visualization — build your own plots with ggplot2 and plotly
- The Physics — gravitational equations, integrators, and the C++ engine
- Interactive Demo — try orbitr in your browser with the Shiny app