Sim Env Builder은(는) 무엇을 하나요?
목표: 하나의 설명으로부터, 가능한 적은 사용자 턴(이상적으로: 요청 -> 한 번의 확인 -> 완료)으로 작동하고, 물리적으로 타당하며, 보기 좋은 시뮬레이션 환경을 제공합니다. 품질 기준: 모든 스모크 테스트를 통과해야 하며, 렌더링 결과를 직접 확인하여 요청 사항과 일치하는지 확인해야 합니다.
SKILL_DIR 아래 = 이 파일의 디렉토리. Python 헬퍼는 SKILL_DIR/scripts/simkit에 있습니다.
Phase 0 - 설정 (1분)
PY=$(bash SKILL_DIR/scripts/setup_env.sh) # python with mujoco, trimesh, usd-core, gymnasium
$PY SKILL_DIR/scripts/check_platform.py # OS, GPU, Isaac 가용성 확인
환경 폴더 선택: 사용자가 지정하지 않은 경우 현재 디렉토리에 ./<짧은_뱀_이름>/을 생성합니다.
Phase 1 - 백엔드 선택 (reference/backend_choice.md 참조)
Isaac Sim은 NVIDIA RTX GPU가 장착된 Linux/Windows가 필요합니다. MuJoCo는 어디서나 실행됩니다.
- MuJoCo: 기본값. 접촉이 많은 조작 및 보행, 빠른 반복, CPU/노트북/macOS, 소형-중형 장면, 모델 기반 제어, 재현 가능한 연구, MJX/Warp를 통한 GPU RL에 적합합니다.
- Isaac Sim: 사실적인 RTX 렌더링 또는 합성 데이터(Replicator), RTX 라이다/카메라 센서 현실감, Isaac Lab에서 수천 개의 병렬 환경, 대규모 USD/Omniverse 장면, 사용자가 이미 Isaac을 사용 중인 경우에 적합합니다.
- Isaac이 더 적합하지만
isaac_runnable_here가 false인 경우, 확인 메시지에 그 사실을 명시하고 다음을 제안합니다: 여기 MuJoCo에서 빌드 + 완전히 테스트하고, USD 스테이지와 Isaac 스모크 스크립트를 GPU 머신용으로 내보내기(reference/isaac.md 참조). 실제로 실행하지 않은 Isaac 결과를 주장하지 마십시오.
Phase 2 - 빌드 전 사용자 확인 (reference/confirmation.md 참조)
- 먼저 빠른 에셋 스캔을 수행하여 브리프를 구체화합니다:
find_assets호출 한 번(Poly Pizza MCP)으로 각 객체 역할에 대해 1-3개의 쿼리를 실행합니다. - 하나의 짧은 브리프(reference/confirmation.md 템플릿)를 보냅니다: 백엔드 및 이유, 장면에 포함될 내용, 로봇/에이전트 및 제어 인터페이스, Poly Pizza vs 절차적 생성에서 가져올 에셋, 주요 물리 속성(중력, 마찰, 시간 간격), 결과물, 그리고 각각 권장 기본값이 포함된 2-4개의 질문.
- AskUserQuestion 도구가 있으면 사용하여 질문합니다. 그렇지 않으면 브리프를 메시지로 전달하고 사용자 응답을 기다립니다. 사용자가 응답하기 전에 빌드하지 마십시오. 예외: 사용자가 묻지 말라고 하거나 "그냥 빌드해"라고 한 경우 -> 가정을 SPEC.md에 기록하고 진행합니다.
- 확인된 결정을
<env>/SPEC.md에 기록합니다(reference/confirmation.md 템플릿).
Phase 3 - 에셋: Poly Pizza 우선, 절차적 생성 대체 (reference/assets.md 참조)
각 객체 역할에 대해:
find_assets/search_models-> 결과 확인(발견됨 / 부족함 / 없음).- 발견됨 또는 부족함 ->
preview_models([...ids])직접 확인: 올바른 객체인가? 스타일 일관성? 사실적인 장면에서 장난감, 만화 스타일, 다중 객체 번들, 잘못된 크기 등급은 거부합니다. - 수락됨 ->
download_model(id, "<abs env path>/assets/polypizza", "<role>")(크레딧은assets/polypizza/CREDITS.md에 자동 기록됨). - 없음, 거부됨 또는 다운로드 오류 -> 절차적 생성:
simkit.procedural레시피(나무, 건물, 가구, 거리 소품, 문, 식기류, 지형...)를 사용하거나 기본 요소 /lathe/extrude/rock으로 직접 구성합니다. 요청된 객체를 절대 빠뜨리지 마십시오. <env>/assets/ASSETS.md작성: 역할 | 출처(Poly Pizza ID + 제목 + 라이선스, 또는 절차적 생성 레시피) | 실제 크기 | 이유. 모델 제목이 역할과 다른 경우("Park Bench"를 피크닉 테이블로 사용한 경우), 그 이유와 여전히 적합한 이유를 명시하거나 다시 검색/절차적 생성합니다. 또한 거부된 후보(ID + 이유: "만화 스타일", "12개 객체 번들")를 나열하여 모든 것이 절차적 생성으로 처리되더라도 검색 내역을 추적 가능하게 합니다. Poly Pizza 모델은 정적 메시입니다: 관절 로봇과 차량은simkit.robots에서 가져옵니다(Poly Pizza 메시를 시각적 기하 형상으로 스킨할 수 있음).
Phase 4 - 빌드 (reference/robots.md, templates/ 참조)
mkdir -p <env> && cp -r SKILL_DIR/scripts/simkit <env>/simkit # vendored: env is self-contained
cp SKILL_DIR/templates/build_env.py SKILL_DIR/templates/env.py SKILL_DIR/templates/view.py <env>/ # 처음 두 개는 편집
build_env.py: 모든 것을 결정론적으로(시드 고정) 재생성 ->scene.xml.simkit.scene.Scene(하늘, 바닥, 조명, 시점 카메라, raw MJCF 섹션),simkit.assets.glb_to_mujoco(glb, env, name, target={"height": m}, yaw_deg=..)(Poly Pizza 모델 처리: 실제 크기, Z-up, 색상별 파트, box/hull/parts 충돌),simkit.procedural(대체 및 지형),simkit.robots(테스트된 로봇: 쿼드로터, 자동차, 차동 구동, 암 + 그리퍼, 사족 보행) 및 해당 컨트롤러를 사용합니다.- 실제 세계 스케일은 필수입니다(reference/assets.md 크기 표 참조). 객체는 지지면 위에 놓입니다.
- 사용자가 지정한 모든 객체 클래스는 개요에서 읽을 수 있는 크기로 명확하게 보여야 합니다("바위 투성이 길"에는 눈에 띄는 바위가 있어야 하며 7cm 알갱이가 아니어야 함; "험준한 지형"에는 로봇 스케일에서 보이는 요철이 있어야 함). 스모크 테스트는
hints아래에 작은 객체를 나열합니다. - 최소 2개의 명명된 카메라: 개요 카메라와 대상(로봇/작업 객체가 프레임의 약 30-50%를 채움)에 초점을 맞춘 카메라; 로봇 장착 카메라(있는 경우). 고정 센서 카메라는 로봇의 초기 자세에 의해 가려지면 안 됩니다(스모크가 15% 이상 가려짐 플래그).
world.py(장면에 자체 동역학이 있는 경우):make_world(model)->world(model, data), 스모크, 검사자, 쇼케이스, env.py, view.py 및 대시보드에서 모든 물리 단계 전에 호출됩니다. 부력/항력, 바람, 컨베이어, 신호등 주기, 스크립트된 보행자 및 NPC 차량은 여기에 위치하며,controller.py내부에는 절대 위치하지 않습니다(수동 테스트나 RL 정책은 보트가 가라앉고 조명이 절대 변하지 않는 세계를 실행하게 됩니다). 작업 검사도 이 함수를 호출해야 합니다.controller.py: 스크립트된 데모 정책(make_controller(model)->ctrl(model, data))으로 환경이 제 역할을 수행하는 것을 보여줍니다(드론이 게이트를 통과, 자동차가 경로를 주행, 암이 객체에 도달...). 모듈 수준에서DEMO_SECONDS = <전체 데모 길이>를 설정합니다: 스모크 테스트는 전체 데모(집기, 들어올리기, 놓기 / 모든 게이트)를 촬영하고 확인하며, 처음 4초만 확인하지 않습니다.task_checks.py: 함수check_<name>(model, data) -> {"status", "value", "expect", "details"}형태로 작업 수준의 물리 검사를 정의합니다. 사용자가 명시했거나 확인한 각 성공 기준에 대해 하나의 검사(이름은 사용자의 말을 따름: "feet in contact" ->check_feet_in_contact), 그리고 생성 상태 검사(로봇이 지지면 위에서 시작)를 포함합니다. 최소 2개. 첫 번째 실행 전에 임계값과 각 지표의 정확한 정의(기준점, 단위: "로버 베이스 중심에서 착륙선 중심까지, 미터")를 SPEC.md에 기록하고 유지합니다: 근소한 차이는 컨트롤러/장면을 수정하는 의미이므로 검사를 완화하지 마십시오(임계값 변경은 "확인된 계획의 변경 사항" 아래에 표시되어야 함). 제한의 15% 이내로 통과하는 검사는 여유를 보고합니다("기울기 25.8도 vs 30도 제한"). 주장하는 모든 동작(장애물 감속, 신호등 주기, 부력, 그리퍼 유지)은 이를 실행하는 검사가 필요합니다(예: 경로에 장애물을 배치하고 로봇이 정지하는지 확인). 장면의 모든 주요 물리 속성은 물리적 목표가 있는 측정 검사를 받습니다: 공의 구름 감속, 보트의 흘수선, 로버의 경사 오르기, 저중력 낙하 시간, 그리퍼 유지력. 필수 센서도 검사합니다: 데모 중 로봇 카메라를 렌더링하고 작업을 보여주는(예: 앞쪽 나무 줄) 비어 있지 않은 이미지를 확인합니다. 라이다의 경우, 합리적인 범위를 확인합니다. 각 작업 검사를 스크립트된 롤아웃과 2-3개의 변형된(다른 시드, 시작 자세, 초기 속도, 조명 위상) 경우에 대해 실행합니다 - 단 하나의 정확한 롤아웃에만 유효한 검사는 증명력이 거의 없습니다. 파지 검사는 들어올리기 및 운반 중에 두 핑거 패드와 객체 사이의 접촉을 요구하며(data.contact확인), 단순히 "객체가 올라갔다"가 아닙니다.- 충돌체: 단순하고 정직합니다. 나무: 줄기 충돌체, 캐노피는 시각적 전용(사용자가 캐노피 충돌을 원하는 경우 제외). 멀티로터: 팔 캡슐 또는 단일 덩어리, 프로펠러를 삼키는 하나의 박스가 아닙니다. 볼록하지 않은 소품(현미경, 의자, 아치, 선반)은
collision="parts"또는 몇 개의 기본 요소를 사용합니다. 하나의 볼록 껍질은 시각적으로 비어 있는 공간을 차단합니다(collision_sheet.png 확인). env.py: Gymnasium 스타일의reset/step/render인터페이스로 작업 관찰, 보상 스텁, 종료 조건을 포함합니다.__main__자체 테스트는 데모 컨트롤러(또는 참조 정책)를 사용하여 env API를 통해 환경을 구동하고 작업 목표에 도달했는지 출력합니다 - 목표에 도달 가능함을 증명합니다.- 디버그/카메라 리그 본체 및 마커: geom 그룹 4-5(절대 렌더링되지 않음), 데이터 카메라에 포함되지 않음.
- 매달린 물체(천장 조명, 걸린 표지판, 벽 선반):
mounted_*또는hanging_*으로 명명하여 부유 객체 검사에서 건너뛰도록 합니다. - 조명: 중성 흰색(색조가 없는 조명); 최대 2-3개의 추가 조명; 흰색 벽이 렌더링에서 흰색-회색으로 유지되는지 확인합니다.
- 장면을 올바르게 읽는 데 필요한 것 이상의 요청되지 않은 장식은 추가하지 않습니다. 선택적 추가 사항은 브리프에 나열하여 사용자가 선택할 수 있게 합니다.
- 시간 제한: 빌드를 시작할 때 시간을 기록합니다(
date). 추가/확장 항목("접기는 추가 항목")은 필수 항목이 모두 통과한 후에만 시도하며, 가장 먼저 제외됩니다. 빌드 시작 후 약 60분이 지나면 남은 항목 튜닝을 중단하고 REPORT.md와 README 결과를 최종 확정하고 보고합니다(제외된 항목 나열). 결과를 보고하지 않는 빌드는 알려진 격차가 있는 빌드보다 나쁩니다. - 예산: 모든 필수 항목이 존재하고 모든 검사가 통과되면 추가 항목을 중단하고 - 시각적 검사, README 및 보고서를 마무리합니다. 추가 아이디어는 README에 기재합니다.
- 모든 변경 후
$PY build_env.py를 실행합니다. 컴파일 오류는 줄 번호를 포함합니다.
Phase 5 - 스모크 테스트 (reference/smoke_tests.md 참조). 세 가지 모두 필요합니다.
cd <env> && $PY -m simkit.smoke scene.xml --out smoke --controller controller.py --task-checks task_checks.py
- 렌더 테스트 - 모든 명명된 카메라 + 자동 뷰가 비어 있지 않고, 조명이 잘 들어오며, 상세한 프레임을 렌더링합니다. 세분화는 어떤 객체가 보이는지 보여줍니다(보이지 않는 객체는 플래그 지정됨).
- 물리 검사자 - 장면 자체 설정을 사용한 솔버/접촉/마찰/중력 프로브, 롤아웃 안정성, 관통, 낙하, 안정화, 액추에이터 단계 응답, 결정론, 시간 간격 민감도, 실시간 계수, 레이아웃(부유/침강/상호 관통 소품) 및 작업 검사.
- 시각적 검사 - 직접
smoke/contact_sheet.png,smoke/filmstrip.png,smoke/collision_sheet.png및smoke/renders/의 클로즈업을 열어보고(읽기 도구 사용), 그런 다음smoke/visual_check.md에 구체적인 관찰 결과를 채워 넣습니다. 모든 FAIL을 수정합니다. 모든 WARN을 조사합니다(수정하거나, README에서 예상된 이유 설명). 결과가 PASS / PASS_WITH_WARNINGS(설명됨)이고 시각적 검사가 정직하게 모두 "예"가 될 때까지 다시 빌드하고 다시 실행합니다. 2-3회 반복을 예상하십시오. 첫 번째 렌더링은 거의 정확하지 않습니다. 또한$PY env.py를 실행합니다(무작위 행동, 유한 관찰).
Phase 6 - Isaac Sim 결과물 (Isaac이 선택된 경우에만; reference/isaac.md 참조)
$PY -m simkit.usd_export scene.xml isaac/scene.usda (내보내기 + 로컬 검증), SKILL_DIR/templates/isaac_smoke.py를 isaac/로 복사하고, GPU 머신에서 실행하는 방법을 문서화합니다.
실행된 것과 실행되지 않은 것을 명확히 명시합니다.
Phase 7 - 전달
<env>/README.md: 장면에 포함된 내용, 실행 방법(빌드, 스모크, env, 뷰어: $PY view.py는 데모 컨트롤러를 실시간으로 실행합니다; 일반 mujoco.viewer는 수동 물리만 표시함), 카메라, 액추에이터, 컨트롤러, 작업 검사, 에셋 크레딧, 알려진 제한 사항. 사용자에게 보내는 최종 메시지: 결과 한 줄, 빌드된 내용, Poly Pizza vs 절차적 생성에서 가져온 에셋, 스모크 결과, smoke/showcase.mp4 (사람들이 시청하는 비디오), contact_sheet 및 filmstrip 경로, 완료되지 않았거나 확인되지 않은 모든 것, 그리고 "확인된 계획의 변경 사항" 목록(에셋 또는 라이선스 교체, 크기/개수 변경, 추가 항목 제외) - 변경 사항이 없으면 비어 있지만 항상 포함됩니다. smoke/smoke_report.json 및 physics_report.json에서 모든 숫자(통과한 검사, 점수, 오류)를 복사하고, summary_line을 있는 그대로 붙여넣습니다("Smoke PASS: examiner 19 pass / 0 warn / 0 fail; task checks 9/9 pass; render ok"). 절대 기억에서 개수를 작성하지 마십시오.
첫 번째 스모크 실행이 완료되는 즉시 <env>/REPORT.md를 시작하고 각 수정 후 업데이트하여 중단된 세션에도 보고서가 남도록 합니다. 최종 메시지는 마지막 버전입니다.
결과물 레이아웃 (정확히 유지; 도구와 대시보드가 이에 의존함)
<env>/
SPEC.md README.md REPORT.md build_env.py scene.xml env.py view.py controller.py task_checks.py
world.py (장면에 자체 동역학이 있는 경우에만)
simkit/ vendored helpers
assets/polypizza/*.glb assets/polypizza/CREDITS.md assets/polypizza/polypizza_assets.json
assets/meshes/ assets/procedural/ assets/ASSETS.md
smoke/ (showcase.mp4 contact_sheet.png filmstrip.png collision_sheet.png renders/ rollout.mp4
physics_report.json render_report.json smoke_report.json env_manifest.json
SMOKE.md visual_check.md)
isaac/ (Isaac인 경우에만: scene.usda, isaac_smoke.py, README section)
경험상의 규칙 (각각은 실제 빌드를 망가뜨린 적이 있습니다)
- 확인된 범위 내에 머무릅니다. 데모는 사용자가 동의한 내용을 보여줍니다(예: "서 있는 것으로 충분하다"는 안정적인 서기이지, 새로운 보행 컨트롤러가 아님). 장면, 에셋, 검사 및 시각적 검토에 시간을 사용하고, 확장 아이디어는 README에 나열합니다.
<visual>설정:sc.set_visual("map", znear=.., zfar=..)등. 각 요소는 한 번만 나타날 수 있습니다.- camera
xyaxes를 수동으로 계산하지 마십시오:Scene.camera(name, pos, target)/simkit.scene.lookat을 사용합니다. - 키프레임 qpos 목록을 수동으로 작성하지 마십시오:
scene.home[joint] = value를 설정합니다(로봇이 자동으로 수행).Scene.write는 조인트 이름으로home키프레임을 작성하고 일치하도록 position-actuator ctrl을 설정합니다. - 평평한/얇은 메시는
inertia="shell"이 필요합니다(glb_to_mujoco가 처리). 시각적 기하 형상:contype=0 conaffinity=0 group=2 mass=0; 충돌 프록시는 group 3. - 세계에 용접된 로봇은 자체 베이스와 충돌합니다: 베이스/첫 번째 링크에
<exclude>를 추가합니다. - Position-actuator
@forcelimited/@forcerange및@ctrlrange를 설정합니다(기본값은 무제한, 드론이 달아날 수 있음). - assetdir:
dir=의 절대 경로가 필요합니다(편집기 재시작/다른 CWD 후 깨짐 방지).simkit.scene.Scene이 이를 처리합니다. - 점-질량 기하 형상은 충돌에 참여하지 않습니다: 실제 객체에는
pos="0 0 0" mass="..."점-질량 대신simkit.assets.box또는sphere를 사용합니다. - Python 스크립트에서
cd <env>를 상대 경로 앞에 사용하거나, 절대 경로를 사용합니다. - 검사자가 렌더링하기 전에
controller.py와world.py가make_controller(model),make_world(model)을 내보내는지 확인합니다(모듈 최상위 수준에서 조건부 임포트 허용). - 큰 고도 변화가 있는 지형을 위한 바닥:
size="100 100 0.1" pos="0 0 -2"대신simkit.procedural.terrain을 사용합니다. - 이미 있는 파일을 다시 쓰기 전에 사용자에게 물어봅니다. 실수로 작업을 덮어쓰지 마십시오.
- 절대
SKILL_DIR아래의 파일을 수정하지 마십시오. 모든 생성된 파일은<env>/아래에 있습니다. @tendon,@sensor,@wrap객체는sceneXML 트리의<worldbody>외부에 있어야 합니다. Worldbody 요소로 오인하지 마십시오.default클래스<geom .../>에group을 설정하지 마십시오(모든 기본값 상속 geom의 그룹을 재정의함). 각 geom에group을 명시적으로 설정합니다.
중요: 스킬 디렉토리 참조
이 스킬에 대한 문서, 도움말 및 템플릿은 다음에 있습니다:
SKILL_DIR/reference/
SKILL_DIR/templates/
SKILL_DIR/scripts/
SKILL_DIR 아래의 모든 것(이 파일 제외)은 Read 도구로 읽거나 Bash 도구로 실행할 수 있습니다.
simkit Python 패키지가 거기에 있습니다: SKILL_DIR/scripts/simkit/.
check_platform.sh는 scripts/ 아래의 스크립트 중 하나입니다.
setup_env.sh는 scripts/ 아래에 있습니다.
시작할 때: PY=$(bash SKILL_DIR/scripts/setup_env.sh)를 실행하십시오. 필요한 패키지가 설치되어 있지 않으면 약 30초가 소요됩니다.
scripts/simkit/를 무언가에 import simkit 하기 전에 sys.path에 추가해야 할 수도 있습니다.
레시피 빌더: scripts/simkit/procedural/.
스모크 테스트 러너: scripts/simkit/smoke/.
Mujoco 장면 유틸리티: scripts/simkit/scene.py.
로봇: scripts/simkit/robots/.
작업 검사 프레임워크: scripts/simkit/task_checks.py, scripts/simkit/physics_examiner.py.
에셋 다운로드: scripts/simkit/assets/.
Isaac 내보내기: scripts/simkit/usd_export/.
템플릿: templates/ (build_env.py, env.py, view.py가 거기에 있음).
scripts/check_platform.py를 실행하면 OS(Windows/macOS/Linux), GPU(없음, NVIDIA RTX), 그리고 isaac_runnable_here 플래그(True/False)를 가져옵니다.
규칙 1: 어떻게 불려도 "phases"를 건너뛰지 마십시오. Phase 1에서 백엔드를 선택하고 Ant를 빌드하기 전에 Phase 2에서 확인하십시오. 확인되지 않은 빌드는 실패한 빌드입니다.
규칙 2: 절대 호기심에 에셋을 검색하지 마십시오: 브리프에 구체적인 객체가 없으면 find_assets를 호출하지 마십시오. 중립적인 "무엇을 배치해야 하나요?"는 시간 낭비입니다. 사용자의 요청에 답하는 객체만 찾으십시오.
규칙 3: 사용자에게 단일 브리프를 던지고 여러 턴에 걸쳐 사양을 뽑아내지 마십시오. 모든 것을 하나로 합치십시오: 배경, 객체, 로봇, 작업, 검사, 선택적 추가 사항. 사용자가 이미 답변을 가지고 있습니다. 그러면 한 번의 확인만 있으면 됩니다.
규칙 4: 최종 메시지에는 항상 EXACT TEXT FROM smoke/smoke_report.json을 포함시키십시오.
규칙 5: 스모크가 PASS할 때까지 절대 전달하지 마십시오. 규칙 5b: 전달 여부를 사용자에게 묻지 마십시오 - 기준은 명확합니다: PASS.
(규칙을 잊을 경우 SKILL_DIR/README.md 참조, 이 스킬 문서와 동일함).