Index
2026-05-13 — Analysis

BUS SAM2 — cube-seed 폐기 & container-from-appearance 재설계

memer / robomme_policy_learning · BUS Pipeline v7→v8 진단 & rearchitect

TL;DR

0/20
1804 SR
56/56
Tests Pass
2
Commits
+207
Lines Added
1808
New Job

1 배경 / 목적

BUS (ButtonUnmaskSwap, 야바위) pipeline의 v7 sweep인 Job 1804가 SR 0/20으로 실패했다. v7은 visual completion-signal gating을 추가한 버전으로, 이전 시간 기반 step advance의 문제(VLA 진행 무관 step 넘김)를 고친 것이었다.

문제 1 — SAM2 tracking 실패: 흰색 container들이 cube를 완전히 덮는 순간, SAM2 mask가 여러 개 사라진다. t=0 cube bbox로 seed했는데 appearance memory가 완전 occlusion을 못 견뎌 collapse.
문제 2 — Viz가 안 보임: viz_swap_tracking의 mask overlay가 stride=3 sparse dot 패턴이라 디버깅에 쓸모없음. P0 sanity (sanity_sam2_swap.py)가 보여준 solid alpha-blend와 시각적으로 완전히 달랐음.
회귀 버그: Job 1804가 swap_buttons=0으로 돌아간 것 확인 — default가 의도 없이 False로 돌아간 회귀. 유저가 "버튼 2번째꺼부터 치는거 고정이야"라고 명시.

근본 문제: v5 rearchitect에서 세운 "SAM2가 occlusion 통과해서 cube identity 유지" 가설이 실측에서 깨졌다. 실제 BUS 시나리오에서 container가 cube를 완전히 덮으면 mask가 collapses되어 position tracking이 불가능해진다.

2 작업 내용

Fix 1: button-2-first 기본값 고정 (commit 3085ef0)

eval.py: bus_swap_buttons: bool = True (was False) run_bus_pipeline_one_episode.sh: SWAP_BUTTONS="${3:-1}" (was 0) ablation flag: SWAP_BUTTONS=0 → --args.no-bus-swap-buttons (단순 flag omit하면 새 default True가 적용돼 ablation 안됨)

Fix 2: SAM2 container-from-appearance (commit fcc3759)

왜 container seed가 cube seed보다 robust한가: SAM2의 P0 sanity (scripts/sanity_sam2_swap.py)는 container 자체를 seed로 12fps × 120프레임 swap motion 통과에 성공했다. cube-from-t=0 가설은 1540/1804 viz에서 깨졌음 — container drop이 cube를 완전히 가리는 순간 mask collapse. SAM2는 visually identical하지만 spatial trajectory가 다른 객체들 사이에서는 강하지만, 완전 occlusion을 시간 차원으로 통과시키는 건 불가능하다.

swap_tracker.py에 추가된 white-blob 검출:

find_white_container_blobs(frame, k=3, rgb_min=200, min_pixels=30, y_band_1000=(280,700)) - scipy.ndimage.label로 white pixel CC → size 큰 순 top-k - y-median이 y_band 안인 것만 필터 (floor/robot 제거) - 1000-scale yxyx bbox 반환 - sanity_sam2_swap.find_top_white_containers의 직접 포팅

orchestrator.py::_finalize_container_tracking 재설계:

1. dense_frames를 forward로 훑어 첫 "3 containers visible" 프레임 idx 찾기 2. 그 프레임에서 find_white_container_blobs(k=3) → 3 bbox 3. match_containers_to_colors(phase-A cube center, spatial proximity) → container_ mapping 4. frames[seed_idx:]만 SAM2 input으로 → container seed → swap motion 통과 → 최종 mask bbox = container_ anchor 등록

viz.py::viz_swap_tracking solid blend로 교체:

원본 해상도 numpy에서 alpha-blend: canvas[m] = canvas[m]//2 + col//2 이후 3x upscale, 그 위에 bbox outline + label. 기존 stride=3 PIL draw.point() 루프 폐기. 01_container_seed.png 다시 살아남 (matching vs SAM2 실패 분리 진단용)

