Skip to content

Repository files navigation

OpenRocket Motor Database

This repository acts as the dynamic backend for OpenRocket's thrust curve data.

Deployment & API Endpoints

This repository utilizes GitHub Pages to act as a static Content Delivery Network (CDN) for the compiled motor data. This ensures high availability and fast downloads for OpenRocket users without requiring a dedicated backend server.

Architecture

  1. Source: John Coker's ThrustCurve.org API (thanks a lot for this incredible resource!).
  2. Automation: GitHub Actions runs weekly.
  3. Process:
    • Checks for new motors.
    • Downloads raw .eng and .rse files to data/.
    • Compiles them into a SQLite database (motors.db).
    • GZips and hashes the database.
  4. Distribution: The resulting motors.db.gz and metadata.json are published to GitHub Pages.

The deployment process follows a split-branch strategy:

  1. main branch: Contains the source code, scripts, and the raw text cache (.eng/.rse files).
  2. gh-pages branch: Contains only the build artifacts (motors.db.gz and metadata.json).

Every time the Update Workflow runs (scheduled weekly), it commits the new raw data to main, compiles the database, and force-pushes the binary artifacts to gh-pages.

Public Endpoints

The OpenRocket client (and other interested 3rd parties) can access the live data at the following URLs:

FileURLDescription
Manifesthttps://openrocket.github.io/motor-database/metadata.jsonLightweight JSON file. Contains database_version, generated_at, last_checked, sha256, and the signature fields for verification. Checked by the client on startup.
Databasehttps://openrocket.github.io/motor-database/motors.db.gzGZipped SQLite database. Downloaded by the client only if the manifest version differs from the local cache.

Manifest Format

The metadata.json structure is defined as follows: database_version is a sortable timestamp in YYYYMMDDHHMMSS format.

{
"schema_version": 2,
"database_version": 20251225140000,
"generated_at": "2025-12-25T14:00:00.000000",
"last_checked": "2025-12-27T14:00:00.000000",
"motor_count": 1033,
"curve_count": 1320,
"sha256": "a1b2c3d4e5f6...",
"sha256_gz": "a1b2c3d4e5f6...",
"sig": "base64-signature...",
"download_url": "https://openrocket.github.io/motor-database/motors.db.gz"
}

Signature notes:

  • sig is an Ed25519 signature over openrocket-motordb-v1\n{database_version}\n{sha256_gz}\n.
  • sha256_gz is the SHA-256 of the gzipped database; sha256 is kept for backward compatibility.
  • key_id is optional for key rotation.

Database Schema

The SQLite schema lives in schema/V1__initial_schema.sql and is optimized for fast client lookups. Foreign keys are enabled with cascade deletes.

Entity Relationship

manufacturers motors thrust_curves thrust_data
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ id (PK) │◄─────│ mfr_id (FK) │ │ id (PK) │◄───────│ curve_id(FK) │
│ name │ 1:N │ id (PK) │◄────│ motor_id(FK) │ 1:N │ id (PK) │
│ abbrev │ │ tc_motor_id │ 1:N │ tc_simfile_id│ │ time_seconds │
└──────────────┘ │ designation │ │ source │ │ force_newtons│
│ impulse_class│ │ format │ └──────────────┘
│ ... │ │ ... │
└──────────────┘ └──────────────┘
  • manufacturersmotors: One manufacturer has many motors
  • motorsthrust_curves: One motor can have multiple thrust curves (different sources/measurements)
  • thrust_curvesthrust_data: One curve has many time/thrust data points

Tables and Columns

meta

ColumnTypeNotes
keyTEXTPrimary key
valueTEXTRequired

Keys stored: schema_version, database_version, generated_at, motor_count, curve_count.


manufacturers

ColumnTypeNotes
idINTEGERPrimary key, autoincrement
nameTEXTRequired, unique (e.g. "AeroTech")
abbrevTEXTShort name (e.g. "AT")

motors

ColumnTypeNotes
idINTEGERPrimary key, autoincrement
manufacturer_idINTEGERFK to manufacturers.id
tc_motor_idTEXTThrustCurve.org motor ID
designationTEXTRequired (e.g. "H128W")
common_nameTEXTDisplay name (e.g. "H128")
impulse_classTEXTLetter class: A, B, C, ... O
diameterREALMotor diameter in mm
lengthREALMotor length in mm
total_impulseREALTotal impulse in Ns
avg_thrustREALAverage thrust in N
max_thrustREALMaximum thrust in N
burn_timeREALBurn time in seconds
propellant_weightREALPropellant weight in grams
total_weightREALTotal weight in grams
typeTEXT"SU" (single-use), "reload", "hybrid"
delaysTEXTAvailable delays, e.g. "0,6,10,14"
case_infoTEXTCase info, e.g. "RMS 38/360"
prop_infoTEXTPropellant info, e.g. "White Lightning"
sparkyINTEGER1 if sparky motor, 0 otherwise
info_urlTEXTURL to motor info page
data_filesINTEGERNumber of data files on ThrustCurve
updated_onTEXTLast update date from ThrustCurve
descriptionTEXTRASP file comments (header notes, newlines removed)
sourceTEXTData source (e.g. "thrustcurve.org", "manual")

