Index
2026-08-13 — Engineering Reference

Online 2-Stage 파이프라인 — 모델 I/O 명세 & 실측 예시

scene_bench | High-level VLM (Letsur gemini-3.6-flash) + Low-level VLA (π0.5-FT) | T1·T2·T3 게이트 통과 후, T4 진입 전 레퍼런스

TL;DR

2
Models
3+1
T3 Decisions
900
Steps/Subgoal
$0.131
Episode Cost

1 전체 루프 — 한 턴의 데이터 흐름

Sim (MuJoCo)
exo 렌더 + 인벤토리
VLM Planner
gemini-3.6-flash
Subgoal JSON
검증+task 생성
π0.5-FT VLA
ws://8080, 15Hz
Sim 실행
success/timeout
↪ outcome을 다음 VLM 턴으로

VLM은 subgoal 하나만 발행하고, 완료 판정(성공 술어 or 스텝 예산 소진)이 나면 결과가 다음 VLM 턴의 입력이 된다. 대화(conversation)가 상태로 유지되므로 메모리 context 주입·추가 지시(multi-turn)는 user 턴 append만으로 확장된다.

2 Model 1 — High-level VLM Planner gemini-3.6-flash @ Letsur

INPUT ① — System 프롬프트 (에피소드당 1회, 고정)

You are the task planner of a household robot in a simulator. Each turn you receive: the current scene image, an object inventory, and the outcome context of the previous subgoal. Decide exactly ONE next subgoal. Skills: - pick(object_id): grasp and lift the object - pick_and_place(object_id, receptacle_id): one atomic unit — you cannot split pick and place into separate subgoals - open/close: DISABLED (이 로봇의 학습 데이터에 없음 — 선택 금지) - done: the user instruction is fully satisfied - abort: impossible to proceed (explain in reasoning) Rules: - Refer to objects ONLY by the exact id in [brackets] from the inventory. - Output a single JSON object, nothing else: {"reasoning": "...", "skill": "...", "object_id": "...", "receptacle_id": "..."}

INPUT ② — 턴마다 들어가는 user 메시지 (T3 k=1 실측 재구성)

파트내용비고
1. 씬 이미지exo_camera_1 렌더 1장, 624×352 JPEG(q85) base64env.render_rgb_frame() — 시뮬 스텝 소모 없음
2. 인벤토리[id] category — room (x, y, z) 줄 목록VLM은 이 id로만 지칭 가능 (자유 텍스트 금지)
3. 직전 결과Previous subgoal outcome: timed_out after 900 stepsoracle 모드만. vlm 모드는 이미지 자가판정 지시로 대체
4. InstructionUser instruction: put the mug on the dining table첫 턴만
VLM 입력 씬 이미지 (T3 subgoal 0 시작)
VLM이 실제로 받는 씬 이미지 (T3 subgoal 0 시작 프레임, exo_camera_1 624×352)
Current object inventory: (house 0 실측 — 총 133줄 중 발췌) [diningtable_f113cf7f8367e89f709b53cbee1a1c05_1_0_2] DiningTable — room_2 (5.9, 6.8, 0.4) [diningtable_f113cf7f8367e89f709b53cbee1a1c05_2_0_3] DiningTable — room_3 (3.0, 5.2, 0.4) [diningtable_15d4d7c88896632c7f36ae642a41eb46_1_0_4] DiningTable — room_4 (3.9, 2.7, 0.5) [mug_3ebc45568ed53a18c8797978b3744a99_1_0_6] Mug — room_6 (11.2, 8.3, 0.3) [mug_8caf1bb3f88e9a00e02dfe9e6518aeb0_1_0_7] Mug — room_7 (15.0, 8.4, 0.8) [cup_4697b73732349085e30935e0f35566dc_1_0_2] Cup — room_2 (5.3, 6.9, 0.8) [microwaveoven_5eaaa6bcab9a252c76d99abaec4c196a_1_0_2] Microwave — room_2 (5.7, 6.5, 1.0) [chair_0ac9b0b021ef299afd8f5636f317ad41_1_0_2] Chair — room_2 (5.0, 6.8, 0.4) …
house 0 실측 전문의 발췌 (133개 객체). [id]=시뮬 body name(=task 생성·성공판정의 유일키), category=에셋 주석, room=infer_room_name 추정, 좌표=월드(m). 구조물(벽/바닥)은 제외
카메라 한계 (실측 확인): 위 이미지는 로봇 베이스 장착 DROID식 카메라(fov 71°)의 작업공간 클로즈업이다 — 씬 오버뷰가 아니며, 팔은 시야에 들어올 때만 보인다. house 0에서 로봇은 침실(협탁 앞)에 있고 mug(room_6)·테이블(room_2~4)은 전부 시야 밖 → VLM의 전역 공간 인지는 사실상 인벤토리 텍스트가 담당한다. 후속: planner 전용 오버뷰 카메라 옵션 + 도달권 내 타깃으로 데모 instruction 교체 (navigation/N0 텔레포트가 붙기 전까지의 제약).

