Index
2026-09-11 — Research / Experiment

FurnitureBench 스크립트 정책 확장 조사 — 4종 FSM 구조 + desk 활성화 시도

FurnitureBench | one_leg v2(0.983 동결) 이후 lamp/round_table/cabinet/desk/stool/chair/drawer 확장 가능성 조사

TL;DR

2종
one_leg 동형(lamp bulb·rt leg)
3종
올려놓기/슬라이드형
0/1
desk 나사 진입 성공
3회
desk 활성화 라운드

1 배경 / 목적

one_leg 스크립트 정책 v2(폐루프, LLM 없음)가 0.47→0.983로 동결된 뒤의 다음 단계는 같은 레시피(다리 끝점 기준 정렬·하강·놓기 판정·나사 사이클 검증·관절각 기반 손목 가드)를 lamp/round_table/cabinet에 적용하고, 스크립트가 아예 없는 desk/stool/chair/drawer에 새 상태기계를 쓰는 것이다. 이를 위해 먼저 furniture-bench/furniture_bench/furniture/parts/의 기존 코드 구조(read-only 조사)를 파악하고, 가장 이식 비용이 싸 보이는 desk부터 실제로 활성화를 시도했다.

기존 상황: one_leg 외 가구는 성공률 측정 자체가 안 돼 있었고(lamp/round_table/cabinet은 stock 스크립트만 존재, desk/stool/chair/drawer는 스크립트 자체가 없음), 어느 가구가 "동형이라 값싸게 이식되는지" vs "신규 상태기계가 필요한지" 판단 근거가 없었다.

2 작업 내용

공통 구조 (환경이 스크립트 정책을 구동하는 방식)

furniture_sim_env.py:1426 get_assembly_action이 should_be_assembled[assemble_idx] 쌍 (part1, part2)를 골라, 상대 자세가 assembled_rel_poses에 맞으면 다음 쌍으로 넘어가고, 아니면 part1.pre_assemble → part2.pre_assemble → 항상 parts[part2].fsm_step(assemble_to=part1.name)를 호출한다. 즉 쌍의 두 번째 부품이 FSM 주체다. 가구별 게이트는 :1433의 화이트리스트 ["one_leg","cabinet","lamp","round_table"] 하나뿐이라, 신규 가구는 이 화이트리스트 해제 + sim_config.py:19 scripted_timeout에 키 추가가 필수 조건이다. 채점 기준은 전역이다: ori_bound=0.94(축별 cos ≈ 20°), 위치 [0.005, 0.005, 0.005](config 기본은 [0.010,0.005,0.010]).

가구별 FSM 분류

가구/부품유형이식 난이도비고
lamp bulb, round_table leg측면 파지→세우기→삽입→−95° 나사 (one_leg 동형)낮음Leg 서브클래스, 상태 이름도 동일. half_width(0.0175/0.01625), grasp_margin_z(0.053/0.03)만 다름.
lamp hood, round_table base, cabinet top올려놓기(+재파지 나사 또는 위치만 판정)중간삽입 대신 "상대 자세 맞춰 놓기" 판정을 새로 써야 함. lamp hood는 기존에 max_gripper_width["cabinet"](0.08)와 비교하는 버그가 있어 lamp(0.07)는 cnt_max=10 시간초과로만 전이됨.
cabinet door슬라이드 삽입, 나사 없음중간목표 [ee−1mm, ee+10mm] 클램프로 진행하는 insert_door(max_len 300) — 진행량 기반 폐루프(끼임 감지·후퇴)가 새로 필요.
deskLeg 상속 가능하지만 다리가 3.8 cm 더 길고 상판이 큼중간→실측 어려움정의만 하면 stock 경로는 돌지만 파지가 빈 손(1차), leg_v2 이식해도 나사 접근에서 손목이 완전히 감김(2·3차) — 아래 §3.
stool, chair, drawer원본 스크립트 없음(plain Part)높음상태기계·pre_assemble·타임아웃·화이트리스트 전부 신규. drawer는 reset() 미정의라 pre_assemble_done=False 상태로 존재하지 않는 pre_assemble을 호출해 즉시 크래시. cabinet도 should_assembled_first[(0,3)] 두 번 대입(:30-31)으로 (0,1)만 남는 버그 발견.

desk 활성화 시도 (3라운드)

1차 (stock 경로): DeskLeg에 grasp_margin_x/z = 0, DeskTableTop에 half_width = 0.1025 정의 + sim_config.scripted_timeout["desk"] = 2400 + env 화이트리스트에 desk 추가. 2차 (leg_v2 이식): Leg 클래스의 운반 높이 리터럴(lift/center/standup/hover/insert)을 클래스 속성화 → DeskLeg가 FURNITURE_SCRIPTED_V2면 LegV2 상속 + 기하(끝 -0.0756, 중심 -0.0131, 상단 +0.0494) 정의. FLIP 실험(파지 시 손을 축으로 180° 회전) 병행. 3차: SCREW_DESCENT_STEP(desk 8mm/step, 다리 축 따라 하강) + APPROACH_GUARDS (접근 전 손목 검사, 하강 감지 즉시 중단, 3회 되감기 실패 시 안전 정지) 추가, 운반 높이는 stock 값으로 롤백(+2cm 유지 시 매번 완전 감김).

메시 AABB 실측으로 확인한 desk vs square_table 다리 형상 차이: desk_leg y ∈ [−0.0756, +0.0494](길이 0.125) vs square_table_leg y ∈ [−0.0562, +0.0312](길이 0.0874) — desk 다리가 3.8 cm 더 길다. 조립 rel y(0.065625) 기준 안착 시 다리 끝이 상판 중심 −0.0100(square −0.0094)으로 규약은 동일.

