diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..d0a0495 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,32 @@ +# .github/release.yml + +changelog: + categories: + - title: "🚀 New Features" + labels: + - feature + + - title: "🐛 Bug Fixes" + labels: + - bug + + - title: "🔧 Improvements" + labels: + - refactor + - enhancement + + - title: "⚠️ Breaking Changes" + labels: + - breaking + + - title: "📚 Documentation" + labels: + - docs + + - title: "🛠 Internal / CI" + labels: + - ci + + exclude: + labels: + - skip-release-notes \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 84ed770..7d81921 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: options: --memory 100g --gpus device=1 --shm-size 53687091200 steps: - uses: actions/checkout@v4 - - name: (CI) Code Style check + - name: Code Style check run: | echo "Workspace: ${GITHUB_WORKSPACE}" ls @@ -46,12 +46,14 @@ jobs: container: *container_template steps: - uses: actions/checkout@v4 - - name: (CI) Build docs + - name: Build docs run: | - pip install -e . + pip install -e . --extra-index-url http://pyp.open3dv.site:2345/simple/ --trusted-host pyp.open3dv.site pip install -r docs/requirements.txt cd ${GITHUB_WORKSPACE}/docs echo "Start Building docs..." + pip uninstall pymeshlab -y + pip install pymeshlab==2023.12.post3 make html - name: Upload docs artifact if: github.event_name == 'push' && github.ref == 'refs/heads/main' @@ -71,11 +73,13 @@ jobs: container: *container_template steps: - uses: actions/checkout@v4 - - name: (CI) Run tests + - name: Run tests run: | - pip install -e . + pip install -e . --extra-index-url http://pyp.open3dv.site:2345/simple/ --trusted-host pyp.open3dv.site echo "Unit test Start" export HF_ENDPOINT=https://hf-mirror.com + pip uninstall pymeshlab -y + pip install pymeshlab==2023.12.post3 pytest tests publish: @@ -92,11 +96,49 @@ jobs: container: *container_template steps: - uses: actions/checkout@v4 - - name: (CI) Publish package - run: echo "start publish stage" - - name: (CI) Download docs artifact + - name: Download docs artifact uses: actions/download-artifact@v4 with: name: github-pages - - name: (CI) Deploy GitHub Pages - uses: actions/deploy-pages@v4 \ No newline at end of file + + - name: Deploy GitHub Pages + uses: actions/deploy-pages@v4 + + + release: + if: startsWith(github.ref, 'refs/tags/v') + runs-on: Linux + permissions: + contents: write + id-token: write # PyPI Trusted Publishing + + container: *container_template + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: (Release) Install build tools + run: | + python -m pip install --upgrade pip + pip install build + + - name: (Release) Build sdist and wheel + run: | + python -m build --wheel + + - name: (Release) Create GitHub Release (draft) + uses: softprops/action-gh-release@v2 + with: + draft: true + generate_release_notes: true + files: | + dist/* + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: (Release) Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index dc87025..cbe0649 100644 --- a/.gitignore +++ b/.gitignore @@ -195,3 +195,5 @@ wandb/ # vscode settings .vscode/ + +embodichain/VERSION diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..ceeea23 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include VERSION diff --git a/docs/source/quick_start/install.md b/docs/source/quick_start/install.md index 58f0bb6..6389101 100644 --- a/docs/source/quick_start/install.md +++ b/docs/source/quick_start/install.md @@ -53,7 +53,7 @@ git clone https://github.com/DexForce/EmbodiChain.git Install the project in development mode: ```bash -pip install -e . +pip install -e . --extra-index-url http://pyp.open3dv.site:2345/simple/ --trusted-host pyp.open3dv.site ``` ### Verify Installation diff --git a/embodichain/__init__.py b/embodichain/__init__.py index f818cf7..c0b0271 100644 --- a/embodichain/__init__.py +++ b/embodichain/__init__.py @@ -21,7 +21,7 @@ # Read version from VERSION file def _get_version(): - version_file = os.path.join(os.path.dirname(embodichain_dir), "VERSION") + version_file = os.path.join(embodichain_dir, "VERSION") try: with open(version_file, "r") as f: return f.read().strip() diff --git a/embodichain/lab/sim/objects/articulation.py b/embodichain/lab/sim/objects/articulation.py index f1325a6..e92a56b 100644 --- a/embodichain/lab/sim/objects/articulation.py +++ b/embodichain/lab/sim/objects/articulation.py @@ -71,10 +71,14 @@ def __init__( # get gpu indices for the entities. # only meaningful when using GPU physics. - self.gpu_indices = torch.as_tensor( - [np.int32(entity.get_gpu_index()) for entity in self.entities], - dtype=torch.int32, - device=self.device, + self.gpu_indices = ( + torch.as_tensor( + [entity.get_gpu_index() for entity in self.entities], + dtype=torch.int32, + device=self.device, + ) + if self.device.type == "cuda" + else None ) self.dof = self.entities[0].get_dof() diff --git a/embodichain/lab/sim/objects/rigid_object.py b/embodichain/lab/sim/objects/rigid_object.py index f6fc48c..a9e88a9 100644 --- a/embodichain/lab/sim/objects/rigid_object.py +++ b/embodichain/lab/sim/objects/rigid_object.py @@ -60,10 +60,14 @@ def __init__( self.device = device # get gpu indices for the entities. - self.gpu_indices = torch.as_tensor( - [entity.get_gpu_index() for entity in self.entities], - dtype=torch.int32, - device=self.device, + self.gpu_indices = ( + torch.as_tensor( + [entity.get_gpu_index() for entity in self.entities], + dtype=torch.int32, + device=self.device, + ) + if self.device.type == "cuda" + else None ) # Initialize rigid body data. diff --git a/embodichain/lab/sim/objects/rigid_object_group.py b/embodichain/lab/sim/objects/rigid_object_group.py index bcf1385..a9eb0ea 100644 --- a/embodichain/lab/sim/objects/rigid_object_group.py +++ b/embodichain/lab/sim/objects/rigid_object_group.py @@ -58,10 +58,17 @@ def __init__( self.device = device # get gpu indices for the rigid bodies with shape of (num_instances, num_objects) - self.gpu_indices = torch.as_tensor( - [[entity.get_gpu_index() for entity in instance] for instance in entities], - dtype=torch.int32, - device=self.device, + self.gpu_indices = ( + torch.as_tensor( + [ + [entity.get_gpu_index() for entity in instance] + for instance in entities + ], + dtype=torch.int32, + device=self.device, + ) + if self.device.type == "cuda" + else None ) # Initialize rigid body group data tensors. Shape of (num_instances, num_objects, data_dim) diff --git a/embodichain/lab/sim/objects/soft_object.py b/embodichain/lab/sim/objects/soft_object.py index 62e45c8..161aafa 100644 --- a/embodichain/lab/sim/objects/soft_object.py +++ b/embodichain/lab/sim/objects/soft_object.py @@ -43,7 +43,7 @@ class SoftBodyData: """Data manager for soft body Note: - 1. The pose data managed by dexsim is in the format of (qx, qy, qz, qw, x, y, z), but in EmbodySim, we use (x, y, z, qw, qx, qy, qz) format. + 1. The pose data managed by dexsim is in the format of (qx, qy, qz, qw, x, y, z), but in EmbodiChain, we use (x, y, z, qw, qx, qy, qz) format. """ def __init__( @@ -171,7 +171,6 @@ def __init__( self._data = SoftBodyData(entities=entities, ps=self._ps, device=device) - # TODO: soft body physical attribute is already set in soft body creation(embodichain/lab/sim/utility/sim_utils.py load_soft_object_from_cfg) self._world.update(0.001) super().__init__(cfg=cfg, entities=entities, device=device) diff --git a/embodichain/lab/sim/sim_manager.py b/embodichain/lab/sim/sim_manager.py index d31e2c6..2102495 100644 --- a/embodichain/lab/sim/sim_manager.py +++ b/embodichain/lab/sim/sim_manager.py @@ -373,7 +373,7 @@ def init_gpu_physics(self) -> None: rigid_body_num = ( 0 if self._get_non_static_rigid_obj_num() == 0 - else len(self._ps.gpu_rigid_indices) + else len(self._ps.get_gpu_rigid_indices()) ) self._rigid_body_pose = torch.zeros( (rigid_body_num, 7), dtype=torch.float32, device=self.device @@ -383,7 +383,7 @@ def init_gpu_physics(self) -> None: articulation_num = ( 0 if len(self._articulations) == 0 and len(self._robots) == 0 - else len(self._ps.gpu_articulation_indices) + else len(self._ps.get_gpu_articulation_indices()) ) max_link_count = self._ps.gpu_get_articulation_max_link_count() self._link_pose = torch.zeros( @@ -452,14 +452,14 @@ def _sync_gpu_data(self) -> None: if len(self._rigid_body_pose) > 0: self._ps.gpu_fetch_rigid_body_data( data=CudaArray(self._rigid_body_pose), - gpu_indices=self._ps.gpu_rigid_indices, + gpu_indices=self._ps.get_gpu_rigid_indices(), data_type=RigidBodyGPUAPIReadType.POSE, ) if len(self._link_pose) > 0: self._ps.gpu_fetch_link_data( data=CudaArray(self._link_pose), - gpu_indices=self._ps.gpu_articulation_indices, + gpu_indices=self._ps.get_gpu_articulation_indices(), data_type=ArticulationGPUAPIReadType.LINK_GLOBAL_POSE, ) diff --git a/pyproject.toml b/pyproject.toml index 85506d9..da8ca26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ # is still executed during build. This is a minimal, non-opinionated pyproject # that modernizes the package while preserving the custom extension build steps. requires = ["setuptools>=61.0", "wheel"] -build-backend = "setuptools.build_meta:__legacy__" +build-backend = "setuptools.build_meta" # Note: @@ -17,17 +17,16 @@ build-backend = "setuptools.build_meta:__legacy__" [project] name = "embodichain" -version = "0.0.1" description = "An end-to-end, GPU-accelerated, and modular platform for building generalized Embodied Intelligence." readme = "README.md" authors = [ { name = "EmbodiChain Developers" } ] requires-python = ">=3.10" - +dynamic = ["version"] # Core install dependencies (kept from requirements.txt). Some VCS links are # specified using PEP 508 direct references where present. dependencies = [ - "dexsim_engine @ http://pyp.open3dv.site:2345/packages/dexsim_engine-0.3.7-cp310-cp310-manylinux_2_31_x86_64.whl", + "dexsim_engine", "setuptools>=78.1.1", "gymnasium==0.29.1", "casadi==3.7.1", @@ -45,7 +44,6 @@ dependencies = [ "transformers>=4.53.0", "diffusers>=0.32.1", "deepspeed>=0.16.2", - "cvxpy==1.4.0", "ortools", "prettytable", "black==24.3.0", @@ -53,6 +51,9 @@ dependencies = [ "h5py", ] +[tool.setuptools.dynamic] +version = { file = ["VERSION"] } + [tool.setuptools.packages.find] where = ["."] exclude = ["docs"] diff --git a/setup.py b/setup.py index ae041d5..8325ffb 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ import os import shutil import sys +import argparse from os import path as osp from pathlib import Path @@ -94,30 +95,44 @@ def get_data_files_of_a_directory(source_dir, target_dir=None, ignore_py=False): return filelist -# Extract version -here = osp.abspath(osp.dirname(__file__)) -version = None -with open(os.path.join(os.path.dirname(__file__), "VERSION")) as f: - full_version = f.read().strip() - version = ".".join(full_version.split(".")[:3]) - -ignore_py = sys.argv[1] == "bdist_nuitka" if len(sys.argv) > 1 else False -data_files = [] -data_files += get_data_files_of_a_directory("embodichain", ignore_py=ignore_py) - -cmdclass = {"clean": CleanCommand} -if BuildExtension is not None: - cmdclass["build_ext"] = BuildExtension.with_options(no_python_abi_suffix=True) - -setup( - name="embodichain", - version=version, - url="https://github.com/DexForce/EmbodiChain", - author="EmbodiChain Developers", - description="An end-to-end, GPU-accelerated, and modular platform for building generalized Embodied Intelligence.", - packages=find_packages(exclude=["docs"]), - data_files=data_files, - entry_points={}, - cmdclass=cmdclass, - include_package_data=True, -) +def get_version(): + with open(os.path.join(os.path.dirname(__file__), "VERSION")) as f: + full_version = f.read().strip() + version = ".".join(full_version.split(".")[:3]) + return version + + +def main(): + # Extract version + version = get_version() + + data_files = [] + data_files += get_data_files_of_a_directory("embodichain", ignore_py=False) + + cmdclass = {"clean": CleanCommand} + if BuildExtension is not None: + cmdclass["build_ext"] = BuildExtension.with_options(no_python_abi_suffix=True) + + setup( + name="embodichain", + version=version, + url="https://github.com/DexForce/EmbodiChain", + author="EmbodiChain Developers", + description="An end-to-end, GPU-accelerated, and modular platform for building generalized Embodied Intelligence.", + packages=find_packages(exclude=["docs"]), + data_files=data_files, + entry_points={}, + cmdclass=cmdclass, + include_package_data=True, + ) + + # Copy VERSION file into the package directory for wheel/sdist + src_version = os.path.join(THIS_DIR, "VERSION") + dst_version = os.path.join(THIS_DIR, "embodichain", "VERSION") + if os.path.exists(src_version): + shutil.copyfile(src_version, dst_version) + logger.info(f"Copied VERSION to {dst_version}") + + +if __name__ == "__main__": + main()