Repository navigation
Conversation
Data-quality inspection and the data-pipeline half of the HG-DAgger
recovery-data feature (the interactive `rd infer --intervene` collection
loop follows in a later commit).
- rd inspect: pre-flight quality check over raw SVO2 recordings — flags
frame-stutter (clean/borderline/bad/broken via a shrink + max-gap
classifier) and black left-eye frames, with a per-episode inspect.json
cache (mtime-keyed) and a task-level inspect_report.json aggregate.
Camera-name agnostic (any cameras/*.svo2 view is scanned).
- convert: per-frame control_source / is_intervention / sample_weight tags
written into each lowdim pickle, resampled onto the camera grid by NEAREST
timestamp (never np.interp, which would smear the 0/1 takeover flag);
--w-intervention upweights human-takeover frames; episode_kind and
intervention_ratio carried raw -> converted; --append numbers new episodes
after the highest existing one and rebuilds split_all.json.
- shardify: --keep {all,interventions,interventions_context} + --keep-context
subsetting on control_source, and episode_kind / is_intervention /
sample_weight propagated into every sample's metadata so a merged shard set
stays splittable for the ABC 80:10:10 base/intervention mix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the data-quality inspection user-guide page and inspector API reference, and wire rd inspect into the README / guide index / nav. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6 tasks
There was a problem hiding this comment.
Pull request overview
This PR adds a new offline data-quality inspection step for raw recordings (rd inspect) and extends the convert→shardify pipeline to carry and optionally subset HG-DAgger-style per-frame provenance tags (control source / intervention / sample weights), with accompanying CLI and docs updates.
Changes:
- Added
rd inspectto scan rawcameras/*.svo2for timing stutter, dropped/missing views, and left-eye black frames with per-episode caching and a task-level report. - Updated
rd convertto write per-frame provenance tags (control_source,is_intervention,sample_weight) and added--appendand--w-intervention. - Updated
rd shardifyto optionally subset anchors based on provenance tags (--keep .../--keep-context) and to carry provenance into per-sample metadata; docs/navigation updated accordingly.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| README.md | Adds rd inspect to the command list. |
| raiden/shardify.py | Implements keep/subsetting logic and propagates provenance into shard sample metadata and processing stats. |
| raiden/inspector.py | New raw SVO2 inspection implementation with caching, concurrency, and report generation. |
| raiden/converter.py | Writes per-frame provenance tags into lowdim frames; adds --append and optional intervention upweighting. |
| raiden/cli.py | Wires rd inspect, new convert flags, and shardify keep flags into the CLI. |
| mkdocs.yml | Adds inspector docs to the nav and API reference. |
| docs/guide/inspection.md | New user-guide page for rd inspect. |
| docs/guide/index.md | Adds inspection into the guide flow and command table. |
| docs/api/inspector.md | Adds mkdocstrings API stub for raiden.inspector. |
| docs/api/cli.md | Adds InspectCommand to CLI API docs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+431
to
+433
| raw = {ep_id: views for ep_id, views in raw.items() if views} | ||
| expected_cams = sorted({cam for views in raw.values() for cam in views}) | ||
|
|
Covers the three pure functions this PR introduces, with no ZED SDK, SVO2
files, or robot attached:
- inspector._classify / _result_from_scan: the shrink / max-dt /
frame-count verdict ladder, exclusive threshold boundaries, worst-axis
-wins, degenerate scans, and the black-left-eye override (which beats
an otherwise-clean timing verdict while preserving timing metrics for
diagnosis); _is_episode_dir on a temp tree.
- converter._resample_flag_nearest: control_source must be resampled by
nearest timestamp and never interpolated — one test asserts np.interp
on the same inputs smears the flag into fractions while this does not.
Also ties, out-of-range clamping, 100 Hz -> 30 Hz downsampling, dtype.
- shardify._keep_anchor: all / interventions / interventions_context,
the forward look-ahead window, keep_context=0 still keeping one
lead-in frame, end-of-episode clamping, and the documented footgun
that --keep interventions empties a pure-teleop dataset.
This is the repo's first tests/ directory; there is no test job in CI, so
they run locally with `uv run pytest tests/ -v`.
Co-Authored-By: Claude Opus 4.8 <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
Two additions to the offline data pipeline, both born from silent data-quality failures we hit while collecting large teleop + HG-DAgger datasets on YAM rigs:
rd inspect— a pre-flight quality checker for raw recordings. It scans every episode's SVO2 streams in parallel and flags frame-stutter, dropped frames, and black/failed camera streams before hours are spent converting (or worse, training) on bad data. Episodes get a verdict (clean / borderline / bad / broken / black / missing) with per-camera reasons and a summary table; results are cached in the episode dir (--forcere-scans).rd convertnow writescontrol_source(0 = policy, 1 = human),is_intervention, andsample_weightinto every lowdim frame, andrd shardifycan subset on them (--keep interventions | interventions_context | all). This is the data-side groundwork for HG-DAgger interactive-correction collection (the collection loop itself is a follow-up PR): record whole rollouts, tag who was in control, and let the trainer mix/upweight (ABC-style 80:10:10) without re-touching raw data.Details
raiden/inspector.py(new): SVO2 scan comparing frame count against wall-clock span (shrink factor), max inter-frame dt, and black-frame detection; camera-name agnostic; thresholds documented at the top of the module.raiden/converter.py:control_sourceflag onto the camera-frame grid by nearest timestamp (never interpolated — it's a 0/1 flag), and only on the ns-timestamp alignment path;--w-intervention Noptionally upweights human-takeover frames (default1.0— ABC uses dataset mixing, not per-frame weights, so tags alone suffice);--appendconverts new raw episodes into an existing converted dataset (numbering continues from the max existing episode, split metadata rebuilt over all episodes).raiden/shardify.py:--keepsubsetting with--keep-context Nframes of lead-in before each intervention; filtered counts surfaced inprocessing_metadata.json; per-sample metadata carriessample_weight/is_intervention/episode_kindso merged shard sets stay splittable.rd inspect+ the new convert/shardify flags; docs: user-guide page (docs/guide/inspection.md) and API reference, wired into the nav.Backward compatibility
Ordinary teleop recordings convert exactly as before, except each lowdim frame gains the three new keys with neutral defaults (
control_source=0,is_intervention=False,sample_weight=1.0) and episode metadata gainsepisode_kind="teleop". No existing key changes.--keep allis the shardify default, so existing pipelines are unaffected.Testing
47 hardware-free unit tests in a new
tests/directory — no ZED SDK, SVO2 files, or robot required (pyzedis imported lazily inside_scan_svo2, so the modules import on a bare machine):tests/test_inspector.py_classify/_result_from_scan— the verdict ladder, exclusive threshold boundaries, worst-axis-wins, degenerate scans, the black-left-eye override;_is_episode_diron a temp treetests/test_converter.py_resample_flag_nearest— nearest-not-interpolated, ties, out-of-range clamping, 100 Hz → 30 Hz downsampling, dtype/shapetests/test_shardify.py_keep_anchor— all / interventions / interventions_context, look-ahead window,keep_context=0, end clamping, the empty-dataset footgunTwo tests are worth calling out as executable documentation of why the code is written the way it is: one asserts
np.interpon the same inputs smearscontrol_sourceinto fractions while_resample_flag_nearestdoes not, and one pins that--keep interventionsyields zero samples on a pure-teleop dataset.This is the repo's first
tests/directory and there's no test job in CI, so they run locally withuv run pytest tests/ -v. Happy to add a CI job and a pytest dev-dependency if you want them gating.ruff format --check+ruff checkclean;mkdocs build --strictclean with the docs-CI dependency set.🤖 Generated with Claude Code