Skip to main content

Module fwgps

Module fwgps 

Source
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:

LayoutFilesHeader
The tracker’s log, older7UTCTIME,UNIXTIME,ALT,LAT,LON,#SATS,FIX,HORZV,VERTV,HEAD,FLAGS,>40,>32,>24,RSSI,BATT
The tracker’s log, newer21the same 16, then Altitude AGL,Launch detection,Apogee detection,Landing detection,Distance (feet)
The ground station’s log8TRACKER,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 figures4TRACKER,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.010

A 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):

ColumnQuantityUnit from
UTCTIME; TIMEQuantity::TimeOfDay: UTC; the ground station’s clockthe clock (below)
UNIXTIMEQuantity::Unrecognized, as writtena note gives its offset from UTCTIME (below)
ALT, TRACKER Alt asl, GS Alt asl, Found rocket altitudeQuantity::GnssAltitudefeet: the manual and the data (below)
Altitude AGL, GS_ASL_offsetQuantity::Distance: a height, not above sea levelfeet, with the altitude
LAT, LON and each … Lat, … Lon, … lat, … lonQuantity::Latitude, Quantity::Longitudedegrees
HORZV, VERTVQuantity::Speedft/s: the manual and the data (below)
HEADQuantity::Angledegrees: the manual and the data (below)
BATTQuantity::Voltagevolts: the data (below)
GS_batt_v, Found rocket batt_vQuantity::Voltagethe header’s v
Distance (feet), Alt AGL (ft), Horizontal range (ft), Total range (ft)Quantity::Distancethe header’s feet
LoRa Max Range (kft)Quantity::Distancethe 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 countsQuantity::Number, as writtenno unit
LoRa Success RateQuantity::Number, in percentwritten 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 detectionQuantity::Number, 1 for TRUE and 0 for FALSEthe 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, HORZV and VERTV. Only HORZV can 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 over HORZV has 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 heights from 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 times HORZV, where over pairs a second apart it runs 1.02 times.
  • Vertical speed. VERTV against 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 whether VERTV is in the altitude’s unit a second (`VERTV` read in feet per second, in the altitude's unit, from the change of altitude, or from the manual alone with fewer than 10 pairs); where its median falls outside 0.7 to 1.4, VERTV and 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, is TRACKER Alt asl less GS Alt asl and GS_ASL_offset to 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 says and `Alt AGL (ft)` among what decided. In the newer tracker log, Altitude AGL is ALT less 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. HEAD stays within −179 to 180 in every file: degrees, as the manual says. A file with a value past ±360 keeps it as written.
  • Battery. BATT stays 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.