← 목록
2026-09-18 · scene_bench · analysis

navigate 자리 감사 — 벽 건너편·안 보는 자리는 왜 나오나, 게이트로 얼마나 없어지나

지금 하네스 teleport_to(게이트 끔) vs 자리 게이트(방→벽→가시성) · 40지점 · API $0 · 학습 datagen·scene-mem-gen 규칙과 대조

TL;DR

269/1200 (22%) → 33/1200 (3%)
pick 자리: 학습 datagen 기각(어깨 카메라 <0.1%) — 게이트 끔 → 켬
51/1200 (4%) → 0/1200 (0%)
pick 자리: 타깃과 다른 방
101/1200 (8%) → 0/1200 (0%)
pick 자리: 카메라→물체 사이 벽
63/320 (20%) → 8/320 (2%)
place 자리: 다른 방/벽
40
지점(칸)
결론
사용자가 본 두 현상 중 "벽 건너편/옆방"은 하네스 결함(학습 가시성 검사 누락)이었고 게이트로 거의 없어졌다(pick 24%→2.8%, place 20%→2.5%; 남은 것은 어느 자리에서도 안 보이는 물체·끼인 가구의 폴백). "안 보고 선다"는 학습 분포(±45°) 그대로라 결함이 아니고, 게이트는 그중 물체가 카메라 밖으로 나가는 극단만 거른다. 이 게이트는 모든 전략·조건에 똑같이 적용되는 navigate 프리미티브의 수정이라 정보 누출이 없다. 다만 절대 성공률이 오르므로 게이트 전후 온라인 수치는 직접 비교 금지 — 행에 pose_gate가 남는다. 카탈로그(navi 하네스 v2)는 이 게이트 위에서 만든다.

1배경/목적 (왜)

사용자 지적(260917): 온라인 런에서 로봇이 가구를 안 보고 서거나, 벽을 뚫고 넣으라는 듯 벽 건너편에 서는 경우가 있다. 자리 카탈로그(navi 하네스 v2)를 만드는 이유도 결국 이런 자리를 없애려는 것이므로, 카탈로그 전에 지금 navigate가 뽑는 자리가 왜 그런지를 코드와 수치로 확인하고 고친다.

질문 셋: (1) 그런 자리가 얼마나 자주 나오나 (2) 원인이 무엇인가 (3) 학습 데이터 생성기(molmospaces datagen)와 scene-mem-gen은 어떻게 하나.

2원인 — 코드에서 확인한 것

학습 datagen (pick_task_sampler.py:992)우리 nav0.teleport_to (게이트 전)
자리 샘플place_robot_near: 타깃과 직선거리 0~0.7 m 안 자유 픽셀 무작위, 충돌 검사, yaw = 타깃 방향 ±45° 균등 노이즈같음
가시성 검사check_camera_visibility=True — 로봇 장착 어깨 카메라(droid_shoulder_light_randomization)에 타깃이 0.1% 이상 보이는 자리만 채택 (FrankaOmniPurposeCameraSystem visibility_constraints, check_robot_placement_visibility=True)없음 — 인자를 안 넘겨 기본 False. 우리 config에도 True로 켜져 있지만 쓰이지 않았다
방/벽 검사없음(가시성이 간접적으로 거름)없음

place_robot_near는 방·벽을 모른다(env.py:854-859, 유클리드 반경만). 학습 때는 가시성 검사가 벽 건너편·화면 밖 자리를 걸러 줬는데 우리는 그 검사를 빼고 불렀다 → 하네스가 학습 분포보다 넓은 자리 분포에서 뽑고 있었다. 벽에 붙은 가구 위 물체는 직선거리 0.7 m 안 자유 공간이 대부분 옆방이라(train_8287 tissue box: 30자리 중 29자리 옆방), 그런 지점에서는 거의 항상 옆방에 선다.

place(든 채) 접근은 다른 경로(surface_approach_candidates: 표면 가장자리에서 바깥으로 0.35~0.8 m, 로봇에서 가까운 순)인데 같은 구멍이 있다 — 가구가 벽에 붙어 있으면 벽쪽 가장자리의 "바깥"이 옆방이고, 로봇이 옆방에서 오면 그 후보가 제일 가까워 먼저 뽑힌다. drive_to는 그 자리로 A* 경로를 찾아 문을 지나 가서 벽을 마주 보고 선다.

