Repository navigation
ros2-poc: the FicTrac record in the bag — one /arena/frame message per frame with 10 columns (LAB-303) - #264
Open
mbreiser wants to merge 1 commit into
Conversation
…r frame with 10 columns (LAB-303) Decided 2026-10-18 (docs/development/fictrac-columns-in-the-bag.md): the bag keeps 10 of FicTrac's 25 columns — the behavior row's 5 plus the error score (col 5), the lab-frame delta rotation (cols 6-8) and the sequence counter (col 23) — on the per-frame /arena/frame record, float64, one MCAP message per frame; the adapter's raw topics (/fictrac/frame, /fictrac/raw: 25 columns + the verbatim line, 68-77 % of a bag) are recorded only with --record-fictrac-raw. - ArenaFrame.msg: err, dr_lab_x/y/z, ft_seq, ft_ns (col 22 as received), flags (bit 0 = untracked FT_BADFR frame). The recorded copy carries NaN in turning_dps/forward_mms: they are live-only, exactly recomputable, and measured at 16 B/frame of incompressible doubles. - bridge_node: the consumer parses each line once (hub.fields) so the record carries the columns of the SAME line as x/y/hd; an FT_BADFR line becomes a flagged record (no run-log row) and connector_status counts bad_frames; raw FicTrac topics gated by --record-fictrac-raw. - _rows.py: parse_fictrac_line (one parser for adapter, node, converter), fictrac_extras, arena_frame_to_row (the ONE record→row mapping; None for a flagged frame). - mcap_convert: rows via _rows; flagged frames skipped; --level full refused without the raw topics (old bags that have them still convert, full included). - mcap_index.reindex: chunk-only index + zstd 19 (the final layout); recorder `default` profile: Zstd / Slowest / noMessageIndex through the plugin's storage options. - sizing/columns.py + `pixi run size-columns`: the bag-vs-jsonl.gz study, reproducible. - tests: merged-record alignment (wrap(dhd) == dr_lab_z), bad-frame injection, full-level rule, pre-2026-10-18 bag still converts, FrameDeriver math, 72 B/frame size guard. pixi run test 60/60 (default env), pixi run -e typed test 63/63. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 task done
mbreiser
added a commit
that referenced
this pull request
Oct 19, 2026
… derived-channel correction (LAB-303) (#265) Follow-up to #263: the reproducible ros2-poc/sizing/columns.py (PR #264) measures the adopted record at 2.41x / 2.68x the jsonl.gz (the first version quoted 2.24x / 2.48x from a scratch script); the live turning_dps / forward_mms cost 16 B/frame of incompressible doubles, not "about 1 %" (that came from a bench bag whose derived fields were the 2026-10-14 mixed-build garbage), so the implementation records them as NaN. Links the implementation PR. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the 2026-10-18 decision in
docs/development/fictrac-columns-in-the-bag.md(PR #263, merged): the bag keeps 10 of FicTrac's 25 columns — the behavior row's 5 plus the error score (col 5), the lab-frame delta rotation (cols 6–8) and the sequence counter (col 23) — on the per-frame/arena/framerecord,float64, one MCAP message per frame. The adapter's raw topics (/fictrac/frame//fictrac/raw: 25 columns + the verbatim line, 68–77 % of a bag) are recorded only with the new--record-fictrac-raw. Stacked on #254's branch (claude/ros-studio-plan-b-c44942); not part of candidate 2026-10-20.ArenaFrame.msg:err,dr_lab_x/y/z,ft_seq,ft_ns(col 22 as received),flags(bit 0 = untrackedFT_BADFRframe). One type for the live topic and the bag. The recorded copy carries NaN inturning_dps/forward_mms: they are live-only, exactly recomputable from x/y/hd/ft, and measured at 16 B per frame of incompressible doubles (a fifth of the record) — the doc's "≈ 1 %" came from a bench bag whose derived fields were the 2026-10-14 mixed-build garbage; a docs follow-up corrects it.bridge_node.py: the consumer parses each line once (hub.fields) so the record carries the columns of the same line as x/y/hd (the harness proves it:wrap(Δhd) == dr_lab_zframe to frame); anFT_BADFRline becomes a flagged record with no run-log row,connector_statuscountsbad_frames; raw FicTrac topics gated by--record-fictrac-raw. The WebSocket hub message to the Studio is unchanged._rows.py:parse_fictrac_line(one parser for the adapter, the node and the converter),fictrac_extras,arena_frame_to_row(the one record→row mapping;Nonefor a flagged frame).mcap_convert.py: rows through_rows; flagged frames skipped;--level fullrefused with a clear error for a bag without the raw topics (bags from before 2026-10-18 still convert,fullincluded).mcap_index.reindex: chunk-only index + zstd 19 (the final layout a cleanly closed run gets); the recorder'sdefaultprofile passesZstd/Slowest/noMessageIndexthrough the plugin's storage options (verified: zstd chunks, 0 message-index entries, both profiles).sizing/columns.py+pixi run size-columns: the bag-vs-jsonl.gz study, reproducible on any bag (--alladds the declined alternatives).telemetry-logging-reference.mdpointer paragraph.fictrac-bridge/bridge.py,BEHAVIOR_V1_COLSand the JSONL row are untouched.Measured (
pixi run size-columns -- <bag> <jsonl> --all, chunk-only index, zstd 19)On the harness run (typed, 1 084 frames): frame records 63.7 B/frame compressed (3.37× the gzip of the frame rows; 4.17× before the derived channels went NaN). For a 30 min run at 50 Hz: ≈ 5–5.5 MB against ≈ 2.3 MB of jsonl.gz. The bench bags cannot show the derived-channel saving (bag 1's derived values were constant garbage, bag 2 had none), which is why their adopted numbers match the doc's layout rows; the reproducible script's packing differs slightly from the doc's scratch matrix (2.41×/2.68× vs 2.24×/2.48×) — the docs follow-up carries the script's numbers.
Tier: next candidate (after 2026-10-20)
Do not merge into
claude/ros-studio-plan-b-c44942: that branch is a pinned constituent of the live Next candidate (release PR #262); moving its head invalidates the candidate. This PR stays open and stacked until #262 has landed, then is retargeted tomain(gh pr edit 264 --base main) and rebased onto main to become a constituent of the next candidate (2026-10-22). No footer/version bump.Release notes
none (bridge-node / ROS 2 record format; no Studio change)
Test plan
pixi run test(default env, String topics): 60/60pixi run -e typed test: 63/63 — merged-record alignment, bad-frame injection,fullrefused, pre-2026-10-18 bag still converts (withfull), FrameDeriver math, 72 B/frame guard (measured 63.7)ft_nsis the camera clock,errnon-zero,dr_lab_z == −Δhd(FicTrac's sign; the simulator's is+)Related: LAB-303. Linear not touched (proposed comment text is in the decision doc §5).
🤖 Generated with Claude Code