OUTPUT — JSON 1개 (T3 실측 원문 4건)

k=0 {"reasoning": "The user wants to place a mug on the dining table. I will pick up mug_3ebc...4a99_1_0_6 and place it on diningtable_f113...1c05_1_0_2.", "skill": "pick_and_place", "object_id": "mug_3ebc45568ed53a18c8797978b3744a99_1_0_6", "receptacle_id": "diningtable_f113cf7f8367e89f709b53cbee1a1c05_1_0_2"} → 실행: 900스텝 timeout k=1 {"reasoning": "The previous attempt timed out while trying to reach the dining table in room_2. I will try placing the mug on the dining table in room_3 instead.", ...} → 같은 머그, 다른 테이블로 전환. 900스텝 timeout k=2 {"reasoning": "Both dining tables in room_2 and room_3 timed out. I will try placing the mug on the dining table in room_4 instead.", ...} → 세 번째 테이블. 900스텝 timeout k=3 {"reasoning": "All attempts to place the mug onto the available dining tables timed out due to navigation or execution failure. Aborting the task.", "skill": "abort", ...} → 에피소드 종료 (final="abort")
확인된 것: VLM이 직전 outcome을 정확히 인용하며 전략을 바꾼다(재시도 → 테이블 전환 → abort). 모든 id가 인벤토리 실존 id — 환각 지칭 0건 (T2/T3 합계 8 결정).

검증 & 재질의 규칙

체크실패 시
JSON 파싱 (raw → 코드펜스 → brace-balance 순 시도)실패 사유를 붙여 재질의 1회:
"Your output was invalid: <err>. Reply with ONLY the corrected JSON object."
2회 연속 실패 → 자동 abort
스키마 (skill enum, pick 계열은 object_id 필수, pnp는 receptacle_id 필수)
id가 인벤토리 valid set에 실존하는가
호출 시점
subgoal 경계만
에피소드당 호출
4~7회
비용 실측 (T3)
$0.1309 / 5 call
게이트웨이
gw.letsur.ai/v1

3 Model 2 — Low-level VLA π0.5-FT franka_2cam_15k/14999

DROID-base π0.5를 MolmoSpaces Franka 데이터로 15k step 파인튜닝한 체크포인트 (SigLIP frozen). openpi websocket 서버(--port 8080)로 서빙, 시뮬 쪽 PI_Policy가 무수정 클라이언트.

INPUT — 추론 1회당 (msgpack over websocket)

형태내용
observation/exterior_image_1_leftuint8 224×224×3exo_camera_1 624×352를 letterbox(비율 유지 + 상하 검은띠 49px) 리사이즈
observation/wrist_image_leftuint8 224×224×3wrist_camera 동일 letterbox
observation/joint_positionfloat (7,)절대 관절각 (rad)
observation/gripper_positionfloat (1,)0(열림)~1, qpos/0.824033 정규화
promptstr정책 프롬프트 — 아래 5 템플릿만 (T3 실측: pick up the mug and place it on the table.)
VLA exterior 입력 예시
VLA의 exterior 입력 원본 예시 (T3 subgoal 2 마지막 프레임, letterbox 전 624×352). wrist 뷰는 손목 장착 카메라로 동일 처리

정책 프롬프트 — 학습 분포와 바이트 일치 (소문자+마침표)

skill템플릿비고
pickpick up the {name}.학습 커버리지 있음 (bench 평균 SR 36%)
pick_and_placepick up the {name} and place it on the {name2}.
open / closeopen the {name}. / close the {name}.Franka 학습 데이터 0% → 기본 비활성
packingpack container.미사용
주의: {name}은 VLM의 객체 id가 아니라 ObjectMeta.short_descriptions 경로로 렌더된 자연어 명칭("mug", "table")이다. 이 5 템플릿 밖의 문구는 OOD로 최대 14% 성능 손실(논문 Fig.13) — 그래서 VLM 출력은 구조화 JSON으로 받고 정책 프롬프트는 규칙으로 렌더한다.