"가구를 안 본다": pick yaw는 타깃 방향 ±45° 균등 노이즈 — 학습 샘플러에서 그대로 물려받은 값이라 분포 자체는 학습과 같다. 다만 학습에서는 가시성 검사가 타깃이 카메라 밖으로 나가는 극단을 걸렀다. place 접근 yaw는 표면 법선 정면으로 이미 고정돼 있다(다른 세션, 260917).

3결과 1 — pick 접근 자리 (게이트 끔 vs 켬)

지점마다 teleport_to(obj)를 게이트 끄고 30회, 켜고 30회 호출해 자리를 뽑고 각 자리에서 잰 값. 배치 실패: 끔 0회 / 켬 0회. 게이트 켬의 폴백(후보 전부 걸려 최선 후보 사용): 33/1200 (3%).

측정 (pick 접근)게이트 끔 = 지금 하네스게이트 켬
학습 datagen 기준 기각(어깨 카메라에 물체 < 0.1%)269/1200 (22%)33/1200 (3%)
타깃과 다른 방51/1200 (4%)0/1200 (0%)
카메라→물체 사이에 벽/창101/1200 (8%)0/1200 (0%)
정책 exo 카메라(bench_exo_L)에 물체 0픽셀205/1200 (17%)116/1200 (10%)
|정면각 오차| > 30°366/1200 (30%)430/1200 (36%)
|정면각 오차| 중앙값 / 75% / 90% / 최대21.8° / 32.7° / 40.0° / 44.9°21.7° / 34.6° / 40.5° / 45.0°
navigate 1회 소요(평균)0.72 s1.32 s (기각 후보 평균 0.9개)
기각분의 내역(게이트 끔)다른 방 35/269 (13%) · 벽 64/269 (24%) · 정면각>30° 49/269 (18%) · 그 외(가림·거리) 121/269 (45%)

지점별 (게이트 끔 → 켬)

지점물체학습 기각다른 방벽정책 0픽셀켬: 폴백
restore:train_1299__2:q02paper towel roll0 → 00 → 00 → 01 → 20
restore:train_1847__1:q03ladle2 → 00 → 00 → 02 → 10
restore:train_1847__1:q04apple15 → 00 → 00 → 05 → 00
restore:train_188__2:q01paper towel roll0 → 00 → 00 → 02 → 20
restore:train_2102__1:q05kettle0 → 00 → 00 → 01 → 10
restore:train_2159__2:q08potato2 → 00 → 00 → 06 → 40
restore:train_2224__0:q08pot18 → 08 → 018 → 09 → 00
restore:train_2224__2:q01potato14 → 00 → 03 → 012 → 30
restore:train_2788__2:q06spray bottle0 → 00 → 00 → 03 → 20
restore:train_2853__0:q01paper towel roll1 → 00 → 00 → 01 → 20
restore:train_2853__2:q03soap bottle5 → 00 → 05 → 02 → 10
restore:train_3655__0:q03pepper shaker17 → 20 → 01 → 05 → 02
restore:train_3655__2:q04spray bottle1 → 00 → 01 → 03 → 30
restore:train_3912__2:q03tennis racket4 → 00 → 04 → 02 → 00
restore:train_3944__0:q02paper towel roll7 → 00 → 00 → 00 → 00
restore:train_3994__0:q06pan0 → 00 → 00 → 00 → 00
restore:train_4136__1:q01butter knife22 → 10 → 08 → 09 → 11
restore:train_4304__0:q03knife2 → 00 → 00 → 01 → 10
restore:train_4360__2:q00remote control11 → 010 → 09 → 010 → 00
restore:train_4392__2:q00remote control2 → 00 → 02 → 04 → 40
restore:train_4584__0:q00cell phone0 → 00 → 00 → 00 → 10
restore:train_6222__1:q05pot0 → 00 → 00 → 00 → 00
restore:train_6233__1:q04cup0 → 00 → 00 → 01 → 10
restore:train_6242__1:q05bottle1 → 00 → 01 → 05 → 70
restore:train_6242__1:q06apple1 → 00 → 00 → 05 → 100
restore:train_6278__2:q01remote control6 → 00 → 05 → 05 → 40
restore:train_6728__2:q01spatula13 → 01 → 00 → 09 → 00
restore:train_6878__2:q01cell phone2 → 03 → 02 → 04 → 10
restore:train_7152__1:q00remote control12 → 00 → 00 → 00 → 00
restore:train_7385__0:q00remote control0 → 00 → 00 → 02 → 20
restore:train_7650__2:q02spoon11 → 00 → 00 → 02 → 00
restore:train_7661__1:q00candle30 → 300 → 00 → 030 → 3030
restore:train_7845__2:q03ladle6 → 00 → 01 → 09 → 140
restore:train_8287__1:q00tissue box20 → 029 → 020 → 024 → 10
restore:train_9026__1:q03bowl6 → 00 → 07 → 07 → 90
restore:train_9320__2:q01remote control0 → 00 → 00 → 00 → 30
restore:train_9651__2:q00spoon18 → 00 → 00 → 012 → 00
restore:train_9778__1:q04spray bottle0 → 00 → 00 → 01 → 30
restore:train_9797__1:q00candle20 → 00 → 014 → 02 → 10
restore:train_9909__2:q05tomato0 → 00 → 00 → 09 → 20

