RASP .eng motor files
A .eng file is a motor’s thrust curve in plain text: a one-line
header with the motor’s name, size, delays and masses, then one time and thrust per line. The
format is named after RASP, the rocket simulation program it comes from. It is the more common of
the two formats ThrustCurve.org serves (the other is
RockSim .rse).
To fly a motor from a .eng file, see
A motor from a file on the Solid motors page. It reads a
file, builds the motor and puts it in a rocket, with a program that CI runs.
This page is the reference for hpr’s reader and writer: what the published spec says, what real files do, and what hpr does with each. All 889 RASP files ThrustCurve.org held on 2026-09-17 read, and write back with every value unchanged (Checked against real files).
Code: hpr_motor::eng (API reference), written for the
solid-motor milestone (M1.3). The rules below are from the spec unless marked
Observed (seen in real files) or Policy (hpr’s own choice).
Sources
- [R] ThrustCurve.org, “RASP File Format”, https://www.thrustcurve.org/info/raspformat.html,
captured 2026-09-17 and pinned as
thrustcurve-rasp-format(sha25669573e9f…) in the reference lock file, which records each source’s address and checksum. Sections are cited as [R Header], [R Data], [R Problems]. The page names the RASP C source as “the ultimate authority”; its license is not stated, so it was not consulted. - Observed: 734 entries in the ThrustCurve manufacturer file sets (12
.engsets) and 13 single-motor API downloads, fetched 2026-09-17 into a local cache,refs/samples/formats/, that is never committed. Counts below are over those entries.
Grammar
Read := as “is made of”, * as “any number of”, + as “one or more”, and | as “or”.
file := entry+
entry := (blank | comment)* header point+ (blank | comment)*
comment := ';' text whole line; [R Header], [R Problems]
header := name dia len delays prop total mfg seven fields "separated by spaces" [R Header]
point := time thrust "usually preceded by a few spaces" [R Data]
- Blank and
;lines are ignored before the header. After the last point an entry “may end or contain comments and blank lines, but nothing else” [R Header], [R Data]. - “All seven must be present for the entry to be read successfully” [R Header].
- Points start “immediately after the header line” [R Data].
- A file may hold several entries; “make sure that each entry is separated by at least one comment
line”. A lone
;after the data is the customary separator [R Data], [R Problems].
Header fields [R Header]
| # | Field | Unit | Meaning |
|---|---|---|---|
| 1 | name | n/a | Common name: “just the impulse class and average thrust” (F32) |
| 2 | diameter | mm | Casing diameter |
| 3 | length | mm | Casing length |
| 4 | delays | s | Available delays “separated by dashes”; 0 = ejection charge, no delay; P = plugged, no ejection charge |
| 5 | propellant mass | kg | “Weight of all consumables” (the propellant, for a solid) |
| 6 | total mass | kg | Motor “loaded and ready for flight” |
| 7 | manufacturer | n/a | Abbreviation, per the combined motor list of the NAR (National Association of Rocketry) |
Thrust curve [R Data], [R Problems]
- Each point is a time (s) and a thrust (N), as “floating-point numbers”.
- An implicit first point at (0, 0) “is assumed and should not be specified explicitly”. An explicit (0, 0) is called “a common mistake”.
- “The final point must have a thrust of zero and it indicates the motor’s burn time.” A zero thrust anywhere else is rejected by ThrustCurve. (ThrustCurve’s metadata uses the burn time of the NFPA 1125 5% rule instead; see Loft lesson L39, where Loft took the last point as the burn time.)
- Points “must be in order of time”. ThrustCurve rejects a point “before the previous point” and a first point at negative time. Equal times are not addressed.
- RASP allowed at most 32 points, including the final zero; modern tools don’t enforce this.
Where the spec is silent
Number syntax (exponents, sign; its own example uses .0377). Whether tabs or several spaces
separate fields. Line endings, text encoding, and a BOM (byte-order mark: an invisible character
some editors put at the start of a file). Delay lists that mix numbers with P, or use other
separators. Equal consecutive times. Inline comments. An entry with no comment separator before the
next header.
Observed in real files
- Whitespace: tabs separate data fields in 4 of 12 sets. 52 headers use several spaces or
column alignment; one header is indented. Trailing spaces are common. 8 of 25 files use CRLF
(Windows line endings, a carriage return then a line feed; other systems use LF alone);
13 of 13 single downloads lack a final newline. There is no BOM, no non-ASCII byte, no inline
;, no blank or comment line inside the data, and no indented comment. - Entries: always separated by a comment; there are 470 lone
;lines. A reader that stops at the first header loses the rest of the file (Loft lesson L36). - Header: never more than 7 fields; spaces in a manufacturer name become
_(Contrail_Rockets). Manufacturer spellings vary (AT,A,Aerotech,AERO,AT-RMS,AT/RCS;CTI,Ces,CSR,Pro38). The name is often the full designation, not class plus thrust (1266-J760-WT-19A,I216-CL(I),O25,000-VM-P,1/2A3T,C6-0). - Numbers: leading dot (
.0377, 21 headers), trailing dot (2415.), leading zeros (068.8604), padded decimals (0.000), binary float noise (0.060700000000000004, 72 headers), up to 15 significant digits. Diameters and lengths can be fractional (114.3). No exponents or signs were seen. - Delays: 574 dash lists, 143
P, 4 comma lists (5,8,11), 8 lists ending inP(6-10-14-P), 1 lowercasep, and 4 malformed (4-7-10,,-,1-3--4-6-7-9-10). 58 lists are descending (14-12-10-8-6). 27 contain100or1000. Checked against ThrustCurve search metadata,100/1000mean plugged in 14 of 14 cases, and0means plugged in 120 of 149, against the spec’s “no delay” (Loft lesson L37: Loft read100and1000as seconds). - Curve: 32 entries have an explicit first point at t = 0 with nonzero thrust. Loft’s bundle also had an explicit (0, 0). 4 entries don’t end at zero thrust. 4 have equal consecutive times (a vertical drop to zero, or rounded times). 69 have more than 32 points. None have decreasing time, negative thrust or an interior zero.
Reader policy (lenient, with diagnostics)
- The reader takes text and strips a UTF-8 BOM. Decoding bytes into text is the caller’s job:
today, read the file into a string yourself, as with
std::fs::read_to_string, which expects UTF-8. That job, and any fallback to Windows-1252 (an older Windows character set), is planned forhpr-io, the crate for other programs’ file formats, which doesn’t do it yet. Lines split on LF, CRLF or a bare CR and are trimmed. - A line whose first non-blank character is
;is a comment. Fields split on runs of spaces and tabs. - Each entry is read in stages (a state machine). Before the header, skip blanks and collect comments. The header is the first other line. In the data, a 2-field numeric line is a point; skip blank lines; a comment ends the data, and an entry that ends with no points is an error. A line with 7 or more fields starts a new entry, with a warning about the missing separator. Anything else is an error, with its line number.
- The header needs 7 or more fields. With more than 7, join fields 7 onward with single spaces
as the manufacturer, and warn. Dia and len must be finite and > 0, and the masses finite and
≥ 0; warn if prop ≥ total. Keep file units (mm, kg) in the file model, in fields named for them
(
diameter_mm). Convert to SI only when building the physical motor: mm → m → mm is not bit-exact (502.1 / 1000 * 1000 != 502.1; with* 1e-3and* 1e3, 30 of 290 distinct header lengths fail). - Numbers: Rust
str::parse::<f64>accepts.5,5.,068.8,+1and1e3, but alsoinf,infinityandNaN. Reject every non-finite value. - Points are kept verbatim; no implicit origin is inserted into the file model. Errors: no points, negative time, time decreasing. Warnings, on the header’s line: last thrust ≠ 0, negative thrust, and delay pieces the delay reader drops or flags. Equal consecutive times are accepted (a step in the physical curve). The RASP 32-point limit is not enforced.
- Delays: keep the raw token verbatim. The derived view splits on
-or,, drops empty pieces (with a warning), mapsP/p→ plugged and100/1000→ plugged, reads0as its own “zero or plugged” setting with a warning (spec: no delay; files: usually plugged), and reads other pieces as seconds. A0never becomes an ejection at burnout without a decision. Physics should prefer catalog metadata for delays. - An entry with an error is skipped, with the error as a warning, when other entries in the file read; the reader resumes at the next comment line. With no entry read, the first error returns. Every warning carries a kind: skipped (an entry lost), dropped (a value ignored) or unusual (read as it stands).
- Comments: store the text after
;verbatim, but drop comments that are empty after trimming. Comments between two entries belong to the next entry; comments after the last entry are file trailer comments. Policy: a comment that names hpr as the program that wrote the file (hpr-sim, a version, thenFS · SW · TOOL 005; see the writer policy) is dropped when reading, because it says who wrote the file, not anything about the motor. Like any comment, it still ends the entry before it.
Conversion to a physical curve (EngEntry::thrust_curve, not part of the file model): prepend
(0, 0) when the first time is > 0. A leading (0, F) stays a step at ignition. Negative thrust is
an error there.
Writer policy (strict, round-trip stable)
Round-trip stable: a file hpr writes reads back to exactly the values it was written from.
- Policy: the first line is a comment naming the program that wrote the file, its version and
its designation in the FusionSpace product system, as every file hpr writes does:
; hpr-sim 0.1.0 · FS · SW · TOOL 005. The·is a middle dot, the file’s only non-ASCII character unless its comments hold others; the file is UTF-8. A comment carried over from the source that is itself such a line, from any version, is left out, so a file converted again holds one such line, not two. Whether other programs (RockSim, OpenRocket, a flight computer’s tools) accept the middle dot in a comment has not been checked. - Each entry: its comments as
;text, then the header with single spaces, then onet Fline per point, then a lone;. Finally the trailer comments. LF endings, a final newline, UTF-8. - The name must be one token that doesn’t start with
;(the line would read as a comment), and the delays one token. The manufacturer may hold spaces if its words are separated by single spaces, since the reader joins extra fields that way. Comment text must be non-empty, on one line, and without trailing whitespace (the reader would trim it). Otherwise return an error, never a silent substitution. - Numbers use Rust
{}(Display). It prints the shortest digits that parse back to the same bits, never uses an exponent (older readers may not accept one), and writes-0.0as-0. - Points are written as stored: no origin is added or removed. The writer rejects negative or decreasing times, the same rules as the reader.
- Invariant (test it): whenever
write(parse(x))succeeds,parse(write(parse(x))) == parse(x), with f64 compared by bits. Dropping empty comments is what keeps the writer’s;separator stable. A lenient read the writer cannot represent (a manufacturer containing spaces) is a write error, not a changed value. - Leading and trailing whitespace inside comment text: the reader trims only trailing whitespace,
and the writer never adds any, so
; textround-trips astext. - Converting to and from
.rse(hpr_motor::convert,hpr convert, since M4.2c, the command-line conversion) is described with that format’s writer policy. From.rse, a code or maker of several words joins them with_, as no real file has more than seven header fields and OpenRocket 24.12 refuses eight (motor_files.pychecks it), andhpr convertjoins a maker read from a.engfile the same way. A leading(0, 0)point is dropped when the next is after ignition, and the comment text becomes one comment per non-blank line.
Checked against real files
On 2026-09-17, all 889 RASP files in ThrustCurve.org’s solid-motor survey
(data notes) and
the 721 entries of its manufacturer sets read, and
write-parse-write reproduces every value bit for bit. The files are cached under refs/samples/
and never committed; the committed test covers the bundled curves.