├── .ipynb_checkpoints └── plot-checkpoint.ipynb ├── README.md ├── __pycache__ ├── reacher_sawyer_env_boundingbox.cpython-36.pyc └── wrapper2.cpython-36.pyc ├── arms └── Sawyer.ttm ├── data ├── reward_log_dense.npy ├── reward_log_dense_aug.npy └── reward_log_sparse.npy ├── figures ├── comparison.pdf ├── comparison.png ├── reacher.gif ├── reacher.png └── training.png ├── hands ├── BaxterGripper.ttm └── JacoHand.ttm ├── model ├── sac_multi_policy ├── sac_multi_q1 ├── sac_multi_q2 └── trained_model │ ├── augmented_dense_reward │ ├── sac_multi_policy │ ├── sac_multi_q1 │ └── sac_multi_q2 │ └── dense_reward │ ├── sac_multi_policy │ ├── sac_multi_q1 │ └── sac_multi_q2 ├── objects └── table.ttm ├── plot.ipynb ├── reward_log.npy ├── sac_learn.py ├── sawyer_grasp_env_boundingbox.py ├── scenes ├── sawyer_reacher_rl_new.ttt └── sawyer_reacher_rl_new_ik.ttt └── training.pdf /.ipynb_checkpoints/plot-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Display Training Curve" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 10, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "data": { 17 | "image/png": "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\n", 18 | "text/plain": [ 19 | "
" 20 | ] 21 | }, 22 | "metadata": { 23 | "needs_background": "light" 24 | }, 25 | "output_type": "display_data" 26 | } 27 | ], 28 | "source": [ 29 | "import numpy as np\n", 30 | "from matplotlib import pyplot as plt\n", 31 | "reward = np.load('reward_log.npy')\n", 32 | "\n", 33 | "def smooth(y, radius=100, mode='two_sided'):\n", 34 | " if len(y) < 2*radius+1:\n", 35 | " return np.ones_like(y) * y.mean()\n", 36 | " elif mode == 'two_sided':\n", 37 | " convkernel = np.ones(2 * radius+1)\n", 38 | " return np.convolve(y, convkernel, mode='same') / \\\n", 39 | " np.convolve(np.ones_like(y), convkernel, mode='same')\n", 40 | " elif mode == 'causal':\n", 41 | " convkernel = np.ones(radius)\n", 42 | " out = np.convolve(y, convkernel,mode='full') / \\\n", 43 | " np.convolve(np.ones_like(y), convkernel, mode='full')\n", 44 | " return out[:-radius+1]\n", 45 | "\n", 46 | " \n", 47 | "def moving_sum(y, window=100):\n", 48 | " c = y.cumsum()\n", 49 | " c[window:] = c[window:] - c[:-window]\n", 50 | " return c/float(window)\n", 51 | " \n", 52 | "success_list=np.zeros(len(reward))\n", 53 | "success_list[np.where(reward>-0)]=1 # reward larger than 0 indicates successful grasping\n", 54 | "\n", 55 | "early_stop=4500\n", 56 | "\n", 57 | "fig, axs = plt.subplots(2)\n", 58 | "# plot smoothed reward curve\n", 59 | "axs[0].plot(smooth(reward[:early_stop], radius=100))\n", 60 | "axs[0].set_title('Learning Curve')\n", 61 | "axs[0].set_ylabel('Smoothed Reward')\n", 62 | "axs[0].grid()\n", 63 | "\n", 64 | "axs[1].plot(moving_sum(success_list[:early_stop]))\n", 65 | "axs[1].set_xlabel('Training Episode')\n", 66 | "axs[1].set_ylabel('Success Rate')\n", 67 | "axs[1].grid()\n", 68 | "plt.tight_layout()\n", 69 | "plt.savefig('training.pdf')\n", 70 | "plt.show()\n" 71 | ] 72 | } 73 | ], 74 | "metadata": { 75 | "kernelspec": { 76 | "display_name": "Python 3", 77 | "language": "python", 78 | "name": "python3" 79 | }, 80 | "language_info": { 81 | "codemirror_mode": { 82 | "name": "ipython", 83 | "version": 2 84 | }, 85 | "file_extension": ".py", 86 | "mimetype": "text/x-python", 87 | "name": "python", 88 | "nbconvert_exporter": "python", 89 | "pygments_lexer": "ipython2", 90 | "version": "2.7.15" 91 | } 92 | }, 93 | "nbformat": 4, 94 | "nbformat_minor": 2 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chapter 16: Robot Learning in Simulation (Project 4) 2 | ## Description: 3 | Example of Sawyer robot learning to reach the target with paralleled Soft Actor-Critic (SAC) algorithm, using PyRep for Sawyer robot simulation and game building. The environment is wrapped into OpenAI Gym format. 4 |

5 | 6 |

7 | 8 | ## Dependencies: 9 | * [V-REP 3.6.2](http://www.coppeliarobotics.com/previousVersions) 10 | * [PyRep](https://github.com/deep-reinforcement-learning-book/PyRep) 11 | * PyTorch 12 | 13 | Note: 14 | * The later version of V-REP 3.6.2 is renamed CoppeliaSim after verison 4.0.0, which may have some incompatible issues with PyRep during the process of this project, so we suggest to use V-REP 3.6.2 [here](http://www.coppeliarobotics.com/previousVersions) and the maintained PyRep in our repository. 15 | * The official repository of PyRep is [here](https://github.com/stepjam/PyRep), but we maintain a stable version [here](https://github.com/deep-reinforcement-learning-book/PyRep) in our repository for supporting V-REP 3.6.2, please use the version we provide ([here](https://github.com/deep-reinforcement-learning-book/PyRep)) for avoiding unnecessary incompatibility. 16 | 17 | ## Contents: 18 | * `arms/`: object models of arms; 19 | * `hands/`: object models of grippers; 20 | * `objects/`: models of other objects in the scene; 21 | * `scenes/`: built scenes for Sawyer robot grasping; 22 | * `figures/`: figures for displaying; 23 | * `model/`: the model after training, and two pre-trained models with different reward functions; 24 | * `data/`: reward logs of with different reward functions; 25 | * `sawyer_grasp_env_boundingbox.py`: script of Sawyer robot grasping environment; 26 | * `sac_learn.py`: pralleled Soft Actor-Critic algorithm for solving Sawyer robot grasping task; 27 | * `reward_log.npy`: log of episode reward during training; 28 | * `plot.ipynb`: displaying the learning curves. 29 | 30 | 31 | ## Usage: 32 | 0. First check the environment can run successfully: 33 | 34 | `$ python sawyer_grasp_env_boundingbox.py` 35 | 36 | If it works properly with VRep called to run a scene, with Sawyer robot arm moving randomly, then go to next step; otherwise check the dependencies for necessary packages and versions. 37 | 1. Run `$ python sac_learn.py --train` for training the policy 38 | 39 | 2. Run `$ python sac_learn.py --test` for testing the trained policy, remember to change the `trained_model_path`, which is default to be the trained model we provided. 40 | 41 | 3. The training process will provide a `reward_log.npy` file for recording the reward value during training, which can be displayed with `$ jupyter notebook` in a new terminal, choose `plot.ipynb`and Shift+Enter to run the first cell, shown as follows: 42 |

43 | 44 |