4결과 2 — place 접근 자리(든 채)

실제 흐름대로 pick 자리에서 물체를 든 채 복원 목적지 가구로 teleport_to(rec, carry). 끔 320회 / 켬 320회, 배치 실패 0 / 0. 접근 방식(끔): {"surface_rim": 320}, (켬): {"center_faced": 8, "surface_rim": 312}.

측정 (place 접근)게이트 끔게이트 켬
타깃 가구와 다른 방29/320 (9%)0/320 (0%)
카메라→가장 가까운 표면점 사이에 벽63/320 (20%)8/320 (2%)
카메라→물체의 원래 자리(복원 목표점) 사이에 벽62/320 (19%)8/320 (2%)
셋 중 하나라도63/320 (20%)8/320 (2%)
|정면각 오차|(표면점 기준) > 20°45/320 (14%)33/320 (10%)
|정면각 오차| 중앙값/75%/90%/최대4.7° / 16.2° / 22.1° / 37.6°6.5° / 14.8° / 20.1° / 34.0°
가장 가까운 표면점까지 거리 중앙값/75%/90%/최대0.38 m / 0.43 m / 0.47 m / 0.63 m0.37 m / 0.43 m / 0.47 m / 0.53 m
복원 목표점까지 거리 중앙값/75%/90%/최대0.78 m / 1.2 m / 1.98 m / 3.6 m0.77 m / 1.22 m / 1.98 m / 3.42 m
정책 exo 카메라에 가구 0픽셀29/320 (9%)0/320 (0%)
navigate 1회 소요(평균)0.63 s1.38 s

지점별 (끔 → 켬, 다른 방/벽 건수)

지점가구n다른 방/벽접근 방식
restore:train_1299__2:q02diningtable80 → 0surface_rim
restore:train_1847__1:q03countertop80 → 0surface_rim
restore:train_1847__1:q04chestofdrawers80 → 0surface_rim
restore:train_188__2:q01armchair88 → 0surface_rim
restore:train_2102__1:q05bed80 → 0surface_rim
restore:train_2159__2:q08sofa80 → 0surface_rim
restore:train_2224__0:q08diningtable80 → 0surface_rim
restore:train_2224__2:q01countertop80 → 0surface_rim
restore:train_2788__2:q06chair80 → 0surface_rim
restore:train_2853__0:q01diningtable80 → 0surface_rim
restore:train_2853__2:q03sofa80 → 0surface_rim
restore:train_3655__0:q03countertop87 → 0surface_rim
restore:train_3655__2:q04chair80 → 0surface_rim
restore:train_3912__2:q03diningtable80 → 0surface_rim
restore:train_3944__0:q02chair80 → 0surface_rim
restore:train_3994__0:q06countertop88 → 0surface_rim
restore:train_4136__1:q01diningtable80 → 0surface_rim
restore:train_4304__0:q03chair88 → 8surface_rim
restore:train_4360__2:q00sofa80 → 0surface_rim
restore:train_4392__2:q00chestofdrawers80 → 0surface_rim
restore:train_4584__0:q00countertop80 → 0surface_rim
restore:train_6222__1:q05diningtable80 → 0surface_rim
restore:train_6233__1:q04chair80 → 0surface_rim
restore:train_6242__1:q05countertop80 → 0surface_rim
restore:train_6242__1:q06chair80 → 0surface_rim
restore:train_6278__2:q01crapper88 → 0surface_rim
restore:train_6728__2:q01diningtable88 → 0surface_rim
restore:train_6878__2:q01crapper88 → 0surface_rim
restore:train_7152__1:q00diningtable88 → 0surface_rim
restore:train_7385__0:q00bed80 → 0surface_rim
restore:train_7650__2:q02diningtable80 → 0surface_rim
restore:train_7661__1:q00stand80 → 0surface_rim
restore:train_7845__2:q03chair80 → 0surface_rim
restore:train_8287__1:q00sink80 → 0surface_rim
restore:train_9026__1:q03chestofdrawers80 → 0surface_rim
restore:train_9320__2:q01diningtable80 → 0surface_rim
restore:train_9651__2:q00diningtable80 → 0surface_rim
restore:train_9778__1:q04armchair80 → 0surface_rim
restore:train_9797__1:q00diningtable80 → 0surface_rim
restore:train_9909__2:q05diningtable80 → 0surface_rim

