Expand description
AltOS’s CSV flight logs, as AltosUI exports a TeleMetrum’s, TeleMega’s, EasyMega’s or EasyMini’s flight.
The file is text: perhaps a few comment lines starting with #, then one header line naming
the columns, then one row per sample, the cells separated by a comma and spaces:
#version,serial,flight,call,time,rssi,lqi,state,state_name,acceleration,pressure,altitude,height,speed,temperature,…
6, 1234, 3,N0CALL, -1.00, -80, 40, 2, pad, 0.10, 98000.00, 250.00, 0.00, 0.00, 21.0,…The columns differ by device and by AltosUI’s version: the header says which there are, and
this reader maps them by name. call is there when the flight came in by radio, and rssi
and lqi when it was received as telemetry; a GPS-equipped unit adds latitude, longitude,
a second altitude, the time of day, the distance and bearing to the pad and the receiver’s
satellite columns sat01…sat32; a TeleMega or EasyMega adds its inertial and magnetic
sensors. One of the files read has no pressure or barometric altitude column at all.
Units. The AltOS manual says the file holds “all of the sensor values … converted to
standard units, with the barometric data reported in both pressure, altitude and height above
pad units”, and that its header and comment lines start with # (Altus Metrum, AltOS
manual, §12.5.1 “Comma Separated Value Format”). It names no column’s unit; these are each
one’s reading, and where it comes from:
| columns | read as | from |
|---|---|---|
time | the clock, s, from the logger’s zero at boost: negative on the pad | Debrief’s reader |
height | Quantity::AltitudeAboveGround, m above the pad | Debrief’s reader; the manual’s “height above pad” |
altitude (the first) | Quantity::AltitudeMsl, m, the barometric altitude | the manual; Debrief’s reader |
altitude after longitude | Quantity::GnssAltitude, m, the GPS receiver’s | Debrief’s reader, which finds it by its place |
pressure | Quantity::Pressure, Pa; hPa if the column never reaches 1,200 (below) | the files read: about 98,000 on a pad |
acceleration, accel_x/_y/_z | Quantity::Acceleration, m/s² | Debrief’s reader and its proof from the data (below) |
speed, accel_speed, baro_speed | Quantity::Speed, m/s, up positive | Debrief’s reader |
temperature | Quantity::Temperature, °C in the file, K here | Debrief’s reader |
battery_voltage, drogue_voltage, main_voltage, pyro, igniter_* | Quantity::Voltage, V | Debrief’s reader (battery); the manual’s §13.9 states the igniter and battery readings in volts |
latitude, longitude | Quantity::Latitude, Quantity::Longitude, degrees | Debrief’s reader |
tilt, pad_az, pad_el | Quantity::Angle, degrees | the manual (its pyro condition’s “angle from vertical”, in degrees; §13.10’s bearing “in degrees”); the files read stay within 0–180 and 0–360 |
pad_dist, pad_range | Quantity::Distance, m | only the manual’s “standard units”: no document states their unit |
version, serial, flight, rssi, lqi, state, connected, locked, nsat, year…second, pdop, hdop, vdop, sat01…sat32 | Quantity::Number, as written | counts, codes, flags, signal strengths and dilutions of precision |
gyro_roll/_pitch/_yaw, mag_x/_y/_z | Quantity::Unrecognized, as written | the record has no quantity for a rotation rate or a magnetic field, and no document states their unit |
Every other column is kept as written, Quantity::Unrecognized, with a note. call (the
radio call sign) and state_name (the flight computer’s state in words) are text, not
channels: each state the file changes to is an Event instead, at the time of the row that
changes it, the first row’s state included. The numeric state column is kept as a channel.
The primary track. FlightLog::altitude_m is height; the vertical speed is
baro_speed, the barometer’s, and absent without it: accel_speed integrates the
accelerometer and speed is the flight computer’s own estimate, which leans on the
accelerometer on the way up, so both stay channels only (Debrief’s reader took accel_speed
first). The temperature is temperature and the battery battery_voltage. Both time and
height are required.
Quirks, and what this reader does about them.
- Repeated times. AltosUI writes rows that share a time with the row before, hundreds in a
flight; in every one of the files read, such rows also repeat the height. The primary track
must have strictly increasing times, so it keeps the first row at each time, and the rows it
leaves out are counted in a note. Rows out of time order (none in the files read) are put in
order on the primary track, again with a note. This is what Debrief does (its
lib/flight/build.ts: sort by time, keep the first row at each time). The channels keep every row, in the file’s order, each on its own time. - Acceleration net of gravity. AltOS writes
accelerationalong the rocket’s axis with gravity taken out: it reads about 0 at rest, not 1 g, while the TeleMega’s body-axisaccel_xon the same row reads about 9.8 m/s² (Debrief’s reader, from the data). The channel is kept as written, and a note says so. The pad’s reading of 1 g along the axis is what comes out, so the channel is the rocket’s own acceleration only while it points straight up; tilted, it is off by the difference between g and g’s share along the axis. - GPS before a fix. AltOS writes a position of exactly (0, 0) before its receiver has a fix (Debrief’s reader). A row with latitude and longitude both 0 has its latitude, longitude and GPS altitude read as gaps, counted in a note. None of the files read has such a row; the rule is Debrief’s, kept so that a track can’t run to the equator.
- Pressure in hectopascals. Debrief’s own sample file writes pressure in hPa (about 983 on
its pad), where AltosUI’s exports write Pa. No launch site’s pressure is below 10 kPa nor
above 120 kPa, and the two units are a hundredfold apart, so the column’s highest value
settles it: from 10,000 to 120,000, Pa; from 100 to 1,200, hPa, converted with a note;
anything else is kept as written,
Quantity::Unrecognized, with a note. - Gaps. AltosUI writes
NaNwhere it has no value (a TeleMega’stiltbefore it has an attitude). A cell that is empty or not a finite number is a gap,NaN, counted per column in a note. - Short and long rows. A row with fewer cells than the header (a file cut off mid-row) has the rest as gaps, with a note; a row with more cells is refused, naming its line, unless the extra cells are empty (a trailing comma). A row whose time isn’t a number can’t be placed on the clock and is left out, with a note.
What the file says about itself. The serial number and flight number come from the comment
lines # serial … and # flight … when the file has them, and from the first row’s serial
and flight cells otherwise; # product … names the device, as in AltOS TeleMetrum. The
file states no firmware version (its version column is the data’s, kept as a channel), no
apogee and no sample count.
Where this comes from. Ported from Debrief’s reader (lib/parsers/altusmetrum.ts, MIT, the
project owner’s own; see THIRD-PARTY-NOTICES.md), which was written from exported files, and
the AltOS manual’s description of the export. No AltOS or AltosUI source code was read. Where
this reader departs from Debrief’s: it keeps every column as a channel where Debrief keeps a
chosen few; it keeps the file’s clock, where Debrief moves the zero to the first row; it reads a
hectopascal pressure as such; it refuses a long row; it requires the header first (after
comment lines), where Debrief searches the first 60 lines for it. AltOS’s radio-telemetry log
(tick, ptype, …) is a different file and isn’t read here.
Functions§
- read
- Reads an AltOS CSV flight log from its text.