45 | 46 | ## Authors: 47 | [Zihan Ding](https://github.com/quantumiracle), [Yanhua Huang](https://github.com/Officium) 48 | 49 | 50 | ## Citing: 51 | 52 | ``` 53 | @misc{DeepReinforcementLearning-Chapter16-RobotLearninginSimulation, 54 | author = {Zihan Ding, Yanhua Huang}, 55 | title = {Chapter16-RobotLearninginSimulation}, 56 | year = {2019}, 57 | publisher = {GitHub}, 58 | journal = {GitHub repository}, 59 | howpublished = {\url{https://github.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation}}, 60 | } 61 | ``` 62 | 63 | or 64 | 65 | ``` 66 | @book{deepRL-2020, 67 | title={Deep Reinforcement Learning: Fundamentals, Research, and Applications}, 68 | editor={Hao Dong, Zihan Ding, Shanghang Zhang}, 69 | author={Hao Dong, Zihan Ding, Shanghang Zhang, Hang Yuan, Hongming Zhang, Jingqing Zhang, Yanhua Huang, Tianyang Yu, Huaqing Zhang, Ruitong Huang}, 70 | publisher={Springer Nature}, 71 | note={\url{http://www.deepreinforcementlearningbook.org}}, 72 | year={2020} 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /__pycache__/reacher_sawyer_env_boundingbox.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/__pycache__/reacher_sawyer_env_boundingbox.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/wrapper2.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/__pycache__/wrapper2.cpython-36.pyc -------------------------------------------------------------------------------- /arms/Sawyer.ttm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/arms/Sawyer.ttm -------------------------------------------------------------------------------- /data/reward_log_dense.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/data/reward_log_dense.npy -------------------------------------------------------------------------------- /data/reward_log_dense_aug.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/data/reward_log_dense_aug.npy -------------------------------------------------------------------------------- /data/reward_log_sparse.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/data/reward_log_sparse.npy -------------------------------------------------------------------------------- /figures/comparison.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/figures/comparison.pdf -------------------------------------------------------------------------------- /figures/comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/figures/comparison.png -------------------------------------------------------------------------------- /figures/reacher.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/figures/reacher.gif -------------------------------------------------------------------------------- /figures/reacher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/figures/reacher.png -------------------------------------------------------------------------------- /figures/training.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/figures/training.png -------------------------------------------------------------------------------- /hands/BaxterGripper.ttm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/hands/BaxterGripper.ttm -------------------------------------------------------------------------------- /hands/JacoHand.ttm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/hands/JacoHand.ttm -------------------------------------------------------------------------------- /model/sac_multi_policy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/sac_multi_policy -------------------------------------------------------------------------------- /model/sac_multi_q1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/sac_multi_q1 -------------------------------------------------------------------------------- /model/sac_multi_q2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/sac_multi_q2 -------------------------------------------------------------------------------- /model/trained_model/augmented_dense_reward/sac_multi_policy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/augmented_dense_reward/sac_multi_policy -------------------------------------------------------------------------------- /model/trained_model/augmented_dense_reward/sac_multi_q1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/augmented_dense_reward/sac_multi_q1 -------------------------------------------------------------------------------- /model/trained_model/augmented_dense_reward/sac_multi_q2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/augmented_dense_reward/sac_multi_q2 -------------------------------------------------------------------------------- /model/trained_model/dense_reward/sac_multi_policy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/dense_reward/sac_multi_policy -------------------------------------------------------------------------------- /model/trained_model/dense_reward/sac_multi_q1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/dense_reward/sac_multi_q1 -------------------------------------------------------------------------------- /model/trained_model/dense_reward/sac_multi_q2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/model/trained_model/dense_reward/sac_multi_q2 -------------------------------------------------------------------------------- /objects/table.ttm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/objects/table.ttm -------------------------------------------------------------------------------- /plot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Display Training Curve" 8 | ] 9 | }, 10 | { 11 | "cell_type": "code", 12 | "execution_count": 85, 13 | "metadata": {}, 14 | "outputs": [ 15 | { 16 | "data": { 17 | "image/png": "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\n", 18 | "text/plain": [ 19 | "
" 20 | ] 21 | }, 22 | "metadata": { 23 | "needs_background": "light" 24 | }, 25 | "output_type": "display_data" 26 | } 27 | ], 28 | "source": [ 29 | "import numpy as np\n", 30 | "from matplotlib import pyplot as plt\n", 31 | "reward = np.load('reward_log.npy')\n", 32 | "\n", 33 | "def smooth(y, radius=10, mode='two_sided'):\n", 34 | " if len(y) < 2*radius+1:\n", 35 | " return np.ones_like(y) * y.mean()\n", 36 | " elif mode == 'two_sided':\n", 37 | " convkernel = np.ones(2 * radius+1)\n", 38 | " return np.convolve(y, convkernel, mode='same') / \\\n", 39 | " np.convolve(np.ones_like(y), convkernel, mode='same')\n", 40 | " elif mode == 'causal':\n", 41 | " convkernel = np.ones(radius)\n", 42 | " out = np.convolve(y, convkernel,mode='full') / \\\n", 43 | " np.convolve(np.ones_like(y), convkernel, mode='full')\n", 44 | " return out[:-radius+1]\n", 45 | "\n", 46 | " \n", 47 | "def moving_sum(y, window=100):\n", 48 | " c = y.cumsum()\n", 49 | " c[window:] = c[window:] - c[:-window]\n", 50 | " return c/float(window)\n", 51 | "\n", 52 | "def success_filter(r, threshold=4):\n", 53 | " success_list=np.zeros(len(r))\n", 54 | " success_list[np.where(r>threshold)]=1 # reward larger than threshold indicates successful grasping\n", 55 | " return success_list\n", 56 | " \n", 57 | "success_list=np.zeros(len(reward))\n", 58 | "success_list[np.where(reward>4)]=1 # reward larger than 0 indicates successful grasping\n", 59 | "\n", 60 | "early_stop=400000\n", 61 | "\n", 62 | "fig, axs = plt.subplots(2)\n", 63 | "# plot smoothed reward curve\n", 64 | "axs[0].plot(smooth(reward[:early_stop], radius=100))\n", 65 | "axs[0].set_title('Learning Curve')\n", 66 | "axs[0].set_ylabel('Smoothed Reward')\n", 67 | "axs[0].grid()\n", 68 | "\n", 69 | "axs[1].plot(moving_sum(success_filter(reward)[:early_stop]))\n", 70 | "axs[1].set_xlabel('Training Episode')\n", 71 | "axs[1].set_ylabel('Success Rate')\n", 72 | "axs[1].grid()\n", 73 | "plt.tight_layout()\n", 74 | "plt.savefig('training.pdf')\n", 75 | "plt.show()\n" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "## Comparision with different reward functions" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 81, 88 | "metadata": {}, 89 | "outputs": [ 90 | { 91 | "data": { 92 | "image/png": "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86tXr86VV17J+++/zy233HLa/pCQkJzRluPi4rj55ps5duwYTz755Fml+0xkT19x8uTJnBnTi5qJvTSoKqpKtWolGVTcmNLxySdufqazsXIlrF3rXk+bBjVrnn26TDlThYkT4dFHC96/YgVERhZ9iQrQgKokVVQNs4MbAFVNFJHGPkiTz40eDcXMYFCozMyQAlv1R0QUP4fnjBkzmDlzZs76jh07SE5O5j//+Q/PPPNMToAzdepU1qxZwyuvvALAkCFDePjhh+nbty9vvfUWEydOpF69enTu3JkaNWrwyiuvMHLkSEJCQvj++++Ji4vj7bff5t1332X58uVERkYydepUwE2m+cQTT5CamkqbNm145513CA0NJSwsjD/84Q988sknpKamMnfuXIKDg5kyZQoBAQFMnz6dyZMnc8EFF3D33XezZ88ewJVA9ezZk4SEBEaMGMG+ffvo0aMHeQeQvOaaa3j00UcLDHDyaty4Ma+//jrdu3dn/PjxZGVlMWbMGGJiYkhNTeXee+/lrrvuIiYmhvHjx9OwYUM2btxI165dmT59OiLCmDFjmD9/PoGBgQwcOJBJkyblTItxapoLExISQkREBPv27QPg+PHjjBo1io0bN5Kens748eMZNmwYgwcP5tlnn6VTp045AdG4ceMYN24cLVu2ZMSIEQwbNozExETS09OZMGECw4YNY/fu3URHRxMZGUlsbCyff/45ixcv5tlnn833XI0piUOHID4ebr01t9FucXbtcj89c9+esfbt4YMPoEOHs7uOKUcHDsCbb7p5LRIT3QLug80zJQ8ATZpA8+blk8YSKkmAkyUi56nqHgARaQV4NwyyIS0tjZ07dxKWp3x29uzZ3HTTTfTu3Zsff/yRgwcP0qRJk0Kv8euvv/L000+zdu1aateuzRVXXEHnzp1z9icmJrJ8+XLmz5/P0KFDWbZsGW+++Sbdu3dn3bp1nHvuuUyYMIFFixZRq1YtJk6cyAsvvMC4ceMAaNiwIWvXruWFF15g0qRJvPnmm9x9992EhobmVNncfPPNPPjgg/Tq1Ys9e/YQHR3Nli1bePLJJ+nVqxfjxo3js88+46233spJV4cOHVi9erVX71Pr1q3JzMwkLi6Ojz/+mLp167J69WpSU1Pp2bMnAwcOBNwcWZs2baJ58+b07NmTZcuWceGFFzJv3jy2bt2KiHDkiIvHH3jggQLTXJjExES2b9+eM8/WM888wxVXXMHbb7/NkSNHuPTSS+nfvz+9e/dm6dKltGrVisDAQJYtWwa4mdqnTJlCcHAw8+bNo06dOsTHxxMVFcXQoW7YqO3btzNt2jSioqLYv38/TzzxBLGxsdStW5d+/frRpUsXr94vYzZvhlmzYEKeFpEXXwynzJdboD594P77vTvWVGFbtrjoNLt5wO9/D7VquVKcOnXKN21noSQBzmPAtyLyDSBAb6CSDZDtFFfSUpSkpJNnNLx/fHw89erVy7dt1qxZzJs3j2rVqvHb3/6WDz/8sMi2F6tWreLyyy+nQYMGANxwww1s27YtZ//VV1+NiNCxY0eaNGlCx44dAbj44ovZvXs3e/fuZfPmzTmlF2lpafTo0SPn/Ouuuw6AiIgIPv/88wLTsGjRIjZv3pyzfuzYMZKTk1myZAkfffQRAIMHD6Z+/fo5xwQEBFC9evUST42wcOFC1q9fz5w5cwA3oef27dupXr06l156Keeee25Oenfv3k1UVBTBwcHcfvvtDBkyhCFDhhSZ5lMtXbqUzp07s337dkaPHk3Tpk1z0jF//nwmTZoEQEpKCnv27KF37968/PLLhIeHM3jwYL788ktOnDjBrl27aN++Penp6YwdO5YlS5ZQrVo19u3bx8GDBwFo1aoVUVFRAKxcuZK+ffvSyPM1evjw4fmeq/FvmZluMsl16zqcNk0BuBF+s43T0RiRAAATwklEQVQfD506wbBhrkmEMUU6fNhN8rVli6uWeust6NcPwsPLO2WloiRTNXwhIpcAUZ5No1U13jfJqnpCQkJIScltk71hwwa2b9/OgAEDABdshIeHc9999xEYGJivoW3e84qSXa1RrVq1fFUc1apVIyMjg4CAAAYMGMCsWbOKPD8gIKDQRsFZWVmsWLGC4OBgr9KULTU11atzdu7cSUBAAI0bN0ZVmTx5MtHR+Zt5xcTE5MtfdnoDAwNZtWoVX331FXPmzOGVV15h8eLFhaY5KW9/VnLb4OzatYuoqChuvPFGIiIiUFXmzp1L+/bt8x2flpbGmjVraN26NQMGDCA+Pp433niDrl27Aq5K8tChQ8TGxhIUFERYWFjOs6xVq5b3b56pEk6ccKPzfvQRvP766WPBFCZ7Qsng4PpcdNHp+7t2dXMx3XwzhIaWXnpNOTpxws1P4W1d45nK/uVq3RoeeAD++Eff3q+MlaSR8bXAYlX91LNeT0SuUdXCp7w2OerXr09mZiYpKSkEBwcza9Ysxo8fz6N5GnGFh4fz888/ExYWxn/+8x+ysrLYt28fq1atAqB79+6MHj2axMREateuzdy5c3NKabwRFRXFvffey08//UTbtm05fvw4+/bto127doWeU7t2bY4dO5azPnDgQCZPnswjjzwCwLp164iIiKBPnz7MnDmTxx9/nAULFpCYXX8LJCQk0LBhQ4KKaXSW3VbmvvvuQ0SIjo7m1Vdf5YorriAoKIht27bRokWLQs9PTk7mxIkTDBo0iJ49e9K6desi01yY8PBwxowZw8SJE5k1axbR0dFMnjyZyZMnIyJ8//33dOnSherVq9OyZUs+/PBDxo0bx6FDh3j44YdzqvOOHj1K48aNCQoK4uuvv+bnn38u8H6RkZE88MADJCQkUKdOHT788MN8VY+m8khLg0mTIM+fTI7p08HTrAsovP1mQUJDoXv3bxkw4PKzT6Sp+J57zrWJ6dvXDfHsS5VxtlIvlaSK6glVnZe9oqpHROQJwAIcLw0cOJBvv/2W/v37M3v27NOqga699lpmz57N/7d37kFWF1ce/3xleLiiIo9QiBJRQYGIiCNR1iGihocuCr5ZS1wfiVZwV4pKjNFV2Y1J0FUscWNcVl3jIz6iCVJbWiooGi0RAXkIKKAhESIPURFYYBg4+0f3ZX4zde/MvcMM93U+Vbdu//p2/359bv8e59fndJ+bbrqJnj170rdvX/r06cPAaCDv3r07t9xyC4MGDaJjx44cf/zxHHrooVkfv0uXLjz22GOMHTuWnTt3AnDnnXc2qOCMGjWKiy66iBdffJEHHniAqVOnMn78ePr3709NTQ1DhgzhoYce4o477mDs2LH069ePwYMH06NHj737eOONNzj33HPT7n/79u0MGDCAXbt2UVFRwRVXXMHEiRMBuPbaa1m9ejUDBw7EzOjSpQvTp2c+3bZs2cL555/Pjh07MDOmTJkCkLHNDXH99ddzzz33sHr1am677TYmTJhA//792bNnDz179uR/o12gqqqKWbNmceCBB1JVVcWaNWuoqqoC4PLLL2fUqFGccMIJVFZWcnyGSIHdunVj0qRJnHbaaXTo0KFB5ctpeTZvDtOb6/Pkk2ENs4ZYsSK8fAOk8xM/88ww07Z3b+jWLbd2zZ7tLo9FS3U1fL13jg6tv/oKNmxIX3bRomBrPPpoeP31sJCQ0ySUnO3SYEFpsZn1r5e3xMyyH0LYT1RWVtq8efPq5C1fvpw+ffrs875z9SNJsmDBAu677z6eaOwu2QBbt26lffv21NTUMGbMGK6++mrGjBnT5P2lY19kTMcFF1zA5MmTG1Sk8kFzy9nSNOUcnj17NmfkeTXRlmZfZaypgenTYft2ePfdsBpvQ5zXSHjh7t3DOmjNHUPJ+7JIWb4cKitrNd9seeklGDmyZdq0H2jJvpQ038wqGyuXywjOPElTgF/H7fHA/KY0rlwZOHAgQ4cOZffu3XXWwsmFSZMmMXPmTHbs2MGwYcMYPXp0M7eyeamurmb06NEFp9w45cnatWHF3erq2ry5c2Hlyrrl7r0X0rmMjRgRXqwdJyP33gsffFC7/dRT4Xv48L3a8YoVKxq+J37nO3WnZjtNItdQDbcBz8bt1whKjpMDV++jE1dqJk+x0KZNG8aNG5fvZjglzM6dBzA/w6vW3XfDrFm12ymfzR496gZyHDwYHnsszDzq1AnqTXh0ypWdO2Hq1OBYlViBPiM1NbWRRY85Jnz36gUTJ8J11+01N/1t9mx6l9pIVQGSyyyqbcDNLdiWFsfMkNsznSIkW1NyufHcczB+/Hf5ooH5nB06QHKNyRNPhB/8oOXb5hQQmzeHgFjJobtsePjh2tUQf/Sj7Pxh2rSBn/40LIjn5JVcZlG9QZqF/czszCzqjgDuB1oBD5vZ5Hq/twUeB04GNgGXmtnq+NvPgGuA3cC/mNkr2bY5Sbt27di0aROdOnVyJccpKsyMTZs25Tw1vxgxS+/gW5/p04MlILjataWqCuIkuTpIUFUFOfjiO4VOdXXtHPv168PIyPbtDdeZMyd35SbFKacEM1OvXk2r7+SNXExUyeiD7YALgfSLpSSQ1Irgt/N9YA3wvqQZZrYsUewa4CszO1bSZcBdwKWS+gKXAf2Aw4GZknqbWRZjhXU54ogjWLNmDRs3bsy1ah1S07xzrJT9ohcFQPWuXbQpgDgiLU0xydmuupojvvgCFi/OqV6nJUtqh8wLmK+3VvDWss782zPHseDT7O1Dw09az41Df8/IIUdCpktsdob8Hj3AV4wuLh58EMan8YwYMKBhu+LgwaGv04U7b4zWrX0mU5GS9SyqtJWluWY2qJEypwGTUkE544gMZvarRJlXYpl3JVUA64AuRJNYqmyyXEPHTDeLal+Z+9p8fnntSnbV7KJ1RfYPxQO37eSwTduatS2OU2o8zVi+Jqx+fSwruYZHGqkB5/AS/VmyT8d9b2hvdh5YHEru1m3baF/iC0Q2KKMZQ14O78UvjhuERaVj07cOZv73imt0Ze3f1tL98MxrepUCWzds5fGrWiaieLPPopLUMbF5AMGclM3Ab3fgs8T2GqB+GNK9ZcysRtJmoFPMn1OvbtqzQtIPiaEjunbtyuzZs7NoWvYsmLWcd/56YZPqmmBLW2H+EuA4Gaihc/fnOXLgFP6u40e81GpXozXCKlLtg+E8x2vruI17+PlL2zl67srGCzsFw7r24l/POZAXjqsXymRR877QtjRmhjaW9gOhc+vOzf4czpVcTFTzqb2V1AB/JpiWCgIzmwZMgzCC09zz78844wwmTi7RdRrqUQ4yQnnIWVwyXhQ/uVFcMjadcpAzGxkfjp9ixvty/5DLLKqmRt9aCxyZ2D4i5qUrsyaaqA4lOBtnU9dxHMdxHKcOjfrgSDoF+MzM1sXtcQQH478Q/GG+bKR+BbACOIugnLwP/KOZLU2UGQ+cYGbXRyfjC8zsEkn9gN8BgwhOxrOAXo05GUvaGNvXEnQGSj3IaDnICOUhp8tYOpSDnOUgI5SHnC0p47fNrEtjhbIZwfkv4GwASUOAyYRF/wYQTEINjilHn5obgFcI08QfNbOlkv4dmGdmM4BHgCckrQK+JMycIpZ7DlhGMIuNz2YGVTaCNxVJ87JxbipmykFGKA85XcbSoRzkLAcZoTzkLAQZs1FwWiVGaS4FppnZC8ALkhZmcxAze4mUT2Bt3u2J9A7g4gx1fwH8IpvjOI7jOI7jQJgN1RitopkJgpnp9cRvuTgpO47jOI7j7BeyUVCeBt6U9AWwHfgTgKRjgcJfQaz5mZbvBuwHykFGKA85XcbSoRzkLAcZoTzkzLuMWS30J+lUoBvwaoxJhaTeQHszW9CyTXQcx3Ecx8mNfVrJ2HEcx3EcpxDJxgfHcRzHcRynqHAFJ0skjZD0saRVkm7Od3uaiqQjJb0haZmkpZJujPmTJK2VtDB+zknU+VmU+2NJw/PX+tyQtFrSkijPvJjXUdJrklbG78NiviRNjXIuljQwv61vHEnHJfproaRvJE0ohb6U9KikDZI+TOTl3HeSrozlV0q6Mh+yZCKDjP8h6aMoxx8ldYj5R0nanujThxJ1To7n+ar4PxRUDIAMcuZ8jhbyPTiDjM8m5FudmnVc5H2Z6flRmNemmfmnkQ9h/Z5PgKOBNsAioG++29VEWboBA2P6YMIijH2BScCP05TvG+VtC/SM/0OrfMuRpayrgc718u4Gbo7pm4G7Yvoc4GVCKJJTgffy3f4cZW1FCFL77VLoS2AIMBD4sKl9B3QEPo3fh8X0YfmWrREZhwEVMX1XQsajkuXq7WdulFvxfxiZb9mykDOnc7TQ78HpZKz3+73A7SXQl5meHwV5bfoITnYMAlaZ2admVg08A5yf5zY1CTP73KJjuJltAZaTIYBp5HzgGTPbaWZ/BlYR/o9i5XzgtzH9W2B0Iv9xC8wBOkjqlo8GNpGzgE/MrKEVvIumL83sLcKin0ly7bvhwGtm9qWZfQW8Boxo+dZnRzoZzexVM6uJm3MI4WkyEuU8xMzmWHhyPE7t/1IQZOjLTGQ6Rwv6HtyQjHEU5hLCjOSMFElfZnp+FOS16QpOdqSLiF70se4lHQWcBLwXs26Iw4iPpoYYKW7ZDXhV0nyFaPMAXc3s85heB3SN6WKWE8Lq38kbaKn1JeTed8Uu79WEt98UPSV9IOlNSVUxrztBrhTFJGMu52gx92UVsN7MkqHri74v6z0/CvLadAWnTJHUHngBmGBm3wC/AY4hhOD4nDCkWuycbmYDgZHAeIVQI3uJb0lFP41QUhvgPOD3MasU+7IOpdJ3mZB0KyE8zVMx63Ogh5mdBEwEfifpkHy1rxko+XM0wVjqvnwUfV+meX7spZCuTVdwsqOkoppLak04OZ8ysz8AmNl6M9ttZnuA/6bWdFG0spvZ2vi9AfgjQab1KdNT/N4QixetnAQFboGZrYfS7MtIrn1XlPJK+ifgH4DL48OCaLLZFNPzCf4ovQnyJM1YRSFjE87RYu3LCuAC4NlUXrH3ZbrnBwV6bbqCkx3vA70k9Yxvy5cBM/LcpiYR7cGPAMvNbEoiP+lvMgZIzQaYAVwmqa2knkAvgiNcQSPpIEkHp9IE580PCfKkPPavBF6M6RnAuOj1fyqwOTHkWujUeUMstb5MkGvfvQIMk3RYNIEMi3kFi6QRwE3AeWb2f4n8LpJaxfTRhL77NMr5jaRT47U9jtr/pWBpwjlarPfgs4GPzGyv6amY+zLT84NCvTab22u5VD8Eb/AVBG371ny3Zx/kOJ0wfLgYWBg/5wBPAEti/gygW6LOrVHujykwr/4G5DyaMNNiEbA01WdAJ2AWsBKYCXSM+QJ+HeVcAlTmW4Ys5TwI2AQcmsgr+r4kKGyfA7sI9vlrmtJ3BD+WVfFzVb7lykLGVQTfhNS1+VAse2E8jxcCC4BRif1UEhSET4D/JC7gWiifDHLmfI4W8j04nYwx/zHg+npli7kvMz0/CvLa9JWMHcdxHMcpOdxE5TiO4zhOyeEKjuM4juM4JYcrOI7jOI7jlByu4DiO4ziOU3K4guM4juM4TsnhCo7jOBmR1Em1UY/XqW4E6DZZ7uN/JB3XSJnxki5vpja/rRB1OtXOZxsp/11J9zXDcZ+UVFCxgxynnPFp4o7jZIWkScBWM7unXr4I95I9eWlYPSS9DdxgZgv383GfBJ43s+n787iO46THR3Acx8kZScdKWibpKcKiZd0kTZM0T9JSSbcnyr4taYCkCklfS5osaZGkdyV9K5a5U9KERPnJkubGkZjBMf8gSS/E4z4fjzUghzY/Kek3CsFXV0gaGfPPljQ9ps+MbVsoaUE85gGSpkj6UNISSRfFsgdIelDSR5JeAzonjnWKQiDF+ZJeltQ1baMcx2kxXMFxHKepHA/cZ2Z9LcT9utnMKoETge9L6pumzqHAm2Z2IvAuYTXTdMjMBgE/AVLK0j8D68ysL/BzQiTjTDybMFFNTuQfCZwCjAKmSWpbr95PgB+a2QBgCLADuBjok5ILuC8qZhcBPYG+wFVAShFrC9wPXGhmJwNPxvY6jrMfqch3AxzHKVo+MbN5ie2xkq4h3FcOJzz4l9Wrs93MXo7p+UBVhn3/IVHmqJg+HbgLwMwWSVraQNsuzWCiei6a0j6W9BkhDlCSd4D748jUC2a2VdLpwNNmthtYF01glQQF6Om4vzWSZsd99AH6ATOD9Y5WhOX7HcfZj7iC4zhOU9mWSkjqBdwIDDKzr6M/Srs0daoT6d1kvgftzKJMU6jvdFhn28zulDQDOBeYI+msJhxDwGIzy6S8OY6zH3ATleM4zcEhwBZCNORuwPAWOMY7wCUAkk4gjBDlysUxsnFvgrlqZfJHSceY2WIz+xUhEOJxwJ8IEa4PiL40fw/MA94CLo353YHvxd0sA7pLGhT32UZSvya01XGcfcBHcBzHaQ4WEB7sHwF/ISgjzc0DwOOSlsVjLQM2Zyj7rKTtMb3ezFIK11qCctKe4GtTHc1IKX4sqQrYQ4iY/CpQA5watw2YaGYbJD0PDI3t+CvBpwgz2xkdkadKOoRgorqX4IztOM5+wqeJO45TFEiqACrMbEc0ib0K9DKzmizr+zRuxykjfATHcZxioT0wKyo6Aq7LVrlxHKf88BEcx3Ecx3FKDncydhzHcRyn5HAFx3Ecx3GcksMVHMdxHMdxSg5XcBzHcRzHKTlcwXEcx3Ecp+T4f4sf48knO+6wAAAAAElFTkSuQmCC\n", 93 | "text/plain": [ 94 | "
" 95 | ] 96 | }, 97 | "metadata": { 98 | "needs_background": "light" 99 | }, 100 | "output_type": "display_data" 101 | } 102 | ], 103 | "source": [ 104 | "import numpy as np\n", 105 | "from matplotlib import pyplot as plt\n", 106 | "file='./data/'\n", 107 | "reward_sparse = np.load(file+'reward_log_sparse.npy')\n", 108 | "reward_dense = np.load(file+'reward_log_dense.npy')\n", 109 | "reward_dense_aug = np.load(file+'reward_log_dense_aug.npy')\n", 110 | "\n", 111 | "def smooth(y, radius=100, mode='two_sided'):\n", 112 | " if len(y) < 2*radius+1:\n", 113 | " return np.ones_like(y) * y.mean()\n", 114 | " elif mode == 'two_sided':\n", 115 | " convkernel = np.ones(2 * radius+1)\n", 116 | " return np.convolve(y, convkernel, mode='same') / \\\n", 117 | " np.convolve(np.ones_like(y), convkernel, mode='same')\n", 118 | " elif mode == 'causal':\n", 119 | " convkernel = np.ones(radius)\n", 120 | " out = np.convolve(y, convkernel,mode='full') / \\\n", 121 | " np.convolve(np.ones_like(y), convkernel, mode='full')\n", 122 | " return out[:-radius+1]\n", 123 | "\n", 124 | " \n", 125 | "def moving_sum(y, window=1000):\n", 126 | " c = y.cumsum()\n", 127 | " c[window:] = c[window:] - c[:-window]\n", 128 | " return c/float(window)\n", 129 | "\n", 130 | "def success_filter(r, threshold=4):\n", 131 | " success_list=np.zeros(len(r))\n", 132 | " success_list[np.where(r>threshold)]=1 # reward larger than threshold indicates successful grasping\n", 133 | " return success_list\n", 134 | "\n", 135 | "fig, axs = plt.subplots(4, figsize=(8,6))\n", 136 | "axs[0].plot(reward_sparse, c='g', label='Sparse Reward')\n", 137 | "axs[0].set_title('Learning Curve (Sparse Reward)')\n", 138 | "axs[0].set_ylabel('Reward')\n", 139 | "axs[0].grid()\n", 140 | "\n", 141 | "axs[1].plot(smooth(reward_dense), c='r', label='Dense Reward')\n", 142 | "axs[1].set_title('Learning Curve (Dense Reward)')\n", 143 | "axs[1].set_ylabel('Smoothed Reward')\n", 144 | "axs[1].grid()\n", 145 | "\n", 146 | "axs[2].plot(smooth(reward_dense_aug), c='b', label='(Augmented) Dense Reward')\n", 147 | "axs[2].set_title('Learning Curve (Augmented Reward)')\n", 148 | "axs[2].set_ylabel('Smoothed Reward')\n", 149 | "axs[2].grid()\n", 150 | "\n", 151 | "axs[3].plot(moving_sum(success_filter(reward_sparse)), c='g', label='Sparse Reward')\n", 152 | "axs[3].plot(moving_sum(success_filter(reward_dense)), c='r', label='Dense Reward')\n", 153 | "axs[3].plot(moving_sum(success_filter(reward_dense_aug)), c='b', label='(Augmented) Dense Reward')\n", 154 | "axs[3].set_title('Success')\n", 155 | "axs[3].set_xlabel('Training Episode')\n", 156 | "axs[3].set_ylabel('Success Rate')\n", 157 | "axs[3].grid()\n", 158 | "axs[3].legend()\n", 159 | "\n", 160 | "plt.tight_layout()\n", 161 | "plt.savefig('comparison.png')\n", 162 | "plt.show()\n" 163 | ] 164 | } 165 | ], 166 | "metadata": { 167 | "kernelspec": { 168 | "display_name": "Python 3", 169 | "language": "python", 170 | "name": "python3" 171 | }, 172 | "language_info": { 173 | "codemirror_mode": { 174 | "name": "ipython", 175 | "version": 2 176 | }, 177 | "file_extension": ".py", 178 | "mimetype": "text/x-python", 179 | "name": "python", 180 | "nbconvert_exporter": "python", 181 | "pygments_lexer": "ipython2", 182 | "version": "2.7.15" 183 | } 184 | }, 185 | "nbformat": 4, 186 | "nbformat_minor": 2 187 | } 188 | -------------------------------------------------------------------------------- /reward_log.npy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deep-reinforcement-learning-book/Chapter16-Robot-Learning-in-Simulation/604f06384106e365d28bb51b1280d884c09ead9e/reward_log.npy -------------------------------------------------------------------------------- /sac_learn.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | 4 | import gym 5 | import numpy as np 6 | 7 | import torch 8 | import torch.nn as nn 9 | import torch.optim as optim 10 | import torch.nn.functional as F 11 | from torch.distributions import Normal 12 | # this line is critical to ensure torch initialization correctly for multi-processing 13 | torch.multiprocessing.set_start_method('forkserver', force=True) 14 | 15 | 16 | from IPython.display import clear_output 17 | import matplotlib.pyplot as plt 18 | from matplotlib import animation 19 | from IPython.display import display 20 | 21 | from sawyer_grasp_env_boundingbox import GraspEnv 22 | import argparse 23 | import time 24 | import pickle 25 | 26 | import torch.multiprocessing as mp 27 | from torch.multiprocessing import Process 28 | 29 | from multiprocessing import Process, Manager 30 | from multiprocessing.managers import BaseManager 31 | 32 | 33 | GPU = True 34 | device_idx = 0 35 | if GPU: 36 | device = torch.device("cuda:" + str(device_idx) if torch.cuda.is_available() else "cpu") 37 | else: 38 | device = torch.device("cpu") 39 | print(device) 40 | 41 | 42 | parser = argparse.ArgumentParser(description='Train or test neural net motor controller.') 43 | parser.add_argument('--train', dest='train', action='store_true', default=False) 44 | parser.add_argument('--test', dest='test', action='store_true', default=False) 45 | 46 | args = parser.parse_args() 47 | 48 | class ReplayBuffer: 49 | def __init__(self, capacity): 50 | self.capacity = capacity 51 | self.buffer = [] 52 | self.position = 0 53 | 54 | def push(self, state, action, reward, next_state, done): 55 | if len(self.buffer) < self.capacity: 56 | self.buffer.append(None) 57 | self.buffer[self.position] = (state, action, reward, next_state, done) 58 | self.position = int((self.position + 1) % self.capacity) # as a ring buffer 59 | 60 | def sample(self, batch_size): 61 | batch = random.sample(self.buffer, batch_size) 62 | state, action, reward, next_state, done = map(np.stack, zip(*batch)) # stack for each element 63 | ''' 64 | the * serves as unpack: sum(a,b) <=> batch=(a,b), sum(*batch) ; 65 | zip: a=[1,2], b=[2,3], zip(a,b) => [(1, 2), (2, 3)] ; 66 | the map serves as mapping the function on each list element: map(square, [2,3]) => [4,9] ; 67 | np.stack((1,2)) => array([1, 2]) 68 | ''' 69 | return state, action, reward, next_state, done 70 | 71 | def __len__(self): # cannot work in multiprocessing case, len(replay_buffer) is not available in proxy of manager! 72 | return len(self.buffer) 73 | 74 | def get_length(self): 75 | return len(self.buffer) 76 | 77 | class NormalizedActions(gym.ActionWrapper): 78 | def _action(self, action): 79 | low = self.action_space.low 80 | high = self.action_space.high 81 | 82 | action = low + (action + 1.0) * 0.5 * (high - low) 83 | action = np.clip(action, low, high) 84 | 85 | return action 86 | 87 | def _reverse_action(self, action): 88 | low = self.action_space.low 89 | high = self.action_space.high 90 | 91 | action = 2 * (action - low) / (high - low) - 1 92 | action = np.clip(action, low, high) 93 | 94 | return action 95 | 96 | class ValueNetwork(nn.Module): 97 | def __init__(self, state_dim, hidden_dim, init_w=3e-3): 98 | super(ValueNetwork, self).__init__() 99 | 100 | self.linear1 = nn.Linear(state_dim, hidden_dim) 101 | self.linear2 = nn.Linear(hidden_dim, hidden_dim) 102 | self.linear3 = nn.Linear(hidden_dim, hidden_dim) 103 | self.linear4 = nn.Linear(hidden_dim, 1) 104 | # weights initialization 105 | self.linear4.weight.data.uniform_(-init_w, init_w) 106 | self.linear4.bias.data.uniform_(-init_w, init_w) 107 | 108 | def forward(self, state): 109 | x = F.relu(self.linear1(state)) 110 | x = F.relu(self.linear2(x)) 111 | x = F.relu(self.linear3(x)) 112 | x = self.linear4(x) 113 | return x 114 | 115 | 116 | class SoftQNetwork(nn.Module): 117 | def __init__(self, num_inputs, num_actions, hidden_size, init_w=3e-3): 118 | super(SoftQNetwork, self).__init__() 119 | 120 | self.linear1 = nn.Linear(num_inputs + num_actions, hidden_size) 121 | self.linear2 = nn.Linear(hidden_size, hidden_size) 122 | self.linear3 = nn.Linear(hidden_size, hidden_size) 123 | self.linear4 = nn.Linear(hidden_size, 1) 124 | 125 | self.linear4.weight.data.uniform_(-init_w, init_w) 126 | self.linear4.bias.data.uniform_(-init_w, init_w) 127 | 128 | def forward(self, state, action): 129 | x = torch.cat([state, action], 1) # the dim 0 is number of samples 130 | x = F.relu(self.linear1(x)) 131 | x = F.relu(self.linear2(x)) 132 | x = F.relu(self.linear3(x)) 133 | x = self.linear4(x) 134 | return x 135 | 136 | 137 | class PolicyNetwork(nn.Module): 138 | def __init__(self, num_inputs, num_actions, hidden_size, action_range=1., init_w=3e-3, log_std_min=-20, log_std_max=2): 139 | super(PolicyNetwork, self).__init__() 140 | 141 | self.log_std_min = log_std_min 142 | self.log_std_max = log_std_max 143 | 144 | self.linear1 = nn.Linear(num_inputs, hidden_size) 145 | self.linear2 = nn.Linear(hidden_size, hidden_size) 146 | self.linear3 = nn.Linear(hidden_size, hidden_size) 147 | self.linear4 = nn.Linear(hidden_size, hidden_size) 148 | 149 | self.mean_linear = nn.Linear(hidden_size, num_actions) 150 | self.mean_linear.weight.data.uniform_(-init_w, init_w) 151 | self.mean_linear.bias.data.uniform_(-init_w, init_w) 152 | 153 | self.log_std_linear = nn.Linear(hidden_size, num_actions) 154 | self.log_std_linear.weight.data.uniform_(-init_w, init_w) 155 | self.log_std_linear.bias.data.uniform_(-init_w, init_w) 156 | 157 | self.action_range = action_range 158 | self.num_actions = num_actions 159 | 160 | 161 | def forward(self, state): 162 | x = F.relu(self.linear1(state)) 163 | x = F.relu(self.linear2(x)) 164 | x = F.relu(self.linear3(x)) 165 | x = F.relu(self.linear4(x)) 166 | 167 | mean = (self.mean_linear(x)) 168 | log_std = self.log_std_linear(x) 169 | log_std = torch.clamp(log_std, self.log_std_min, self.log_std_max) 170 | 171 | return mean, log_std 172 | 173 | def evaluate(self, state, epsilon=1e-6): 174 | ''' 175 | generate sampled action with state as input wrt the policy network; 176 | ''' 177 | mean, log_std = self.forward(state) 178 | std = log_std.exp() # no clip in evaluation, clip affects gradients flow 179 | 180 | normal = Normal(0, 1) 181 | z = normal.sample() 182 | action_0 = torch.tanh(mean + std*z.to(device)) # TanhNormal distribution as actions; reparameterization trick 183 | action = self.action_range*action_0 184 | log_prob = Normal(mean, std).log_prob(mean+ std*z.to(device)) - torch.log(1. - action_0.pow(2) + epsilon) - np.log(self.action_range) 185 | # both dims of normal.log_prob and -log(1-a**2) are (N,dim_of_action); 186 | # the Normal.log_prob outputs the same dim of input features instead of 1 dim probability, 187 | # needs sum up across the features dim to get 1 dim prob; or else use Multivariate Normal. 188 | log_prob = log_prob.sum(dim=1, keepdim=True) 189 | return action, log_prob, z, mean, log_std 190 | 191 | 192 | def get_action(self, state, deterministic): 193 | state = torch.FloatTensor(state).unsqueeze(0).to(device) 194 | mean, log_std = self.forward(state) 195 | std = log_std.exp() 196 | 197 | normal = Normal(0, 1) 198 | z = normal.sample().to(device) 199 | action = self.action_range* torch.tanh(mean + std*z) 200 | 201 | action = self.action_range* torch.tanh(mean).detach().cpu().numpy()[0] if deterministic else action.detach().cpu().numpy()[0] 202 | return action 203 | 204 | 205 | def sample_action(self,): 206 | a=torch.FloatTensor(self.num_actions).uniform_(-1, 1) 207 | return self.action_range*a.numpy() 208 | 209 | 210 | class SAC_Trainer(): 211 | def __init__(self, replay_buffer, hidden_dim, action_range): 212 | self.replay_buffer = replay_buffer 213 | 214 | self.soft_q_net1 = SoftQNetwork(state_dim, action_dim, hidden_dim).to(device) 215 | self.soft_q_net2 = SoftQNetwork(state_dim, action_dim, hidden_dim).to(device) 216 | self.target_soft_q_net1 = SoftQNetwork(state_dim, action_dim, hidden_dim).to(device) 217 | self.target_soft_q_net2 = SoftQNetwork(state_dim, action_dim, hidden_dim).to(device) 218 | self.policy_net = PolicyNetwork(state_dim, action_dim, hidden_dim, action_range).to(device) 219 | self.log_alpha = torch.zeros(1, dtype=torch.float32, requires_grad=True, device=device) 220 | print('Soft Q Network (1,2): ', self.soft_q_net1) 221 | print('Policy Network: ', self.policy_net) 222 | 223 | for target_param, param in zip(self.target_soft_q_net1.parameters(), self.soft_q_net1.parameters()): 224 | target_param.data.copy_(param.data) 225 | for target_param, param in zip(self.target_soft_q_net2.parameters(), self.soft_q_net2.parameters()): 226 | target_param.data.copy_(param.data) 227 | 228 | self.soft_q_criterion1 = nn.MSELoss() 229 | self.soft_q_criterion2 = nn.MSELoss() 230 | 231 | soft_q_lr = 3e-4 232 | policy_lr = 3e-4 233 | alpha_lr = 3e-4 234 | 235 | self.soft_q_optimizer1 = optim.Adam(self.soft_q_net1.parameters(), lr=soft_q_lr) 236 | self.soft_q_optimizer2 = optim.Adam(self.soft_q_net2.parameters(), lr=soft_q_lr) 237 | self.policy_optimizer = optim.Adam(self.policy_net.parameters(), lr=policy_lr) 238 | self.alpha_optimizer = optim.Adam([self.log_alpha], lr=alpha_lr) 239 | 240 | 241 | def update(self, batch_size, reward_scale=10., auto_entropy=True, use_demons=False, target_entropy=-2, gamma=0.99,soft_tau=1e-2): 242 | state, action, reward, next_state, done = self.replay_buffer.sample(batch_size) 243 | 244 | if use_demons==True: # using demonstration data by feeding into training buffer 245 | data_file=open('./demons_data/demon_data.pickle', "rb") 246 | demons_data = pickle.load(data_file) 247 | state_, action_, reward_, next_state_, done_=map(np.stack, zip(*demons_data)) 248 | state = np.concatenate((state, state_), axis=0) 249 | action = np.concatenate((action, action_), axis=0) 250 | reward = np.concatenate((reward, reward_), axis=0) 251 | next_state = np.concatenate((next_state, next_state_), axis=0) 252 | done = np.concatenate((done, done_), axis=0) 253 | 254 | 255 | state = torch.FloatTensor(state).to(device) 256 | next_state = torch.FloatTensor(next_state).to(device) 257 | action = torch.FloatTensor(action).to(device) 258 | reward = torch.FloatTensor(reward).unsqueeze(1).to(device) # reward is single value, unsqueeze() to add one dim to be [reward] at the sample dim; 259 | done = torch.FloatTensor(np.float32(done)).unsqueeze(1).to(device) 260 | 261 | predicted_q_value1 = self.soft_q_net1(state, action) 262 | predicted_q_value2 = self.soft_q_net2(state, action) 263 | new_action, log_prob, z, mean, log_std = self.policy_net.evaluate(state) 264 | new_next_action, next_log_prob, _, _, _ = self.policy_net.evaluate(next_state) 265 | reward = reward_scale * (reward - reward.mean(dim=0)) / (reward.std(dim=0) + 1e-6) # normalize with batch mean and std; plus a small number to prevent numerical problem 266 | # Updating alpha wrt entropy 267 | # alpha = 0.0 # trade-off between exploration (max entropy) and exploitation (max Q) 268 | if auto_entropy is True: 269 | alpha_loss = -(self.log_alpha * (log_prob + target_entropy).detach()).mean() 270 | self.alpha_optimizer.zero_grad() 271 | alpha_loss.backward() 272 | self.alpha_optimizer.step() 273 | self.alpha = self.log_alpha.exp() 274 | else: 275 | self.alpha = 1. 276 | alpha_loss = 0 277 | 278 | # Training Q Function 279 | target_q_min = torch.min(self.target_soft_q_net1(next_state, new_next_action),self.target_soft_q_net2(next_state, new_next_action)) - self.alpha * next_log_prob 280 | target_q_value = reward + (1 - done) * gamma * target_q_min # if done==1, only reward 281 | q_value_loss1 = self.soft_q_criterion1(predicted_q_value1, target_q_value.detach()) # detach: no gradients for the variable 282 | q_value_loss2 = self.soft_q_criterion2(predicted_q_value2, target_q_value.detach()) 283 | 284 | 285 | self.soft_q_optimizer1.zero_grad() 286 | q_value_loss1.backward() 287 | self.soft_q_optimizer1.step() 288 | self.soft_q_optimizer2.zero_grad() 289 | q_value_loss2.backward() 290 | self.soft_q_optimizer2.step() 291 | 292 | # Training Policy Function 293 | predicted_new_q_value = torch.min(self.soft_q_net1(state, new_action),self.soft_q_net2(state, new_action)) 294 | policy_loss = (self.alpha * log_prob - predicted_new_q_value).mean() 295 | 296 | self.policy_optimizer.zero_grad() 297 | policy_loss.backward() 298 | self.policy_optimizer.step() 299 | 300 | # Soft update the target value net 301 | for target_param, param in zip(self.target_soft_q_net1.parameters(), self.soft_q_net1.parameters()): 302 | target_param.data.copy_( # copy data value into target parameters 303 | target_param.data * (1.0 - soft_tau) + param.data * soft_tau 304 | ) 305 | for target_param, param in zip(self.target_soft_q_net2.parameters(), self.soft_q_net2.parameters()): 306 | target_param.data.copy_( # copy data value into target parameters 307 | target_param.data * (1.0 - soft_tau) + param.data * soft_tau 308 | ) 309 | return predicted_new_q_value.mean() 310 | 311 | def save_model(self, path): 312 | torch.save(self.soft_q_net1.state_dict(), path+'_q1') # have to specify different path name here! 313 | torch.save(self.soft_q_net2.state_dict(), path+'_q2') 314 | torch.save(self.policy_net.state_dict(), path+'_policy') 315 | 316 | def load_model(self, path): 317 | self.soft_q_net1.load_state_dict(torch.load(path+'_q1')) 318 | self.soft_q_net2.load_state_dict(torch.load(path+'_q2')) 319 | self.policy_net.load_state_dict(torch.load(path+'_policy')) 320 | 321 | self.soft_q_net1.eval() 322 | self.soft_q_net2.eval() 323 | self.policy_net.eval() 324 | 325 | 326 | def worker(id, sac_trainer, rewards_queue, replay_buffer, max_episodes, max_steps, batch_size, explore_steps, \ 327 | update_itr, AUTO_ENTROPY, DETERMINISTIC, USE_DEMONS, hidden_dim, model_path, headless): 328 | ''' 329 | the function for sampling with multi-processing 330 | ''' 331 | 332 | print(sac_trainer, replay_buffer) # sac_tainer are not the same, but all networks and optimizers in it are the same; replay buffer is the same one. 333 | env = GraspEnv(headless=headless) # no need to configure different port_number for calling different Vrep env at the same time 334 | 335 | action_dim = env.action_space.shape[0] 336 | state_dim = env.observation_space.shape[0] 337 | 338 | frame_idx=0 339 | # training loop 340 | for eps in range(max_episodes): 341 | 342 | episode_reward = 0 343 | state = env.reset() 344 | 345 | # reinitialize the environment every fixed interval during training, 346 | # to avoid the problems in environment, e.g. broken gripper, etc 347 | if eps%20==0 and eps>0: 348 | env.reinit() 349 | 350 | for step in range(max_steps): 351 | if frame_idx > explore_steps: 352 | action = sac_trainer.policy_net.get_action(state, deterministic = DETERMINISTIC) 353 | else: 354 | action = sac_trainer.policy_net.sample_action() 355 | 356 | try: 357 | next_state, reward, done, _ = env.step(action) 358 | except KeyboardInterrupt: 359 | print('Finished') 360 | sac_trainer.save_model(model_path) 361 | replay_buffer.push(state, action, reward, next_state, done) 362 | 363 | state = next_state 364 | episode_reward += reward 365 | frame_idx += 1 366 | 367 | # if len(replay_buffer) > batch_size: 368 | if replay_buffer.get_length() > batch_size: 369 | for i in range(update_itr): 370 | _=sac_trainer.update(batch_size, reward_scale=10., auto_entropy=AUTO_ENTROPY, use_demons=USE_DEMONS, target_entropy=-1.*action_dim) 371 | 372 | if eps % 10 == 0 and eps>0: 373 | sac_trainer.save_model(model_path) 374 | 375 | if done: 376 | break 377 | print('Episode: ', eps, '| Episode Reward: ', episode_reward) 378 | rewards_queue.put(episode_reward) 379 | 380 | sac_trainer.save_model(model_path) 381 | env.shutdown() 382 | 383 | 384 | 385 | def ShareParameters(adamoptim): 386 | ''' share parameters of Adamoptimizers for multiprocessing ''' 387 | for group in adamoptim.param_groups: 388 | for p in group['params']: 389 | state = adamoptim.state[p] 390 | # initialize: have to initialize here, or else cannot find 391 | state['step'] = 0 392 | state['exp_avg'] = torch.zeros_like(p.data) 393 | state['exp_avg_sq'] = torch.zeros_like(p.data) 394 | 395 | # share in memory 396 | state['exp_avg'].share_memory_() 397 | state['exp_avg_sq'].share_memory_() 398 | 399 | def plot(rewards): 400 | clear_output(True) 401 | # plt.figure(figsize=(20,5)) 402 | plt.plot(rewards) 403 | plt.savefig('sac_multi.png') 404 | # plt.show() 405 | plt.clf() 406 | 407 | 408 | if __name__ == '__main__': 409 | 410 | replay_buffer_size = 1e6 411 | # the replay buffer is a class, have to use torch manager to make it a proxy for sharing across processes 412 | BaseManager.register('ReplayBuffer', ReplayBuffer) 413 | manager = BaseManager() 414 | manager.start() 415 | replay_buffer = manager.ReplayBuffer(replay_buffer_size) # share the replay buffer through manager 416 | 417 | # hyper-parameters for RL training, no need for sharing across processes 418 | max_episodes = 500000 419 | max_steps = 30 420 | explore_steps = 0 # for random action sampling in the beginning of training 421 | batch_size=128 422 | update_itr = 1 423 | AUTO_ENTROPY=True 424 | DETERMINISTIC=False 425 | USE_DEMONS = False # using demonstrations 426 | hidden_dim = 512 427 | model_path = './model/sac_multi' 428 | num_workers=6 # or: mp.cpu_count() 429 | headless = True # if headless is True, no visualization 430 | 431 | # choose env 432 | env = GraspEnv(headless=headless) 433 | 434 | action_dim = env.action_space.shape[0] 435 | state_dim = env.observation_space.shape[0] 436 | action_range=1. # 0.1 for end_position control and 1. for joint_velocity control 437 | env.shutdown() 438 | 439 | 440 | sac_trainer=SAC_Trainer(replay_buffer, hidden_dim=hidden_dim, action_range=action_range ) 441 | 442 | if args.train: 443 | #sac_trainer.load_model(model_path) # if using pre-training 444 | 445 | # share the global parameters in multiprocessing 446 | sac_trainer.soft_q_net1.share_memory() 447 | sac_trainer.soft_q_net2.share_memory() 448 | sac_trainer.target_soft_q_net1.share_memory() 449 | sac_trainer.target_soft_q_net2.share_memory() 450 | sac_trainer.policy_net.share_memory() 451 | sac_trainer.log_alpha.share_memory_() 452 | ShareParameters(sac_trainer.soft_q_optimizer1) 453 | ShareParameters(sac_trainer.soft_q_optimizer2) 454 | ShareParameters(sac_trainer.policy_optimizer) 455 | ShareParameters(sac_trainer.alpha_optimizer) 456 | 457 | rewards_queue=mp.Queue() # used for get rewards from all processes and plot the curve 458 | processes=[] 459 | rewards=[] 460 | 461 | for i in range(num_workers): 462 | process = Process(target=worker, args=(i, sac_trainer, rewards_queue, replay_buffer, max_episodes, max_steps, \ 463 | batch_size, explore_steps, update_itr, AUTO_ENTROPY, DETERMINISTIC, USE_DEMONS, hidden_dim, model_path, headless)) # the args contain shared and not shared 464 | process.daemon=True # all processes closed when the main stops 465 | processes.append(process) 466 | 467 | [p.start() for p in processes] 468 | while True: # keep geting the episode reward from the queue 469 | r = rewards_queue.get() 470 | if r is not None: 471 | rewards.append(r) 472 | else: 473 | break 474 | 475 | if len(rewards)%20==0 and len(rewards)>0: 476 | # plot(rewards) 477 | np.save('reward_log', rewards) 478 | 479 | 480 | [p.join() for p in processes] # finished at the same time 481 | 482 | sac_trainer.save_model(model_path) 483 | 484 | if args.test: 485 | env = GraspEnv(headless=False, control_mode='joint_velocity') # for visualizing in test 486 | trained_model_path1 = './model/trained_model/augmented_dense_reward/sac_multi' # pre-trained model with augmented dense reward 487 | trained_model_path2 = './model/trained_model/dense_reward/sac_multi' # pre-trained model with dense reward 488 | sac_trainer.load_model(model_path) # new model after training 489 | for eps in range(30): 490 | state = env.reset() 491 | episode_reward = 0 492 | 493 | for step in range(max_steps): 494 | action = sac_trainer.policy_net.get_action(state, deterministic = DETERMINISTIC) 495 | next_state, reward, done, _ = env.step(action) 496 | episode_reward += reward 497 | state=next_state 498 | 499 | print('Episode: ', eps, '| Episode Reward: ', episode_reward) 500 | 501 | env.shutdown() 502 | -------------------------------------------------------------------------------- /sawyer_grasp_env_boundingbox.py: -------------------------------------------------------------------------------- 1 | """ 2 | The environment of Sawyer Arm + Baxter Gripper for graping object. 3 | With a bounding box of the arange that the gripper cannot move outside. 4 | """ 5 | from os.path import dirname, join, abspath 6 | from pyrep import PyRep 7 | from pyrep.robots.arms.sawyer import Sawyer 8 | from pyrep.robots.end_effectors.baxter_gripper import BaxterGripper 9 | from pyrep.objects.proximity_sensor import ProximitySensor 10 | from pyrep.objects.vision_sensor import VisionSensor 11 | from pyrep.objects.shape import Shape 12 | from pyrep.objects.dummy import Dummy 13 | from pyrep.const import JointType, JointMode 14 | import numpy as np 15 | import matplotlib.pyplot as plt 16 | import math 17 | 18 | POS_MIN, POS_MAX = [0.1, -0.3, 1.], [0.45, 0.3, 1.] # valid position range of target object 19 | 20 | 21 | class GraspEnv(object): 22 | ''' Sawyer robot grasping a cuboid ''' 23 | def __init__(self, headless, control_mode='joint_velocity'): 24 | ''' 25 | parameters: 26 | :headless: bool, if True, no visualization, else with visualization. 27 | :control mode: str, 'end_position' or 'joint_velocity'. 28 | ''' 29 | # set public variables 30 | self.headless = headless # if headless is True, no visualization 31 | self.reward_offset = 10.0 # reward of achieving the grasping object 32 | self.reward_range = self.reward_offset # reward range for register gym env when using vectorized env wrapper 33 | self.penalty_offset = 1. # penalty value for undesired cases 34 | self.fall_down_offset = 0.1 # distance for judging the target object fall off the table 35 | self.metadata=[] # gym env argument 36 | self.control_mode = control_mode # the control mode of robotic arm: 'end_position' or 'joint_velocity' 37 | 38 | # launch and set up the scene, and set the proxy variables in represent of the counterparts in the scene 39 | self.pr = PyRep() # call the PyRep 40 | if control_mode == 'end_position': # need to use different scene, the one with all joints in inverse kinematics mode 41 | SCENE_FILE = join(dirname(abspath(__file__)), './scenes/sawyer_reacher_rl_new_ik.ttt') # scene with joints controlled by ik (inverse kinematics) 42 | elif control_mode == 'joint_velocity': # the scene with all joints in force/torch mode for forward kinematics 43 | SCENE_FILE = join(dirname(abspath(__file__)), './scenes/sawyer_reacher_rl_new.ttt') # scene with joints controlled by forward kinematics 44 | self.pr.launch(SCENE_FILE, headless=headless) # lunch the scene, headless means no visualization 45 | self.pr.start() # start the scene 46 | self.agent = Sawyer() # get the robot arm in the scene 47 | self.gripper = BaxterGripper() # get the gripper in the scene 48 | self.gripper_left_pad = Shape('BaxterGripper_leftPad') # the left pad on the gripper finger 49 | self.proximity_sensor = ProximitySensor('BaxterGripper_attachProxSensor') # need the name of the sensor here 50 | self.vision_sensor = VisionSensor('Vision_sensor') # need the name of the sensor here 51 | self.table = Shape('diningTable') # the table in the scene for checking collision 52 | if control_mode == 'end_position': # control the robot arm by the position of its end using inverse kinematics 53 | self.agent.set_control_loop_enabled(True) # if false, inverse kinematics won't work 54 | self.action_space = np.zeros(4) # 3 DOF end position control + 1 rotation of gripper 55 | elif control_mode == 'joint_velocity': # control the robot arm by directly setting velocity values on each joint, using forward kinematics 56 | self.agent.set_control_loop_enabled(False) 57 | self.action_space = np.zeros(7) # 7 DOF velocity control, no need for extra control of end rotation, the 7th joint controls it. 58 | else: 59 | raise NotImplementedError 60 | self.observation_space = np.zeros(17) # position and velocity of 7 joints + position of the target 61 | self.agent.set_motor_locked_at_zero_velocity(True) 62 | self.target = Shape('target') # get the target object 63 | self.agent_ee_tip = self.agent.get_tip() # a part of robot as the end of inverse kinematics chain for controlling 64 | self.tip_target = Dummy('Sawyer_target') # the target point of the tip (end of the robot arm) to move towards 65 | self.tip_pos = self.agent_ee_tip.get_position() # tip x,y,z position 66 | 67 | # set a proper initial robot gesture or tip position 68 | if control_mode == 'end_position': 69 | initial_pos = [0.3, 0.1, 0.9] 70 | self.tip_target.set_position(initial_pos) 71 | # one big step for rotation setting is enough, with reset_dynamics=True, set the rotation instantaneously 72 | self.tip_target.set_orientation([0,np.pi,np.pi/2], reset_dynamics=True) # first two dimensions along x and y axis make gripper face downwards 73 | elif control_mode == 'joint_velocity': 74 | self.initial_joint_positions = [0.001815199851989746, -1.4224984645843506, \ 75 | 0.704303503036499, 2.54307222366333, 2.972468852996826, -0.4989511966705322, 4.105560302734375] # a proper initial gesture 76 | self.agent.set_joint_positions(self.initial_joint_positions) 77 | self.pr.step() 78 | self.initial_tip_positions = self.agent_ee_tip.get_position() 79 | self.initial_target_positions = self.target.get_position() 80 | 81 | def _get_state(self): 82 | ''' 83 | Return state containing arm joint positions/velocities & target position. 84 | ''' 85 | return np.array(self.agent.get_joint_positions() + # list, dim=7 86 | self.agent.get_joint_velocities() + # list, dim=7 87 | self.target.get_position()) # list, dim=3 88 | 89 | def _is_holding(self): 90 | ''' 91 | Return the state of holding the target or not, return bool. 92 | ''' 93 | # Note that the collision check is not always accurate all the time, 94 | # for continuous collision frames, maybe only the first 4-5 frames of collision can be detected. 95 | pad_collide_object = self.gripper_left_pad.check_collision(self.target) 96 | if pad_collide_object and self.proximity_sensor.is_detected(self.target)==True: 97 | return True 98 | else: 99 | return False 100 | 101 | 102 | def _move(self, action, bounding_offset=0.15, step_factor=0.2, max_itr=20, max_error=0.05, rotation_norm =5.): 103 | ''' 104 | Move the end effector on robot arm according to the action with inverse kinematics for 'end_position' control mode; 105 | Inverse kinematics mode control is achieved through setting the tip target instead of using .solve_ik(), 106 | because sometimes the .solve_ik() does not function correctly. 107 | Mode: a close-loop proportional control, using ik. 108 | 109 | parameters: 110 | :bounding_offset: offset of bounding box outside the valid target position range, as valid and safe range of action 111 | :step_factor: small step factor mulitplied on the difference of current and desired position, i.e. proportional factor 112 | :max_itr: maximum moving iterations 113 | :max_error: upper bound of distance error for movement at each call 114 | :rotation_norm: factor for normalization of rotation values, since the action are of the same scale for each dimension 115 | ''' 116 | pos=self.gripper.get_position() 117 | 118 | # check if state+action will be within of the bounding box, if so, move normally; otherwise the action is not conducted. 119 | # i.e. x_min < x < x_max and y_min < y < y_max and z > z_min 120 | if pos[0]+action[0]>POS_MIN[0]-bounding_offset and pos[0]+action[0] POS_MIN[1]-bounding_offset and pos[1]+action[1] < POS_MAX[1]+2*bounding_offset \ 122 | and pos[2]+action[2] > POS_MIN[2]-2*bounding_offset: # larger offset in z axis 123 | 124 | # there is a mismatch between the object set_orientation() and get_orientation(): 125 | # the (x,y,z) in set_orientation() will be (y,x,-z) in get_orientation(). 126 | ori_z=-self.agent_ee_tip.get_orientation()[2] # the minus is because the mismatch between the set_orientation() and get_orientation() 127 | target_pos = np.array(self.agent_ee_tip.get_position())+np.array(action[:3]) 128 | diff=1 # intialization 129 | itr=0 130 | while np.sum(np.abs(diff))>max_error and itr0.1 and itr