|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import json |
|
|
import os |
|
|
import shutil |
|
|
from dataclasses import dataclass |
|
|
|
|
|
import tyro |
|
|
from embodied_gen.scripts.simulate_sapien import entrypoint as sim_cli |
|
|
from embodied_gen.utils.enum import LayoutInfo |
|
|
from embodied_gen.utils.geometry import bfs_placement, compose_mesh_scene |
|
|
from embodied_gen.utils.log import logger |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class LayoutPlacementConfig: |
|
|
layout_path: str |
|
|
output_dir: str | None = None |
|
|
seed: int | None = None |
|
|
max_attempts: int = 1000 |
|
|
output_iscene: bool = False |
|
|
insert_robot: bool = False |
|
|
|
|
|
|
|
|
def entrypoint(**kwargs): |
|
|
if kwargs is None or len(kwargs) == 0: |
|
|
args = tyro.cli(LayoutPlacementConfig) |
|
|
else: |
|
|
args = LayoutPlacementConfig(**kwargs) |
|
|
|
|
|
output_dir = ( |
|
|
args.output_dir |
|
|
if args.output_dir is not None |
|
|
else os.path.dirname(args.layout_path) |
|
|
) |
|
|
os.makedirs(output_dir, exist_ok=True) |
|
|
out_scene_path = f"{output_dir}/Iscene.glb" |
|
|
out_layout_path = f"{output_dir}/layout.json" |
|
|
|
|
|
layout_info = bfs_placement(args.layout_path, seed=args.seed) |
|
|
origin_dir = os.path.dirname(args.layout_path) |
|
|
for key in layout_info.assets: |
|
|
src = f"{origin_dir}/{layout_info.assets[key]}" |
|
|
dst = f"{output_dir}/{layout_info.assets[key]}" |
|
|
if src == dst: |
|
|
continue |
|
|
shutil.copytree(src, dst, dirs_exist_ok=True) |
|
|
|
|
|
with open(out_layout_path, "w") as f: |
|
|
json.dump(layout_info.to_dict(), f, indent=4) |
|
|
|
|
|
if args.output_iscene: |
|
|
compose_mesh_scene(layout_info, out_scene_path) |
|
|
|
|
|
sim_cli( |
|
|
layout_path=out_layout_path, |
|
|
output_dir=output_dir, |
|
|
insert_robot=args.insert_robot, |
|
|
) |
|
|
|
|
|
logger.info(f"Layout placement completed in {output_dir}") |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
entrypoint() |
|
|
|