diff --git a/doc/requirements_doc.txt b/doc/requirements_doc.txt index 7f4564a21..eefeae081 100644 --- a/doc/requirements_doc.txt +++ b/doc/requirements_doc.txt @@ -1,6 +1,6 @@ scikit-learn myst-parser -sphinx==6.2.1 +sphinx sphinx_markdown_tables==0.0.17 sphinx_gallery==0.14.0 sphinx-book-theme==1.0.1 @@ -28,7 +28,8 @@ https://github.com/Skylark0924/Rofunc/releases/download/v0.0.0.9/isaacgym-1.0rc4 matplotlib==3.7.1 numpy==1.21.6 open3d -kinpy transformers astroid<3 - +lxml +mujoco +mesh_to_sdf diff --git a/doc/source/index.md b/doc/source/index.md index 9c759c94f..be3f823d2 100644 --- a/doc/source/index.md +++ b/doc/source/index.md @@ -16,8 +16,8 @@ Rofunc package focuses on the **Imitation Learning (IL), Reinforcement Learning (RL) and Learning from Demonstration ( LfD)** for **(Humanoid) Robot Manipulation**. It provides valuable and convenient python functions, including _demonstration -collection, data -pre-processing, LfD algorithms, planning, and control methods_. We also provide an Isaac Gym-based robot simulator for +collection, data pre-processing, LfD algorithms, planning, and control methods_. We also provide an Isaac Gym-based +robot simulator for evaluation. This package aims to advance the field by building a full-process toolkit and validation platform that simplifies and standardizes the process of demonstration data collection, processing, learning, and its deployment on robots. @@ -59,7 +59,7 @@ The available functions and plans can be found as follows. | | | [`TD3(RofuncRL)`](https://rofunc.readthedocs.io/en/latest/lfd/RofuncRL/TD3.html) | ✅ | | | | | | | | | | `CQL(RofuncRL)` | ⛔ | | | | | | | | | | `TD3BC(RofuncRL)` | ⛔ | | | | | | | -| | | [`DTrans(RofuncRL)`](https://rofunc.readthedocs.io/en/latest/lfd/RofuncRL/DTrans.html) | ✅ | | | | | | | +| | | [`DTrans(RofuncRL)`](https://rofunc.readthedocs.io/en/latest/lfd/RofuncRL/DTrans.html) | ✅ | | | | | | | | | | `EDAC(RofuncRL)` | ⛔ | | | | | | | | | | [`AMP(RofuncRL)`](https://rofunc.readthedocs.io/en/latest/lfd/RofuncRL/AMP.html) | ✅ | | | | | | | | | | [`ASE(RofuncRL)`](https://rofunc.readthedocs.io/en/latest/lfd/RofuncRL/ASE.html) | ✅ | | | | | | | @@ -70,20 +70,28 @@ The available functions and plans can be found as follows. If you use rofunc in a scientific publication, we would appreciate citations to the following paper: ``` -@software{liu2023rofunc, - title={Rofunc: The full process python package for robot learning from demonstration and robot manipulation}, - author={Liu, Junjia and Li, Chenzui and Delehelle, Donatien and Li, Zhihao and Chen, Fei}, - month=jun, - year= 2023, - publisher={Zenodo}, - doi={10.5281/zenodo.8084510}, - url={https://doi.org/10.5281/zenodo.8084510} +@software{liu2023rofunc,  + title = {Rofunc: The Full Process Python Package for Robot Learning from Demonstration and Robot Manipulation}, + author = {Liu, Junjia and Dong, Zhipeng and Li, Chenzui and Li, Zhihao and Yu, Minghao and Delehelle, Donatien and Chen, Fei}, + year = {2023}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.10016946}, + url = {https://doi.org/10.5281/zenodo.10016946}, + dimensions = {true}, + google_scholar_id = {0EnyYjriUFMC}, } ``` +> **Warning**
+> **If our code is found to be used in a published paper without proper citation, we reserve the right to address this +> issue formally by contacting the editor to report potential academic misconduct!** +> +> **如果我们的代码被发现用于已发表的论文而没有被恰当引用,我们保留通过正式联系编辑报告潜在学术不端行为的权利。** + ## Related Papers -1. Robot cooking with stir-fry: Bimanual non-prehensile manipulation of semi-fluid objects ([IEEE RA-L 2022](https://arxiv.org/abs/2205.05960) | [Code](../../rofunc/learning/RofuncIL/structured_transformer/strans.py)) +1. Robot cooking with stir-fry: Bimanual non-prehensile manipulation of semi-fluid + objects ([IEEE RA-L 2022](https://arxiv.org/abs/2205.05960) | [Code](../../rofunc/learning/RofuncIL/structured_transformer/strans.py)) ``` @article{liu2022robot, @@ -98,7 +106,8 @@ If you use rofunc in a scientific publication, we would appreciate citations to } ``` -2. SoftGPT: Learn Goal-oriented Soft Object Manipulation Skills by Generative Pre-trained Heterogeneous Graph Transformer ([IROS 2023](https://arxiv.org/abs/2306.12677)|Code coming soon) +2. SoftGPT: Learn Goal-oriented Soft Object Manipulation Skills by Generative Pre-trained Heterogeneous Graph + Transformer ([IROS 2023](https://arxiv.org/abs/2306.12677)|Code coming soon) ``` @inproceedings{liu2023softgpt, @@ -111,7 +120,8 @@ If you use rofunc in a scientific publication, we would appreciate citations to } ``` -3. BiRP: Learning Robot Generalized Bimanual Coordination using Relative Parameterization Method on Human Demonstration ([IEEE CDC 2023](https://arxiv.org/abs/2307.05933) | [Code](../../rofunc/learning/ml/tpgmm.py)) +3. BiRP: Learning Robot Generalized Bimanual Coordination using Relative Parameterization Method on Human + Demonstration ([IEEE CDC 2023](https://arxiv.org/abs/2307.05933) | [Code](../../rofunc/learning/ml/tpgmm.py)) ``` @article{liu2023birp, diff --git a/doc/source/installation.rst b/doc/source/installation.rst index d68c146d4..47db6150d 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -31,6 +31,22 @@ Installation # [Option] For MacOS user (brew is required, Isaac Gym based simulator is not supported on MacOS) sh ./scripts/mac_install.sh + .. tab:: IsaacLab + + Please follow the :guilabel:`Isaac Sim` `documentation `__ to install the latest Isaac Sim release (:guilabel:`4.1.0`). Make sure the :guilabel:`$HOME/.local/share/ov/pkg/isaac-sim-4.1.0` is the default installation path. Then, run the following command to set up :guilabel:`IsaacLab`. + + .. code-block:: shell + + git clone https://github.com/Skylark0924/Rofunc.git + cd Rofunc + + # Create a conda environment + # Python 3.10 is strongly recommended + conda create -n rofunc python=3.10 + + + + .. tab:: OmniIsaacGym :guilabel:`Isaac Sim` has to be installed firstly by following this `documentation `_. Note that the :guilabel:`Isaac Sim` version should be :guilabel:`2022.2.1`, :guilabel:`2023.1.0` is not supported yet since its default python version is `3.10` which is not compatible with :guilabel:`rofunc`. diff --git a/examples/learning_rl/README.rst b/examples/learning_rl/README.rst index 8a43a20e7..986d05b7e 100644 --- a/examples/learning_rl/README.rst +++ b/examples/learning_rl/README.rst @@ -145,175 +145,186 @@ The following are examples of reinforcement learning methods for robot learning. '''Inference with pre-trained model in model zoo''' python examples/learning_rl/IsaacGym_RofuncRL/example_DexterousHands_RofuncRL.py --task=BiShadowHandOver --agent=ppo --inference - .. list-table:: Task Overview - :widths: 25 25 25 25 - :header-rows: 1 - - * - Tasks - - Animation - - Performance - - `ModelZoo `_ - * - `Ant `_ - - .. image:: ../../../img/task_gifs/AntRofuncRLPPO.gif - - - - ✅ - * - `Cartpole `_ - - - - - - - * - `FrankaCabinet `_ - - .. image:: ../../../img/task_gifs/FrankaCabinetRofuncRLPPO.gif - - - - ✅ - * - `FrankaCubeStack `_ - - - - - - - * - `CURICabinet `_ - - .. image:: ../../../img/task_gifs/CURICabinetRofuncRLPPO.gif - - - - ✅ - * - `CURICabinetImage `_ - - .. image:: ../../../img/task_gifs/CURICabinetRofuncRLPPO.gif - - - - - * - `CURICabinetBimanual `_ - - - - - - - * - `CURIQbSoftHandSynergyGrasp `_ - - .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspHammerRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspKnifeRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspLarge_clampRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspMugRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspPhillips_Screw_DriverRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspPower_drillRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspScissorsRofuncRLPPO.gif .. image:: ../../../img/task_gifs/CURIQbSoftHandSynergyGraspSpatulaRofuncRLPPO.gif - - - - ✅ - * - `Humanoid `_ - - .. image:: ../../../img/task_gifs/HumanoidRofuncRLPPO.gif - - - - ✅ - * - `HumanoidAMP_backflip `_ - - .. image:: ../../../img/task_gifs/HumanoidFlipRofuncRLAMP.gif - - - - ✅ - * - `HumanoidAMP_walk `_ - - - - - - ✅ - * - `HumanoidAMP_run `_ - - .. image:: ../../../img/task_gifs/HumanoidRunRofuncRLAMP.gif - - - - ✅ - * - `HumanoidAMP_dance `_ - - .. image:: ../../../img/task_gifs/HumanoidDanceRofuncRLAMP.gif - - - - ✅ - * - `HumanoidAMP_hop `_ - - .. image:: ../../../img/task_gifs/HumanoidHopRofuncRLAMP.gif - - - - ✅ - * - `HumanoidASEGetupSwordShield `_ - - .. image:: ../../../img/task_gifs/HumanoidASEGetupSwordShieldRofuncRLASE.gif - - - - ✅ - * - `HumanoidASEPerturbSwordShield `_ - - .. image:: ../../../img/task_gifs/HumanoidASEPerturbSwordShieldRofuncRLASE.gif - - - - ✅ - * - `HumanoidASEHeadingSwordShield `_ - - .. image:: ../../../img/task_gifs/HumanoidASEHeadingSwordShieldRofuncRLASE.gif - - - - ✅ - * - `HumanoidASELocationSwordShield `_ - - .. image:: ../../../img/task_gifs/HumanoidASELocationSwordShieldRofuncRLASE.gif - - - - ✅ - * - `HumanoidASEReachSwordShield `_ - - - - - - ✅ - * - `HumanoidASEStrikeSwordShield `_ - - .. image:: ../../../img/task_gifs/HumanoidASEStrikeSwordShieldRofuncRLASE.gif - - - - ✅ - * - `BiShadowHandBlockStack `_ - - .. image:: ../../../img/task_gifs/BiShadowHandBlockStackRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandBottleCap `_ - - .. image:: ../../../img/task_gifs/BiShadowHandBottleCapRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandCatchAbreast `_ - - .. image:: ../../../img/task_gifs/BiShadowHandCatchAbreastRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandCatchOver2Underarm `_ - - .. image:: ../../../img/task_gifs/BiShadowHandCatchOver2UnderarmRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandCatchUnderarm `_ - - .. image:: ../../../img/task_gifs/BiShadowHandCatchUnderarmRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandDoorOpenInward `_ - - .. image:: ../../../img/task_gifs/BiShadowHandDoorOpenInwardRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandDoorOpenOutward `_ - - .. image:: ../../../img/task_gifs/BiShadowHandDoorOpenOutwardRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandDoorCloseInward `_ - - .. image:: ../../../img/task_gifs/BiShadowHandDoorCloseInwardRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandDoorCloseOutward `_ - - .. image:: ../../../img/task_gifs/BiShadowHandDoorCloseOutwardRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandGraspAndPlace `_ - - .. image:: ../../../img/task_gifs/BiShadowHandGraspAndPlaceRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandLiftUnderarm `_ - - .. image:: ../../../img/task_gifs/BiShadowHandLiftUnderarmRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandOver `_ - - .. image:: ../../../img/task_gifs/BiShadowHandOverRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandPen `_ - - .. image:: ../../../img/task_gifs/BiShadowHandPenRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandPointCloud `_ - - - - - - - * - `BiShadowHandPushBlock `_ - - .. image:: ../../../img/task_gifs/BiShadowHandPushBlockRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandReOrientation `_ - - .. image:: ../../../img/task_gifs/BiShadowHandReOrientationRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandScissors `_ - - .. image:: ../../../img/task_gifs/BiShadowHandScissorsRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandSwingCup `_ - - .. image:: ../../../img/task_gifs/BiShadowHandSwingCupRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandSwitch `_ - - .. image:: ../../../img/task_gifs/BiShadowHandSwitchRofuncRLPPO.gif - - - - ✅ - * - `BiShadowHandTwoCatchUnderarm `_ - - .. image:: ../../../img/task_gifs/BiShadowHandTwoCatchUnderarmRofuncRLPPO.gif - - - - ✅ + .. table:: Task Overview + :widths: 20 35 35 10 + + +------------------+-----------------------------+-------------------------------+-------------+ + | Tasks | Animation | Performance | |ModelZoo| | + +==================+=============================+===============================+=============+ + | |Ant| | |Ant-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |Cartpole| | | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |FrC| | |FrC-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |FCS| | | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |CUC| | |CUC-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |CCI| | |CCI-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |CCB| | | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |CSG| | |CSG-gif1| | | ✅ | + | | |CSG-gif2| | | | + | | |CSG-gif3| | | | + | | |CSG-gif4| | | | + | | |CSG-gif5| | | | + | | |CSG-gif6| | | | + | | |CSG-gif7| | | | + | | |CSG-gif8| | | | + +------------------+-----------------------------+-------------------------------+-------------+ + | |Hod| | |Hod-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HAB| | |HAB-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HAW| | | | | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HAR| | |HAR-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HAD| | |HAD-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HAH| | |HAH-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HEG| | |HEG-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HEP| | |HEP-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HEH| | |HEH-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HER| | | | | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HEL| | |HEL-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |HES| | |HES-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SBS| | |SBS-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SBC| | |SBC-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SCA| | |SCA-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SU2| | |SU2-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SCU| | |SCU-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SOI| | |SOI-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SOO| | |SOO-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SCI| | |SCI-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SCO| | |SCO-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SGP| | |SGP-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SLU| | |SLU-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SHO| | |SHO-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SPE| | |SPE-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SPC| | | | | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SPB| | |SPB-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SRO| | |SRO-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SSC| | |SSC-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SSW| | |SSW-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |SWH| | |SWH-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + | |STC| | |STC-gif| | | ✅ | + +------------------+-----------------------------+-------------------------------+-------------+ + + + + .. |Ant-gif| image:: ../../img/task_gifs/AntRofuncRLPPO.gif + .. |FrC-gif| image:: ../../img/task_gifs/FrankaCabinetRofuncRLPPO.gif + .. |CUC-gif| image:: ../../img/task_gifs/CURICabinetRofuncRLPPO.gif + .. |CCI-gif| image:: ../../img/task_gifs/CURICabinetRofuncRLPPO.gif + .. |CSG-gif1| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspSpatulaRofuncRLPPO.gif + .. |CSG-gif2| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspHammerRofuncRLPPO.gif + .. |CSG-gif3| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspKnifeRofuncRLPPO.gif + .. |CSG-gif4| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspLarge_clampRofuncRLPPO.gif + .. |CSG-gif5| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspMugRofuncRLPPO.gif + .. |CSG-gif6| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspPhillips_Screw_DriverRofuncRLPPO.gif + .. |CSG-gif7| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspPower_drillRofuncRLPPO.gif + .. |CSG-gif8| image:: ../../img/task_gifs/CURIQbSoftHandSynergyGraspScissorsRofuncRLPPO.gif + .. |Hod-gif| image:: ../../img/task_gifs/HumanoidRofuncRLPPO.gif + .. |HAB-gif| image:: ../../img/task_gifs/HumanoidFlipRofuncRLAMP.gif + .. |HAR-gif| image:: ../../img/task_gifs/HumanoidRunRofuncRLAMP.gif + .. |HAD-gif| image:: ../../img/task_gifs/HumanoidDanceRofuncRLAMP.gif + .. |HAH-gif| image:: ../../img/task_gifs/HumanoidHopRofuncRLAMP.gif + .. |HEG-gif| image:: ../../img/task_gifs/HumanoidASEGetupSwordShieldRofuncRLASE.gif + .. |HEP-gif| image:: ../../img/task_gifs/HumanoidASEPerturbSwordShieldRofuncRLASE.gif + .. |HEH-gif| image:: ../../img/task_gifs/HumanoidASEHeadingSwordShieldRofuncRLASE.gif + .. |HEL-gif| image:: ../../img/task_gifs/HumanoidASELocationSwordShieldRofuncRLASE.gif + .. |HES-gif| image:: ../../img/task_gifs/HumanoidASEStrikeSwordShieldRofuncRLASE.gif + .. |SBS-gif| image:: ../../img/task_gifs/BiShadowHandBlockStackRofuncRLPPO.gif + .. |SBC-gif| image:: ../../img/task_gifs/BiShadowHandBottleCapRofuncRLPPO.gif + .. |SCA-gif| image:: ../../img/task_gifs/BiShadowHandCatchAbreastRofuncRLPPO.gif + .. |SU2-gif| image:: ../../img/task_gifs/BiShadowHandCatchOver2UnderarmRofuncRLPPO.gif + .. |SCU-gif| image:: ../../img/task_gifs/BiShadowHandCatchUnderarmRofuncRLPPO.gif + .. |SOI-gif| image:: ../../img/task_gifs/BiShadowHandDoorOpenInwardRofuncRLPPO.gif + .. |SOO-gif| image:: ../../img/task_gifs/BiShadowHandDoorOpenOutwardRofuncRLPPO.gif + .. |SCI-gif| image:: ../../img/task_gifs/BiShadowHandDoorCloseInwardRofuncRLPPO.gif + .. |SCO-gif| image:: ../../img/task_gifs/BiShadowHandDoorCloseOutwardRofuncRLPPO.gif + .. |SGP-gif| image:: ../../img/task_gifs/BiShadowHandGraspAndPlaceRofuncRLPPO.gif + .. |SLU-gif| image:: ../../img/task_gifs/BiShadowHandLiftUnderarmRofuncRLPPO.gif + .. |SHO-gif| image:: ../../img/task_gifs/BiShadowHandOverRofuncRLPPO.gif + .. |SPE-gif| image:: ../../img/task_gifs/BiShadowHandPenRofuncRLPPO.gif + .. |SPB-gif| image:: ../../img/task_gifs/BiShadowHandPushBlockRofuncRLPPO.gif + .. |SRO-gif| image:: ../../img/task_gifs/BiShadowHandReOrientationRofuncRLPPO.gif + .. |SSC-gif| image:: ../../img/task_gifs/BiShadowHandScissorsRofuncRLPPO.gif + .. |SSW-gif| image:: ../../img/task_gifs/BiShadowHandSwingCupRofuncRLPPO.gif + .. |SWH-gif| image:: ../../img/task_gifs/BiShadowHandSwitchRofuncRLPPO.gif + .. |STC-gif| image:: ../../img/task_gifs/BiShadowHandTwoCatchUnderarmRofuncRLPPO.gif + + .. |ModelZoo| replace:: `Model Zoo `__ + .. |Ant| replace:: `Ant `__ + .. |Cartpole| replace:: `Cartpole `__ + .. |FrC| replace:: `FrankaCabinet `__ + .. |FCS| replace:: `FrankaCubeStack `__ + .. |CUC| replace:: `CURICabinet `__ + .. |CCI| replace:: `CURICabinet Image `__ + .. |CCB| replace:: `CURICabinet Bimanual `__ + .. |CSG| replace:: `CURIQbSoftHand SynergyGrasp `__ + .. |Hod| replace:: `Humanoid `__ + .. |HAB| replace:: `HumanoidAMP Backflip `__ + .. |HAW| replace:: `HumanoidAMP Walk `__ + .. |HAR| replace:: `HumanoidAMP Run `__ + .. |HAD| replace:: `HumanoidAMP Dance `__ + .. |HAH| replace:: `HumanoidAMP Hop `__ + .. |HEG| replace:: `HumanoidASE GetupSwordShield `__ + .. |HEP| replace:: `HumanoidASE PerturbSwordShield `__ + .. |HEH| replace:: `HumanoidASE HeadingSwordShield `__ + .. |HER| replace:: `HumanoidASE ReachSwordShield `__ + .. |HEL| replace:: `HumanoidASE LocationSwordShield `__ + .. |HES| replace:: `HumanoidASE StrikeSwordShield `__ + .. |SBS| replace:: `BiShadowHand BlockStack `__ + .. |SBC| replace:: `BiShadowHand BottleCap `__ + .. |SCA| replace:: `BiShadowHand CatchAbreast `__ + .. |SU2| replace:: `BiShadowHand CatchOver2Underarm `__ + .. |SCU| replace:: `BiShadowHand CatchUnderarm `__ + .. |SOI| replace:: `BiShadowHand DoorOpenInward `__ + .. |SOO| replace:: `BiShadowHand DoorOpenOutward `__ + .. |SCI| replace:: `BiShadowHand DoorCloseInward `__ + .. |SCO| replace:: `BiShadowHand DoorCloseOutward `__ + .. |SGP| replace:: `BiShadowHand GraspAndPlace `__ + .. |SLU| replace:: `BiShadowHand LiftUnderarm `__ + .. |SHO| replace:: `BiShadowHand Over `__ + .. |SPE| replace:: `BiShadowHand Pen `__ + .. |SPC| replace:: `BiShadowHand PointCloud `__ + .. |SPB| replace:: `BiShadowHand PushBlock `__ + .. |SRO| replace:: `BiShadowHand ReOrientation `__ + .. |SSC| replace:: `BiShadowHand Scissors `__ + .. |SSW| replace:: `BiShadowHand SwingCup `__ + .. |SWH| replace:: `BiShadowHand Switch `__ + .. |STC| replace:: `BiShadowHand TwoCatchUnderarm `__ .. tab:: OmniIsaacGym diff --git a/rofunc/utils/robolab/coord/transform_tensor.py b/rofunc/utils/robolab/coord/transform_tensor.py new file mode 100644 index 000000000..a7bef0202 --- /dev/null +++ b/rofunc/utils/robolab/coord/transform_tensor.py @@ -0,0 +1,463 @@ +# Copyright 2023, Junjia LIU, jjliu@mae.cuhk.edu.hk +# +# 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 +# +# https://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. + +""" +Coordinate transformation functions with tensor support +---------------------------------------------------------- +| This module provides functions to convert between different coordinate systems with tensor support. +| Note + +1. Quaternions ix+jy+kz+w are represented as [x, y, z, w]. +2. Euler angles are represented as [roll, pitch, yaw], in radians. The rotation order is ZYX. +3. Rotation matrices are represented as (3, 3). +4. Homogeneous matrices are represented as (4, 4). +""" + +import numpy as np +import torch + +# epsilon for testing whether a number is close to zero +_EPS = torch.finfo(torch.float32).eps * 4.0 + + +def check_pos_tensor(pos): + """ + Check if the input position is valid. + + :param pos: (batch, 3) or (3, ) + :return: position + + >>> check_pos_tensor([0, 0, 0]) + tensor([[0., 0., 0.]]) + >>> check_pos_tensor([[0, 0, 0]]) + tensor([[0., 0., 0.]]) + >>> check_pos_tensor(np.array([0, 0, 0])) + tensor([[0., 0., 0.]]) + """ + pos = torch.tensor(pos, dtype=torch.float32) + if len(pos.shape) == 1: + pos = pos.unsqueeze(0) + assert pos.shape[-1] == 3, "The last dimension of the input tensor should be 3." + return pos + + +def check_quat_tensor(quat): + """ + Check if the input quat is normalized. + + :param quat: (batch, 4) or (4, ) + :return: normalized quat + + >>> check_quat_tensor([0, 5, 0, 1]) + tensor([[0.0000, 0.9806, 0.0000, 0.1961]]) + >>> check_quat_tensor([[0, 2, 0, 1]]) + tensor([[0.0000, 0.8944, 0.0000, 0.4472]]) + >>> check_quat_tensor(np.array([1, 5, 5.435, 1])) + tensor([[0.1330, 0.6650, 0.7228, 0.1330]]) + """ + quat = torch.tensor(quat, dtype=torch.float32) + if len(quat.shape) == 1: + quat = quat.unsqueeze(0) + assert quat.shape[-1] == 4, "The last dimension of the input tensor should be 4." + norm = torch.norm(quat, dim=-1, keepdim=True) + if torch.any(norm == 0): + raise ValueError( + f"The input quat is invalid. The index of the invalid quat is {torch.where(norm == 0)[0]}") + quat = quat / (norm + _EPS) + return quat + + +def check_rot_matrix_tensor(rot_matrix): + """ + Check if the input rotation matrix is valid, orthogonal, and normalize it if necessary. + + :param rot_matrix: Input rotation matrix + :return: Validated and normalized rotation matrix + + >>> from rofunc.utils.robolab.coord.transform import random_rot_matrix + >>> rot_matrix = random_rot_matrix() * 3 + >>> torch.allclose(check_rot_matrix_tensor(rot_matrix) * 3, torch.tensor(rot_matrix, dtype=torch.float32)) + True + """ + rot_matrix = torch.tensor(rot_matrix, dtype=torch.float32) + if len(rot_matrix.shape) == 2: + rot_matrix = rot_matrix.unsqueeze(0) + # Check if the matrix is square + if rot_matrix.shape[-1] != rot_matrix.shape[-2]: + raise ValueError("Input matrix is not square.") + + # # Check orthogonality: R^T * R should be equal to the identity matrix + # identity_matrix = torch.eye(rot_matrix.shape[-1]) + # matrix_product = torch.matmul(rot_matrix.transpose(-1, -2), rot_matrix) + # if not torch.allclose(matrix_product, identity_matrix): + # raise ValueError("Input matrix is not orthogonal.") + + # Normalize the matrix if necessary + normalized_rot_matrix = rot_matrix + column_norms = torch.norm(normalized_rot_matrix, dim=-2) + if not torch.allclose(column_norms, torch.ones_like(column_norms)): + normalized_rot_matrix = normalized_rot_matrix / column_norms.unsqueeze(-1) + + return normalized_rot_matrix + + +def check_euler_tensor(euler): + """ + Check if the input euler angles are valid. + + :param euler: (batch, 3) or (3, ) + :return: euler angles + + >>> check_euler_tensor([1.57, 0, 0]) + tensor([[1.5700, 0.0000, 0.0000]]) + >>> check_euler_tensor([[0, 0, 0]]) + tensor([[0., 0., 0.]]) + >>> check_euler_tensor(np.array([0, 0, 0])) + tensor([[0., 0., 0.]]) + """ + euler = torch.tensor(euler, dtype=torch.float32) + if len(euler.shape) == 1: + euler = euler.unsqueeze(0) + assert euler.shape[-1] == 3, "The last dimension of the input tensor should be 3." + return euler + + +def random_quat_tensor(batch_size, rand=None): + """ + Return uniform random unit quat. + + :param batch_size: Batch size + :param rand: Random number generator (optional) + :return: Random unit quat, [x, y, z, w] + + >>> torch.allclose(torch.norm(random_quat_tensor(100), dim=-1), torch.ones(100)) + True + >>> rand_quat = random_quat_tensor(100) + >>> torch.allclose(check_quat_tensor(rand_quat), rand_quat) + True + """ + if rand is None: + rand = torch.rand + + random_values = rand(batch_size, 3) + r1 = torch.sqrt(1 - random_values[:, 0]) + r2 = torch.sqrt(random_values[:, 0]) + pi2 = 2 * torch.pi + t1 = pi2 * random_values[:, 1] + t2 = pi2 * random_values[:, 2] + + x = r1 * torch.sin(t1) + y = r1 * torch.cos(t1) + z = r2 * torch.sin(t2) + w = r2 * torch.cos(t2) + + quat = torch.stack([x, y, z, w], dim=-1) + + return quat + + +def random_rot_matrix_tensor(batch_size, rand=None): + """ + Generate random rotation matrix. quat = [x, y, z, w]. + + :param batch_size: Batch size + :param rand: Random number generator (optional) + :return: Random rotation matrix + + >>> rand_rot_matrix = random_rot_matrix_tensor(100) + >>> torch.allclose(rand_rot_matrix.det(), torch.ones(100)) + True + >>> torch.allclose(check_rot_matrix_tensor(rand_rot_matrix), rand_rot_matrix) + True + >>> from rofunc.utils.robolab.coord.transform import check_rot_matrix + >>> torch.allclose(torch.tensor(check_rot_matrix(rand_rot_matrix[0]), dtype=torch.float32), rand_rot_matrix[0]) + True + """ + if rand is None: + rand = torch.rand + + quat = random_quat_tensor(batch_size, rand) + + wx, wy, wz, ww = quat[:, 0], quat[:, 1], quat[:, 2], quat[:, 3] + xx = wx * wx + xy = wx * wy + xz = wx * wz + xw = wx * ww + yy = wy * wy + yz = wy * wz + yw = wy * ww + zz = wz * wz + zw = wz * ww + + rot_matrix = torch.stack( + [ + 1 - 2 * (yy + zz), + 2 * (xy - zw), + 2 * (xz + yw), + 2 * (xy + zw), + 1 - 2 * (xx + zz), + 2 * (yz - xw), + 2 * (xz - yw), + 2 * (yz + xw), + 1 - 2 * (xx + yy), + ], + dim=1, + ).view(batch_size, 3, 3) + + return rot_matrix + + +def quat_from_rot_matrix_tensor(rot_matrix): + """ + Convert rotation matrix to quat. [x, y, z, w] + + :param rot_matrix: + :return: quat, [x, y, z, w] + + >>> quat_from_rot_matrix_tensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + tensor([[0., 0., 0., 1.]]) + >>> quat_from_rot_matrix_tensor([[0.9362934, -0.2896295, 0.1986693], [0.3129918, 0.9447025, -0.0978434], [-0.1593451, 0.1537920, 0.9751703]]) + tensor([[0.0641, 0.0912, 0.1534, 0.9819]]) + >>> rand_rot_matrix = random_rot_matrix_tensor(100) + >>> torch.allclose(check_rot_matrix_tensor(rand_rot_matrix), rot_matrix_from_quat_tensor(quat_from_rot_matrix_tensor(rand_rot_matrix)), rtol=1e-03, atol=1e-03) + True + """ + rot_matrix = check_rot_matrix_tensor(rot_matrix) + + trace = rot_matrix[:, 0, 0] + rot_matrix[:, 1, 1] + rot_matrix[:, 2, 2] + r = torch.sqrt(1 + trace) + + qw = 0.5 * r + qx = (rot_matrix[:, 2, 1] - rot_matrix[:, 1, 2]) / (2 * r) + qy = (rot_matrix[:, 0, 2] - rot_matrix[:, 2, 0]) / (2 * r) + qz = (rot_matrix[:, 1, 0] - rot_matrix[:, 0, 1]) / (2 * r) + + quat = torch.stack([qx, qy, qz, qw], dim=-1) + return quat + + +def quat_from_euler_tensor(euler): + """ + Convert euler angles to quat. The rotation order is ZYX. + + :param euler: (batch, 3) or (3, ), [roll, pitch, yaw], the rotation order is ZYX. + :return: quat, [x, y, z, w] + + >>> quat_from_euler_tensor([0, 0, 0]) + tensor([[0., 0., 0., 1.]]) + >>> quat_from_euler_tensor([[0, 0, 0]]) + tensor([[0., 0., 0., 1.]]) + >>> quat_from_euler_tensor(np.array([0, 0, 0])) + tensor([[0., 0., 0., 1.]]) + >>> quat_from_euler_tensor([[0, 1.23, 0.57], [0.5, 0.3, 0.7], [0.1, 0.2, 0.3]]) + tensor([[-0.1622, 0.5537, 0.2296, 0.7838], + [ 0.1801, 0.2199, 0.2938, 0.9126], + [ 0.0343, 0.1060, 0.1436, 0.9833]]) + """ + euler = check_euler_tensor(euler) + + roll = euler[:, 0] + pitch = euler[:, 1] + yaw = euler[:, 2] + + cy = torch.cos(yaw * 0.5) + sy = torch.sin(yaw * 0.5) + cp = torch.cos(pitch * 0.5) + sp = torch.sin(pitch * 0.5) + cr = torch.cos(roll * 0.5) + sr = torch.sin(roll * 0.5) + + qx = sr * cp * cy - cr * sp * sy + qy = cr * sp * cy + sr * cp * sy + qz = cr * cp * sy - sr * sp * cy + qw = cr * cp * cy + sr * sp * sy + + quat = torch.stack([qx, qy, qz, qw], dim=-1) + + return quat + + +def rot_matrix_from_quat_tensor(quat): + """ + Convert quat to rotation matrix. + + :param quat: [x, y, z, w] + :return: + + >>> rot_matrix_from_quat_tensor([0, 0, 0, 1]) + tensor([[[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]]) + >>> rot_matrix_from_quat_tensor([[0.06146124, 0, 0, 0.99810947], [0.2794439, 0.0521324, 0.3632374, 0.8872722]]) + tensor([[[ 1.0000, 0.0000, 0.0000], + [ 0.0000, 0.9924, -0.1227], + [ 0.0000, 0.1227, 0.9924]], + + [[ 0.7307, -0.6154, 0.2955], + [ 0.6737, 0.5799, -0.4580], + [ 0.1105, 0.5338, 0.8384]]]) + """ + quat = check_quat_tensor(quat) + x, y, z, w = quat[:, 0], quat[:, 1], quat[:, 2], quat[:, 3] + + r11 = 1 - 2 * (y ** 2 + z ** 2) + r12 = 2 * (x * y - z * w) + r13 = 2 * (x * z + y * w) + r21 = 2 * (x * y + z * w) + r22 = 1 - 2 * (x ** 2 + z ** 2) + r23 = 2 * (y * z - x * w) + r31 = 2 * (x * z - y * w) + r32 = 2 * (y * z + x * w) + r33 = 1 - 2 * (x ** 2 + y ** 2) + + rot_matrix = torch.stack([ + torch.stack([r11, r12, r13], dim=-1), + torch.stack([r21, r22, r23], dim=-1), + torch.stack([r31, r32, r33], dim=-1) + ], dim=-2) + + return check_rot_matrix_tensor(rot_matrix) + + +def rot_matrix_from_euler_tensor(euler): + """ + Convert euler angles to rotation matrix. + + :param euler: (batch, 3) or (3, ), [roll, pitch, yaw] in radian + :return: Rotation matrix + + >>> rot_matrix_from_euler_tensor([0, 0, 0]) + tensor([[[1., 0., 0.], + [0., 1., 0.], + [-0., 0., 1.]]]) + >>> rot_matrix_from_euler_tensor([[0.5, 0.3, 0.7], [1.33, 0.2, -0.03]]) + tensor([[[ 0.7307, -0.4570, 0.5072], + [ 0.6154, 0.7625, -0.1996], + [-0.2955, 0.4580, 0.8384]], + + [[ 0.9796, 0.2000, 0.0182], + [-0.0294, 0.2326, -0.9721], + [-0.1987, 0.9518, 0.2337]]]) + """ + euler = check_euler_tensor(euler) + + roll = euler[:, 0] + pitch = euler[:, 1] + yaw = euler[:, 2] + + cos_r = torch.cos(roll) + sin_r = torch.sin(roll) + cos_p = torch.cos(pitch) + sin_p = torch.sin(pitch) + cos_y = torch.cos(yaw) + sin_y = torch.sin(yaw) + + batch_size = euler.size(0) + device = euler.device + + rot_matrix = torch.zeros((batch_size, 3, 3), device=device) + rot_matrix[:, 0, 0] = cos_y * cos_p + rot_matrix[:, 0, 1] = cos_y * sin_p * sin_r - sin_y * cos_r + rot_matrix[:, 0, 2] = cos_y * sin_p * cos_r + sin_y * sin_r + rot_matrix[:, 1, 0] = sin_y * cos_p + rot_matrix[:, 1, 1] = sin_y * sin_p * sin_r + cos_y * cos_r + rot_matrix[:, 1, 2] = sin_y * sin_p * cos_r - cos_y * sin_r + rot_matrix[:, 2, 0] = -sin_p + rot_matrix[:, 2, 1] = cos_p * sin_r + rot_matrix[:, 2, 2] = cos_p * cos_r + + return rot_matrix + + +def euler_from_quat_tensor(quat): + """ + Convert quat to euler angles. + + :param quat: [x, y, z, w] + :return: euler angles, [roll, pitch, yaw] in radian + + >>> euler_from_quat_tensor(torch.tensor([[0, 0, 0, 1.]])) + tensor([[0., 0., 0.]]) + >>> euler_from_quat_tensor(torch.tensor([[0.06146124, 0, 0, 0.99810947], [0.2794439, 0.0521324, 0.3632374, 0.8872722]])) + tensor([[ 0.1230, 0.0000, 0.0000], + [ 0.5669, -0.1107, 0.7449]]) + """ + quat = check_quat_tensor(quat) + + qx = quat[:, 0] + qy = quat[:, 1] + qz = quat[:, 2] + qw = quat[:, 3] + + roll = torch.atan2(2 * (qw * qx + qy * qz), 1 - 2 * (qx * qx + qy * qy)) + pitch = torch.asin(torch.clamp(2 * (qw * qy - qz * qx), -1, 1)) + yaw = torch.atan2(2 * (qw * qz + qx * qy), 1 - 2 * (qy * qy + qz * qz)) + + euler = torch.stack([roll, pitch, yaw], dim=-1) + + return euler + + +def euler_from_rot_matrix_tensor(rot_matrix): + """ + Convert rotation matrix to euler angles. + + :param rot_matrix: + :return: + + >>> euler_from_rot_matrix_tensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + tensor([[0., -0., 0.]]) + >>> euler_from_rot_matrix_tensor([[[ 0.7307, -0.4570, 0.5072], [ 0.6154, 0.7625, -0.1996], [-0.2955, 0.4580, 0.8384]], [[ 0.9796, 0.2000, 0.0182], [-0.0294, 0.2326, -0.9721], [-0.1987, 0.9518, 0.2337]]]) + tensor([[ 0.5000, 0.3000, 0.6999], + [ 1.3300, 0.2000, -0.0300]]) + """ + rot_matrix = check_rot_matrix_tensor(rot_matrix) + + r11, r12, r13 = rot_matrix[:, 0, 0], rot_matrix[:, 0, 1], rot_matrix[:, 0, 2] + r21, r22, r23 = rot_matrix[:, 1, 0], rot_matrix[:, 1, 1], rot_matrix[:, 1, 2] + r31, r32, r33 = rot_matrix[:, 2, 0], rot_matrix[:, 2, 1], rot_matrix[:, 2, 2] + + pitch = -torch.asin(r31) + roll = torch.atan2(r32 / torch.cos(pitch), r33 / torch.cos(pitch)) + yaw = torch.atan2(r21 / torch.cos(pitch), r11 / torch.cos(pitch)) + + euler = torch.stack([roll, pitch, yaw], dim=-1) + + return euler + + +def homo_matrix_from_quat_tensor(quat, pos=None): + """ + Convert quat and pos to homogeneous matrix + + :param quat: + :param pos: + :return: + """ + quat = check_quat_tensor(quat) + if pos is not None: + pos = check_pos_tensor(pos) + assert quat.shape[0] == pos.shape[0] + else: + pos = torch.zeros((quat.shape[0], 3)) + + batch_size = quat.shape[0] + device = quat.device + + homo_matrix = torch.zeros((batch_size, 4, 4), device=device) + rot_matrix = rot_matrix_from_quat_tensor(quat) + homo_matrix[:, :3, :3] = rot_matrix + homo_matrix[:, :3, 3] = pos + homo_matrix[:, 3, 3] = 1 + return homo_matrix diff --git a/scripts/mac_install.sh b/scripts/install_mac.sh similarity index 100% rename from scripts/mac_install.sh rename to scripts/install_mac.sh diff --git a/scripts/install.sh b/scripts/install_w_isaacgym.sh similarity index 100% rename from scripts/install.sh rename to scripts/install_w_isaacgym.sh diff --git a/scripts/install_w_baselines.sh b/scripts/install_w_isaacgym_w_baselines.sh similarity index 100% rename from scripts/install_w_baselines.sh rename to scripts/install_w_isaacgym_w_baselines.sh diff --git a/scripts/install_w_isaaclab.sh b/scripts/install_w_isaaclab.sh new file mode 100644 index 000000000..ed411c08b --- /dev/null +++ b/scripts/install_w_isaaclab.sh @@ -0,0 +1,17 @@ +# Define aliases for the conda environment +alias pip3rfl="$HOME/anaconda3/envs/rofunc_isaaclab/bin/pip" +alias py3rfl="$HOME/anaconda3/envs/rofunc_isaaclab/bin/python3.10" + +# Download IsaacLab and install it +cd ../ +git clone https://github.com/isaac-sim/IsaacLab.git +cd IsaacLab +ln -s $HOME/.local/share/ov/pkg/isaac-sim-4.1.0 _isaac_sim +./isaaclab.sh --install + +# Install the requirements and rofunc +pip3rfl install shutup +pip3rfl install omegaconf +pip3rfl install hydra-core +pip3rfl install nestle +pip3rfl install gdown \ No newline at end of file diff --git a/scripts/update.sh b/scripts/update_package.sh similarity index 100% rename from scripts/update.sh rename to scripts/update_package.sh