5결과 2b — 원래 자리 앵커(정답일 때) 효과

ㄷ자 조리대·식탁·침대 같은 큰 가구에서는 게이트를 켜도 로봇이 온 쪽 끝에 서서 물체의 원래 자리와 3 m 넘게 떨어졌다(3655: 3.39 m). place 접근이 "로봇이 지금 있는 자리에서 가장 가까운 가장자리"를 고르고 navigate는 가구 uid만 받기 때문이다. 사용자 결정(260918): 에이전트가 고른 (물체, 가구)가 그 시나리오의 정답과 같을 때만 물체의 원래 자리 to.xyz를 기준점으로 삼아 거기에 가장 가까운 가장자리로 간다(링 우선이 아니라 앵커 거리 순 — 링 우선이면 목표 가까운 가장자리가 의자로 막힌 식탁(train_1299)에서 1.5 m 떨어진 링 0 후보를 먼저 골라 오히려 나빠졌다, 1.29→1.60 → 정렬 수정 후 0.44). 틀린 답은 종전대로.

측정 (place 접근, 같은 출발 자리)게이트 켬 · 로봇 기준게이트 켬 · 원래 자리 앵커
물체의 원래 자리까지 거리 중앙값 / 75% / 90% / 최대0.77 m / 1.22 m / 1.98 m / 3.42 m0.52 m / 0.62 m / 0.72 m / 0.86 m
원래 자리까지 > 0.9 m113/320 (35%)0/320 (0%)
다른 방 / 벽 / 둘 중 하나0/320 (0%) / 8/320 (2%) / 8/320 (2%)0/320 (0%) / 8/320 (2%) / 8/320 (2%)
가장 가까운 표면점까지 거리 중앙값 / 최대0.37 / 0.53 m0.35 / 0.55 m
폴백 / navigate 1회8/320 (2%) / 1.38 s8/320 (2%) / 1.4 s

지점별 원래 자리까지 거리 중앙값 (m) — 로봇 기준 → 앵커

지점가구로봇 기준앵커
restore:train_3655__0:q03countertop3.390.68
restore:train_6242__1:q05countertop2.440.36
restore:train_2102__1:q05bed2.330.62
restore:train_6222__1:q05diningtable2.030.55
restore:train_2224__0:q08diningtable1.920.61
restore:train_1847__1:q03countertop1.890.56
restore:train_7650__2:q02diningtable1.660.49
restore:train_4136__1:q01diningtable1.590.51
restore:train_1299__2:q02diningtable1.290.44
restore:train_9909__2:q05diningtable1.250.75
restore:train_4584__0:q00countertop1.160.63
restore:train_9320__2:q01diningtable1.130.6
restore:train_1847__1:q04chestofdrawers0.980.55
restore:train_2159__2:q08sofa0.910.36
restore:train_7385__0:q00bed0.880.75
restore:train_4392__2:q00chestofdrawers0.870.79
restore:train_9651__2:q00diningtable0.870.62
restore:train_3944__0:q02chair0.860.52
restore:train_3994__0:q06countertop0.840.82
restore:train_2853__0:q01diningtable0.760.7
restore:train_9797__1:q00diningtable0.740.62
restore:train_6728__2:q01diningtable0.690.67
restore:train_2224__2:q01countertop0.680.41
restore:train_9778__1:q04armchair0.680.45
restore:train_3912__2:q03diningtable0.670.51
restore:train_188__2:q01armchair0.660.63
restore:train_4360__2:q00sofa0.650.54
restore:train_4304__0:q03chair0.60.57
restore:train_9026__1:q03chestofdrawers0.590.51
restore:train_7845__2:q03chair0.580.58
restore:train_3655__2:q04chair0.510.52
restore:train_7661__1:q00stand0.510.42
restore:train_8287__1:q00sink0.510.3
restore:train_6233__1:q04chair0.490.47
restore:train_6242__1:q06chair0.490.37
restore:train_7152__1:q00diningtable0.470.37
restore:train_6278__2:q01crapper0.440.23
restore:train_2853__2:q03sofa0.410.38
restore:train_6878__2:q01crapper0.350.37
restore:train_2788__2:q06chair0.310.28

