From 71dd9d1e4841f5dd248f87312c2d0eb50bbdb866 Mon Sep 17 00:00:00 2001 From: yuecideng Date: Wed, 1 Apr 2026 20:09:32 +0800 Subject: [PATCH 1/2] feat(cli): add top-level CLI entry points for preview_asset and run_env Allow `python -m embodichain.preview_asset` and `python -m embodichain.run_env` as shortcuts, following the same pattern as `python -m embodichain.data`. Also adds CLI reference documentation. Co-Authored-By: Claude Opus 4.6 --- docs/source/guides/cli.md | 124 +++++++++++++++++++++++ docs/source/guides/index.rst | 3 +- embodichain/lab/scripts/preview_asset.py | 10 +- embodichain/lab/scripts/run_env.py | 11 +- embodichain/preview_asset.py | 21 ++++ embodichain/run_env.py | 21 ++++ 6 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 docs/source/guides/cli.md create mode 100644 embodichain/preview_asset.py create mode 100644 embodichain/run_env.py diff --git a/docs/source/guides/cli.md b/docs/source/guides/cli.md new file mode 100644 index 00000000..5e1a93a3 --- /dev/null +++ b/docs/source/guides/cli.md @@ -0,0 +1,124 @@ +# CLI Reference + +EmbodiChain provides command-line tools for common tasks. +All CLIs are invoked via ``python -m ``. + +--- + +## Asset Download + +List and download simulation assets (robots, objects, scenes, etc.). + +```bash +# List all available assets +python -m embodichain.data list + +# List assets in a category +python -m embodichain.data list --category robot + +# Download a specific asset +python -m embodichain.data download --name CobotMagicArm + +# Download all assets in a category +python -m embodichain.data download --category robot + +# Download everything +python -m embodichain.data download --all +``` + +--- + +## Preview Asset + +Preview a USD or mesh asset in the simulation without writing code. + +```bash +# Preview a rigid object +python -m embodichain.preview_asset \ + --asset_path /path/to/sugar_box.usda \ + --asset_type rigid \ + --preview + +# Preview an articulation +python -m embodichain.preview_asset \ + --asset_path /path/to/robot.usd \ + --asset_type articulation \ + --preview + +# Headless check (no render window) +python -m embodichain.preview_asset \ + --asset_path /path/to/asset.usda \ + --headless +``` + +### Arguments + +| Argument | Default | Description | +|---|---|---| +| ``--asset_path`` | *(required)* | Path to the asset file (``.usd``/``.usda``/``.usdc``/``.obj``/``.stl``/``.glb``) | +| ``--asset_type`` | ``rigid`` | Asset type: ``rigid`` or ``articulation``. URDF files are auto-detected as articulation. | +| ``--uid`` | *(from filename)* | Unique identifier for the asset in the scene | +| ``--init_pos X Y Z`` | ``0 0 0.5`` | Initial position | +| ``--init_rot RX RY RZ`` | ``0 0 0`` | Initial rotation in degrees | +| ``--body_type`` | ``kinematic`` | Body type for rigid objects: ``dynamic``, ``kinematic``, or ``static`` | +| ``--use_usd_properties`` | ``False`` | Use physical properties from the USD file | +| ``--fix_base`` | ``True`` | Fix the base of articulations | +| ``--sim_device`` | ``cpu`` | Simulation device | +| ``--headless`` | ``False`` | Run without rendering window | +| ``--enable_rt`` | ``False`` | Enable ray tracing | +| ``--preview`` | ``False`` | Enter interactive embed mode after loading | + +### Preview Mode + +When ``--preview`` is enabled, an interactive REPL is available: + +- **``p``** — enter an IPython embed session with ``sim`` and ``asset`` in scope +- **``s ``** — step the simulation *N* times (default 10) +- **``q``** — quit + +--- + +## Run Environment + +Launch a Gymnasium environment for data generation or interactive preview. + +```bash +# Run an environment with a gym config file +python -m embodichain.run_env --gym_config path/to/config.json + +# Run with multiple environments on GPU +python -m embodichain.run_env \ + --gym_config config.json \ + --num_envs 4 \ + --device cuda \ + --gpu_id 0 + +# Preview mode for interactive development +python -m embodichain.run_env --gym_config config.json --preview + +# Headless execution +python -m embodichain.run_env --gym_config config.json --headless +``` + +### Arguments + +| Argument | Default | Description | +|---|---|---| +| ``--gym_config`` | *(required)* | Path to gym config file | +| ``--action_config`` | ``None`` | Path to action config file | +| ``--num_envs`` | ``1`` | Number of parallel environments | +| ``--device`` | ``cpu`` | Device (``cpu`` or ``cuda``) | +| ``--headless`` | ``False`` | Run in headless mode | +| ``--enable_rt`` | ``False`` | Use RTX rendering backend | +| ``--arena_space`` | ``5.0`` | Arena space size | +| ``--gpu_id`` | ``0`` | GPU ID to use | +| ``--preview`` | ``False`` | Enter interactive preview mode | +| ``--filter_visual_rand`` | ``False`` | Filter out visual randomization | +| ``--filter_dataset_saving`` | ``False`` | Filter out dataset saving | + +### Preview Mode + +When ``--preview`` is enabled, an interactive REPL is available: + +- **``p``** — enter an IPython embed session with ``env`` in scope +- **``q``** — quit diff --git a/docs/source/guides/index.rst b/docs/source/guides/index.rst index 3d3a45eb..e5c0f2de 100644 --- a/docs/source/guides/index.rst +++ b/docs/source/guides/index.rst @@ -6,4 +6,5 @@ How-to Guides :hidden: add_robot - + cli + diff --git a/embodichain/lab/scripts/preview_asset.py b/embodichain/lab/scripts/preview_asset.py index 99884ca2..54688acd 100644 --- a/embodichain/lab/scripts/preview_asset.py +++ b/embodichain/lab/scripts/preview_asset.py @@ -207,7 +207,11 @@ def main(args: argparse.Namespace) -> None: sim.destroy() -if __name__ == "__main__": +def cli(): + """Command-line interface for asset preview. + + Parses CLI arguments and launches the preview workflow. + """ parser = argparse.ArgumentParser( description="Preview a USD or mesh asset in the EmbodiChain simulation." ) @@ -298,3 +302,7 @@ def main(args: argparse.Namespace) -> None: args.uid = os.path.splitext(os.path.basename(args.asset_path))[0] main(args) + + +if __name__ == "__main__": + cli() diff --git a/embodichain/lab/scripts/run_env.py b/embodichain/lab/scripts/run_env.py index 4569f025..50ff124f 100644 --- a/embodichain/lab/scripts/run_env.py +++ b/embodichain/lab/scripts/run_env.py @@ -172,7 +172,12 @@ def preview(env: gymnasium.Env) -> None: exit(0) -if __name__ == "__main__": +def cli(): + """Command-line interface for environment runner. + + Parses CLI arguments, builds the environment config, and launches + the data generation or preview workflow. + """ np.set_printoptions(5, suppress=True) torch.set_printoptions(precision=5, sci_mode=False) @@ -187,3 +192,7 @@ def preview(env: gymnasium.Env) -> None: env = gymnasium.make(id=gym_config["id"], cfg=env_cfg, **action_config) main(args, env, gym_config) + + +if __name__ == "__main__": + cli() diff --git a/embodichain/preview_asset.py b/embodichain/preview_asset.py new file mode 100644 index 00000000..a29b2ee9 --- /dev/null +++ b/embodichain/preview_asset.py @@ -0,0 +1,21 @@ +# ---------------------------------------------------------------------------- +# Copyright (c) 2021-2026 DexForce Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------- + +"""Allow ``python -m embodichain.preview_asset`` to invoke the asset preview CLI.""" + +from embodichain.lab.scripts.preview_asset import cli + +cli() diff --git a/embodichain/run_env.py b/embodichain/run_env.py new file mode 100644 index 00000000..6a8c2aa9 --- /dev/null +++ b/embodichain/run_env.py @@ -0,0 +1,21 @@ +# ---------------------------------------------------------------------------- +# Copyright (c) 2021-2026 DexForce Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------- + +"""Allow ``python -m embodichain.run_env`` to invoke the environment runner CLI.""" + +from embodichain.lab.scripts.run_env import cli + +cli() From bfbc7f4f366d17bf611ef8d84944a07374644a06 Mon Sep 17 00:00:00 2001 From: yuecideng Date: Wed, 1 Apr 2026 20:29:33 +0800 Subject: [PATCH 2/2] wip --- docs/source/guides/cli.md | 17 +++--- embodichain/__main__.py | 91 ++++++++++++++++++++++++++++++ embodichain/lab/sim/sim_manager.py | 2 +- embodichain/preview_asset.py | 21 ------- embodichain/run_env.py | 21 ------- 5 files changed, 100 insertions(+), 52 deletions(-) create mode 100644 embodichain/__main__.py delete mode 100644 embodichain/preview_asset.py delete mode 100644 embodichain/run_env.py diff --git a/docs/source/guides/cli.md b/docs/source/guides/cli.md index 5e1a93a3..debb0078 100644 --- a/docs/source/guides/cli.md +++ b/docs/source/guides/cli.md @@ -1,7 +1,6 @@ # CLI Reference -EmbodiChain provides command-line tools for common tasks. -All CLIs are invoked via ``python -m ``. +EmbodiChain provides a unified CLI via ``python -m embodichain ``. --- @@ -34,19 +33,19 @@ Preview a USD or mesh asset in the simulation without writing code. ```bash # Preview a rigid object -python -m embodichain.preview_asset \ +python -m embodichain preview-asset \ --asset_path /path/to/sugar_box.usda \ --asset_type rigid \ --preview # Preview an articulation -python -m embodichain.preview_asset \ +python -m embodichain preview-asset \ --asset_path /path/to/robot.usd \ --asset_type articulation \ --preview # Headless check (no render window) -python -m embodichain.preview_asset \ +python -m embodichain preview-asset \ --asset_path /path/to/asset.usda \ --headless ``` @@ -84,20 +83,20 @@ Launch a Gymnasium environment for data generation or interactive preview. ```bash # Run an environment with a gym config file -python -m embodichain.run_env --gym_config path/to/config.json +python -m embodichain run-env --gym_config path/to/config.json # Run with multiple environments on GPU -python -m embodichain.run_env \ +python -m embodichain run-env \ --gym_config config.json \ --num_envs 4 \ --device cuda \ --gpu_id 0 # Preview mode for interactive development -python -m embodichain.run_env --gym_config config.json --preview +python -m embodichain run-env --gym_config config.json --preview # Headless execution -python -m embodichain.run_env --gym_config config.json --headless +python -m embodichain run-env --gym_config config.json --headless ``` ### Arguments diff --git a/embodichain/__main__.py b/embodichain/__main__.py new file mode 100644 index 00000000..5125296b --- /dev/null +++ b/embodichain/__main__.py @@ -0,0 +1,91 @@ +# ---------------------------------------------------------------------------- +# Copyright (c) 2021-2026 DexForce Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ---------------------------------------------------------------------------- + +"""Unified CLI entry point for ``python -m embodichain``. + +Usage examples:: + + python -m embodichain preview-asset --asset_path /path/to/asset.usda --preview + python -m embodichain run-env --env_name my_env +""" + +from __future__ import annotations + +import argparse +import sys + + +def main() -> None: + """Dispatch to the appropriate sub-command CLI.""" + parser = argparse.ArgumentParser( + prog="embodichain", + description="EmbodiChain command-line interface.", + ) + subparsers = parser.add_subparsers(dest="command") + + # -- preview-asset ------------------------------------------------------- + preview_asset_parser = subparsers.add_parser( + "preview-asset", + help="Preview a USD or mesh asset in the simulation.", + ) + # Import and wire up the existing CLI so argparse is handled by the + # sub-command module itself. We pass ``parse_known_args`` style by + # letting the sub-command parser own its own arguments. + from embodichain.lab.scripts.preview_asset import cli as preview_asset_cli + + preview_asset_parser.set_defaults(func=preview_asset_cli) + + # Re-add the preview-asset arguments here so ``--help`` works on the + # sub-command. We delegate to the existing ``cli()`` which calls + # ``parse_args()`` internally, so we pass through the raw argv. + # Instead of duplicating argument definitions, we let the sub-command + # module handle its own argument parsing by slicing sys.argv. + + # -- run-env ------------------------------------------------------------- + run_env_parser = subparsers.add_parser( + "run-env", + help="Run an environment for data generation or preview.", + ) + from embodichain.lab.scripts.run_env import cli as run_env_cli + + run_env_parser.set_defaults(func=run_env_cli) + + # -- Parse --------------------------------------------------------------- + # If no sub-command is given, print help and exit. + if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"): + parser.print_help() + sys.exit(0) + + # Determine which sub-command was selected, then reconstruct argv so + # that each sub-command's ``cli()`` can call ``parse_args()`` normally. + known, _ = parser.parse_known_args() + + if hasattr(known, "func"): + # Rewrite sys.argv so the sub-command's argparse sees only its own args. + subcommand_argv = [f"embodichain {sys.argv[1]}"] + sys.argv[2:] + original_argv = sys.argv + sys.argv = subcommand_argv + try: + known.func() + finally: + sys.argv = original_argv + else: + parser.print_help() + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/embodichain/lab/sim/sim_manager.py b/embodichain/lab/sim/sim_manager.py index 6a8bf537..bee36aa5 100644 --- a/embodichain/lab/sim/sim_manager.py +++ b/embodichain/lab/sim/sim_manager.py @@ -322,7 +322,7 @@ def reset(cls, instance_id: int = 0) -> None: This allows creating a new instance with different configuration. """ if instance_id in cls._instances: - logger.log_info(f"Resetting SimulationManager instance {instance_id}.") + logger.log_debug(f"Resetting SimulationManager instance {instance_id}.") del cls._instances[instance_id] @classmethod diff --git a/embodichain/preview_asset.py b/embodichain/preview_asset.py deleted file mode 100644 index a29b2ee9..00000000 --- a/embodichain/preview_asset.py +++ /dev/null @@ -1,21 +0,0 @@ -# ---------------------------------------------------------------------------- -# Copyright (c) 2021-2026 DexForce Technology Co., Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ---------------------------------------------------------------------------- - -"""Allow ``python -m embodichain.preview_asset`` to invoke the asset preview CLI.""" - -from embodichain.lab.scripts.preview_asset import cli - -cli() diff --git a/embodichain/run_env.py b/embodichain/run_env.py deleted file mode 100644 index 6a8c2aa9..00000000 --- a/embodichain/run_env.py +++ /dev/null @@ -1,21 +0,0 @@ -# ---------------------------------------------------------------------------- -# Copyright (c) 2021-2026 DexForce Technology Co., Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ---------------------------------------------------------------------------- - -"""Allow ``python -m embodichain.run_env`` to invoke the environment runner CLI.""" - -from embodichain.lab.scripts.run_env import cli - -cli()