단위 테스트 추가 (test_swap_tracker.py)

test_find_white_container_blobs_three_squares: 256×256 frame, y-band 안 3개 + 밖 1개 → 3 반환, 첫째가 가장 큰 blob test_find_white_container_blobs_min_pixels_filter: 9px 블롭 → 빈 리스트 test_find_white_container_blobs_no_white_returns_empty

3 결과

JobVersionSR비고
1804v7 (completion gating + cube-from-t=0)0/20cube mask collapse 실측 확인
1808v8 (container-from-appearance)PENDING2GPU/16CPU/400GB/qos=extra

코드 변경 수치

2
Commits
+207
Lines Added
-64
Lines Removed
56/56
Tests Pass
+3
New Tests
핵심 진단: 1804 SR=0만으로는 원인을 알 수 없었다. 유저가 mp4/png 직접 보고 "container 나오면 cube들 사라져"라는 관찰이 결정적이었음. viz 품질이 곧 진단 능력.
Test: 53→56 pass: white-blob 검출 로직 3개 유닛테스트 추가. GPU SAM2 테스트 포함 전체 ~126s 통과.
검증 대기: Job 1808 SR 결과 확인 후 container-from-appearance 가설의 옳고그름 판정.

4 Takeaway

Cube-from-t=0 가설 폐기 — P0 sanity pattern으로 retreat

SAM2의 appearance memory는 short-term occlusion은 통과해도 완전+장기간 occlusion은 못 견딘다는 게 실측으로 확인됐다. v5 rearchitect의 핵심 가정이 틀렸음.

Container-from-appearance는 P0 sanity가 이미 검증한 패턴이다. 새로 발견한 트릭이 아니라 "왜 sanity를 그대로 따르지 않았나"의 retreat. 코드 복잡도를 높여가며 cube-from-t=0를 구현했던 건 낭비였다.

Viz 품질 = 진단 능력

1804 결과 SR 0만으로는 원인이 전혀 안 보였다. 유저가 mp4/png를 직접 보고 container가 등장하면 cube mask가 사라진다는 걸 관찰한 게 결정적이었다. Solid alpha-blend로 viz를 재정비한 것은 다음 fix cycle의 진단 속도를 높이는 투자다.

BUS pipeline의 핵심 병목이 "SAM2로 cube identity를 swap 이후에도 추적할 수 있는가"에 달려있다는 게 재확인됐다. container-from-appearance가 P0 sanity에서 이미 검증된 만큼, v8이 SR > 0를 달성한다면 pipeline 전체의 방향이 확정된다.

5 Next Steps

Job 1808 결과 확인 (즉시)

SR 확인: runs/api_mem_smoke/ButtonUnmaskSwap_bus_v8_container/.../log.json

Viz 확인: 01_container_seed.png (container-color matching 정확한지), 02_container_tracking.mp4 (mask가 swap 따라가는지)

SR > 0 이면 (가설 확정)

swap_buttons=1 vs 0 비교 (RIGHT first 효과 측정). max_episodes 50으로 full sweep 진행.

SR = 0 또 나오면 — 분기 진단

경우 A: 02_container_tracking.mp4에서 mask가 swap을 통과 못함 → SAM2 자체 한계 (P0 sanity와 BUS frame distribution 차이?).

경우 B: mask는 정확한데 SR = 0 → VLA layer 문제 (pi0.5 ckpt가 BUS task 자체에서 약함). 좌표 정확해도 실행 못 따라가는 것.

알려진 위험 요소

_n_containers_visible의 GroundingDINO white container label이 0.20 threshold라 false-positive 가능. 첫 "≥3 visible" 프레임이 실제 swap 시작 전일 수도 있음 → seed_idx 시각 검증 필요.

find_white_container_blobsrgb_min=200 이 너무 빡세면 grayer container 놓침, 너무 느슨하면 robot/floor 영역과 merge. y-band가 1차 방어선이지만 실 frame에서 검증 필요.