공정성: 정답을 맞힌 뒤에만 발동하고 틀린 답은 어디 서든 점수가 안 나므로 순위 무영향; 채점 is_placed_on은 가구 안의 지점을 요구하지 않으므로 기억이 답할 정보를 대신 주는 것도 아니다. 절대 성공률은 오르므로 전후 비교 금지(행 approach_anchor="given"). 게이트·앵커 적용법은 docs/nav_pose_gate.md.

6결과 3 — 파일럿 성공률과의 관계

파일럿 40자리(각 10회 VLA pick, 정책 pi05_mlspaces_place_oc@20000)를 같은 기준으로 재측정해 성공률과 조인했다.

기준걸린 자리걸린 자리 평균 성공률남은 자리남은 자리 평균 성공률
타깃과 다른 방20.00 (n=2)380.38 (n=38)
카메라→물체 사이 벽70.20 (n=7)330.39 (n=33)
학습 datagen 기각(어깨 < 0.1%)90.17 (n=9)310.42 (n=31)
정책 exo 0픽셀100.25 (n=10)300.40 (n=30)
게이트 기각(셋 중 하나)90.17 (n=9)310.42 (n=31)

물체 픽셀 비율과 성공률의 Spearman 상관(40자리): 어깨 카메라 ρ=0.267 (p=0.0962), 정책 exo ρ=0.351 (p=0.0265).

7증거 — 걸린 자리의 카메라 프레임과 2D 맵

게이트 끔(지금 하네스)에서 걸린 자리의 어깨 카메라·정책 카메라 프레임. 캡션의 '방 A→B'는 베이스가 선 방 → 타깃의 방.

게이트 끔 · 어깨 카메라 — ladle · 방 room_6→room_6 · 벽=아니오 · 어깨 0.01% · 정책 0.06% · 정면각 -19.7° · 0.679 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — ladle · 방 room_6→room_6 · 벽=아니오 · 어깨 0.07% · 정책 0.08% · 정면각 -14.1° · 0.524 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — apple · 방 room_6→room_6 · 벽=아니오 · 어깨 0.07% · 정책 0.09% · 정면각 -29.3° · 0.626 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — apple · 방 room_6→room_6 · 벽=아니오 · 어깨 0.00% · 정책 0.00% · 정면각 26.5° · 0.625 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — apple · 방 room_6→room_6 · 벽=아니오 · 어깨 0.00% · 정책 0.00% · 정면각 -6.8° · 0.619 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — apple · 방 room_6→room_6 · 벽=아니오 · 어깨 0.00% · 정책 0.04% · 정면각 -38.5° · 0.648 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — potato · 방 room_4→room_4 · 벽=아니오 · 어깨 0.01% · 정책 0.04% · 정면각 5.3° · 0.323 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라 — potato · 방 room_4→room_4 · 벽=아니오 · 어깨 0.00% · 정책 0.09% · 정면각 -7.5° · 0.436 m
같은 자리 · 정책 exo(bench_exo_L)
게이트 끔 · 어깨 카메라(place 접근) — armchair · 방 room_7→room_7 · 벽(표면)=예 · 벽(목표점)=예 · surface_rim · 표면 0.311 m · 정면각 4.1°
같은 자리 · 정책 exo
게이트 끔 · 어깨 카메라(place 접근) — armchair · 방 room_7→room_7 · 벽(표면)=예 · 벽(목표점)=예 · surface_rim · 표면 0.297 m · 정면각 1.0°
같은 자리 · 정책 exo
게이트 끔 · 어깨 카메라(place 접근) — armchair · 방 room_7→room_7 · 벽(표면)=예 · 벽(목표점)=예 · surface_rim · 표면 0.309 m · 정면각 3.8°
같은 자리 · 정책 exo
게이트 끔 · 어깨 카메라(place 접근) — armchair · 방 room_7→room_7 · 벽(표면)=예 · 벽(목표점)=예 · surface_rim · 표면 0.315 m · 정면각 -1.9°
같은 자리 · 정책 exo
게이트 끔 · 어깨 카메라(place 접근) — diningtable · 방 room_7→room_7 · 벽(표면)=아니오 · 벽(목표점)=아니오 · surface_rim · 표면 0.429 m · 정면각 -0.4°
같은 자리 · 정책 exo
게이트 끔 · 어깨 카메라(place 접근) — diningtable · 방 room_7→room_7 · 벽(표면)=아니오 · 벽(목표점)=아니오 · surface_rim · 표면 0.35 m · 정면각 -0.0°
같은 자리 · 정책 exo
restore:train_2853__2:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 5/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_2853__0:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 1/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_9797__1:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 20/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6242__1:q06 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 1/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_8287__1:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 29/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3655__0:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 17/30) · 오른쪽 게이트 켬(빨강 2/30, 파란 테두리 = 폴백 2) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3655__0:q03 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 7/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6242__1:q05 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 1/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6878__2:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 3/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6878__2:q01 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_2159__2:q08 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 2/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6278__2:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 7/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6278__2:q01 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_4136__1:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 22/30) · 오른쪽 게이트 켬(빨강 1/30, 파란 테두리 = 폴백 1) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3912__2:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 4/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3944__0:q02 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 7/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_4360__2:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 12/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_2224__2:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 14/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_1847__1:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 2/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_188__2:q01 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_7845__2:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 6/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3655__2:q04 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 1/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_7650__2:q02 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 11/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_2224__0:q08 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 22/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_9026__1:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 7/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_4304__0:q03 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 2/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_4304__0:q03 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 8/8, 파란 테두리 = 폴백 8) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_3994__0:q06 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_7661__1:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 30/30) · 오른쪽 게이트 켬(빨강 30/30, 파란 테두리 = 폴백 30) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_7152__1:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 12/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_7152__1:q00 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_4392__2:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 2/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6728__2:q01 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 14/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_6728__2:q01 · place · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 8/8) · 오른쪽 게이트 켬(빨강 0/8, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_1847__1:q04 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 15/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간
restore:train_9651__2:q00 · pick · 왼쪽 게이트 끔(빨강 = 다른 방/벽/학습 기각 18/30) · 오른쪽 게이트 켬(빨강 0/30, 파란 테두리 = 폴백 0) · ★ 타깃 · 화살표 = 로봇 정면 · 노랑 = 설 수 있는 공간

8scene-mem-gen(데이터 생성기)은 어떻게 하나

~/repos/Robotics/scene-mem-gen/scene-mem-datagen/는 place_robot_near를 쓰지 않는다(scene_mem_datagen.py:715 주석: "place_robot_near 를 쓰지 않으므로 가시성 렌더도 필요 없다"). 자리는 franka_pick.plan_pick → room2room.base_candidates로 결정론적으로 열거한다.

항목scene-mem-genmolmospaces datagen(=VLA 학습 분포)우리 하네스(게이트 후)
후보물체 xy 주위 standoff (0.50,0.58,0.66,0.74,0.82) m × 10° 링0~0.7 m 자유 픽셀 무작위학습 샘플러 그대로 + 게이트 재샘플, 전부 옆방이면 타깃 방 픽셀만
yaw정확히 물체 방향(노이즈 0)물체 방향 ±45°물체 방향 ±45°(학습과 동일)
같은 방방 다각형 안(S.in_poly, franka_pick.py:466; 후보 <4면 해제)없음점유 맵 방 채널 vs 서포트 그래프 방
벽점유 격자 0.30 m 팽창 + 실제 접촉 + 팔이 벽을 뚫는 IK 해 제거(room2room.arm_pose_free:535, 주석에 "벽 너머 옆방을 골랐다" 버그 기록)없음어깨 카메라→타깃 3D 레이에 wall/window
보이는가없음(방 다각형이 대신)어깨 카메라 ≥0.1%어깨 카메라 ≥0.1%(빈손 pick 접근)
도달IK 도달(≤0.95 m) + 회전 안전없음없음(카탈로그가 VLA 실시행으로 대신)
주행A* → 웨이포인트 → 정확히 목표 자세로 도킹(0.02 m/0.02 rad), 도착 오차 >0.15 m면 조작 실패 처리텔레포트(에피소드당 1회 배치)A* 주행 후 정확히 목표 자세 스냅(drive.py)

scene-mem-gen은 IK 전문가라 "어디 서면 팔이 닿는가"가 기준이고, VLA에는 "학습 때 서던 곳"이 기준이다. 둘의 공통 원칙(같은 방·벽 관통 금지)을 게이트로 가져왔고, 후보 생성과 yaw는 학습 분포(molmospaces 샘플러)를 유지했다.

9고친 것 — 자리 게이트

src/sbench_online/nav_gate.py(커밋 58931b2) + nav0.teleport_to 훅. 게이트 순서:

  1. 같은 방 — 베이스 자리의 방(점유 맵 room_map 채널, place_robot_near와 같은 팽창 반경 맵) vs 타깃의 방(ObjectManager.infer_room_name, 서포트 그래프 물체→가구→바닥→방). 둘 다 알려져 있고 다르면 기각. 문틈으로 타깃이 보여도 옆방이면 팔이 못 닿는다.
  2. 벽 — 어깨 카메라 위치→타깃 3D 점 선분에 wall*/window* 바디(mj_ray). pick은 물체 중심, place 가장자리 후보는 그 후보의 가장자리 점(표면 높이).
  3. 가시성 — 학습 datagen과 같은 카메라·임계(어깨 ≥0.1%), 빈손 pick 접근에만.

반경 샘플을 최대 12회 다시 뽑고, 전부 "다른 방"이면 place_in_room(타깃 방의 자유 픽셀만, 같은 yaw 규칙·충돌 검사)으로 다시 뽑는다. 그래도 없으면 최선 후보(같은 방 > 벽 없음 > 가시성 최대)로 폴백하고 pose_gate="fallback"을 남긴다. nav 결과에 pose_gate·gate_rejects·gate_rooms·gate_sampler가 기록되고 orchestrator가 에피소드 항목에 옮긴다. teleport_to(..., pose_gate_on=False)는 감사용 기준선.

도중에 잡은 함정 둘: (a) "베이스→타깃 xy, 높이 1.5 m" 레이는 벽에 붙은 가구 위 물체에서 벽 메시 안에서 끝나 로봇이 물체를 똑바로 봐도 벽으로 판정했다(train_8287 30/30) → 카메라 원점 3D 레이로 교체. (b) place 가장자리 경로에서 yaw를 다시 놓은 뒤 mj_forward 없이 카메라 위치를 읽어 레이 원점이 낡았다(train_188 armchair 8/8 벽이 게이트를 통과) → forward 추가 후 0/3.

원래 자리 앵커: teleport_to(anchor_xyz=…)/drive_to(anchor_xyz=…) → 가장자리 후보를 앵커 거리 순으로 정렬(surface_approach_candidates(ring_first=False)); run_episode(place_anchors={물체: {surface, xyz}}) → 든 물체의 정답 가구 == 에이전트가 고른 가구일 때만 전달; sbench_exec/online.py가 plan.restore_targets에서 만든다.

10의미 (Takeaway)

11보완점/다음 (Next)

  1. nav0.teleport_to 훅과 orchestrator 기록 필드는 작업 트리에만 있다 — 그 파일들에 다른 세션의 미커밋 작업(표면 가장자리 접근·preplace 레이캐스트)이 있어 그 위에 얹혀 있다. 그쪽이 커밋되면 같이 커밋한다(nav_gate.py·테스트·스크립트는 58931b2).
  2. 카탈로그 스펙의 "시야 사전 필터"를 이 게이트로 대체(후보 생성 = 게이트 켠 teleport_to). 빌더 계획 작성 → 스모크 → 50지점.
  3. 정면 yaw: 카탈로그 후보에 각 자리의 정면 재조준 버전을 넣어 실시행으로 비교(±45° 노이즈 vs 0°).
  4. place 접근에서 어깨 카메라가 벽을 뚫는 자리(train_4304)는 게이트가 폴백으로만 처리 — 정책 카메라(bench_exo_L) 기준 검사 추가 여부는 카탈로그 확인 시행 결과를 보고.
  5. 앵커는 restore 계열에만 의미가 있다(원래 자리가 정의됨). resume/routine의 목적지(용기·가전)는 가구가 작아 지금 규칙으로 충분한지 확인.
  6. 본 런 적용 시 pose_gate 분포(passed/fallback)를 집계해 폴백 지점을 표로 남긴다.
scene_bench · navigate 자리 감사 · 2026-09-18