fix(g4): close fixture-top pose_tolerance via iterated fixed-point converged-rest; flag bimodal cabinet#39
Merged
Merged
Conversation
…nverged-rest (Option-2); flag genuinely-bimodal cabinet RCA g4_remaining_arenas.md §3b: task objects resting on a fixture EXTERIOR top never reach a stable rest in the 50-step validation settle. The analytic on-fixture spawn z (rule 2 of spawn_clearance) uses the fixture AABB top (highest geom), which sits far above the real rest face (flat_stove cook_region grate is visual-only — #32/#34; microwave/cabinet tops have a raised lip/rounded shell). The object is injected too high and falls ~48-64 mm per 50-step settle, so no single analytic clearance is a fixed point → pose_tolerance fails on z. DIAGNOSIS (scripts/measure_g4_fixture_fixedpoint.py): iterate the settle map f(z)=settle50(inject at z) to its fixed point z* (|Δz|<1mm). Both objects fall STRAIGHT DOWN (xy drift <0.15 mm — not a roll-off) to a deterministic converged rest — diagnosis (a), the record case. FIXED (additive VARIANT_CLEARANCES rows; rule 1 supersedes rule-2 analytic; gate stays 5 mm; renderer+simulator resolve the same z* → scenic_z==settled z): * white_bowl|microwave = 0.0794 (z*=0.8994, spread 0.0 mm, n=18/3 tasks) * akita_black_bowl|flat_stove = 0.0784 (z*=0.8984, spread 1.5 mm, n=18/3 tasks) Per-case pose_tolerance (position subset, 3 seeds): white_bowl|microwave 0/9→9/9 (dz 48.8→0.0 mm); akita|flat_stove 0/6→6/6 (dz 64.5→1.2 mm). FLAGGED, not forced — akita_black_bowl|wooden_cabinet: the cabinet top has a NON-UNIFORM collision surface — a solid edge region rests at z*≈1.126, visual-gap regions fall to ≈0.898, and the top_drawer placement is metastable across seeds (0.898↔1.119, spread 221 mm). No single scalar is a fixed point; forcing the dominant 0.078 would inject the solid-region bowl inside the cabinet body (contact-explosion regression risk). Needs an xy-aware rest surface (out of scope for scalar Option-2). Corpus :init-block scan confirms these are the ONLY 3 task-object-on-fixture- exterior pairs (moka_pot/cabinet-bowl/wine/book fixture relations are all :goal; object starts table-resting). Guards/no-regression: purely additive (2 rows, 0 changed/removed — proven); fixture_geometry.json, stack_offsets.json, spawn_clearances.json, asset_metadata.py, consistency.py (5 mm gate) all byte-identical. Untouched-arena CONTROL (study + table-center, all classes) 30/30=100%; white_bowl|table byte-identical. Updated test_fixture_task_residual → asserts measured pairs present at fixed-point value + cabinet stays flagged. CI Tier-1 182 passed; validation smoke G0-G3 6/6; ruff+black clean on src/+tests/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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
Closes the g4 NON-CONVERGENT FIXTURE-TOP residual (RCA
g4_remaining_arenas.md§3b). Task objects resting on a fixture exterior top never reach a stable rest inside the 50-step validation settle, so no single analytic clearance is a fixed point and they fail g4pose_toleranceon z. This PR implements a principled iterated fixed-point (converged-rest) measurement and emits the converged z (Option-2: renderer z == settled z; gate stays 5 mm). Zero band-aid: no tolerance widening, no masking, no exclusion.Non-convergence diagnosis
The analytic on-fixture spawn z (
spawn_clearancerule 2) uses the fixture AABB top (highest geom), which sits far above the real rest face:flat_stovecook_regionis a visual-only grate (same mode as fix(distractor-settle): identity rest-orient for bowl_drainer + measured stability gate for tall distractors on the flat_stove grate #32/feat(fixtures): seat alphabet_soup on flat_stove burner plate (un-exclude from grate) #34)microwave/cabinettops have a raised lip / rounded shellSo the object is injected too high and falls ~48–64 mm per 50-step settle — a constant per-injection drop (no fixed point at 50 steps), exactly matching the predecessor's observation. This is diagnosis (a) (over-estimated rest face), not (b) (rolls/oscillates).
Fixed-point method
scripts/measure_g4_fixture_fixedpoint.pyiterates the settle mapf(z) = settle50(inject at z)from the analytic z until|Δz| < 1 mm— the object has landed on its true rest face and the 50-step map is now a fixed point. Roll-off guard: if xy drifts >30 mm (slid off) the case is flagged, not recorded. The harness auto-discovers every:initfixture-supported object from the realized scene'ssupport_surface_class(robust to init-vs-goal grep confusion). A corpus:init-block scan confirms these are the only 3 task-object-on-fixture-exterior pairs in the whole BDDL set.Both recorded objects fall straight down (xy drift <0.15 mm — not a roll-off) to a deterministic converged rest.
Per-case before/after (position subset, real LIBERO env, 3 seeds)
white_bowl|microwaveakita_black_bowl|flat_stoveDeterminism: spread ≤ 1.5 mm across 6 seeds × all
:inittasks/instances.Flagged residual (not forced)
akita_black_bowl|wooden_cabinet— the cabinet top has a non-uniform collision surface: a solid edge region rests at z*≈1.126 (clear 0.306), visual-gap regions fall to ≈0.898 (clear 0.078), and thetop_drawerplacement is genuinely metastable across seeds (0.898↔1.119, spread 221 mm). No single scalar is a fixed point across the sampled xy region; forcing the dominant 0.078 would inject the solid-region bowl inside the cabinet body (contact-explosion regression risk). Per the no-force guard it is FLAGGED — it needs an xy-aware rest surface (out of scope for scalar Option-2).Additive-merge evidence
spawn_clearances_variants.json: +2 rows, 0 changed, 0 removed (proven by semantic diff) + a provenance_metablock.fixture_geometry.json,stack_offsets.json,spawn_clearances.json,asset_metadata.py,consistency.py(5 mm gate) — all byte-identical.spawn_clearance, superseding the rule-2 analytic for these two pairs only; every other pair (renderer + simulator) is byte-identical.No-regression control
Untouched arenas (STUDY + table-center, all classes, position+object, 3 seeds): 30/30 = 100% pass, max dz 1.98 mm.
white_bowl|tablebyte-identical (proves the microwave row is isolated). All wooden_cabinet cases fail identically before/after (flagged, unchanged).Tests / CI
test_scenic,test_perturbation_policy,test_sweep_g3_budget,test_invariants_*): 182 passedtest_spawn_z_consistency: 102 passed (updatedtest_fixture_task_residual→ asserts measured pairs present at fixed-point value + cabinet stays flagged)src/+tests/🤖 Generated with Claude Code