3 결과 (수치)

라운드변경결과
1차 (stock)grasp margin·half_width 정의만크래시 없이 전 상태기계 진행되지만 첫 파지가 빈손(그리퍼 폭 0.034 → 0.000) → 빈 손으로 삽입·나사 루프 반복 → 실패
2차 (leg_v2 이식)운반 높이 클래스 속성화, LEG_TOP_LOCAL 파라미터화seed 100: 첫 다리 파지·운반·삽입·안착(3.0°) 성공 → 그러나 세우기 후 손목이 완전히 감김(q5 −2.75, q6 3.22, q7 2.90=한계 3.7525/2.897 근접)이라 top-down 나사 파지 접근 불가. 되감기 3종(40° 기울여 유지 / 멀리서 수직 / 60° 기울임) 모두 이어지는 수직 명령이 즉시 다시 감음
2차 FLIP (파지 시 180° 회전)q7≈−2.1에서 출발해 한계와 반대쪽에서 시작one_leg seed 700~702는 3/3 성공(553~721 step)했지만, desk seed 100은 첫 다리 3.1° 안착 후 나사 5사이클에 높이 +4.5mm 정체(미판정) → 두 번째 다리 세우기가 반대 방향으로 감겨(q5 +1.63, q7 +2.47 한계 고정) 접근 자체 불가 → 다리 쳐냄. 분포를 옮길 뿐 근본 해결 아님
3차 (가드+운반높이 롤백)SCREW_DESCENT_STEP, APPROACH_GUARDS 추가세우기 후 손목 부분 감김(q5 −1.07, q7 1.57)으로 완화, 다리는 3~16°로 안착 재현. 그러나 나사 접근(다리 상단 +1.9cm 수직 툴)에서 팔이 14 cm 아래로 내려앉으며 다리를 쳐냄(q6 3.5~3.7, 한계 3.75 근접). 되감기 3종 재시도 → 앞으로 40°만 q5 −2.5→−1.0으로 일부 풀리나 q6 3.7에 남고 이어지는 수직 명령이 즉시 재감김 → 0/1
확인된 사실: lamp bulb·round_table leg는 구조가 one_leg와 완전히 동일(Leg 서브클래스, 동일 상태 이름) — 별도 조사 없이 LegV2를 부품 파라미터화(끝점 로컬 좌표, half_width, 앵커 축/구멍 오프셋)해 바로 이식 가능한 후보로 확정.
미해결: desk는 3라운드 시도(파라미터 정의 → leg_v2 이식 → 운반높이 롤백+가드) 전부 나사 사이클 진입에 실패했다. 가설: desk 상판이 크고(21×15 cm) 구멍이 중심에서 ±0.08/±0.05로 멀어, 어떤 손목 경로를 택해도 나사 접근 자세가 손목 한계(q6≈3.5+, one_leg는 2.6)에 걸린다. "바로 되나"라는 사용자 요청에는 아니오로 답이 확정됐다.

4 Takeaway

의미

이번 조사로 "one_leg에서 만든 폐루프 레시피가 얼마나 재사용 가능한가"에 대한 명확한 지도를 얻었다. lamp bulb·round_table leg는 사실상 무료 이식(구조 100% 동일, 파라미터만 교체)이라 다음 실험으로 바로 넘어갈 수 있다. 반면 desk는 겉보기엔 가장 싸 보였지만(Leg 상속) 실제로는 상판 크기·구멍 위치라는 구조적 차이가 손목 특이점 회피 전략 자체를 무력화시켰다 — one_leg에서 통했던 "감긴 채로도 안전한 경로" 전략이 desk에서는 통하지 않는다는 것이 3라운드 실측으로 확인됐다. lamp hood/round_table base/cabinet top(올려놓기형)과 cabinet door(슬라이드형)는 처음부터 별도 판정 로직이 필요함이 코드 레벨에서 확정됐고, stool/chair/drawer는 신규 상태기계가 불가피해 우선순위가 가장 낮다.

5 Next Steps

미해결 한계

desk 나사 접근 자세가 손목 한계에 걸리는 근본 원인이 파라미터가 아니라 구멍-베이스 간 거리로 추정되지만 아직 검증되지 않았다. 3라운드 모두 "첫 다리 안착까지는 재현 가능, 나사 사이클 진입 불가"로 수렴 — 추가 반복 없이는 desk는 미지원 상태로 유지된다.

다음 실험

1) one_leg v2d 30ep 결과 확정 후 LegV2를 부품 파라미터화(PART_BOTTOM_LOCAL, half_width, 앵커 부품 축/구멍 오프셋)해 lamp bulb, round_table leg에 적용 → 각 30ep 측정(비용 낮음, 우선순위 최상).
2) desk는 세 가지 미시도 해법 중 하나를 실험: (a) stock의 상판 밀기(장애물 모서리로 → 베이스에 가깝게)를 desk에서도 유지, (b) assembled_rel_poses가 4모서리를 모두 허용하므로 다리마다 베이스에 가장 가까운 빈 구멍을 동적으로 선택, (c) 먼 구멍은 다리를 잡은 채 상판을 끌어오는 별도 기술. 각각 최소 1회 반복 필요 — "바로"는 아니라는 결론 재확인 후 진행.
3) 데모 수집(collect_scripted.sh)에 FURNITURE_SCRIPTED_V2=1 적용은 lamp/round_table 이식 완료 후 병행.