- Notifications
You must be signed in to change notification settings - Fork1
A motor database for OpenRocket based on thrustcurve.org data and other sources
License
openrocket/motor-database
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This repository acts as the dynamic backend for OpenRocket's thrust curve data.
This repository utilizesGitHub 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.
- Source: John Coker'sThrustCurve.org API (thanks a lot for this incredible resource!).
- Automation: GitHub Actions runs weekly.
- Process:
- Checks for new motors.
- Downloads raw
.engand.rsefiles todata/. - Compiles them into a SQLite database (
motors.db). - GZips and hashes the database.
- Distribution: The resulting
motors.db.gzandmetadata.jsonare published to GitHub Pages.
The deployment process follows a split-branch strategy:
mainbranch: Contains the source code, scripts, and the raw text cache (.eng/.rsefiles).gh-pagesbranch: Containsonly the build artifacts (motors.db.gzandmetadata.json).
Every time theUpdate Workflow runs (scheduled weekly), it commits the new raw data tomain, compiles the database, and force-pushes the binary artifacts togh-pages.
The OpenRocket client (and other interested 3rd parties) can access the live data at the following URLs:
| File | URL | Description |
|---|---|---|
| Manifest | https://openrocket.github.io/motor-database/metadata.json | Lightweight JSON file. Containsdatabase_version,generated_at,last_checked,sha256, and the signature fields for verification. Checked by the client on startup. |
| Database | https://openrocket.github.io/motor-database/motors.db.gz | GZipped SQLite database. Downloaded by the clientonly if the manifest version differs from the local cache. |
Themetadata.json structure is defined as follows:database_version is a sortable timestamp inYYYYMMDDHHMMSS 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:
sigis an Ed25519 signature overopenrocket-motordb-v1\n{database_version}\n{sha256_gz}\n.sha256_gzis the SHA-256 of the gzipped database;sha256is kept for backward compatibility.key_idis optional for key rotation.
The SQLite schema lives inschema/V1__initial_schema.sql and is optimized for fast client lookups. Foreign keys are enabled with cascade deletes.
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 │ └──────────────┘ │ ... │ │ ... │ └──────────────┘ └──────────────┘- manufacturers →motors: One manufacturer has many motors
- motors →thrust_curves: One motor can have multiple thrust curves (different sources/measurements)
- thrust_curves →thrust_data: One curve has many time/thrust data points
meta
| Column | Type | Notes |
|---|---|---|
| key | TEXT | Primary key |
| value | TEXT | Required |
Keys stored:schema_version,database_version,generated_at,motor_count,curve_count.
manufacturers
| Column | Type | Notes |
|---|---|---|
| id | INTEGER | Primary key, autoincrement |
| name | TEXT | Required, unique (e.g. "AeroTech") |
| abbrev | TEXT | Short name (e.g. "AT") |
motors
| Column | Type | Notes |
|---|---|---|
| id | INTEGER | Primary key, autoincrement |
| manufacturer_id | INTEGER | FK tomanufacturers.id |
| tc_motor_id | TEXT | ThrustCurve.org motor ID |
| designation | TEXT | Required (e.g. "H128W") |
| common_name | TEXT | Display name (e.g. "H128") |
| impulse_class | TEXT | Letter class: A, B, C, ... O |
| diameter | REAL | Motor diameter in mm |
| length | REAL | Motor length in mm |
| total_impulse | REAL | Total impulse in Ns |
| avg_thrust | REAL | Average thrust in N |
| max_thrust | REAL | Maximum thrust in N |
| burn_time | REAL | Burn time in seconds |
| propellant_weight | REAL | Propellant weight in grams |
| total_weight | REAL | Total weight in grams |
| type | TEXT | "SU" (single-use), "reload", "hybrid" |
| delays | TEXT | Available delays, e.g. "0,6,10,14" |
| case_info | TEXT | Case info, e.g. "RMS 38/360" |
| prop_info | TEXT | Propellant info, e.g. "White Lightning" |
| sparky | INTEGER | 1 if sparky motor, 0 otherwise |
| info_url | TEXT | URL to motor info page |
| data_files | INTEGER | Number of data files on ThrustCurve |
| updated_on | TEXT | Last update date from ThrustCurve |
| description | TEXT | RASP file comments (header notes, newlines removed) |
| source | TEXT | Data source (e.g. "thrustcurve.org", "manual") |
thrust_curves
Each motor can have multiple thrust curves from different sources (certification, manufacturer, user submissions).
| Column | Type | Notes |
|---|---|---|
| id | INTEGER | Primary key, autoincrement |
| motor_id | INTEGER | FK tomotors.id, cascade delete |
| tc_simfile_id | TEXT | ThrustCurve.org simfile ID |
| source | TEXT | "cert", "mfr", or "user" |
| format | TEXT | "RASP" or "RSE" |
| license | TEXT | "PD", "free", or other |
| info_url | TEXT | URL to simfile info page |
| data_url | TEXT | URL to download simfile |
| total_impulse | REAL | Calculated total impulse (Ns) |
| avg_thrust | REAL | Calculated average thrust (N) |
| max_thrust | REAL | Calculated max thrust (N) |
| burn_time | REAL | Calculated burn time (s) |
thrust_data
Time/thrust data points for each thrust curve.
| Column | Type | Notes |
|---|---|---|
| id | INTEGER | Primary key, autoincrement |
| curve_id | INTEGER | FK tothrust_curves.id, cascade delete |
| time_seconds | REAL | Time in seconds |
| force_newtons | REAL | Thrust force in Newtons |
| Index | Table | Columns | Purpose |
|---|---|---|---|
| idx_motor_mfr | motors | manufacturer_id | Filter by manufacturer |
| idx_motor_diameter | motors | diameter | Filter by size |
| idx_motor_impulse | motors | total_impulse | Filter by impulse |
| idx_motor_impulse_class | motors | impulse_class | Filter by class (A-O) |
| idx_motor_tc_id | motors | tc_motor_id | Lookup by ThrustCurve ID |
| idx_curve_motor | thrust_curves | motor_id | Get curves for a motor |
| idx_curve_simfile | thrust_curves | tc_simfile_id | Lookup by simfile ID |
| idx_thrust_curve | thrust_data | curve_id | Get data for a curve |
pip install -r scripts/requirements.txtpython scripts/fetch_updates.py(Downloads new files)python scripts/build_database.py(Generates DB)
state/last_update.json: timestamp of the most recent data/metadata change detected byscripts/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 byscripts/build_database.pyto skip rebuilding when the schema/data inputs are unchanged.
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_gzis the SHA-256 ofmotors.db.gz(the compressed DB)
What gets added tometadata.json by the signing step:
sha256_gz: SHA-256 ofmotors.db.gz(currently matchessha256)sig: base64-encoded Ed25519 signature of the canonical messagekey_id(optional): identifier for key rotation
How CI handles it:
.github/workflows/update-motors.ymlinstallscryptography- 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
pip install -r scripts/requirements.txtpip install pytest cryptographypytest
The motor data in this repository is cached fromThrustCurve.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 theThrustCurve.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
License
Uh oh!
There was an error while loading.Please reload this page.