OUTPUT — action chunk

actions: float (15, 8) # horizon 15 [:, 0:7] → 절대 관절 타깃 (rad) # 변환 없이 그대로 arm 명령 [:, 7] → 그리퍼 (이진화: >0.5 → 닫힘 255, else 0) 소비 규칙: 앞 8스텝만 실행 후 재추론 (chunk_size=8), 15Hz (policy_dt 66ms)
체크포인트
14999 step
추론 GPU
B200 1장 (~12GB)
Embodiment
Franka FR3 고정베이스
Zero-shot → FT
SR 10% → 36%

4 Subgoal 완료 판정 (VLA → VLM 복귀 조건)

모드판정 주체VLM에 주는 정보용도
oracle (기본)시뮬 물리 술어: pick=들림+로봇단독접촉 / pnp=receptacle 지지 / open,close=관절 비율. + 스텝 예산(pnp 900) 소진 시 timeoutsucceeded | timed_out after N steps벤치 측정 — done 노이즈가 메모리 신호에 안 섞임 (공리 A3)
vlmVLM이 새 이미지 보고 자가판정 (oracle 결과 비공개, timeout은 안전망)자가판정 지시문만실전 근사 / oracle ablation
polling (예약)MemER식 N스텝 주기 폴링필요 시 추가 (호출 5~7배)
중요: 성공 술어는 dataset 주석이 아니라 task 클래스 내장 물리 체크라 VLM이 씬의 임의 객체 조합을 골라도 자동 바인딩된다. 새 술어가 필요한 스킬은 TOGGLE 하나(예정)뿐.

5 T3 실측 에피소드 타임라인 (풀스택 증거)

kVLM 결정정책 프롬프트결과
0pnp: mug → DiningTable(room_2)pick up the mug and place it on the table.timeout 900
1pnp: 같은 mug → DiningTable(room_3) 전략 변경timeout 900
2pnp: 같은 mug → DiningTable(room_4) 전략 변경timeout 900
3abort: "All attempts ... timed out. Aborting."final=abort
subgoal 0 시작
subgoal 0 시작
subgoal 0 종료
subgoal 0 종료 (900스텝 후) — 팔이 움직였고(프레임간 diff가 flatline 없음) 물리 상태가 다음 subgoal로 이어짐
π0.5 물리 실패의 진짜 원인 (실측 좌표로 확정): 로봇은 침실 협탁 앞에 스폰됐고 mug는 room_6 (11.2, 8.3), 테이블들은 room_2~4 — 고정베이스 Franka에게 기하학적으로 불가능한 태스크였다. 3×900스텝 timeout → abort는 이 상황에서 시스템이 낼 수 있는 최선의 궤적. 게이트 기준은 메커니즘(전환/피드백/기록)이라 전부 통과. 물리 성공 데모는 도달권 내 타깃(협탁 위 물체)으로 T4에서 교체.
벤치 설계 인사이트 (T2에서 관측): 이미 receptacle 위에 있는 물체를 고르면 1스텝 만에 성공 처리 — 설계 공리의 "instant-success hazard"가 실측으로 확인됨. 에피소드 생성 시 이미-충족 타깃 배제 필수.

6 Takeaway & Next

의미

"online으로 API가 명령을 줘가며 제어 가능한가"에 대한 답은 실측 YES. VLM↔VLA 사이의 모든 계약(입출력 형식·검증·재질의·완료판정)이 위 표대로 고정됐고, 다른 세션은 VlmPlanner의 conversation에 [메모리 context 턴 / 추가 instruction 턴]만 꽂으면 된다.

남은 게이트

T4: 같은 데모를 sbm worker job으로 (worker egress는 사전 실측 완료, EGL만 검증 필요). retract-home 구현 진행 중 (팔이 실패 자세를 물려받는 문제 — T3 실측으로 필요성 확정).

알려진 한계

open/close는 Franka 학습 데이터 0%로 비활성. navigation은 고정베이스라 부재 — 벤치마크의 N0 텔레포트 설계로 해결 예정. done 판정 oracle은 시뮬 전용(실로봇 이전 시 vlm 모드/학습 detector로 교체).