thrust_curves

Each motor can have multiple thrust curves from different sources (certification, manufacturer, user submissions).

ColumnTypeNotes
idINTEGERPrimary key, autoincrement
motor_idINTEGERFK to motors.id, cascade delete
tc_simfile_idTEXTThrustCurve.org simfile ID
sourceTEXT"cert", "mfr", or "user"
formatTEXT"RASP" or "RSE"
licenseTEXT"PD", "free", or other
info_urlTEXTURL to simfile info page
data_urlTEXTURL to download simfile
total_impulseREALCalculated total impulse (Ns)
avg_thrustREALCalculated average thrust (N)
max_thrustREALCalculated max thrust (N)
burn_timeREALCalculated burn time (s)

thrust_data

Time/thrust data points for each thrust curve.

ColumnTypeNotes
idINTEGERPrimary key, autoincrement
curve_idINTEGERFK to thrust_curves.id, cascade delete
time_secondsREALTime in seconds
force_newtonsREALThrust force in Newtons

Indices

IndexTableColumnsPurpose
idx_motor_mfrmotorsmanufacturer_idFilter by manufacturer
idx_motor_diametermotorsdiameterFilter by size
idx_motor_impulsemotorstotal_impulseFilter by impulse
idx_motor_impulse_classmotorsimpulse_classFilter by class (A-O)
idx_motor_tc_idmotorstc_motor_idLookup by ThrustCurve ID
idx_curve_motorthrust_curvesmotor_idGet curves for a motor
idx_curve_simfilethrust_curvestc_simfile_idLookup by simfile ID
idx_thrust_curvethrust_datacurve_idGet data for a curve

Manual Usage

  1. pip install -r scripts/requirements.txt
  2. python scripts/fetch_updates.py (Downloads new files)
  3. python scripts/build_database.py (Generates DB)
  4. python scripts/report_thrustcurve_variants.py (Generates an HTML comparison report for motors with multiple downloadable ThrustCurve simfiles)

The build database does not rebuild if no changes are detected. However, in some case, a forced rebuild may be necessary, e.g. if you made changes to the build script. In which case, add a --force command line argument: python scripts/build_database.py --force (Forces a rebuild even when inputs are unchanged)

Variant report filters:

  • python scripts/report_thrustcurve_variants.py --designation F32
  • python scripts/report_thrustcurve_variants.py --manufacturer AeroTech --limit 25
  • python scripts/report_thrustcurve_variants.py --motor-id 5f4294d20002310000000015

State Files

  • state/last_update.json: timestamp of the most recent data/metadata change detected by scripts/fetch_updates.py.
  • state/last_check.json: timestamp of the most recent update check, even if no changes were found.
  • state/last_build.json: input hash + build outputs used by scripts/build_database.py to skip rebuilding when the schema/data inputs are unchanged.

Signing

Signing is done in CI after the database build completes.

What is signed:

  • Canonical message: openrocket-motordb-v1\n{database_version}\n{sha256_gz}\n
  • sha256_gz is the SHA-256 of motors.db.gz (the compressed DB)

What gets added to metadata.json by the signing step:

  • sha256_gz: SHA-256 of motors.db.gz (currently matches sha256)
  • sig: base64-encoded Ed25519 signature of the canonical message
  • key_id (optional): identifier for key rotation

How CI handles it:

  • .github/workflows/update-motors.yml installs cryptography
  • It runs python scripts/sign_database.py motors.db.gz metadata.json
  • The private key is provided via secrets

Set the private key in:

  • MOTOR_DB_PRIVATE_KEY_BASE64 (Ed25519 private key, DER or PEM encoded, then base64)
  • MOTOR_DB_KEY_ID (optional, for key rotation)

Manual signing: python scripts/sign_database.py motors.db.gz metadata.json

Unit Tests

  1. pip install -r scripts/requirements.txt
  2. pip install pytest cryptography
  3. pytest

Data Attribution & License

The motor data in this repository is cached from ThrustCurve.org.

  • Source: ThrustCurve.org (maintained by John Coker).
  • Copyright: The data files (.eng, .rse) retain their original internal copyright headers.
  • Usage: This data is intended for use within OpenRocket. If you wish to use this data for other projects, please use the ThrustCurve.org API directly to ensure you are respecting the latest updates and restrictions.

About

A motor database for OpenRocket based on thrustcurve.org data and other sources

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages