O que Sim Env Builder faz?
Objetivo: a partir de uma descrição, entregar um ambiente simulado funcional, fisicamente sólido e visualmente agradável no menor número possível de interações com o usuário (idealmente: solicitação -> uma confirmação -> pronto). Padrão de qualidade: todos os testes de fumaça passam, você OLHOU para os renders e eles correspondem à solicitação.
SKILL_DIR abaixo = o diretório deste arquivo. Os helpers Python estão em SKILL_DIR/scripts/simkit.
Fase 0 - Configuração (1 minuto)
PY=$(bash SKILL_DIR/scripts/setup_env.sh) # python com mujoco, trimesh, usd-core, gymnasium
$PY SKILL_DIR/scripts/check_platform.py # SO, GPU, disponibilidade do Isaac
Escolha a pasta do ambiente: ./<short_snake_name>/ no diretório atual, a menos que o usuário tenha nomeado uma.
Fase 1 - Escolher o backend (leia reference/backend_choice.md)
O Isaac Sim precisa de uma GPU NVIDIA RTX no Linux/Windows. O MuJoCo funciona em qualquer lugar.
- MuJoCo: padrão. Manipulação e locomoção com contato, iteração rápida, CPU/laptop/macOS, cenas pequenas a médias, controle baseado em modelo, pesquisa reproduzível, MJX/Warp para RL em GPU.
- Isaac Sim: renderização RTX fotorrealista ou dados sintéticos (Replicator), realismo de sensores RTX lidar/câmera, milhares de ambientes paralelos no Isaac Lab, grandes cenas USD/Omniverse, usuário já está no Isaac.
- Se o Isaac for a melhor opção, mas
isaac_runnable_herefor falso, diga isso na confirmação e ofereça: construir + testar totalmente no MuJoCo aqui E exportar um palco USD + script de teste Isaac para a máquina GPU (reference/isaac.md). Nunca reivindique resultados do Isaac que você não executou.
Fase 2 - Confirmar com o usuário ANTES de construir (reference/confirmation.md)
- Primeiro faça uma varredura rápida de ativos para que o resumo seja fundamentado: uma chamada
find_assets(MCP polypizza) listando cada função de objeto, 1-3 consultas cada. - Envie UM resumo curto (template em reference/confirmation.md): backend + porquê, o que estará na cena, o robô/agente e sua interface de controle, quais ativos vêm do Poly Pizza vs procedurais, física chave (gravidade, atrito, timestep), entregáveis e 2-4 perguntas que cada uma carrega sua recomendação padrão.
- Pergunte com AskUserQuestion se essa ferramenta existir. Caso contrário, termine seu turno com o resumo como sua mensagem e espere. Não construa antes que o usuário responda. Exceção: o usuário disse para não perguntar / "apenas construa" -> escreva as suposições em SPEC.md, prossiga.
- Registre as decisões confirmadas em
<env>/SPEC.md(template em reference/confirmation.md).
Fase 3 - Ativos: Poly Pizza primeiro, fallback procedural (reference/assets.md)
Para cada função de objeto:
find_assets/search_models-> leia o veredito (encontrado / fraco / não_encontrado).- encontrado ou fraco ->
preview_models([...ids])e OLHE: objeto certo? estilo consistente? rejeite brinquedos, desenhos animados em cenas realistas, pacotes multi-objeto, classe de escala errada. - Aceite ->
download_model(id, "<abs env path>/assets/polypizza", "<role>")(os créditos são registrados automaticamente emassets/polypizza/CREDITS.md). - não_encontrado, rejeitado ou erro de download -> procedural: receitas
simkit.procedural(árvores, edifícios, móveis, adereços de rua, portões, louças, terreno...) ou componha o seu próprio a partir de primitivas /lathe/extrude/rock. Nunca deixe um objeto solicitado de fora. - Escreva
<env>/assets/ASSETS.md: função | fonte (id do Poly Pizza + título + licença, ou receita procedural) | tamanho real | porquê. Se o título de um modelo diferir da função ("Banco de Parque" usado como mesa de piquenique), diga isso e por que ainda se encaixa - ou pesquise novamente / vá para procedural. Liste também os candidatos REJEITADOS (id + motivo: "estilo cartoon", "pacote de 12 objetos") para que a pesquisa seja rastreável, mesmo quando tudo terminar procedural. Os modelos do Poly Pizza são malhas estáticas: robôs e veículos articulados vêm desimkit.robots(você pode revesti-los com uma malha Poly Pizza como geoms visuais).
Fase 4 - Construir (reference/robots.md, templates/)
mkdir -p <env> && cp -r SKILL_DIR/scripts/simkit <env>/simkit # vendido: ambiente autocontido
cp SKILL_DIR/templates/build_env.py SKILL_DIR/templates/env.py SKILL_DIR/templates/view.py <env>/ # edite os dois primeiros
build_env.pyregenera tudo deterministicamente (semeado) ->scene.xml. Usesimkit.scene.Scene(céu, chão, luzes, câmeras look-at, seções para MJCF bruto),simkit.assets.glb_to_mujoco(glb, env, name, target={"height": m}, yaw_deg=..)para modelos Poly Pizza (tamanho real, Z-up, partes por cor, colisão box/hull/parts),simkit.proceduralpara fallbacks e terreno,simkit.robotspara robôs testados (quadrotor, carro, diff_drive, braço- gripper, quadrúpede) e seus controladores.
- Escala do mundo real é obrigatória (tabela de tamanhos em reference/assets.md). As coisas repousam sobre seu suporte.
- Cada classe de objeto que o usuário nomeou deve estar claramente visível em um tamanho legível na visão geral
(uma "trilha rochosa" precisa de rochas que você possa ver, não de manchas de 7 cm; "terreno acidentado" precisa de solavancos visíveis
na escala do robô). O teste de fumaça lista manchas sob
hints. - Pelo menos 2 câmeras nomeadas: uma visão geral e uma enquadrada no assunto (o robô/objeto da tarefa preenche aproximadamente 30-50% do quadro; montada no robô, se houver). Câmeras de sensor fixas não devem ser bloqueadas pela pose inicial do robô (fumaça sinaliza > 15% de cobertura).
world.py(quando a cena tem sua própria dinâmica):make_world(model)->world(model, data), chamado ANTES de cada passo de física por fumaça, examinador, vitrine, env.py, view.py e o painel. Flutuação/arrasto, vento, esteiras, ciclos de semáforos, pedestres scriptados e NPCs de carros vivem aqui, nunca dentro de controller.py (um teste passivo ou uma política RL executaria um mundo onde barcos afundam e luzes nunca mudam). Tarefas que verificam o passo da simulação também devem chamá-lo.controller.py: uma política de demonstração scriptada (make_controller(model)->ctrl(model, data)) que mostra o ambiente fazendo seu trabalho (drone voa pelos portões, carro dirige a rota, braço alcança o objeto...). DefinaDEMO_SECONDS = <duração da demonstração completa>no nível do módulo: o teste de fumaça então filma e verifica a demonstração INTEIRA (pegar, levantar, colocar / cada portão), não apenas os primeiros 4 segundos.task_checks.py: funçõescheck_<nome>(model, data) -> {"status", "value", "expect", "details"}para verificações de física no nível da tarefa. Uma verificação por critério de sucesso que o usuário declarou ou confirmou (nomeie-o com as palavras do usuário: "pés em contato" ->check_feet_in_contact), além de sanidade de spawn (o robô começa em seu suporte). Pelo menos 2. Escreva os limites E a definição exata de cada métrica (ponto de referência, unidades: "centro da base do rover ao centro do módulo de pouso, metros") em SPEC.md ANTES da primeira execução e mantenha -os: um erro por pouco significa corrigir o controlador/cena, nunca afrouxe a verificação (qualquer alteração de limite deve aparecer em "Mudanças do plano confirmado"). Uma verificação aprovada dentro de 15% do seu limite é relatada com sua margem ("inclinação 25,8 graus vs limite de 30 graus"). Qualquer comportamento que você reivindique (desaceleração por obstáculo, ciclo de semáforo, flutuação, aperto de garra) precisa de uma verificação que o exercite, por exemplo, coloque um obstáculo no caminho e afirme que o robô para. Cada propriedade física chave da cena recebe uma verificação medida com um alvo físico: desaceleração de rolamento de uma bola, linha d'água de um barco, subida de inclinação de um rover, tempo de queda com baixa gravidade, força de aperto da garra. Um sensor necessário também recebe uma verificação: renderize a câmera do robô durante a demonstração e afirme uma imagem não em branco que mostre a tarefa (por exemplo, fileiras de árvores à frente); para lidar, afirme intervalos sensatos. Execute cada verificação de tarefa na execução scriptada E em 2-3 execuções perturbadas (outra semente, pose inicial, velocidade inicial, fase da luz) - uma verificação que só é válida para uma execução exata prova pouco. Verificações de aperto exigem contato entre AMBAS as almofadas dos dedos e o objeto durante a elevação e o transporte (leiadata.contact), não apenas "o objeto subiu".- Colisores: simples e honestos. Árvores: colisor de tronco, dossel apenas visual, a menos que o usuário queira
pancadas no dossel. Multirotores: cápsulas de braço ou um casco, não uma caixa que engula as hélices.
Adereços não convexos (microscópio, cadeira, arco, prateleira) recebem
collision="parts"ou algumas primitivas; um casco convexo ao redor deles bloqueia espaço que está visivelmente vazio (verifique collision_sheet.png). env.py:reset/step/renderestilo Gymnasium com observação de tarefa, recompensa fictícia, terminação. Seu__main__de autoteste dirige o ambiente ATRAVÉS da API do ambiente com o controlador de demonstração (ou uma política de referência) e imprime se o objetivo da tarefa foi alcançado - prova de que o objetivo é alcançável.- Corpos e marcadores de depuração/rig de câmera: grupo geom 4-5 (nunca renderizado), não em câmeras de dados.
- Coisas suspensas (luzes de teto, placas penduradas, prateleiras de parede): nomeie-as
mounted_*ouhanging_*para que a verificação de objeto flutuante as ignore. - Iluminação: branco neutro (sem luzes coloridas); no máximo 2-3 luzes extras; verifique se uma parede branca permanece branco-acinzentada nos renders.
- Sem decoração não solicitada além do que faz a cena ser lida corretamente; liste extras opcionais no resumo para que o usuário possa optar por incluí-los.
- Time box: anote a hora ao começar a construir (
date). Itens de bônus/alongamento ("dobrar é um bônus") vêm somente depois que todos os itens obrigatórios passam, e são descartados primeiro. Cerca de 60 minutos após o início da construção, pare de ajustar o que resta: torne REPORT.md e os resultados do README finais e relate (itens descartados listados). Uma construção que nunca relata é pior do que uma com uma lacuna conhecida. - Orçamento: uma vez que todos os itens obrigatórios existem e todas as verificações passam, pare de adicionar extras - termine a verificação visual, README e relatório. Extras vão no README como ideias.
- Execute
$PY build_env.pyapós cada alteração; erros de compilação carregam números de linha.
Fase 5 - Testes de fumaça (reference/smoke_tests.md). Todos os três são obrigatórios.
cd <env> && $PY -m simkit.smoke scene.xml --out smoke --controller controller.py --task-checks task_checks.py
- Teste de renderização - cada câmera nomeada + visualizações automáticas renderizam quadros não em branco, iluminados e detalhados; a segmentação mostra quais objetos estão visíveis (objetos não vistos são sinalizados).
- Examinador de física - sondas de solver/contatos/atrito/gravidade com as configurações da própria cena, estabilidade de rollout, penetração, queda, estabilização, respostas de passo do atuador, determinismo, sensibilidade a timestep, fator de tempo real, layout (adereços flutuando / afundados / interpenetrantes), além de suas verificações de tarefa.
- Verificação visual - VOCÊ deve abrir e olhar para
smoke/contact_sheet.png,smoke/filmstrip.png,smoke/collision_sheet.pnge os close-ups emsmoke/renders/(ferramenta Leitura), então preencha a lista de verificação emsmoke/visual_check.mdcom observações concretas. Corrija cada FALHA. Investigue cada AVISO (corrija-o ou explique no README por que é esperado). Reconstrua e execute novamente até que o veredito seja PASS / PASS_COM_AVISOS-explicados E a verificação visual seja honestamente toda "sim". Espere 2-3 iterações; o primeiro render raramente está correto. Execute também$PY env.py(ações aleatórias, observações finitas).
Fase 6 - Entrega do Isaac Sim (apenas se o Isaac foi escolhido; reference/isaac.md)
$PY -m simkit.usd_export scene.xml isaac/scene.usda (exportação + validação local), copie
SKILL_DIR/templates/isaac_smoke.py para isaac/, documente como executá-lo na máquina GPU.
Declare claramente o que foi e o que não foi executado.
Fase 7 - Entregar
<env>/README.md: o que está na cena, como executar (construir, fumaça, ambiente, visualizador:
$PY view.py, que executa o controlador de demonstração ao vivo; mujoco.viewer simples mostra física passiva apenas), câmeras, atuadores, controlador, verificações de tarefa, créditos de ativos, limitações conhecidas. Mensagem final para o usuário: linha de veredito, o que foi construído, quais ativos
vieram do Poly Pizza vs procedural, resultados de fumaça, caminhos para smoke/showcase.mp4 (o vídeo que as pessoas
assistem), contact sheet e filmstrip, qualquer coisa não feita ou não verificada, e uma lista "Mudanças do plano
confirmado" (ativos ou licenças trocados, tamanhos/quantidades alterados, extras descartados) - vazia
se nenhuma, mas sempre presente. Copie cada número (verificações passadas, pontuações, erros) de
smoke/smoke_report.json e physics_report.json; cole seu summary_line literalmente
("Fumaça PASS: examinador 19 pass / 0 aviso / 0 falha; verificações de tarefa 9/9 pass; render ok") e nunca escreva
contagens de memória.
Inicie <env>/REPORT.md assim que a primeira execução de fumaça for concluída e atualize-o após cada correção, para que uma
sessão interrompida ainda deixe um relatório; a mensagem final é sua última versão.
Layout do entregável (mantenha exatamente; ferramentas e painéis dependem disso)
<env>/
SPEC.md README.md REPORT.md build_env.py scene.xml env.py view.py controller.py task_checks.py
world.py (apenas se a cena tiver sua própria dinâmica)
simkit/ helpers vendidos
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/ (apenas para Isaac: scene.usda, isaac_smoke.py, seção README)
Regras duramente conquistadas (cada uma já quebrou uma construção real)
-
Permaneça dentro do escopo confirmado. A demonstração mostra o que o usuário concordou (por exemplo, "ficar em pé é suficiente" significa uma postura estável, não um novo controlador de locomoção). Gaste o tempo na cena, nos ativos, nas verificações e na revisão visual; liste ideias de alongamento no README.
-
Configurações
<visual>:sc.set_visual("map", znear=.., zfar=..)etc. Cada elemento pode aparecer uma vez. -
Nunca calcule manualmente
xyaxesde câmera: useScene.camera(name, pos, target)/simkit.scene.lookat. -
Nunca escreva manualmente listas de qpos de quadro-chave: defina
scene.home[joint] = valor(robôs fazem isso por você);Scene.writeconstrói o quadro-chavehomepor nome de junta e define o ctrl do atuador de posição para corresponder. -
Malhas planas/finas precisam de
inertia="shell"(glb_to_mujoco faz isso). Geoms visuais:contype=0 conaffinity=0 group=2 mass=0; proxies de colisão no grupo 3. -
Um robô soldado ao mundo colide com sua própria base: adicione
<exclude>para base/primeiro link. -
Posit… (truncado para tradução)