Skip to content

feat(data_load_mcap): always-include transform-tree channels (/tf et al.) in the topic picker#192

Open
facontidavide wants to merge 12 commits into
mainfrom
feat/mcap-always-include-tf
Open

feat(data_load_mcap): always-include transform-tree channels (/tf et al.) in the topic picker#192
facontidavide wants to merge 12 commits into
mainfrom
feat/mcap-always-include-tf

Conversation

@facontidavide

Copy link
Copy Markdown
Contributor

Problem

The MCAP topic-picker treats every channel identically. When a user narrows their selection instead of loading everything, /tf / /tf_static are easy to leave out — and PJ4's Scene3D then silently fails to place PointCloud/Mesh3D/other 3D objects, because the transform tree never reaches the ObjectStore.

Mechanism: generic (schema, encoding) whitelist — no ROS code path

Channels whose (schema name, message encoding) matches kAlwaysIncludeRules are always loaded — pre-checked and locked (disabled row + tooltip) in the picker:

schema encoding convention
tf2_msgs/msg/TFMessage cdr ROS 2
foxglove.FrameTransform protobuf Foxglove

Matching is deliberately on message type, not topic name: verified with the mcap CLI on real recordings, Foxglove files publish transforms under arbitrary topic names (e.g. tf, no leading slash — example-023-av-argo-2.mcap), so a /tf name rule would silently miss them. Likewise the encoding is the channel's message_encoding (cdr), not the schema-record encoding (ros2msg) — an easy field to confuse. The loader stays format-agnostic: the whitelist is data, the mechanism knows nothing about ROS.

Enforcement is model-layer, view is garnish

reassertAlwaysIncluded() (idempotent) re-inserts whitelisted non-empty channels into selected_topics_ after every mutation point: analyzeFile() (covers loadConfig() restore of pre-feature layouts), onSelectionChanged, and btnDeselectAll. Zero-message channels are never force-included. mcap_source.cpp is untouched — it already reads only selectedTopics(), so the guarantee holds even if the view desyncs.

Also included: selection restore switched from index-keyed setSelectedRows to text-keyed setSelectedItems, the same sort-safety pattern as #188 (the table has sortingEnabled=true; index restore desyncs after a user sort). disabled_rows stays index-keyed — cosmetic-only risk, documented in the spec.

Tests

Restored the mcap_dialog_test target deleted in #144 (McapDialog previously had zero direct coverage) — now 10 tests: whitelist hit/near-miss matrix, force-include surviving stale saved configs, Deselect All, host-reported deselection, zero-message exclusion, locked-row disabled+tooltip rendering, text-keyed selection, and fixture pinning. New fixture test_dialog_whitelist.mcap (5 channels incl. a non-conventional-name Foxglove transform and a right-schema/wrong-encoding near miss) generated via generate_verification_mcaps.py. Full plugin suite: 6/6 targets green.

Codex review

Independent Codex review verdict: ship with fixes — guarantee coverage confirmed complete; its minor test-vacuity finding is fixed here (fixture pinning). Its major finding is real but pre-existing and cross-cutting: the PJ4 host applies selected_items only to QListWidget — the QTableWidget branch in pj_dialog_host/src/widget_binding.cpp honors selected_rows only (verified on PJ4 origin/main and every branch). This affects foxglove on main and #188's ros2/webrtc identically: the model round-trips fine (table selection read-back is already text-based), but visual pre-selection isn't restored on dialog open. Follow-up: small PJ4 host patch mirroring the QListWidget selected_items apply into the QTableWidget branch — fixes all three plugins at once.

Spec and plan: docs/superpowers/specs/2026-07-06-mcap-always-include-tf-design.md, docs/superpowers/plans/2026-07-06-mcap-always-include-tf.md.

🤖 Generated with Claude Code

facontidavide and others added 12 commits July 6, 2026 20:17
Users narrowing their topic selection can leave out /tf and /tf_static,
silently breaking Scene3D transform-tree rendering. Design keeps the
plugin format-agnostic: a generic (topic, encoding) whitelist forces
these channels selected and locked in the picker, verified against real
ROS 2 bags (message_encoding=cdr, not the schema's ros2msg tag).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Topic-name matching (/tf, /tf_static) breaks on real Foxglove-recorded
files, which have no fixed topic-name convention for transforms (verified
with the mcap CLI: a real file uses topic "tf", no leading slash). Key
the whitelist on message type instead — tf2_msgs/msg/TFMessage (cdr) and
foxglove.FrameTransform (protobuf), both already classified as
kFrameTransforms in parser_ros/parser_protobuf — so it works regardless
of topic naming.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…Transform)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… smoke test

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ebrtc pickers

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…eFile()

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…he picker

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t All / host selection changes

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ks can't pass vacuously

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant