teleport_to는 place_robot_near를 학습 datagen이 켜던 가시성 검사 없이 불렀다(어깨 카메라에 타깃 ≥0.1%). 그 검사가 학습 때 벽 건너편·옆방·화면 밖 자리를 걸러 줬는데 우리는 직선거리 0~0.7 m 반경만으로 뽑았다 — 학습 분포보다 넓은 분포.place_robot_near를 안 쓰고 물체 주위 링을 결정론적으로 열거(정면 yaw, 같은 방 다각형, IK, 팔 벽 관통 검사, A* 도킹). IK 전문가 기준이라 VLA 하네스엔 학습 샘플러 + 학습 가시성 검사가 맞고, 같은 방·벽 금지 원칙만 가져왔다.pose_gate가 남는다. 카탈로그(navi 하네스 v2)는 이 게이트 위에서 만든다.사용자 지적(260917): 온라인 런에서 로봇이 가구를 안 보고 서거나, 벽을 뚫고 넣으라는 듯 벽 건너편에 서는 경우가 있다. 자리 카탈로그(navi 하네스 v2)를 만드는 이유도 결국 이런 자리를 없애려는 것이므로, 카탈로그 전에 지금 navigate가 뽑는 자리가 왜 그런지를 코드와 수치로 확인하고 고친다.
질문 셋: (1) 그런 자리가 얼마나 자주 나오나 (2) 원인이 무엇인가 (3) 학습 데이터 생성기(molmospaces datagen)와 scene-mem-gen은 어떻게 하나.
학습 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).
지점마다 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 s | 1.32 s (기각 후보 평균 0.9개) |
| 기각분의 내역(게이트 끔) | 다른 방 35/269 (13%) · 벽 64/269 (24%) · 정면각>30° 49/269 (18%) · 그 외(가림·거리) 121/269 (45%) | |
| 지점 | 물체 | 학습 기각 | 다른 방 | 벽 | 정책 0픽셀 | 켬: 폴백 |
|---|---|---|---|---|---|---|
| restore:train_1299__2:q02 | paper towel roll | 0 → 0 | 0 → 0 | 0 → 0 | 1 → 2 | 0 |
| restore:train_1847__1:q03 | ladle | 2 → 0 | 0 → 0 | 0 → 0 | 2 → 1 | 0 |
| restore:train_1847__1:q04 | apple | 15 → 0 | 0 → 0 | 0 → 0 | 5 → 0 | 0 |
| restore:train_188__2:q01 | paper towel roll | 0 → 0 | 0 → 0 | 0 → 0 | 2 → 2 | 0 |
| restore:train_2102__1:q05 | kettle | 0 → 0 | 0 → 0 | 0 → 0 | 1 → 1 | 0 |
| restore:train_2159__2:q08 | potato | 2 → 0 | 0 → 0 | 0 → 0 | 6 → 4 | 0 |
| restore:train_2224__0:q08 | pot | 18 → 0 | 8 → 0 | 18 → 0 | 9 → 0 | 0 |
| restore:train_2224__2:q01 | potato | 14 → 0 | 0 → 0 | 3 → 0 | 12 → 3 | 0 |
| restore:train_2788__2:q06 | spray bottle | 0 → 0 | 0 → 0 | 0 → 0 | 3 → 2 | 0 |
| restore:train_2853__0:q01 | paper towel roll | 1 → 0 | 0 → 0 | 0 → 0 | 1 → 2 | 0 |
| restore:train_2853__2:q03 | soap bottle | 5 → 0 | 0 → 0 | 5 → 0 | 2 → 1 | 0 |
| restore:train_3655__0:q03 | pepper shaker | 17 → 2 | 0 → 0 | 1 → 0 | 5 → 0 | 2 |
| restore:train_3655__2:q04 | spray bottle | 1 → 0 | 0 → 0 | 1 → 0 | 3 → 3 | 0 |
| restore:train_3912__2:q03 | tennis racket | 4 → 0 | 0 → 0 | 4 → 0 | 2 → 0 | 0 |
| restore:train_3944__0:q02 | paper towel roll | 7 → 0 | 0 → 0 | 0 → 0 | 0 → 0 | 0 |
| restore:train_3994__0:q06 | pan | 0 → 0 | 0 → 0 | 0 → 0 | 0 → 0 | 0 |
| restore:train_4136__1:q01 | butter knife | 22 → 1 | 0 → 0 | 8 → 0 | 9 → 1 | 1 |
| restore:train_4304__0:q03 | knife | 2 → 0 | 0 → 0 | 0 → 0 | 1 → 1 | 0 |
| restore:train_4360__2:q00 | remote control | 11 → 0 | 10 → 0 | 9 → 0 | 10 → 0 | 0 |
| restore:train_4392__2:q00 | remote control | 2 → 0 | 0 → 0 | 2 → 0 | 4 → 4 | 0 |
| restore:train_4584__0:q00 | cell phone | 0 → 0 | 0 → 0 | 0 → 0 | 0 → 1 | 0 |
| restore:train_6222__1:q05 | pot | 0 → 0 | 0 → 0 | 0 → 0 | 0 → 0 | 0 |
| restore:train_6233__1:q04 | cup | 0 → 0 | 0 → 0 | 0 → 0 | 1 → 1 | 0 |
| restore:train_6242__1:q05 | bottle | 1 → 0 | 0 → 0 | 1 → 0 | 5 → 7 | 0 |
| restore:train_6242__1:q06 | apple | 1 → 0 | 0 → 0 | 0 → 0 | 5 → 10 | 0 |
| restore:train_6278__2:q01 | remote control | 6 → 0 | 0 → 0 | 5 → 0 | 5 → 4 | 0 |
| restore:train_6728__2:q01 | spatula | 13 → 0 | 1 → 0 | 0 → 0 | 9 → 0 | 0 |
| restore:train_6878__2:q01 | cell phone | 2 → 0 | 3 → 0 | 2 → 0 | 4 → 1 | 0 |
| restore:train_7152__1:q00 | remote control | 12 → 0 | 0 → 0 | 0 → 0 | 0 → 0 | 0 |
| restore:train_7385__0:q00 | remote control | 0 → 0 | 0 → 0 | 0 → 0 | 2 → 2 | 0 |
| restore:train_7650__2:q02 | spoon | 11 → 0 | 0 → 0 | 0 → 0 | 2 → 0 | 0 |
| restore:train_7661__1:q00 | candle | 30 → 30 | 0 → 0 | 0 → 0 | 30 → 30 | 30 |
| restore:train_7845__2:q03 | ladle | 6 → 0 | 0 → 0 | 1 → 0 | 9 → 14 | 0 |
| restore:train_8287__1:q00 | tissue box | 20 → 0 | 29 → 0 | 20 → 0 | 24 → 1 | 0 |
| restore:train_9026__1:q03 | bowl | 6 → 0 | 0 → 0 | 7 → 0 | 7 → 9 | 0 |
| restore:train_9320__2:q01 | remote control | 0 → 0 | 0 → 0 | 0 → 0 | 0 → 3 | 0 |
| restore:train_9651__2:q00 | spoon | 18 → 0 | 0 → 0 | 0 → 0 | 12 → 0 | 0 |
| restore:train_9778__1:q04 | spray bottle | 0 → 0 | 0 → 0 | 0 → 0 | 1 → 3 | 0 |
| restore:train_9797__1:q00 | candle | 20 → 0 | 0 → 0 | 14 → 0 | 2 → 1 | 0 |
| restore:train_9909__2:q05 | tomato | 0 → 0 | 0 → 0 | 0 → 0 | 9 → 2 | 0 |
실제 흐름대로 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 m | 0.37 m / 0.43 m / 0.47 m / 0.53 m |
| 복원 목표점까지 거리 중앙값/75%/90%/최대 | 0.78 m / 1.2 m / 1.98 m / 3.6 m | 0.77 m / 1.22 m / 1.98 m / 3.42 m |
| 정책 exo 카메라에 가구 0픽셀 | 29/320 (9%) | 0/320 (0%) |
| navigate 1회 소요(평균) | 0.63 s | 1.38 s |
| 지점 | 가구 | n | 다른 방/벽 | 접근 방식 |
|---|---|---|---|---|
| restore:train_1299__2:q02 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_1847__1:q03 | countertop | 8 | 0 → 0 | surface_rim |
| restore:train_1847__1:q04 | chestofdrawers | 8 | 0 → 0 | surface_rim |
| restore:train_188__2:q01 | armchair | 8 | 8 → 0 | surface_rim |
| restore:train_2102__1:q05 | bed | 8 | 0 → 0 | surface_rim |
| restore:train_2159__2:q08 | sofa | 8 | 0 → 0 | surface_rim |
| restore:train_2224__0:q08 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_2224__2:q01 | countertop | 8 | 0 → 0 | surface_rim |
| restore:train_2788__2:q06 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_2853__0:q01 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_2853__2:q03 | sofa | 8 | 0 → 0 | surface_rim |
| restore:train_3655__0:q03 | countertop | 8 | 7 → 0 | surface_rim |
| restore:train_3655__2:q04 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_3912__2:q03 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_3944__0:q02 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_3994__0:q06 | countertop | 8 | 8 → 0 | surface_rim |
| restore:train_4136__1:q01 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_4304__0:q03 | chair | 8 | 8 → 8 | surface_rim |
| restore:train_4360__2:q00 | sofa | 8 | 0 → 0 | surface_rim |
| restore:train_4392__2:q00 | chestofdrawers | 8 | 0 → 0 | surface_rim |
| restore:train_4584__0:q00 | countertop | 8 | 0 → 0 | surface_rim |
| restore:train_6222__1:q05 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_6233__1:q04 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_6242__1:q05 | countertop | 8 | 0 → 0 | surface_rim |
| restore:train_6242__1:q06 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_6278__2:q01 | crapper | 8 | 8 → 0 | surface_rim |
| restore:train_6728__2:q01 | diningtable | 8 | 8 → 0 | surface_rim |
| restore:train_6878__2:q01 | crapper | 8 | 8 → 0 | surface_rim |
| restore:train_7152__1:q00 | diningtable | 8 | 8 → 0 | surface_rim |
| restore:train_7385__0:q00 | bed | 8 | 0 → 0 | surface_rim |
| restore:train_7650__2:q02 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_7661__1:q00 | stand | 8 | 0 → 0 | surface_rim |
| restore:train_7845__2:q03 | chair | 8 | 0 → 0 | surface_rim |
| restore:train_8287__1:q00 | sink | 8 | 0 → 0 | surface_rim |
| restore:train_9026__1:q03 | chestofdrawers | 8 | 0 → 0 | surface_rim |
| restore:train_9320__2:q01 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_9651__2:q00 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_9778__1:q04 | armchair | 8 | 0 → 0 | surface_rim |
| restore:train_9797__1:q00 | diningtable | 8 | 0 → 0 | surface_rim |
| restore:train_9909__2:q05 | diningtable | 8 | 0 → 0 | surface_rim |
ㄷ자 조리대·식탁·침대 같은 큰 가구에서는 게이트를 켜도 로봇이 온 쪽 끝에 서서 물체의 원래 자리와 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 m | 0.52 m / 0.62 m / 0.72 m / 0.86 m |
| 원래 자리까지 > 0.9 m | 113/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 m | 0.35 / 0.55 m |
| 폴백 / navigate 1회 | 8/320 (2%) / 1.38 s | 8/320 (2%) / 1.4 s |
| 지점 | 가구 | 로봇 기준 | 앵커 |
|---|---|---|---|
| restore:train_3655__0:q03 | countertop | 3.39 | 0.68 |
| restore:train_6242__1:q05 | countertop | 2.44 | 0.36 |
| restore:train_2102__1:q05 | bed | 2.33 | 0.62 |
| restore:train_6222__1:q05 | diningtable | 2.03 | 0.55 |
| restore:train_2224__0:q08 | diningtable | 1.92 | 0.61 |
| restore:train_1847__1:q03 | countertop | 1.89 | 0.56 |
| restore:train_7650__2:q02 | diningtable | 1.66 | 0.49 |
| restore:train_4136__1:q01 | diningtable | 1.59 | 0.51 |
| restore:train_1299__2:q02 | diningtable | 1.29 | 0.44 |
| restore:train_9909__2:q05 | diningtable | 1.25 | 0.75 |
| restore:train_4584__0:q00 | countertop | 1.16 | 0.63 |
| restore:train_9320__2:q01 | diningtable | 1.13 | 0.6 |
| restore:train_1847__1:q04 | chestofdrawers | 0.98 | 0.55 |
| restore:train_2159__2:q08 | sofa | 0.91 | 0.36 |
| restore:train_7385__0:q00 | bed | 0.88 | 0.75 |
| restore:train_4392__2:q00 | chestofdrawers | 0.87 | 0.79 |
| restore:train_9651__2:q00 | diningtable | 0.87 | 0.62 |
| restore:train_3944__0:q02 | chair | 0.86 | 0.52 |
| restore:train_3994__0:q06 | countertop | 0.84 | 0.82 |
| restore:train_2853__0:q01 | diningtable | 0.76 | 0.7 |
| restore:train_9797__1:q00 | diningtable | 0.74 | 0.62 |
| restore:train_6728__2:q01 | diningtable | 0.69 | 0.67 |
| restore:train_2224__2:q01 | countertop | 0.68 | 0.41 |
| restore:train_9778__1:q04 | armchair | 0.68 | 0.45 |
| restore:train_3912__2:q03 | diningtable | 0.67 | 0.51 |
| restore:train_188__2:q01 | armchair | 0.66 | 0.63 |
| restore:train_4360__2:q00 | sofa | 0.65 | 0.54 |
| restore:train_4304__0:q03 | chair | 0.6 | 0.57 |
| restore:train_9026__1:q03 | chestofdrawers | 0.59 | 0.51 |
| restore:train_7845__2:q03 | chair | 0.58 | 0.58 |
| restore:train_3655__2:q04 | chair | 0.51 | 0.52 |
| restore:train_7661__1:q00 | stand | 0.51 | 0.42 |
| restore:train_8287__1:q00 | sink | 0.51 | 0.3 |
| restore:train_6233__1:q04 | chair | 0.49 | 0.47 |
| restore:train_6242__1:q06 | chair | 0.49 | 0.37 |
| restore:train_7152__1:q00 | diningtable | 0.47 | 0.37 |
| restore:train_6278__2:q01 | crapper | 0.44 | 0.23 |
| restore:train_2853__2:q03 | sofa | 0.41 | 0.38 |
| restore:train_6878__2:q01 | crapper | 0.35 | 0.37 |
| restore:train_2788__2:q06 | chair | 0.31 | 0.28 |
공정성: 정답을 맞힌 뒤에만 발동하고 틀린 답은 어디 서든 점수가 안 나므로 순위 무영향; 채점 is_placed_on은 가구 안의 지점을 요구하지 않으므로 기억이 답할 정보를 대신 주는 것도 아니다. 절대 성공률은 오르므로 전후 비교 금지(행 approach_anchor="given"). 게이트·앵커 적용법은 docs/nav_pose_gate.md.
파일럿 40자리(각 10회 VLA pick, 정책 pi05_mlspaces_place_oc@20000)를 같은 기준으로 재측정해 성공률과 조인했다.
| 기준 | 걸린 자리 | 걸린 자리 평균 성공률 | 남은 자리 | 남은 자리 평균 성공률 |
|---|---|---|---|---|
| 타깃과 다른 방 | 2 | 0.00 (n=2) | 38 | 0.38 (n=38) |
| 카메라→물체 사이 벽 | 7 | 0.20 (n=7) | 33 | 0.39 (n=33) |
| 학습 datagen 기각(어깨 < 0.1%) | 9 | 0.17 (n=9) | 31 | 0.42 (n=31) |
| 정책 exo 0픽셀 | 10 | 0.25 (n=10) | 30 | 0.40 (n=30) |
| 게이트 기각(셋 중 하나) | 9 | 0.17 (n=9) | 31 | 0.42 (n=31) |
물체 픽셀 비율과 성공률의 Spearman 상관(40자리): 어깨 카메라 ρ=0.267 (p=0.0962), 정책 exo ρ=0.351 (p=0.0265).
게이트 끔(지금 하네스)에서 걸린 자리의 어깨 카메라·정책 카메라 프레임. 캡션의 '방 A→B'는 베이스가 선 방 → 타깃의 방.
































































~/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-gen | molmospaces 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 샘플러)를 유지했다.
src/sbench_online/nav_gate.py(커밋 58931b2) + nav0.teleport_to 훅. 게이트 순서:
room_map 채널, place_robot_near와 같은 팽창 반경 맵) vs 타깃의 방(ObjectManager.infer_room_name, 서포트 그래프 물체→가구→바닥→방). 둘 다 알려져 있고 다르면 기각. 문틈으로 타깃이 보여도 옆방이면 팔이 못 닿는다.wall*/window* 바디(mj_ray). pick은 물체 중심, place 가장자리 후보는 그 후보의 가장자리 점(표면 높이).반경 샘플을 최대 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에서 만든다.
nav0.teleport_to 훅과 orchestrator 기록 필드는 작업 트리에만 있다 — 그 파일들에 다른 세션의 미커밋 작업(표면 가장자리 접근·preplace 레이캐스트)이 있어 그 위에 얹혀 있다. 그쪽이 커밋되면 같이 커밋한다(nav_gate.py·테스트·스크립트는 58931b2).teleport_to). 빌더 계획 작성 → 스모크 → 50지점.pose_gate 분포(passed/fallback)를 집계해 폴백 지점을 표로 남긴다.