Skip to main content

hpr_flightdata/
lib.rs

1//! Flight-log importers, the canonical flight record, smoothing and time alignment, and the
2//! readings taken from a flight with the provenance of each.
3//!
4//! **Guide:** [Start here][guide-start] says what works today and what is planned.
5//!
6//! [guide-start]: https://nrdptel.github.io/hpr-sim/start-here.html
7//! [roadmap]: https://github.com/nrdptel/hpr-sim/blob/main/docs/ROADMAP.md
8//! [adr-046]: https://github.com/nrdptel/hpr-sim/blob/main/docs/DECISIONS.md#adr-046-debrief-folded-in-and-flight-log-analysis-that-stands-without-the-simulator-2026-09-20
9//!
10//! This crate does not depend on the simulator, and [must not][adr-046]: reading a flight log and
11//! working out what it says is a use of this project in its own right, for someone who has a log
12//! and neither a design file nor any wish to simulate anything. Comparing a flight with a
13//! simulation of it is `hpr-forensics`, which depends on both.
14//!
15//! Every reading carries where it came from (measured by an instrument, derived from what was
16//! measured, or clipped because the sensor saturated), and a reading the log cannot support is
17//! withheld with a reason rather than printed.
18//!
19//! Status: pre-alpha. One format is read so far, PerfectFlite's `.pf2` ([`perfectflite`]), into
20//! the record every reader produces ([`log::FlightLog`]), and [`readings`] takes a first set of
21//! readings from it: liftoff, apogee, the top speed, landing and the descent. The guide's
22//! [reading a flight log][guide-log] page shows them on a log. The other loggers' formats are
23//! planned for milestone [M7.1][roadmap] of the roadmap, and the rest of the readings, smoothing and
24//! reconstruction for [M7.2][roadmap].
25//!
26//! [guide-log]: https://nrdptel.github.io/hpr-sim/reading-a-flight-log.html
27//!
28//! ```
29//! use hpr_flightdata::{perfectflite, readings};
30//!
31//! // A few rows of an invented PerfectFlite log: feet and seconds.
32//! let mut text = String::from("PerfectFlite Pnut\nData: (Time, Altitude, Velocity)\n");
33//! for (i, feet) in [0, 0, 0, 40, 90, 120, 130, 130, 120, 90, 40, 5, 0, 0, 0, 0].iter().enumerate() {
34//!     text.push_str(&format!("{}, {feet}, 0\n", i as f64 * 0.5));
35//! }
36//! let log = perfectflite::read(&text)?;
37//! let read = readings::read(&log);
38//! let apogee = read.apogee.value().expect("the log climbs");
39//! assert_eq!(apogee.altitude_m, 130.0 * 0.3048);
40//! assert_eq!(apogee.time_s, 3.25); // midway between the two samples at the top
41//! # Ok::<(), hpr_flightdata::error::LogError>(())
42//! ```
43
44pub mod error;
45pub mod filter;
46pub mod log;
47pub mod perfectflite;
48pub mod readings;
49
50#[cfg(test)]
51mod synthetic;