hpr_flightdata/log.rs
1//! The flight record every log reader produces: a clock, the channels the logger recorded on it,
2//! and what the file states about itself.
3//!
4//! Units are SI, converted from the file's own at reading: meters, meters per second, kelvin,
5//! volts. A gap in a channel, such as a row that left a column out, is `NaN`.
6
7use serde::{Deserialize, Serialize};
8
9/// A flight log, read.
10#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub struct FlightLog {
12 /// The file format it was read from.
13 pub format: LogFormat,
14 /// The logger, as the file names it, such as `PerfectFlite Pnut`.
15 pub logger: String,
16 /// The logger's serial number, as the file states it.
17 pub serial_number: Option<String>,
18 /// The logger's firmware version, as the file states it.
19 pub firmware: Option<String>,
20 /// The flight's number in the logger's memory, as the file states it.
21 pub flight_number: Option<u32>,
22 /// What the file states about the flight: the logger's own figures, kept beside hpr's
23 /// readings and never in place of them.
24 pub stated: Stated,
25 /// Each sample's time, s, from the logger's own zero. Strictly increasing.
26 pub time_s: Vec<f64>,
27 /// The barometric altitude, m, as the logger converts its pressure, above the logger's own
28 /// zero: for a PerfectFlite, its reading on the pad.
29 pub altitude_m: Vec<f64>,
30 /// The vertical speed, m/s, up positive, as the logger computes it; `None` if the file has
31 /// no such column. A barometric logger works it out from its own altitude.
32 pub vertical_speed_m_s: Option<Vec<f64>>,
33 /// The logger's temperature sensor, K; `None` if the file has no such column. It sits in the
34 /// electronics bay, so it reads the bay, not the air.
35 pub temperature_k: Option<Vec<f64>>,
36 /// The logger's battery voltage, V; `None` if the file has no such column.
37 pub battery_v: Option<Vec<f64>>,
38 /// What the reader noticed and worked around, such as a sample count that differs from the
39 /// one the file states.
40 pub notes: Vec<String>,
41}
42
43/// A flight log's file format.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
45#[serde(rename_all = "snake_case")]
46#[non_exhaustive]
47pub enum LogFormat {
48 /// PerfectFlite's `.pf2`, as its software writes a Pnut's flights. The StratoLogger and
49 /// StratoLoggerCF are expected to write the same layout, as Debrief's reader assumes; no file
50 /// of theirs has been read.
51 PerfectFlitePf2,
52}
53
54impl LogFormat {
55 /// The altitude's resolution in the format, m: a PerfectFlite writes whole feet.
56 pub fn altitude_resolution_m(self) -> f64 {
57 match self {
58 Self::PerfectFlitePf2 => crate::perfectflite::FOOT_M,
59 }
60 }
61
62 /// The format's usual file extension, with its dot.
63 pub fn extension(self) -> &'static str {
64 match self {
65 Self::PerfectFlitePf2 => ".pf2",
66 }
67 }
68}
69
70/// What a flight log states about the flight, in SI.
71#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)]
72pub struct Stated {
73 /// The apogee the logger computed, m above its own zero; `None` if the file states none, or
74 /// states something that isn't a height, such as a PerfectFlite's `PWRLOSS`.
75 pub apogee_m: Option<f64>,
76 /// The launch site's elevation, m above mean sea level, as the logger states it.
77 pub ground_elevation_msl_m: Option<f64>,
78 /// How many samples the file says it holds.
79 pub samples: Option<usize>,
80}