Expand description
Featherweight’s GPS tracker logs, as the tracker’s app and its ground station write them to comma-separated files: positions from a GPS receiver, with no barometer.
Featherweight’s GPS tracker radios its fixes to a ground station, which passes them to a phone app over Bluetooth; the tracker also keeps its own “flight data logging” (Featherweight, Featherweight GPS Tracker User’s Manual, February 20, 2025, p17). As of 2026-10-12, among the project’s sample logs, 40 distinct files hold one of four layouts, each a header line naming the columns, then one row per fix:
| Layout | Files | Header |
|---|---|---|
| The tracker’s log, older | 7 | UTCTIME,UNIXTIME,ALT,LAT,LON,#SATS,FIX,HORZV,VERTV,HEAD,FLAGS,>40,>32,>24,RSSI,BATT |
| The tracker’s log, newer | 21 | the same 16, then Altitude AGL,Launch detection,Apogee detection,Landing detection,Distance (feet) |
| The ground station’s log | 8 | TRACKER,DATE,TIME,LAT,LON,ALT,FIX,HORZV,VERTV,HEAD,FLAGS,#TOT,>40,>32,>24,RSSI,BATT |
| The ground station’s log with its radio’s figures | 4 | TRACKER,DATE,TIME,GS Lat,GS Lon,GS Alt asl,TRACKER Lat,TRACKER Lon,TRACKER Alt asl,… (40 columns) |
UTCTIME,UNIXTIME,ALT,LAT,LON,#SATS,FIX,HORZV,VERTV,HEAD,FLAGS,>40,>32,>24,RSSI,BATT
Jun 3 2024 15:20:00.100 UTC,1717446000.100,4000,40.1234567,-105.1234567,18,3,0,0,90,0x03,4,9,3,-40,4.010A file is one of these when its first line that isn’t blank opens with UTCTIME,UNIXTIME and
names LAT and LON, or opens with TRACKER,DATE,TIME and names LAT and LON or TRACKER Lat and TRACKER Lon. Columns are then mapped by name, not by place; a name is matched as
written, its spaces at either end trimmed.
No barometer. The files hold a GPS receiver’s positions only, so the record’s primary track is empty, as for a Blue Raven’s high-rate file (ADR-253 §6, on the RRC3, Eggtimer and Blue Raven readers) and as ADR-254 §2 decided for GPS logs, and every column is a channel, with a note saying so. The readings withhold on such a log.
Channels. Every column but the clock’s parts, the tracker’s name and Found rocket ID is a
channel, in the file’s order, in the record’s SI unit (Quantity::unit):
| Column | Quantity | Unit from |
|---|---|---|
UTCTIME; TIME | Quantity::TimeOfDay: UTC; the ground station’s clock | the clock (below) |
UNIXTIME | Quantity::Unrecognized, as written | a note gives its offset from UTCTIME (below) |
ALT, TRACKER Alt asl, GS Alt asl, Found rocket altitude | Quantity::GnssAltitude | feet: the manual and the data (below) |
Altitude AGL, GS_ASL_offset | Quantity::Distance: a height, not above sea level | feet, with the altitude |
LAT, LON and each … Lat, … Lon, … lat, … lon | Quantity::Latitude, Quantity::Longitude | degrees |
HORZV, VERTV | Quantity::Speed | ft/s: the manual and the data (below) |
HEAD | Quantity::Angle | degrees: the manual and the data (below) |
BATT | Quantity::Voltage | volts: the data (below) |
GS_batt_v, Found rocket batt_v | Quantity::Voltage | the header’s v |
Distance (feet), Alt AGL (ft), Horizontal range (ft), Total range (ft) | Quantity::Distance | the header’s feet |
LoRa Max Range (kft) | Quantity::Distance | the header’s thousands of feet |
#SATS, #TOT, FIX, FLAGS, >40, >32, >24, RSSI, RSSI Down, RSSI Up, Found RSSI, Found rocket fix, the radio’s packet counts | Quantity::Number, as written | no unit |
LoRa Success Rate | Quantity::Number, in percent | written 67%, “the packet success rate, expressed as a percentage, based on the last 50 packets” (Featherweight Swift User’s Manual, April 10 2026, p10) |
Launch detection, Apogee detection, Landing detection | Quantity::Number, 1 for TRUE and 0 for FALSE | the manual’s “flag“s (p17) |
>40, >32 and >24 are, in the manual’s words, the “Number of GPS satellites with > 40
signal strength” and so on (p17), its color table giving signal strengths in dB-Hz (p10). FLAGS is written in hexadecimal (0x03) in the
older tracker log and both ground-station logs, and in decimal in the newer tracker log; either
is read as the number it writes. A column the reader doesn’t know is kept as written,
Quantity::Unrecognized, with a note.
Units no header states. The manual lists the tracker’s log as “Altitude (ASL, Feet)”,
“Horizontal velocity (feet/second)”, “Vertical velocity (feet/second)”, “Heading (degrees from
North)” and “Tracker battery voltage” (p17), in the order of the tracker log’s columns, and the
ground station’s serial packet gives the same units (Appendix A, p21). Each is checked against
the file’s own rows, and each file’s record carries one note per kind: the decision and what
decided it, the same words for every file decided alike, then after the colon this file’s
evidence, such as `ALT` read in feet, from the manual and the horizontal speed: …. The
checks, and what they found as of 2026-10-12, among the project’s 40 sample files:
- The file’s length unit. One rule decides it for every length and speed the manual gives
in feet: the heights,
HORZVandVERTV. OnlyHORZVcan be checked against an absolute length, the great-circle distance between two fixes. Taking each tracker’s rows in time order, and each pair of rows more than 0.5 s and at most 2.5 s apart (from the last row whose position differed, as the ground station repeats a fix it hasn’t heard anew) at a speed of at least 20 as written, the distance in feet a second overHORZVhas a median between 0.95 and 1.32 in the 37 files with 10 such pairs or more (1.32 in one ground-station log, the rest below 1.08); meters per second would give 3.28, knots 1.69, miles per hour 1.47. A median inside 0.7 to 1.4 keeps the manual’s feet (from the manual and the distance between fixes, and for the heightsfrom the manual and the horizontal speed); with fewer than 10 pairs, as in 3 files, the manual decides alone (from the manual alone); a median outside the band keeps every one of those columns as written, with a note. The band’s upper edge sits 6% above the highest sample median and 4.5% below miles per hour’s 1.467, so a file in miles per hour whose fixes ran 4.5% or more short of its speeds would be read in feet per second: the band errs toward the manual’s unit, not away from it. Kilometers per hour would give 0.91, inside the band: the manual, not the check, rules them out. Pairs a tenth of a second apart are left out: in one of the older tracker logs, whose rows step back and repeat, the distance over such pairs runs 1.6 timesHORZV, where over pairs a second apart it runs 1.02 times. - Vertical speed.
VERTVagainst the change of the altitude a second, over the same pairs, shows only that the two share a length unit, not which: a file all in meters agrees as well as one all in feet. It decides only whetherVERTVis in the altitude’s unit a second (`VERTV` read in feet per second, in the altitude's unit, from the change of altitude, orfrom the manual alonewith fewer than 10 pairs); where its median falls outside 0.7 to 1.4,VERTVand the heights are kept as written. The medians fall between 0.94 and 1.03 in the 38 files with 10 such pairs or more. - Heights. In the 40-column ground-station log,
Alt AGL (ft), whose header says feet, isTRACKER Alt asllessGS Alt aslandGS_ASL_offsetto 0.15 ft on every row with a fix of all 4 files, which ties those three to feet too: the heights there are kept as written if it holds on under half the rows, and its note saysand `Alt AGL (ft)`among what decided. In the newer tracker log,Altitude AGLisALTless one height, the pad’s, to 0.05 ft (in all 21 files, on all but one row), which shows the two share a unit but not which.Distance (feet)is, by a median of 1.000 to 1.002 times, the great-circle distance from the first row’s position in the 21 newer tracker logs. - Heading.
HEADstays within −179 to 180 in every file: degrees, as the manual says. A file with a value past ±360 keeps it as written. - Battery.
BATTstays between 0 and 4.16 in every file, as one lithium cell’s volts do (the ground station’s serial packet writes millivolts, p21, which would be thousands), and reads 0 on every row of the 8 shorter ground-station logs. A value outside 0 to 5 keeps it as written.
The speeds’ and heights’ unit is also what fw2kml’s KML of the same flights shows (the GPS logs’ decision, ADR-254 §5), a check across files the reader can’t make.
The clock. The tracker’s clock is UTCTIME, written Jul 14 2031 17:04:31.250 UTC: an
English month’s first three letters, the day, the year, the time of day and UTC. Read as UTC,
it puts the first fix between 6.8 h and 15.4 h of local mean solar time at the fix’s longitude
in the 28 tracker files. UNIXTIME is a Unix time, but a whole number of hours, 4 to 8, ahead
of UTCTIME on every row of every tracker file, as if the site’s offset from UTC had been
added where it should have been taken away: read as UTC, it would put a fix at up to 22.9 h of
solar time. It is kept as a channel as written, with a note giving its offset. The ground
station’s clock is DATE (2031-07-14) and TIME (14:27:09.375), in a zone the file
doesn’t state. At the first fix, TIME falls between 6.6 h and 13.5 h in 11 of the 12
ground-station files, as a clock on the site’s zone would on a launch day, and read as UTC it
would put 8 of them between 22.8 h and 4.0 h of local mean solar time, at night; in the
twelfth, TIME is 0.2 h, 16.2 h of solar time read as UTC, as a clock on UTC would be. The
times are kept on that clock as written, with a note, `DATE` and `TIME` kept as written, in a time zone the file doesn't state: …, giving this file’s figures after the colon.
The log’s zero is the first row’s time, in the file’s order. Channels keep every row in the file’s order, so a time may go back: in each of the 7 older tracker logs, rows step back 1 to 11 times, by 0.9 s to 9 s, and in two of them once by about 847 s and 4,407 s; 1 to 76 rows of each repeat a time already written. A note counts how often and how far times go back, and how many rows repeat a time. The rows of the ground-station logs and of the newer tracker logs run forward, but for one repeated time in 4 of the newer. A clock cell that isn’t a time is refused, naming its line.
Trackers. A ground station logs every tracker it hears; 3 of the 8 shorter ground-station
logs and 1 of the 4 longer hold several (up to 5). Each tracker has its own set of channels, in
the order the trackers first appear, each named with the tracker’s trimmed name in brackets,
such as LAT [Rocket-1], when the file holds more than one; a file of one tracker keeps the
header’s names. Past MAX_TRACKERS trackers, or MAX_CHANNELS channels in all, a further
tracker’s rows are left out, counted in a note, so a file of many names can’t make the reader
hold a set of channels for each.
No fix. Before it has a fix, a tracker writes 0 for its latitude, longitude and altitude:
372 rows of 6 shorter ground-station logs and 74 of a longer one do. A row whose latitude and
longitude are both exactly 0 has them and the altitude beside them read as gaps, counted in a
note, for the tracker’s, the ground station’s and the found rocket’s positions alike, as
crate::altos does for AltOS’s (0, 0). A latitude beyond ±90° or a longitude beyond ±180° is
a gap too, counted per column in a note, as crate::kml and crate::nmea read theirs; no
sample file has one.
Cells and rows. A cell is a decimal number, hexadecimal digits after 0x, TRUE or
FALSE (1 or 0), or a number followed by %. A cell that is empty or none of these, such as
the literal NaN in Distance (feet) (27 cells over the 21 newer tracker logs), is a gap,
counted per column in a note. A row with fewer cells than the header has the rest as gaps; a
row with more is refused. A file whose rows, down to any row, hold under a quarter of the cells
its header names (past the first 65,536) is refused at that row. Blank lines are skipped; lines
may end in CR, LF or both (2 of the shorter ground-station logs end in CR LF); a byte-order mark
is dropped.
What the file says about itself. The logger is a Featherweight GPS tracker or a
Featherweight GPS ground station; the files state no serial number, firmware, flight number,
apogee or ground elevation.
Where this comes from. The layouts and their quirks, from the sample files; the units,
from the manual as cited and the files; the tracker log’s clock, columns and feet, following
Debrief’s lib/parsers/featherweightGps.ts (MIT, the project owner’s own; see
THIRD-PARTY-NOTICES.md). Where this reader departs from Debrief’s: it keeps every row in the
file’s order on UTCTIME, where Debrief sorts by UNIXTIME and drops repeated times; it reads
the shorter ground-station log, which Debrief doesn’t, and keeps each tracker apart, where
Debrief reads every row as one tracker’s; it keeps every column, where Debrief keeps a chosen
few; and it reads a position’s no-fix zeros as gaps by the zeros themselves, where Debrief reads
them by the FIX column.
Constants§
- MAX_
CHANNELS - The most channels a file’s trackers may have in all; past it, a further tracker’s rows are left out. Two trackers of the 40-column log hold 74.
- MAX_
TRACKERS - The most trackers one file’s channels are kept for; past it, a tracker’s rows are left out. The sample files hold at most 5.
Functions§
- read
- Reads a Featherweight GPS tracker’s or ground station’s CSV.