From 3e2f3d975344d0a16cb561483c343fdd658ad0cc Mon Sep 17 00:00:00 2001 From: JustaGist Date: Tue, 6 Aug 2024 14:39:43 +0100 Subject: [PATCH] add support for pre-loaded robot objects and mjcf files; fix bug in pypi installation --- CHANGELOG.md | 12 + examples/demo_task_space_control.py | 4 +- pixi.lock | 463 +++--------------- pybullet_robot/bullet_robot.py | 47 +- .../{urdf_utils.py => robot_loader_utils.py} | 66 ++- pyproject.toml | 12 +- 6 files changed, 165 insertions(+), 439 deletions(-) rename pybullet_robot/utils/{urdf_utils.py => robot_loader_utils.py} (53%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54b93d2..ee5f596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # CHANGELOG.md +## [0.1.3] - 2024-08-07 + +### Adds + +- support using pre-loaded robot to create bulletrobot class +- utility tool for retrieving mjcf files from robot_descriptions.py +- (experimental): support for mjcf files in bulletrobot + +### Fixes + +- pypi installation does not work with conda dependencies; use pypi dependencies instead + ## [0.1.2] - 2024-08-06 ### Features diff --git a/examples/demo_task_space_control.py b/examples/demo_task_space_control.py index f260705..110d674 100644 --- a/examples/demo_task_space_control.py +++ b/examples/demo_task_space_control.py @@ -1,7 +1,9 @@ import time import numpy as np from pybullet_robot.bullet_robot import BulletRobot -from pybullet_robot.utils.urdf_utils import get_urdf_from_awesome_robot_descriptions +from pybullet_robot.utils.robot_loader_utils import ( + get_urdf_from_awesome_robot_descriptions, +) from impedance_controllers import CartesianImpedanceController diff --git a/pixi.lock b/pixi.lock index 027c892..15da13c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9,49 +9,31 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/bullet-cpp-3.25-hfb8ada1_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.7.4-hbcca054_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-23_linux64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-23_linux64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h77fa898_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-14.1.0-h69a702a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-14.1.0-hc5f4f2c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-23_linux64_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_hac2b453_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-14.1.0-hc0a3c3a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.16-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4bc722e_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/pybullet-3.25-py312hfb8ada1_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.4-h194c7f8_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.0-py312hc2bc53b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-h7f98852_1002.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-hb711507_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.11-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.3-h7f98852_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-h0b41bf4_1003.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-h7f98852_1007.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - pypi: https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2c/f3/61eeef119beb37decb58e7cb29940f19a1464b8608f2cab8a8616aba75fd/numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/39/a6/6d6a8c535b82460527edc04b5fbf0374541d041668515e35822e53d7f66f/pybullet-3.2.6.tar.gz - pypi: https://files.pythonhosted.org/packages/f3/94/5ce4c471f79a516492dda65d81e1864cdc1378eebd0e7ae0bdc871a12e91/robot_descriptions-1.11.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/00/ce54410e344b3a6032cd42ed53fe425cf57a66d28e337670292bbb419ebc/scipy-1.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl - pypi: . @@ -87,26 +69,6 @@ packages: purls: [] size: 23621 timestamp: 1650670423406 -- kind: conda - name: bullet-cpp - version: '3.25' - build: hfb8ada1_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/bullet-cpp-3.25-hfb8ada1_2.conda - sha256: f806db7366beaf8f5104296eb05db43ca5995d2af2ebd61233d374177591e617 - md5: 612465ad2322dbd5e73d0de9077bfaa7 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - numpy >=1.26.0,<2.0a0 - - python_abi 3.12.* *_cp312 - - xorg-libx11 >=1.8.7,<2.0a0 - - xorg-libxext >=1.3.4,<2.0a0 - license: Zlib - purls: [] - size: 42326669 - timestamp: 1697298022245 - kind: conda name: bzip2 version: 1.0.8 @@ -188,48 +150,6 @@ packages: purls: [] size: 707602 timestamp: 1718625640445 -- kind: conda - name: libblas - version: 3.9.0 - build: 23_linux64_openblas - build_number: 23 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-23_linux64_openblas.conda - sha256: edb1cee5da3ac4936940052dcab6969673ba3874564f90f5110f8c11eed789c2 - md5: 96c8450a40aa2b9733073a9460de972c - depends: - - libopenblas >=0.3.27,<0.3.28.0a0 - - libopenblas >=0.3.27,<1.0a0 - constrains: - - liblapacke 3.9.0 23_linux64_openblas - - libcblas 3.9.0 23_linux64_openblas - - liblapack 3.9.0 23_linux64_openblas - - blas * openblas - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 14880 - timestamp: 1721688759937 -- kind: conda - name: libcblas - version: 3.9.0 - build: 23_linux64_openblas - build_number: 23 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-23_linux64_openblas.conda - sha256: 3e7a3236e7e03e308e1667d91d0aa70edd0cba96b4b5563ef4adde088e0881a5 - md5: eede29b40efa878cbe5bdcb767e97310 - depends: - - libblas 3.9.0 23_linux64_openblas - constrains: - - liblapacke 3.9.0 23_linux64_openblas - - liblapack 3.9.0 23_linux64_openblas - - blas * openblas - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 14798 - timestamp: 1721688767584 - kind: conda name: libexpat version: 2.6.2 @@ -281,38 +201,6 @@ packages: purls: [] size: 842109 timestamp: 1719538896937 -- kind: conda - name: libgfortran-ng - version: 14.1.0 - build: h69a702a_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-14.1.0-h69a702a_0.conda - sha256: ef624dacacf97b2b0af39110b36e2fd3e39e358a1a6b7b21b85c9ac22d8ffed9 - md5: f4ca84fbd6d06b0a052fb2d5b96dde41 - depends: - - libgfortran5 14.1.0 hc5f4f2c_0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 49893 - timestamp: 1719538933879 -- kind: conda - name: libgfortran5 - version: 14.1.0 - build: hc5f4f2c_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-14.1.0-hc5f4f2c_0.conda - sha256: a67d66b1e60a8a9a9e4440cee627c959acb4810cb182e089a4b0729bfdfbdf90 - md5: 6456c2620c990cd8dde2428a27ba0bc5 - depends: - - libgcc-ng >=14.1.0 - constrains: - - libgfortran-ng 14.1.0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 1457561 - timestamp: 1719538909168 - kind: conda name: libgomp version: 14.1.0 @@ -328,26 +216,6 @@ packages: purls: [] size: 456925 timestamp: 1719538796073 -- kind: conda - name: liblapack - version: 3.9.0 - build: 23_linux64_openblas - build_number: 23 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-23_linux64_openblas.conda - sha256: 25c7aef86c8a1d9db0e8ee61aa7462ba3b46b482027a65d66eb83e3e6f949043 - md5: 2af0879961951987e464722fd00ec1e0 - depends: - - libblas 3.9.0 23_linux64_openblas - constrains: - - liblapacke 3.9.0 23_linux64_openblas - - libcblas 3.9.0 23_linux64_openblas - - blas * openblas - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 14823 - timestamp: 1721688775172 - kind: conda name: libnsl version: 2.0.1 @@ -363,26 +231,6 @@ packages: purls: [] size: 33408 timestamp: 1697359010159 -- kind: conda - name: libopenblas - version: 0.3.27 - build: pthreads_hac2b453_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_hac2b453_1.conda - sha256: 714cb82d7c4620ea2635a92d3df263ab841676c9b183d0c01992767bb2451c39 - md5: ae05ece66d3924ac3d48b4aa3fa96cec - depends: - - libgcc-ng >=12 - - libgfortran-ng - - libgfortran5 >=12.3.0 - constrains: - - openblas >=0.3.27,<0.3.28.0a0 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 5563053 - timestamp: 1720426334043 - kind: conda name: libsqlite version: 3.46.0 @@ -398,21 +246,6 @@ packages: purls: [] size: 865346 timestamp: 1718050628718 -- kind: conda - name: libstdcxx-ng - version: 14.1.0 - build: hc0a3c3a_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-14.1.0-hc0a3c3a_0.conda - sha256: 88c42b388202ffe16adaa337e36cf5022c63cf09b0405cf06fc6aeacccbe6146 - md5: 1cb187a157136398ddbaae90713e2498 - depends: - - libgcc-ng 14.1.0 h77fa898_0 - license: GPL-3.0-only WITH GCC-exception-3.1 - license_family: GPL - purls: [] - size: 3881307 - timestamp: 1719538923443 - kind: conda name: libuuid version: 2.38.1 @@ -428,24 +261,6 @@ packages: purls: [] size: 33601 timestamp: 1680112270483 -- kind: conda - name: libxcb - version: '1.16' - build: hd590300_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.16-hd590300_0.conda - sha256: 7180375f37fd264bb50672a63da94536d4abd81ccec059e932728ae056324b3a - md5: 151cba22b85a989c2d6ef9633ffee1e4 - depends: - - libgcc-ng >=12 - - pthread-stubs - - xorg-libxau >=1.0.11,<2.0a0 - - xorg-libxdmcp - license: MIT - license_family: MIT - purls: [] - size: 394932 - timestamp: 1693088990429 - kind: conda name: libxcrypt version: 4.4.36 @@ -493,30 +308,12 @@ packages: purls: [] size: 887465 timestamp: 1715194722503 -- kind: conda +- kind: pypi name: numpy - version: 1.26.4 - build: py312heda63a1_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda - sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 - md5: d8285bea2a350f63fab23bf460221f3f - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libgcc-ng >=12 - - liblapack >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy?source=conda-forge-mapping - size: 7484186 - timestamp: 1707225809722 + version: 2.0.1 + url: https://files.pythonhosted.org/packages/2c/f3/61eeef119beb37decb58e7cb29940f19a1464b8608f2cab8a8616aba75fd/numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a + requires_python: '>=3.9' - kind: conda name: openssl version: 3.3.1 @@ -537,50 +334,21 @@ packages: purls: [] size: 2895213 timestamp: 1721194688955 -- kind: conda - name: pthread-stubs - version: '0.4' - build: h36c2ea0_1001 - build_number: 1001 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2 - sha256: 67c84822f87b641d89df09758da498b2d4558d47b920fd1d3fe6d3a871e000ff - md5: 22dad4df6e8630e8dff2428f6f6a7036 - depends: - - libgcc-ng >=7.5.0 - license: MIT - license_family: MIT - purls: [] - size: 5625 - timestamp: 1606147468727 -- kind: conda +- kind: pypi name: pybullet - version: '3.25' - build: py312hfb8ada1_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pybullet-3.25-py312hfb8ada1_2.conda - sha256: 65746a57c164e6ac3cbf21c0bef2e055f257affb00da75bb99b433980f9395c5 - md5: b74ae047db52b9092976ac255654cc46 - depends: - - bullet-cpp 3.25 hfb8ada1_2 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - numpy >=1.26.0,<2.0a0 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - license: Zlib - purls: - - pkg:pypi/pybullet?source=conda-forge-mapping - size: 62942254 - timestamp: 1697298309816 + version: 3.2.6 + url: https://files.pythonhosted.org/packages/39/a6/6d6a8c535b82460527edc04b5fbf0374541d041668515e35822e53d7f66f/pybullet-3.2.6.tar.gz + sha256: da27525433c88698dc9fd8bc20fa4ae4d07738b4656633659ebd82c2d2884e08 - kind: pypi name: pybullet-robot - version: 0.1.2 + version: 0.1.3 path: . - sha256: 4e434d7ebeed36523478bf71039560c8ed07d75278f93fd3d90a7d34ccae6a7a + sha256: d1b5679d85ae4548d742a72ba86e61c570695b4a9a86e6bf930af61b5fa891e1 requires_dist: - robot-descriptions>=1.11.0,<2 + - numpy>=2.0.1,<3 + - scipy>=1.14.0,<2 + - pybullet>=3.2.6,<4 requires_python: '>=3.10' editable: true - kind: conda @@ -614,22 +382,6 @@ packages: purls: [] size: 32073625 timestamp: 1718621771849 -- kind: conda - name: python_abi - version: '3.12' - build: 4_cp312 - build_number: 4 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda - sha256: 182a329de10a4165f6e8a3804caf751f918f6ea6176dd4e5abcdae1ed3095bf6 - md5: dccc2d142812964fcc6abdc97b672dff - constrains: - - python 3.12.* *_cpython - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 6385 - timestamp: 1695147396604 - kind: conda name: readline version: '8.2' @@ -660,33 +412,48 @@ packages: - robomeshcat>=1.0.4 ; extra == 'opts' - yourdfpy>=0.0.56 ; extra == 'opts' requires_python: '>=3.7' -- kind: conda +- kind: pypi name: scipy version: 1.14.0 - build: py312hc2bc53b_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.0-py312hc2bc53b_1.conda - sha256: 6bd24bc823863bb568ffe0ebdfb506d4413d94d15b478b12a0b223d9373f531e - md5: eae80145f63aa04a02dda456d4883b46 - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libgcc-ng >=12 - - libgfortran-ng - - libgfortran5 >=12.3.0 - - liblapack >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - - numpy <2.3 - - numpy >=1.19,<3 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/scipy?source=conda-forge-mapping - size: 17653680 - timestamp: 1720324049729 + url: https://files.pythonhosted.org/packages/9b/00/ce54410e344b3a6032cd42ed53fe425cf57a66d28e337670292bbb419ebc/scipy-1.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a01cc03bcdc777c9da3cfdcc74b5a75caffb48a6c39c8450a9a05f82c4250a14 + requires_dist: + - numpy<2.3,>=1.23.5 + - pytest ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-timeout ; extra == 'test' + - pytest-xdist ; extra == 'test' + - asv ; extra == 'test' + - mpmath ; extra == 'test' + - gmpy2 ; extra == 'test' + - threadpoolctl ; extra == 'test' + - scikit-umfpack ; extra == 'test' + - pooch ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' + - array-api-strict ; extra == 'test' + - cython ; extra == 'test' + - meson ; extra == 'test' + - ninja ; sys_platform != 'emscripten' and extra == 'test' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' + - numpydoc ; extra == 'doc' + - jupytext ; extra == 'doc' + - myst-nb ; extra == 'doc' + - pooch ; extra == 'doc' + - jupyterlite-sphinx>=0.13.1 ; extra == 'doc' + - jupyterlite-pyodide-kernel ; extra == 'doc' + - mypy==1.10.0 ; extra == 'dev' + - typing-extensions ; extra == 'dev' + - types-psutil ; extra == 'dev' + - pycodestyle ; extra == 'dev' + - ruff>=0.0.292 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' + - rich-click ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' + - pydevtool ; extra == 'dev' + requires_python: '>=3.10' - kind: pypi name: smmap version: 5.0.1 @@ -738,122 +505,6 @@ packages: purls: [] size: 119815 timestamp: 1706886945727 -- kind: conda - name: xorg-kbproto - version: 1.0.7 - build: h7f98852_1002 - build_number: 1002 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-h7f98852_1002.tar.bz2 - sha256: e90b0a6a5d41776f11add74aa030f789faf4efd3875c31964d6f9cfa63a10dd1 - md5: 4b230e8381279d76131116660f5a241a - depends: - - libgcc-ng >=9.3.0 - license: MIT - license_family: MIT - purls: [] - size: 27338 - timestamp: 1610027759842 -- kind: conda - name: xorg-libx11 - version: 1.8.9 - build: hb711507_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-hb711507_1.conda - sha256: 66eabe62b66c1597c4a755dcd3f4ce2c78adaf7b32e25dfee45504d67d7735c1 - md5: 4a6d410296d7e39f00bacdee7df046e9 - depends: - - libgcc-ng >=12 - - libxcb >=1.16,<1.17.0a0 - - xorg-kbproto - - xorg-xextproto >=7.3.0,<8.0a0 - - xorg-xproto - license: MIT - license_family: MIT - purls: [] - size: 832198 - timestamp: 1718846846409 -- kind: conda - name: xorg-libxau - version: 1.0.11 - build: hd590300_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.11-hd590300_0.conda - sha256: 309751371d525ce50af7c87811b435c176915239fc9e132b99a25d5e1703f2d4 - md5: 2c80dc38fface310c9bd81b17037fee5 - depends: - - libgcc-ng >=12 - license: MIT - license_family: MIT - purls: [] - size: 14468 - timestamp: 1684637984591 -- kind: conda - name: xorg-libxdmcp - version: 1.1.3 - build: h7f98852_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.3-h7f98852_0.tar.bz2 - sha256: 4df7c5ee11b8686d3453e7f3f4aa20ceef441262b49860733066c52cfd0e4a77 - md5: be93aabceefa2fac576e971aef407908 - depends: - - libgcc-ng >=9.3.0 - license: MIT - license_family: MIT - purls: [] - size: 19126 - timestamp: 1610071769228 -- kind: conda - name: xorg-libxext - version: 1.3.4 - build: h0b41bf4_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda - sha256: 73e5cfbdff41ef8a844441f884412aa5a585a0f0632ec901da035a03e1fe1249 - md5: 82b6df12252e6f32402b96dacc656fec - depends: - - libgcc-ng >=12 - - xorg-libx11 >=1.7.2,<2.0a0 - - xorg-xextproto - license: MIT - license_family: MIT - purls: [] - size: 50143 - timestamp: 1677036907815 -- kind: conda - name: xorg-xextproto - version: 7.3.0 - build: h0b41bf4_1003 - build_number: 1003 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-xextproto-7.3.0-h0b41bf4_1003.conda - sha256: b8dda3b560e8a7830fe23be1c58cc41f407b2e20ae2f3b6901eb5842ba62b743 - md5: bce9f945da8ad2ae9b1d7165a64d0f87 - depends: - - libgcc-ng >=12 - license: MIT - license_family: MIT - purls: [] - size: 30270 - timestamp: 1677036833037 -- kind: conda - name: xorg-xproto - version: 7.0.31 - build: h7f98852_1007 - build_number: 1007 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-xproto-7.0.31-h7f98852_1007.tar.bz2 - sha256: f197bb742a17c78234c24605ad1fe2d88b1d25f332b75d73e5ba8cf8fbc2a10d - md5: b4a4381d54784606820704f7b5f05a15 - depends: - - libgcc-ng >=9.3.0 - license: MIT - license_family: MIT - purls: [] - size: 74922 - timestamp: 1607291557628 - kind: conda name: xz version: 5.2.6 diff --git a/pybullet_robot/bullet_robot.py b/pybullet_robot/bullet_robot.py index d22313a..9fec325 100644 --- a/pybullet_robot/bullet_robot.py +++ b/pybullet_robot/bullet_robot.py @@ -275,6 +275,7 @@ def __init__(self, object_id: int, cid: int = 0): cid (int, optional): Pybullet physics client ID. Defaults to 0. verbose (bool, optional): Verbosity flag. Defaults to False. """ + print(pb.getBodyInfo(object_id, physicsClientId=cid)) self.name = pb.getBodyInfo(object_id, physicsClientId=cid)[1].decode() self.base_name = pb.getBodyInfo(object_id, physicsClientId=cid)[0].decode() self.object_id = object_id @@ -293,7 +294,9 @@ class BulletRobot(BulletObject): def __init__( self, - urdf_path: str, + robot_uid: int = None, + urdf_path: str = None, + mjcf_path: str = None, cid: int = None, run_async: bool = True, ee_names: List[str] = None, @@ -310,13 +313,20 @@ def __init__( """Robot interface utility for a generic robot in pybullet. Args: - urdf_path (str): Path to urdf file of robot. + robot_uid (int, optional): If a robot instance is already created in a pybullet + instance, you can give the robots object unique id here directly and use + all available functions of this class on that robot. In this case, the + associated physics client id of the pybullet instance should be provided + via the `cid` argument. + urdf_path (str, optional): Path to URDF file of the robot to be loaded. + mjcf_path (str, optional): Path to MJCF file of the robot to be loaded. cid (int, optional): Physics client id of pybullet physics engine (if already running). If None provided, will create a new physics GUI instance. Defaults to None. run_async (bool, optional): Whether to run physics in a separate thread. If set to False, step() method has to be called in the main thread. Defaults to True. ee_names (List[str], optional): List of end-effectors for the robot. Defaults to None. use_fixed_base (bool, optional): Robot will be fixed in the world. Defaults to True. + NOTE: Only works if robot is created using the `urdf_path` argument. default_joint_positions (List[float], optional): Optional starting values for joints. Defaults to None. NOTE: These values should be in the order of joints in pybullet. place_on_ground (bool): If true, the base position height will automatically be adjusted @@ -326,10 +336,12 @@ def __init__( with the ground object only. It can be with any object in the world. default_base_position (Vector3D, optional): Default position of the base of the robot in the world frame during start-up. Note that the height value (z) is only used if - 'place_on_ground' is set to False. Defaults to np.zeros(3). + 'place_on_ground' is set to False. Defaults to np.zeros(3). Only used if robot is + created using the `urdf_path` argument. default_base_orientation (QuatType, optional): Default orientation quaternion in the world frame for the base of the robot during start-up. Defaults to - np.array([0, 0, 0, 1]). + np.array([0, 0, 0, 1]). Only used if robot is created using the `urdf_path` + argument. enable_torque_mode (bool, optional): Flag to enable effort controlling of the robot (control commands have to be sent continuously to keep the robot from falling). Defaults to True. @@ -357,13 +369,25 @@ def __init__( if self.ee_names is None: self.ee_names = [] - self.robot_id = pb.loadURDF( - urdf_path, - basePosition=self.default_start_pose[0], - baseOrientation=self.default_start_pose[1], - useFixedBase=use_fixed_base, - physicsClientId=self.cid, - ) + self.robot_id: int + """The uid of the robot in the physics engine.""" + + if robot_uid is not None: + self.robot_id = robot_uid + elif urdf_path is not None: + self.robot_id = pb.loadURDF( + urdf_path, + basePosition=self.default_start_pose[0], + baseOrientation=self.default_start_pose[1], + useFixedBase=use_fixed_base, + physicsClientId=self.cid, + ) + elif mjcf_path is not None: + self.robot_id = pb.loadMJCF(mjcf_path, physicsClientId=self.cid)[0] + else: + raise ValueError( + "Either robot_uid, urdf_path or mjcf_path should be provided." + ) super().__init__(object_id=self.robot_id, cid=self.cid) @@ -410,6 +434,7 @@ def __init__( ) self.urdf_path = urdf_path + self.mjcf_path = mjcf_path self._in_torque_mode = False if place_on_ground: diff --git a/pybullet_robot/utils/urdf_utils.py b/pybullet_robot/utils/robot_loader_utils.py similarity index 53% rename from pybullet_robot/utils/urdf_utils.py rename to pybullet_robot/utils/robot_loader_utils.py index f25e293..7b63761 100644 --- a/pybullet_robot/utils/urdf_utils.py +++ b/pybullet_robot/utils/robot_loader_utils.py @@ -10,6 +10,27 @@ """List of all available robots from the Awesome Robots List that can be used.""" +def _get_file_from_ard_pkg(description_pkg_name, filetype): + + try: + return getattr( + importlib.import_module(f"robot_descriptions.{description_pkg_name}"), + f"{filetype}_PATH", + ) + except AttributeError as e: + msg = f"{filetype} has not been provided for robot {description_pkg_name}." + logging.error(msg) + raise AttributeError(msg) from e + except (ModuleNotFoundError, KeyError) as e: + msg = ( + f"No description package called {description_pkg_name} in" + " Awesome Robot Descriptions list. Use on of the description names from " + "https://github.com/robot-descriptions/robot_descriptions.py/tree/main?tab=readme-ov-file#descriptions." + ) + logging.error(msg) + raise ModuleNotFoundError(msg) from e + + def get_urdf_from_awesome_robot_descriptions( robot_description_pkg_name: str, ) -> str: @@ -31,19 +52,32 @@ def get_urdf_from_awesome_robot_descriptions( Returns: str: Path to the robot's urdf file. """ - try: - return importlib.import_module( - f"robot_descriptions.{robot_description_pkg_name}" - ).URDF_PATH - except AttributeError as e: - msg = f"URDF has not been provided for robot {robot_description_pkg_name}." - logging.error(msg) - raise AttributeError(msg) from e - except (ModuleNotFoundError, KeyError) as e: - msg = ( - f"No description package called {robot_description_pkg_name} in" - " Awesome Robot Descriptions list. Use on of the description names from " - "https://github.com/robot-descriptions/robot_descriptions.py/tree/main?tab=readme-ov-file#descriptions." - ) - logging.error(msg) - raise ModuleNotFoundError(msg) from e + return _get_file_from_ard_pkg( + description_pkg_name=robot_description_pkg_name, filetype="URDF" + ) + + +def get_mjcf_from_awesome_robot_descriptions( + robot_description_pkg_name: str, +) -> str: + """Get robot mjcf file for the specified robot description package. + + The specified package should be from the list of awesome robot descriptions + (https://github.com/robot-descriptions/robot_descriptions.py/tree/main?tab=readme-ov-file#descriptions). + + The list of available robot descriptions can also be viewed in the variable `AWESOME_ROBOTS` + imported from `utils.urdf_utils`. + + Downloads description package for the specified robot and caches it locally (only needs + downloadin once). + + Args: + robot_description_pkg_name (str): The package name as specified in the Awesome Robot + Descriptions list. + + Returns: + str: Path to the robot's MJCF file. + """ + return _get_file_from_ard_pkg( + description_pkg_name=robot_description_pkg_name, filetype="MJCF" + ) diff --git a/pyproject.toml b/pyproject.toml index fb1aff4..6ca43d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,16 @@ [project] name = "pybullet_robot" -version = "0.1.2" +version = "0.1.3" description = "A generel Python interface class for robot simulations using PyBullet. Also provides an IK interface for multi-end-effector robots that uses bullet physics as a solver." readme = "README.md" authors = [{ name = "Saif Sidhik", email = "mail@saifsidhik.page" }] requires-python = ">= 3.10" -dependencies = ["robot-descriptions>=1.11.0,<2"] +dependencies = [ + "robot-descriptions>=1.11.0,<2", + "numpy>=2.0.1,<3", + "scipy>=1.14.0,<2", + "pybullet>=3.2.6,<4", +] [build-system] requires = ["setuptools"] @@ -20,6 +25,3 @@ pybullet_robot = { path = ".", editable = true } [tool.pixi.dependencies] python = ">=3.10" -pybullet = ">=3.25,<4" -numpy = ">=1.26.4,<2" -scipy = ">=1.14.0,<2"