orlab scripts OpenRocket from Python via
JPype: load .ork files, run simulations
(optionally with custom listeners), and extract time series, flight
summaries, and events as Python/numpy data — up to parallel dispersion
studies with one verified jar fetch and a worker pool.
import orlab
with orlab.OpenRocketInstance(jar_path="OpenRocket-24.12.jar") as instance:
orl = orlab.Helper(instance)
doc = orl.load_doc("rocket.ork")
sim = doc.getSimulation(0)
orl.run_simulation(sim)
data = orl.get_timeseries(
sim, [orlab.FlightDataType.TYPE_TIME, orlab.FlightDataType.TYPE_ALTITUDE]
)
events = orl.get_events(sim) # {FlightEvent.APOGEE: [3.51], ...}The project is an evolution of orhelper. Beyond the basics, orlab ships the plumbing you'd otherwise hand-roll for dispersion studies:
python -m orlab fetch— sha256-verified jar download and cache;OpenRocketInstance()then boots with zero configuration.orl.get_summary(sim)— the scalar flight report (apogee, stability, descent, landing distance/bearing, …) as plain Python;orl.export_csv/orl.get_dataframefor full timeseries tables.orlab.SimulationPool— parallel monte-carlo across JVM worker processes, with replayable seeds and progress reporting.orl.set_motor(sim, "C6", manufacturer="Estes")— swap the motor the simulation actually flies, from the motor database or a.engfile.
The guides cover each.
Where orhelper targets a single OpenRocket version, orlab detects the jar's version before the JVM starts and adapts to it — package roots, startup path, and available flight-data constants all come from checked-in, generated version profiles.
Documentation: https://cameronbrooks11.github.io/orlab/ — getting started, API reference, and maintainer procedures.
| OpenRocket | Status | Notes |
|---|---|---|
| 24.12 | CI-tested (JDK 17, 21) | official headless bootstrap |
| 23.09 | CI-tested (JDK 17, 21) | |
| 22.02 | CI-tested (JDK 17, 21) | |
| 15.03 | CI-tested (JDK 17, 21) | |
| newer releases | forward fallback | run day-one on the nearest older profile, with a warning; full support is one profile-regeneration PR |
Every version in the table runs real simulations in CI (no display server needed on any of them) on every pull request and push to main, and a monthly canary checks the newest upstream release against the newest profile.
Version differences are enforced with clear errors: requesting a constant the
loaded version does not have raises UnsupportedFlightDataType naming the
versions that have it. Constants newer than the enum can be passed as strings,
e.g. orl.get_timeseries(sim, ["TYPE_SOME_NEW_TYPE"]).
-
Install the package (Python 3.10+)
pip install orlab -
Install a JDK (17 or 21, Adoptium Temurin tested). Let the installer set
JAVA_HOME— JPype finds the JVM through it. See Setting up the JDK if it doesn't. -
Fetch an OpenRocket jar — orlab downloads it into a local cache and verifies its sha256:
python -m orlab fetchAfter that,
OpenRocketInstance()finds the cached jar with no further configuration. To use a jar you already have instead, passjar_path=toOpenRocketInstance(...)or setORLAB_JAR:export ORLAB_JAR=/path/to/OpenRocket-24.12.jarThe full resolution order is
ORLAB_JAR, the legacyCLASSPATH, the newest supportedOpenRocket-*.jarin the current directory, then the cache;python -m orlab whichshows what would be used. See Getting an OpenRocket jar for details.
The examples/ directory demonstrates the main
workflows against a bundled .ork file:
simple_plot.py— run one simulation, plot altitude and vertical velocityadvanced_plot.py— multiple series, events annotated on the plotmonte_carlo.py— dispersion study with randomized parameters and custom listeners (landing-point capture, air start)lazy.py— optimize a design parameter against simulation output
The plotting examples need matplotlib (and lazy.py needs scipy) —
pip install matplotlib scipy, or uv sync --group examples in a clone.
Worth knowing:
- One OpenRocket jar per process (JPype cannot restart a JVM). The JVM
starts on first use and stays up until the interpreter exits; sequential
withblocks and notebook re-runs on the same jar reuse it, a different jar raisesOrlabError. Use subprocesses to compare versions. run_simulationrandomizes the simulation seed by default (what monte-carlo loops want); passrandomize_seed=Falseto keep a seed you set yourself.- JVM options:
OpenRocketInstance(jvm_args=("-Xmx4g",))for large runs;jvm_path=selects a specific JVM. - Exceptions raised inside your
AbstractSimulationListenersubclass propagate out ofrun_simulationintact.
For background, see the OpenRocket wiki on scripting with Python and JPype.
JPype locates the JVM via JAVA_HOME. If startup fails with a JVM-not-found
error:
- Linux:
export JAVA_HOME=/usr/lib/jvm/<your-jdk>(add to~/.bashrc), or install via your package manager (temurin-21-jdk,openjdk-21-jdk). - Windows: set
JAVA_HOMEunder System Properties → Environment Variables to e.g.C:\Program Files\Eclipse Adoptium\jdk-21, and add%JAVA_HOME%\bintoPath. - Any platform: pass the JVM library path directly —
OpenRocketInstance(jvm_path="/path/to/libjvm.so").
The toolchain is uv + just; working agreements live in AGENTS.md.
git clone https://github.com/CameronBrooks11/orlab.git
cd orlab
just setup # uv sync
just check # format check + lint + mypy
just test # unit tests (no jar or JVM needed)
just test-integration runs real simulations against every supported
OpenRocket version (jars are downloaded and cached on first run). Releases
are tagged from main and published to PyPI by CI — see
CHANGELOG.md.
- The original orhelper project by SilentSys
- All contributors to the OpenRocket project over the years