2-프로세스 RPC 브리지로, 관절제어 vs OSC delta 불일치를 Cartesian 서보로 풀어 새 시뮬레이터로 붙였다.1/30 = 0.033 — 사용자 지적("실물에서 얻을 수 있는 정보만, 원본처럼 IK 관절 제어")대로 채점 자세 API·파지 캘리브레이션·벤치마크 내부 문장을 걷어내고 pyroki IK→관절 제어로 바꾼 뒤 재실행. 4차 3/30과 유의차 없음(p=0.61). 30/30이 `is_reachable`·`get_holes`를 썼고 28/30이 에이전트 자신의 검사문(RuntimeError)으로 중단 — 대부분 나사·재파지 중 다리 기울어짐. 손 oracle은 공식 경로 2/3.3/30 = 0.100, 3차(옛 파지 측 규칙) 0/30. 1·2차 0/30은 제 환경 포팅 결함(채점 대상 미지정, grasp 높이 z=0, 슬롯 의미, 나사 조임 문서 부재, Euler yaw 짐벌, 손목 한계 측 선택)이 만든 값이라 폐기. 코드 생성 100%·sandbox 에러 0.0.0°로 세워 운반, grasp transform 재측정 등 oracle보다 나은 코드. 수정 후 낙하 안착은 스크립트 정답(17.2°/+13.8 mm)과 일치(14.2°/+12.6 mm).goto_pose 하위 스텝(누르며 −90° 회전 → 풀고 되감기)으로 5 사이클 +6.3 → +0.3 mm. 그 프로그램을 oracle로 공식 경로(launch.py)에서 3/3 reward 1.0 재현. 낙하 안착은 스크립트 에이전트도 ~45% 확률라 성공률 상한 자체가 낮다.p = 0.017 — pi0.5가 유의하게 높음; vs pi0.5 초기 0.24 (12/50) p = 0.15 — 유의차 없음; vs LingBot 0.133 (4/30) p = 1.00 — 동급; vs 스크립트 정답 0.45 (9/20) p = 0.007. 데모 0개 단일 턴 코드 정책이 demo-fine-tuned LingBot과 동급, pi0.5 최종 모델에는 못 미친다.요청: "Cap-X로 FurnitureBench Eval". CaP-X(NVIDIA·Berkeley·Stanford·CMU, arXiv 2603.22435)는 LLM이 perception/control 프리미티브를 조합하는 Python 코드를 생성해 로봇을 제어하는 Code-as-Policy 벤치마크다. 이 프로젝트의 기존 트랙(pi0.5 0.36, LingBot 0.133)은 모두 학습된 VLA라, 학습 없이 추론만으로 푸는 CaP-X는 one_leg 삽입 병목이 정책 용량 문제인지 기하 추론 문제인지 가르는 대조군이 된다.
grep -ri furniture의 유일한 히트는 BEHAVIOR의 "rearranging kitchen furniture". CaP-X 39개 태스크 중 FurnitureBench는 0개. "명령 실행"이 아니라 CaP-Gym에 FurnitureSim을 새 시뮬레이터로 통합하는 작업이었다.하드 블로커 1 — Python. Isaac Gym Preview 4는 gym_36/37/38.so만 제공(python_requires='>=3.6,<3.9'), CaP-X는 >=3.10. 한 프로세스 불가 → py3.8 FurnitureSim 워커 ↔ py3.10 CaP-X 어댑터를 길이 프리픽스 JSON RPC로 연결(numpy는 base64). 하드 블로커 2 — 제어. CaP-X goto_pose는 PyRoKi IK → move_to_joints_blocking인데 FurnitureSim은 OSC delta EE pose만 노출(컨트롤러 osc.py 하나). IK를 우회하고 Cartesian 목표를 OSC delta로 서보. 프레임은 robot-base/WXYZ로 통일(Isaac Gym은 XYZW, EE는 이미 base 프레임, 파트는 world → base 변환).
VLA와 입력 비교. VLA는 5~10 스텝마다 정면·손목 224² 이미지 + 15-D 상태를 받아 delta EE를 낸다. CaP-X(단일턴·privileged)는 에피소드당 1번 ~4.6 KB 텍스트(태스크 설명 + API docstring)만 받고 Python 프로그램을 낸다. 이미지 0장. 코드는 실행 중 get_object_pose()로 시뮬레이터 GT 좌표를 읽으므로 인식 난이도에서는 유리하고, 데모 300개 대신 프롬프트가 곧 데모다.
클러스터 실측. worker pod(bare ubuntu:22.04)에 curl·python3·CA 인증서·libGL 없음 → venv python + certifi + conda glvnd로 우회. 외부 egress는 열려 있음(requests → 401 확인). LETSUR_API_KEY 환경변수는 만료(401), 유효 키는 ~/envs/letsur_key_override.txt. Letsur에 gpt-6-astra·gemini-3.1-pro-preview(논문 기준 모델) 모두 존재.
git status 기준 수정한 원본 파일은 등록용 __init__.py 3개(+29줄)와 uv.lock뿐. 에이전트 루프(launch.py/base.py 프롬프트 조립 → LLM 1회 → sandbox 실행 → env reward), llm/client.py, privileged 의미(GT 자세를 API로, 이미지 없음)는 원본 그대로.
| 항목 | 원본 CaP-X (nut_assembly 등) | 이번 FurnitureBench | 에이전트에 유리? |
|---|---|---|---|
| 시뮬레이터 | Robosuite/LIBERO/BEHAVIOR, in-process | FurnitureSim(py3.8 Isaac Gym) — 별도 프로세스 RPC 브리지 | 중립 |
| 로봇 제어 | goto_pose = pyroki IK → 관절 제어 | OSC delta-EE 위 Cartesian 서보 자작(적분항·정지 감지·compliant) | 불리(접촉 제어가 더 어려움) |
| 태스크 프롬프트 | ~10줄, 힌트 3~4문장("손잡이로 잡아라", "rigid transform 재적용") | ~50줄, 절차를 산문으로(놓아서 안착→재파지→누르며 회전, 재측정, 확인·재놓기, 되감기, compliant, 허용오차) | 유리 |
| 목표 자세 | get_object_pose("peg")만 — 삽입 자세는 에이전트가 계산 | get_assembly_slots()가 다리의 최종 채점 자세 그대로, get_target_assembly()가 채점 다리 이름 | 유리 |
sample_grasp_pose | GT 위치 + 고정 쿼터니언 [0,0,1,0] | AABB 중심 + 손목 한계 캘리브레이션(q7 ≈ yaw+2.06)으로 파지 측 선택 — 3차 0/30 → 4차 3/30의 원인 | 유리 |
| LLM 엔드포인트 | OpenRouter 프록시 | 같은 패턴의 Letsur 프록시. gpt-6-astra는 GPT_MODELS에 없어 generic 분기 → reasoning_effort 미전달(게이트웨이 기본값) | 불명 |
| oracle | 사람이 쓴 oracle로 환경 검증 | 제 oracle 6종 실패 → 에이전트 trial 05 프로그램을 oracle로 채택(프롬프트엔 미포함) | 중립 |
| 규모 | trials 100, workers 12 | trials 30, workers 4 (0.100의 95% CI ≈ 0.02~0.27) | 중립 |
2b의 "유리" 세 항목을 제거하고 제어를 원본 경로로 맞춘 변형. 사용자 결정: IK → 관절 제어(원본과 동일) + 물리 사실만 담은 프롬프트.
| 항목 | 4차 (0.100) | v5 real-faithful |
|---|---|---|
| 제어 | OSC delta-EE 서보 + compliant | pyroki IK → 관절 위치 제어. 워커가 팔 7 DOF를 런타임에 PhysX position drive(k=2000, d=60)로 전환; 1 rad/s 보간 + settle. numpy FK(Craig DH)로 IK 잔차 검증 — 시뮬 EE와 0.0000 m 일치 |
| 목표 자세 | get_assembly_slots = 채점기 정답 자세 | 제거. get_holes(part) → 구멍 입구 위치 + 축(CAD 정보). 다리 길이(bbox)로 안착 자세는 에이전트가 구성 |
| 채점 다리 | get_target_assembly() | 지시문 "attach square_table_leg4" |
| 파지 | 손목 한계 캘리브레이션 상수(q7 ≈ yaw+2.06) | 상수 제거. 후보 파지(거울 파지 유효 명시) + is_reachable(pose)(IK+FK 잔차+한계) + get_joint_positions |
| IK | — | 원본 pyroki 서버(api_servers). vel-cost 해가 큰 회전에서 미달(90°가 10° 부족) → 반환 해에서 재해석(≤4회) + 전역 해 fallback을 API에 내장 |
| 프롬프트 | ~50줄 절차 레시피 + 벤치마크 내부 문장 3개 | ~20줄: 과제·프레임 규약·물리 사실 4개(나사식이라 돌려야 함, 손에서 밀릴 수 있음, 손목 회전 한계, step 예산). 놓기·재파지 순서·허용오차 전부 삭제 (원문) |
| 워커 pod 함정 | — | robot_descriptions→GitPython이 git 바이너리 요구 → conda env에 git 설치 + GIT_PYTHON_GIT_EXECUTABLE. LLM 프록시가 async def+blocking requests로 4 worker 호출을 직렬화 → 200 s timeout 14/16 trial 무효(118494) → 동기 엔드포인트로 수정, 30 trial 15분(4차 60분) |
로그인 GPU에서 7회 반복 끝에 reward 1.0 (478 step) — 세우기 0.4°, 호버 폐루프 0.7 mm, 입구 3 mm 안에서 놓기 → 안착 +8.3 mm, −90° 나사 4사이클 +8.3 → +6.2 → +4.0 → +1.7 → +0.3 mm, 최종 1.1 mm / 0.0°. 워커 pod 공식 경로(launch.py oracle×3) 2/3(실패 1건은 놓기 직전 0.7°/3.1 mm로 정상 → 놓은 뒤 낙하 확률). OSC 시절 손 oracle 6종 전패와 대조 — 강성 관절 제어가 "누르며 돌리기"에 유리. 놓기 깊이: 입구 4 mm 위에서 놓으면 넘어지고 3 mm 안에 넣고 놓으면 안착 — 프롬프트엔 안 씀.
| 실행 | API | 성공 | 예외 없이 끝난 trial | 소요 |
|---|---|---|---|---|
| Astra 4차 | 누설 포함, OSC | 3/30 = 0.100 | 30/30 | 60분 |
| Astra v5 | 실물-충실, IK 관절 | 1/30 = 0.033 | 2/30 (28건 에이전트 자체 RuntimeError) | 15분 |
| 손 oracle (v5 API) | — | 2/3 (공식 경로) | — | — |
Fisher: v5 vs 4차 p = 0.61(유의차 없음), vs LingBot 0.133 p = 0.35, vs pi0.5 0.36 p = 0.0008, vs scripted 0.45 p = 0.0005.
| 단계 | n | 메시지 예 |
|---|---|---|
| 나사·재파지 중 다리 기울어짐/이탈 | 16 | "The leg tilted during threading", "…tipped during regrasp", "…slipped away from the hole", "…rotated in the wrong threading direction" |
| 삽입 전 정렬 실패 | 7 | "The threaded end is not aligned with the hole", "…could not be aligned", "The upright leg lost alignment before engagement", "Cannot align the lifted leg above the hole" |
| 도달성 포기 | 5 | "Required pose is outside the robot's reachable workspace" ×3, "No reachable tightening stroke remains", "The wrist cannot start threading from this grasp" |
| 예외 없이 종료(실패) | 2 | trial 01, 23 |
| 성공 | 1 | trial 22 — 조립 등록 후 계속 조이다 "lost axial alignment"로 raise (채점은 이미 완료) |
is_reachable·get_holes를 사용.raise로 끝낸다(28/30). 단일 턴이라 그 예외가 곧 trial 종료. 손 oracle이 2/3인 것과의 차이는 (a) 놓기 깊이(입구 3 mm 안)와 (b) 나사 중 재측정·보정 루프의 유무. 4차 대비 성공률 차이는 통계적으로 구분되지 않는다(1 vs 3, p=0.61) — 이 규모에선 "누설 제거로 성능이 떨어졌다"고도 말할 수 없다.30 trial 계측 재생(sbatch 118663)이 끝나면 4차와 같은 안착 지표 표를 추가.
| 실행 | job | 성공 | 코드 생성 / sandbox 에러 | leg4 조준 | 비고 |
|---|---|---|---|---|---|
| Astra 1차 | 117038 | 0/30 | 30/30 / 0 | 0/30 | 프롬프트가 어느 다리인지 미지정 → 최근접 다리 선택 |
| Astra 2차 (결함 1·2 수정) | 117063 | 0/30 | 30/30 / 0 | 30/30 | 다리 +7.3 cm 들어올림, 기울기 0.0°, 슬롯까지 2.8 cm |
| Astra 3차 (결함 1~5 수정, 옛 파지 측 규칙) | 117337 | 0/30 | 30/30 / 0 | 30/30 | 세우기 52° 손목 한계(q5/q7 ±2.90)에 갇힘 — 측 규칙 결함 잔존 |
| Astra 4차 (완전 수정 API) | 117430 | 3/30 = 0.100 | 30/30 / 0 | 30/30 | trial 05 성공: 놓기 +6.3 mm → 나사 5사이클 → 1.0 mm / 0.0°. 나머지는 낙하 불안착·재시도 소진 |
| 에이전트 trial 05 프로그램 = oracle (launch.py 공식 경로) | login | 3/3 | — | — | reward 1.0 ×3, seed 고정 결정적 재현 |
| 스크립트 에이전트 (reference) | login | 3/3 (일반적으론 ~0.45) | — | — | 471~522 step; 낙하 안착 자체가 ~45% (9/20) |
| # | 결함 | 증거 | 수정 |
|---|---|---|---|
| 1 | 채점 대상을 알 수 없음 — should_be_assembled=[(0,4)]라 leg4만 채점, 프롬프트는 "the square table leg" | 30/30이 list_parts() 최근접 다리, leg4 0건 | get_target_assembly() 추가 → 2차 30/30 leg4 |
| 2 | sample_grasp_pose가 파트 원점(z=0, 테이블 표면) 반환 | HD 재생 dz≈0, 다리 밀리기만 | 월드 수직 반-extent 보정 → z=+0.015, dz +0.084 |
| 3 | get_assembly_slots를 "구멍 위치"로 문서화, 실제는 조립 시 다리 원점 | 서로 다른 3 프로그램이 동일 2.8 cm 오차 | 파트가 도달할 완전한 자세(pos+quat) 반환 |
| 4 | 나사 조임 부재 (사용자 지적) — 다리는 나사식, insert→pre_grasp→screw_grasp→screw→release 반복 필요 | 1차 프롬프트: "come down onto the hole from directly above" | 프롬프트에 물리 사실 명시. 프리미티브 screw_in은 만들었다 제거 — 에이전트가 goto_pose로 조합할 몫 |
screw_in(turns=) 프리미티브를 만들어 호출하라고 쓴 것도 잘못 — 에이전트가 풀 문제를 대신 푼 것. 걷어냈다.FurnitureBench 자체 스크립트 에이전트를 상태 전이마다 같은 프레임으로 기록(scripted_trace.py)해 정답을 얻고, oracle을 단계에서 잘라 비교.
| 단계 | 스크립트 성공 (ep2) | 스크립트 실패 (ep0) | oracle 수정 전 | oracle 수정 후 |
|---|---|---|---|---|
| 놓기 직전 기울기 | 0.6° | 6.3° | 2.3° | 0.8° |
| 놓기 직전 수평 오차 | 1.4 / 1.2 mm | 12.4 / 7.9 mm | 1.2 / 2.0 mm | 1.1 / 0.4 mm |
| 놓는 높이 (조립 위치 대비) | +21.8 mm | +33.5 mm | +39.6 mm | +28 mm |
| 놓은 직후 기울기 | 17.2° | 90° (넘어짐) | 66~76° | 14.2° |
| 놓은 직후 구멍축 오차 | +13.8 mm | — | — | +12.6 mm |
원인 순서: ① 놓는 높이 4 cm는 튀어 넘어짐 → 2.2~2.9 cm. ② 자유공간 처짐용 서보 적분항이 접촉에서 "테두리 밀어붙이기"가 되어 그립 안에서 피벗(+24 mm에서 19.2°) → goto_pose(compliant=True)(적분 off, 1 cm 스텝, 회전 3°/tick) 추가 → 0.8°. ③ 재파지는 정상, -95° 비틀기 중 다리가 뽑힘 — 그러나 같은 낙하 코드가 회차마다 구멍 안(G) / 누움(I) / 옆에 섬(J)으로 갈려, 단일 에피소드로는 비틀기를 판정할 수 없다는 것이 드러났다.
1.3°·6.1 mm / 1.3°·6.1 mm(2·3회 0.1 mm까지 동일). 낙하가 되면 조립 위치 6 mm 위에서 거의 다 들어간다 — 스크립트 성공의 낙하 직후(17°/+13.8 mm)보다 낫다. 남은 건 압입 몇 mm뿐이고, 비틀기는 오히려 뽑아낸다.sample_grasp_pose yaw: 오일러 "xyz"[2]로 뽑은 yaw가 옆으로 누운 파트에서 짐벌 분기가 뒤집혀 손목이 45° 기운 grasp를 만들고, 그 transform으로 계산한 호버 목표가 테이블 밖으로 갔다(변형 L: 다리를 1.34 m 날림). 장축의 수평 투영에서 yaw를 잡도록 수정(닫힘 축 = 그리퍼 X, 스크립트 정책의 reset 파지에서 역산), 5개 자세 검증 통과.0.017, #14 0.003 — 다리 폭 0.030인데 손가락이 지나쳐 닫힘 = 파지 실패, 이후 빈 손으로 "놓기" 수행. 3번째에 잡힌 뒤 호버(강성 서보)는 2.0° / 2.2 mm로 완벽했으나, 호버에서 채점 yaw로 돌리는 컴플라이언트 회전이 28° / 26 mm로 망쳤다. 결함 5의 첫 수정(+90°)이 틀렸던 것 — 8.75 cm 길이 방향으로 닫으면 6.5 cm 개방을 넘어 못 잡는다(회귀 프로브 90°/22 cm 재확인). 정정: yaw = atan2(장축). 그간 "종료 90°" 실행 대부분이 파지 실패 → 빈 손 → 재시도 폭주였을 가능성이 크고, 나사/누르기 루프는 아직 안착된 다리 위에서 한 번도 시험되지 않았다.7.0 mm까지 (16:25): atan2 yaw로 첫 파지 grip 0.030 ✓. 3번째 시도에서 강성 yaw 회전 → 1.9°/0.9 mm, 컴플라이언트 하강 → 0.8°/2.0 mm, 놓기 → 2.3°/2.2 mm, dy +6.7 mm. 최종 pos error 7.0 mm·tilt 2.9°·yaw 정렬. 누르기 루프는 oracle 판정 반경(8 mm)이 벤치마크 구멍축 허용(5 mm)보다 느슨해 1.6 mm 남기고 조기 종료 — 판정을 축별로 정확히 미러링한 P2 대기 중. 1·2번째 시도는 세우는 동안 그립 내 미끄러짐(호버 51.7°, 또는 yaw 회전 후 60 mm) → 호버에서 grasp transform 재측정·재서보하는 P 실행 중.tilt 51.6°, lat 2 mm, 재측정·재서보 3회에도 51.6° 고정. 슬립이 아니라 그 파지 자세의 손목 회전을 OSC가 도달 못 하는 것(위치만 수렴). 4개 대칭 후보를 가까운 순으로 시도해 tilt<10°인 첫 후보를 채택하는 변형 Q 큐.gpt-6-astra × one_leg 30 trial 재실행 (own QOS, 1 GPU, 4 workers, ~25분). 결과는 호출별 트레이스로 재생해 성공률뿐 아니라 안착 지표(기울기·mm)까지 기록. 참고: 그간의 변형 I~Q는 LLM 없이 제 oracle을 검증한 것이며 CaP-X 평가가 아니다.52.0° 고정. 관절각: q5 = −2.90, q7 = +2.90 = Panda 한계(±2.8973)에 두 관절이 못 박힘. 이 파지 자세에서 세우기 롤은 기구학적으로 불가. 수정: sample_grasp_pose가 장축 가로지름 yaw 두 후보(θ, θ+180°) 중 현재 손목 yaw에 가까운 쪽을 택해 회전 여유 확보(프로브 T 검증 중). Astra 3차에는 미반영(이미 import).q7 = 1.97, 세우기 롤 +0.93 → 2.90(한계). 반대쪽(θ+180°)이면 −1.17 → 롤 후 −0.24. 규칙을 "파지 후 예측 |q7| 최소"로 교체.+1.97(atan2 쪽) vs −1.16(반대쪽); 호버 기울기 52.0° vs 1.8° / 1.7 mm(첫 후보에서 수렴). 툴 yaw +Δ → q7 −Δ로 부호 확정, API 규칙 수정. Astra 3차는 옛 규칙으로 실행 중 → 4차 필요.1.5°/2.9 mm → 컴플라이언트 하강 1.0°/0.9 mm → 놓기 1.4°, 0.4 mm, dy +6.2 mm(판정 5 mm까지 0.8 mm). 누르기용 재파지가 grip 0.003(빈 손) — 결함 6: sample_grasp_pose가 세워진 다리의 꼭대기(원점+4.4 cm)를 가리킴. AABB 중심 + 1.5 cm 클램프로 수정. 에이전트의 낙하·재시도·컴플라이언트·재측정 사용은 모두 정확했다.−0.932 rad. 측정 q7(A +1.97 / B −1.16)이 후보 yaw(−0.091 / +3.05)와 q7 ≈ yaw + 2.06으로 두 점 모두 0.01 이내 일치. "손목 회전 최소"(A +1.02 vs B −2.12)는 정반대를 고르는 오답이었다. 규칙: 후보 yaw 중 −2.06에 가까운 쪽(캘리브레이션 상수, 근거 명시). 동작 프로브 Y 통과 시 v4 자동 제출.2.2° / 3.1 mm → Astra 4차 job 117430. 프로브 Z — 에이전트 trial-1 코드가 완전 수정 API로 첫 시도에 3.0°, 2.4 mm, dy +6.4 mm 안착, 재파지 0.030 ✓, 최종 dy +6.3 mm(판정까지 1.3 mm). 낙하 직후는 항상 +6.1~6.7 mm이고 누르기로는 더 안 내려간다 — 마지막 6 mm는 나사산, 회전이 필요(사용자 최초 지적). 누르기-전용 설계 폐기, 컴플라이언트 소각 비틀기 사이클(AA) 시험 중.14.9°/11.9 mm/+13.2(스크립트 성공형)를 수용하고 재파지도 잡혔지만 3사이클 동안 dy +12.3 → +11.9 mm, 기울기 ~18° 불변. 스크립트 screw는 강성 OSC 절대 목표 −95°+5 mm 압입으로 첫 사이클에 17→1.3°, 13.8→6.4 mm. 예전 강성 비틀기 실패는 재파지 yaw 버그 상태였으므로 반증이 아니다.27.6°/22.7 mm → 놓자 73.5°. 컴플라이언트 재파지가 기운 다리를 따라 툴이 기운 채 잡혀, 비틀기가 그 축 둘레로 돌며 밑면을 소켓 밖으로 끌어냄. 스크립트 pre_grasp는 절대 수직·강성 — 손가락이 다리를 세우고 비틀기는 수직축 둘레.trial_05 reward 1.0. 완전 수정 API에서 CaP-X 에이전트가 one_leg를 조립했다. 생성 코드(211줄)의 주석: "The grasp may slip during the large rotation. Measure it again." · "Regrasp from above with a neutral wrist for each bounded turn." · "Rotate about the measured leg axis, not the gripper origin. Two compliant substeps keep contact loads and wrist travel small." — 제 oracle이 실패한 지점(툴 축 둘레 비틀기)을 에이전트는 스스로 피했다. 영상 · 코드 · 프롬프트. 최종 성공률은 30 trial 완료 후.launch.py --use-oracle-code(모듈 oracle = Astra v4 trial 05 프로그램) 3/3 reward 1.0 (Task Completed True ×3). 환경·API가 CaP-X 공식 경로로 조립 가능함이 재현 가능하게 확정 — 참조 프로그램은 에이전트 자신의 코드.p = 0.017 — pi0.5가 유의하게 높음; vs pi0.5 초기 0.24 (12/50) p = 0.15 — 유의차 없음; vs LingBot 0.133 (4/30) p = 1.00 — 동급; vs 스크립트 정답 0.45 (9/20) p = 0.007. 데모 0개 단일 턴 코드 정책이 demo-fine-tuned LingBot과 동급, pi0.5 최종 모델에는 못 미친다.| 정책 | 입력 | 학습 데이터 | 성공률 | n |
|---|---|---|---|---|
| pi0.5 (fine-tuned) | 이미지 2뷰 + 관절 | scripted demo | 0.24 / 0.36 | 50 / 50 |
| LingBot-VA | 이미지 + 관절 | scripted demo | 0.133 / 0.0 | 30 / 80 |
| 스크립트 에이전트 (정답 정책) | GT 자세 | — | ~0.45 | 20 |
| CaP-X gpt-6-astra (privileged, 단일 턴) | 텍스트 프롬프트 + API 문서 + GT 자세 (이미지 없음) | 0 demo, 0 fine-tune | 0.100 | 30 |
| trial | 평가 성공 | step | 최대 들어올림 mm | 최소 기울기 ° | 최소 수평 오차 mm | 최종 기울기 ° | 최종 자세 오차 mm | 재생 성공 | 유형 |
|---|---|---|---|---|---|---|---|---|---|
| 01 | 0 | 3000 | 91 | 1.1 | 1.1 | 7.5 | 15.8 | 예산 소진, 세워졌으나 이탈 | |
| 02 | 0 | 539 | 138 | 0.6 | 0.4 | 3.0 | 6.5 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 03 | 0 | 3000 | 100 | 2.4 | 1.1 | 90.0 | 378.0 | 다리 넘어짐 (90°) | |
| 04 | 0 | 2944 | 141 | 1.0 | 1.3 | 83.4 | 52.5 | 다리 넘어짐 (90°) | |
| 05 | 1 | 1898 | 177 | 0.9 | 0.6 | 0.0 | 1.3 | ✓ | 성공 |
| 06 | 0 | 3000 | 93 | 1.0 | 0.2 | 0.0 | 1.2 | ✓ | 재생에선 성공 (낙하 확률) |
| 07 | 0 | 2877 | 102 | 1.0 | 0.7 | 90.0 | 735.0 | 다리 넘어짐 (90°) | |
| 08 | 0 | 3000 | 143 | 0.6 | 2.1 | 13.0 | 81.4 | 예산 소진, 세워졌으나 이탈 | |
| 09 | 0 | 3000 | 143 | 0.5 | 1.4 | 90.0 | 45.6 | 다리 넘어짐 (90°) | |
| 10 | 0 | 1738 | 52 | 1.0 | 0.8 | 0.0 | 0.8 | ✓ | 재생에선 성공 (낙하 확률) |
| 11 | 0 | 3000 | 129 | 0.5 | 3.5 | 90.0 | 79.8 | 다리 넘어짐 (90°) | |
| 12 | 0 | 528 | 77 | 2.5 | 3.9 | 3.0 | 6.8 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 13 | 0 | 3000 | 112 | 0.9 | 2.0 | 90.0 | 675.3 | 다리 넘어짐 (90°) | |
| 14 | 0 | 3000 | 170 | 0.2 | 0.7 | 0.0 | 61.5 | 예산 소진, 세워졌으나 이탈 | |
| 15 | 0 | 3000 | 171 | 0.0 | 0.7 | 4.5 | 99.1 | 예산 소진, 세워졌으나 이탈 | |
| 16 | 0 | 534 | 85 | 1.0 | 1.7 | 3.1 | 6.6 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 17 | 0 | 3000 | 143 | 1.1 | 1.8 | 90.0 | 1489.8 | 다리 넘어짐 (90°) | |
| 18 | 1 | 2778 | 145 | 0.9 | 1.0 | 0.0 | 1.0 | ✓ | 성공 |
| 19 | 0 | 3000 | 100 | 0.5 | 2.3 | 90.0 | 134.6 | 다리 넘어짐 (90°) | |
| 20 | 0 | 2792 | 117 | 2.4 | 1.8 | 90.0 | 73.0 | 다리 넘어짐 (90°) | |
| 21 | 1 | 1852 | 85 | 1.1 | 1.2 | 0.0 | 1.3 | ✓ | 성공 |
| 22 | 0 | 1978 | 138 | 0.5 | 1.1 | 0.7 | 6.4 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 23 | 0 | 3000 | 83 | 1.0 | 1.6 | 90.0 | 813.8 | 다리 넘어짐 (90°) | |
| 24 | 0 | 3000 | 90 | 2.4 | 0.5 | 90.0 | 1714.8 | 다리 넘어짐 (90°) | |
| 25 | 0 | 665 | 90 | 1.0 | 0.5 | 1.4 | 6.4 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 26 | 0 | 3000 | 99 | 2.4 | 2.3 | 90.0 | 92.7 | 다리 넘어짐 (90°) | |
| 27 | 0 | 567 | 123 | 1.0 | 0.9 | 3.1 | 6.6 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 28 | 0 | 550 | 60 | 1.6 | 2.4 | 3.0 | 6.7 | 자체 완료 판정 조기 종료 (~6.5 mm) | |
| 29 | 0 | 3000 | 91 | 1.1 | 2.2 | 90.0 | 325.3 | 다리 넘어짐 (90°) | |
| 30 | 0 | 2662 | 120 | 2.5 | 2.0 | 90.0 | 61.6 | 다리 넘어짐 (90°) |
| 결과 유형 (30 trial) | n | 설명 |
|---|---|---|
| 성공 | 3 | trial 05·18·21. 재생에서도 3/3 재현 |
| 다리 넘어짐 (최종 90°) | 14 | 나사 사이클·재파지 중 다리가 튕겨 눕고, 이후 회복 실패(대부분 3000 step 소진) |
| 자체 완료 판정 조기 종료 | 7 | 528~1978 step에 종료, 최종 6.4~6.8 mm(= 낙하 직후 잔차). 프로그램의 "조립됨" 판정이 ‖p−target‖ < 7~8 mm라 낙하만으로 통과 → 나사 루프가 돌지 않음. 채점은 구멍 축 ≤ 5 mm |
| 예산 소진, 세워졌으나 이탈 | 4 | 기울기 0~13°이나 자세 오차 16~99 mm — 구멍 옆에 서 있음 |
| 재생에선 성공 | 2 | trial 06·10: 평가 땐 실패, 같은 코드 재생은 reward 1.0 — 낙하 안착 확률(같은 코드가 갈림) |
"Assembly is registered at roughly 5-10 mm of position error" — 에이전트가 이 범위에서 7~8 mm를 골랐고, 낙하만으로 6.5 mm가 되니 통과했다. 실제 채점은 축별 [10, 5, 10] mm(구멍 축 5 mm)라 "낙하 직후는 ~6 mm 위에 걸리며 5 mm 안으로는 나사로만 내려간다"고 써야 한다. 30 trial 전원 세우기·호버(≤2.5°, ≤3.9 mm)까지는 도달하므로 병목은 접촉 단계뿐이다.주의: 재생은 같은 코드·seed 0이지만 물리가 완전히 결정적이지 않아 평가 결과와 다를 수 있다(성공 3/3 재현, 실패 2/27은 재생에서 성공). 원본 TSV: astra_v4_summary_all30.tsv.
최종 숫자는 Astra 4차 3/30 = 0.100 (1·2차 0/30, 3차 0/30은 환경 결함이 만든 값이라 벤치마크 수치가 아니다). 데모 0개·fine-tune 0으로 텍스트 프롬프트와 API 문서만 받은 단일 턴 코드 정책이 pi0.5(demo 수백 개 fine-tune) 0.36 / LingBot 0.133 옆에 놓인다. Astra의 계획·기하 추론은 사람이 짠 oracle보다 나았다(grasp transform 재측정, 손목 회전 최소 자세 선택, z_approach 축 인지) — 그리고 제가 손으로 만든 나사 변형 6종(AA~AD 등)이 전부 실패한 나사 조임을 에이전트 프로그램이 처음으로 성공시켰다.
에이전트가 받은 것 vs 제가 준 것 (귀속). Astra의 입력은 텍스트 8.7 KB 한 번뿐이다 — 시스템 문장 1줄 + 제가 쓴 태스크 지시(~50줄) + 제가 쓴 API docstring. 이미지 없음, 예시 코드 없음, oracle 없음, 피드백 턴 없음; 30 trial은 같은 프롬프트의 독립 샘플(temperature 1)이고 실행 중 GT 자세는 API 호출로 읽는다. 대신 제 지시문에는 4번의 실패를 보고 쓴 전략 힌트가 들어 있다: 밀어 넣지 말고 놓아서 안착 → 재파지 후 누르며 돌리기, 세운 뒤 자세 재측정, 낙하 후 확인·재놓기, 손목 한계 때문에 잡고-놓고-되감기, 접촉 구간은 compliant, 허용오차 "5~10 mm / 20°". API도 답을 상당히 품고 있다: get_target_assembly가 채점 다리를 지목하고, get_assembly_slots가 다리의 최종 목표 자세를 그대로 주며, sample_grasp_pose가 손목 한계 캘리브레이션으로 파지 측을 고른다(이 규칙 하나가 3차 0/30 → 4차 3/30). 즉 0.100은 "Astra 단독"이 아니라 "Astra + 제 프롬프트/API"의 수치다. 에이전트가 스스로 한 것은 그 산문을 기하·코드로 바꾼 부분 — 프레임/쿼터니언 변환, grasp transform 측정, 손목이 아니라 다리 축을 중심으로 회전하는 명령 합성, 되감기 루프, 상태 확인 분기.
CaP-X에서는 프롬프트가 곧 데모다. VLA에 데모 300개가 "나사식"을 가르치듯, 여기선 프롬프트의 한 줄이 그 역할을 한다. 그 한 줄이 빠지면 성공률이 구조적으로 0이 된다 — 그래서 나오는 숫자는 모델 능력만큼 프롬프트 완성도의 함수다.
FurnitureBench one_leg의 난이도는 "삽입"이 아니라 "낙하 안착 확률 + 나사 조임"이다. 정답 정책조차 낙하가 동전 던지기(~45%)이고, 그 뒤 5 사이클의 접촉 제어가 필요하다. 열린 루프 코드 정책이 이걸 풀려면 get_object_pose로 상태를 읽어 재시도하는 폐루프가 필수이며, 그건 code-as-policy가 원래 시험하려는 능력이다.
(해결됨: 나사 실행부 — 에이전트 프로그램이 조립, oracle 3/3.) 남은 병목은 낙하 안착 확률(~45%)과 안착 실패 후 재시도 예산(3000 step) 소진. 이전 기록: 낙하 후 구멍 안·수직을 확인하고 아니면 다시 놓는 폐루프(변형 L/M) + 컴플라이언트 -45° 비틀기. 검증되면 모듈 oracle·프롬프트 반영 완료 상태.
① multi-turn(피드백 포함) 모드에서 Astra 재평가 — 단일 턴은 실행 중 관측을 프롬프트로 되돌려 받지 못한다. ② max_steps 3000→6000으로 재시도 예산 영향 확인. ③ 낙하 안착 확인 후 재놓기를 프롬프트 지침이 아닌 관측 기반으로 에이전트가 짜는지 trial별 코드 분석. ④ gemini-3.1-pro-preview로 같은 config — 논문 기준 모델과 직접 비교. ③ 멀티턴(M1–M4, visual differencing) — VLM_MODELS에 astra 추가 + 카메라 intrinsics/extrinsics 노출 필요. ④ lamp/round_table/cabinet은 등록만 됨, 가구별 프롬프트 필요.
pgrep -f/grep 가드가 자기 셸이나 다른 살아있는 셸의 명령줄 텍스트를 매칭해 교착·자기-kill 4회. 가드는 실제 런칭 줄에만 나타나는 --out-dir …/diag_<name>으로 걸 것.