Skip to main content

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}